A best practice for retrieving and using third party libraries with a platform independent build system (for c++) is currently not available. So I have decided to throw my hat in the ring by adding package control to cmake. I compete with other great solutions in this area:
- biicode a file based dependency management system depending on a central webservice.
- hunter a decentralized package manager with a central repository for
hunter gates
- cpm a git, subversion and hg based package manager also indexes packages in a github repository
I want to be able to use decentralized package sources (ie not a centralized server through which all requests go) and be easily extinsible to incoporate other package services with minimal overhead.
I want package search and retrieval to be a very simple process so it can be applied generally. (no specialization on C++, no callbacks, installation, etc - these subjects are important and are adressed but not in respect to package search and retrieval)
Using package search and retrieval as a base I will extend it by dependency management and cpp project generation.
I chose a very simple interface to handle packages note: these functions exist for every package source
(not globally) - except pull which is only implemented by writable data sources:
<package>
is an abstract term. It describes a set of files and meta information (<package descriptor>
) which is identified by a<package uri>
<package descriptor>
meta information on a package. No constraint on the data is made. There are however some properties which have special meaning and are listed hereid: <string>
the name of thepackage
it should be uniqueish. At least in its usage context it should be unique.version: <semver>
the version of the package...
other properties do not pertain to package search and retrieval but rather to project- and dependency-management these are described elsewhere.
<package uri>
is a<uri>
of an existing uniquely identified<package>
this uri identifies a<package>
's contents andpackage descriptor
the content and meta information of the package SHOULD BE immutable. This constraint is needed to allow for dependency management and guaranteeing a package's reliability. Everypackage source
will tell you what kind of guarantee it gives your.<package handle>
a package handle is an object containing information on a package and has a unique key calleduri
. The data varies for a package handle depending on thepackage source
it stems from. Some sources might add more meta information than others.- properties
uri :<package uri>
required. uniquely identifies this packagepackage_descriptor: <package_descriptor?>
required after resolve (may be null or generated.)content_dir:<content dir>
required after successful pull...
- properties
query(<~uri> [--package-handle]) -> <package uri...>
takes a uri query and returns a list of unique unchanging<package uri>
which will be valid now and generally in the future. It is important to note the unchanging aspect as once a package is uniquely identified the user expects it only to change when he/she wants it to.--package-handle
will return a<package handle>
instead of a<package uri>
--refresh
will cause an update of any cache being used.package source
s which do not cache will silently ignore this flag.
resolve(<~uri> [--refresh]) -> <package handle?>
takes a uri and returns a<package handle>
if the uri uniquely identifies a package. If the uri specified is not unique null is returned.--refresh
will cause an update of any cache being used.package source
s which do not cache will silently ignore this flag.
pull(<~uri> <target_dir?> [--refresh] [--reference]) -> <package handle>
takes a uri which is resolved to a package. The content of the package is then loaded into the specified target dir (relative to currentpwd
) The returned package handle will contain a property calledcontent_dir
which will normally but not necessarily be the same totarget_dir
--refresh
will cause an update of any cache being used--reference
will set thecontent_dir
of the package handle to a local path which already contains the content associated with thepackage uri
if thepackage source
does not support the reference flag it ifnore the--reference
flag
push(<~package handle> ...) -> <package uri>
the implemenation of this function is not necessary and not available for allpackage source
s - it allows upload of a package to apackage source
. After the successfull upload the<package uri>
is returned....
arguments dependening on thepackage source
being used.
The package source
s described hitherto all have a constructor function which returns a package source
object. The pull
/push
/resolve
/query
implementations have a longer function name and SHOULD NOT be used directly but by calling them on the package source
object using call(...)
or assign(...)
.
If your are just interested in pulling packages from a remote to a target directory you should use the default package methods: pull_package
, resolve_package
, query_package
which work globally and need no special package source
object.
Examples
## create a github package source and use it to find all local repositories of a github user and print them to the console
set(user "toeb")
assign(source = github_package_source())
assign(package_uris = source.query("${user}"))
message("all packages for ${user}")
foreach(package_uri ${package_uris})
message(" ${package_uri}")
endforeach()
A package source
is a set of methods and possibly some implementation specific properties. The interface for a package source
was already described and consists of the methods.
query
resolve
pull
push
optional
In the following sections the package source implementations are briefly discussed.