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_dependency
function 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__dependency
must be able to accept whatever input is needed for the various package manager backends.
- CMake target
The user of the
find_or_build_dependency
function will provide a name for the dependency. That name will be tied to that particular invocation offind_or_build_dependency
and 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_dependency
call or when specifying the project’s assets (e.g.,cmaize_add_library
)
Find or Build Dependency Function Design
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
PackageSpecification
object.Obtains the active
CMaizeProject
object.Gets the active
PackageManager
from theCMaizeProject
object.Determines if the
PackageManager
object has a dependency matching thePackageSpecification
object.If yes, then the
PackageManager
retrieves the already installed dependency which is returned as aInstalledTarget
object.If no, then the
PackageManager
creates aBuildTarget
object which will be built during the build phase.Finally the target is registered to the active
CMaizeProject
object.
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_dependency
function 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_dependency
function relies onPackageManager
instances to actually find and/or build the various dependencies.- CMake target
The
BuildTarget
andInstalledTarget
classes are responsible for ensuring that a traditional CMake target is created under the name the user provides to thefind_or_build_dependency
function.