Designing CMaize’s Find or Build Dependency Function
This page describes the process of designing the find_or_build_dependency
function.
What is CMaize’s Find or Build Dependency Function?
The find_or_build_dependency function is the user-facing function CMaize
provides to help developers manage their project’s dependencies. Under the hood
the find_or_build_dependency function is responsible for mapping the user’s
dependency needs to a target (a build target if the build system will
build it and an install target if it already exists). This mapping is done via
the package manager component (see
Designing CMaize’s PackageManager Component).
Why Do We Need a Find or Build Dependency Function?
The need for the find_or_build_dependency function arose in the discussions
of the overall user API (see Overview of CMaize’s User API Design). In
particular, CMaize is designed to rely on existing packaging managers. The
find_or_build_dependency API abstracts away the details of how those
package managers work so that CMaize consumers can simply specify the dependency
details.
Find or Build Dependency Function Considerations
- CMake based
- As user-facing functionality, the - find_or_build_dependencyfunction should have an interface which is consistent with traditional CMake. In particular this means the input should be strings and the result should be the name of a traditional CMake target.
- wrap package managers
- As stated above, one of the primary reasons for this function is to abstract away the details of how CMaize interacts with the underlying package managers. - As a corollary, this also means that - find_or_build__dependencymust be able to accept whatever input is needed for the various package manager backends.
 
- CMake target
- The user of the - find_or_build_dependencyfunction will provide a name for the dependency. That name will be tied to that particular invocation of- find_or_build_dependencyand will represent that specific package specification. This is explicitly done by creating a traditional CMake target under the provided name.- As a corollary, if the user wants to have multiple specifications of a package, then there must be be multiple calls to - find_or_build_dependency, each call must provide a unique name.
- The user should continue to refer to this package specification via the provided name, e.g., when using it as a dependency for another - find_or_build_dependencycall or when specifying the project’s assets (e.g.,- cmaize_add_library)
 
Find or Build Dependency Function Design
 
Fig. 3 Overview of the control flow in the find_or_build_dependency function.
The control flow of find_or_build_dependency is diagramed in
Fig. 3. In addressing the CMake based
consideration the inputs to the find_or_build_dependency function are the
name of the dependency and any inputs needed to specify the dependency (e.g.,
version or URL) and any necessary build options. Internally,
find_or_build_dependency then:
- Converts the dependency’s information into a - PackageSpecificationobject.
- Obtains the active - CMaizeProjectobject.
- Gets the active - PackageManagerfrom the- CMaizeProjectobject.
- Determines if the - PackageManagerobject has a dependency matching the- PackageSpecificationobject.
- If yes, then the - PackageManagerretrieves the already installed dependency which is returned as a- InstalledTargetobject.
- If no, then the - PackageManagercreates a- BuildTargetobject which will be built during the build phase.
- Finally the target is registered to the active - CMaizeProjectobject.
In turn, find_or_build_dependency thus works like a driver managing the
interactions of the CMaizeProject object with the PackageManager
objects. The reliance on a PackageManager object addresses the
wrap package managers consideration.
API Design
The API of the find_or_build_dependency function must be capable of
accepting whatever input a PackageSpecification object may need. This is
because the PackageManager will ultimately work with the
PackageSpecification. To that end, the API will accept a number of
kwargs which will be forwarded to the PackageSpecification and the
basic API will be:
cmaize_find_or_build_dependency(name_of_dependency <kwargs>)
Here name_of_dependency will be the base name assigned to the CMake target,
as required by the CMake target consideration. N.B., “CMake target”
in this context refers to a traditional CMake target, NOT a CMaize object.
Users should continue to refer to the dependency as name_of_dependency in
all future CMaize calls, e.g.:
cmaize_find_or_build_dependency(foo <kwargs>)
cmaize_find_or_build_dependency(bar DEPENDS foo <other_kwargs>)
Summary
- CMake based
- The - find_or_build_dependencyfunction relies on traditional CMake inputs and ultimately produces a native CMake target which is used by dependees.
- wrap package managers
- The body of the - find_or_build_dependencyfunction relies on- PackageManagerinstances to actually find and/or build the various dependencies.
- CMake target
- The - BuildTargetand- InstalledTargetclasses are responsible for ensuring that a traditional CMake target is created under the name the user provides to the- find_or_build_dependencyfunction.