cx::pm docs

Quickstart

This goes from nothing to an installed package of a library of your own: create it, build it, test it, pack it, install it.

The whole walkthrough, from the download on a fresh account:

A terminal: cxpm is downloaded from soft-forge.dev, its checksum checked and installed under ~/.local; then a library is created, built, tested, packed, installed and removed.

Install cxpm

Download cxpm for Linux x86_64 and put its bin/ on your PATH:

tar -xzf cxpm-0.4.0-linux-x86_64.tar.gz
mkdir -p ~/.local && cp -r cxpm-0.4.0-linux-x86_64/. ~/.local/
cxpm help

cxpm builds with the compilers you already have: g++ 13 or newer (or clang++ 18 or newer), with git and pkg-config on the machine. bubblewrap (bwrap, from your distribution’s packages) is optional and recommended: with it, manifests and build steps run confined .

Create a project

cxpm project create greeter --type static-library --tests --example
cd greeter
greeter/package.cpp                   the library
greeter/include/greeter/greeter.hpp
greeter/src/greeter.cpp
greeter/tests/package.cpp             a project that tests it
greeter/tests/src/main.cpp
greeter/example/package.cpp           a project that uses it
greeter/example/src/main.cpp

package.cpp is the manifest:

#include <cx/pm/project.hpp>
#include <cx/pm/target.hpp>

using namespace cx::pm;

auto package = cx::pm::target()
                  .name_set("greeter")
                  .version_set("0.1.0")
                  .type_set("static-library")
                  .sources_append({"src/*.cpp"})
                  .include_directories_append({"include"})
                  .create();

auto project = cx::pm::project().target_set(package).members_append("example").tests_append("tests").create();

A project has one target. The tests and the example are projects too: each has its own package.cpp whose target depends on greeter by name.

--type is executable (the default), shared-library, static-library or header-library.

Build and test

cxpm build
cxpm test
Building greeter (static-library) with g++
Installing greeter into .../greeter/.cxpm/sysroot
Building greeter-example (executable) with g++
Building greeter-tests (executable) with g++
Running greeter-tests
greeter-tests passed
1 of 1 tests projects passed

Everything cxpm writes goes under .cxpm/: objects and the built target in .cxpm/build/<name>/, and the library installed where the example and the tests find it, in .cxpm/sysroot/. Nothing is written to your system. A second cxpm build compiles nothing; changing one source recompiles that object and links again.

cxpm test exits with 0 only if every tests project builds and its executable exits with 0.

Add a dependency

A dependency is a name and, optionally, a version constraint:

.dependencies_append({"zlib >= 1.2"})

cxpm dependency add "zlib >= 1.2" writes that line for you, and fetches the dependency when the package index publishes it.

The name is a project of the same workspace, a dependency the manifest fetches, or a package installed in the sysroot, found through pkg-config. One that is fetched says where from:

#include <cx/pm/dependency.hpp>

.dependencies_append(cx::pm::dependency()
                         .name_set("greeter")
                         .repository_set("https://example.org/greeter.git")
                         .revision_set("v0.1.0"))

cxpm fetch clones it into .cxpm/sources/ and writes the exact commit to .cxpm/lock.json; cxpm build then builds it from its own manifest and installs it into .cxpm/sysroot. Commit the lock file if you want everyone to build the same commit.

Pack and install

cxpm pack
cxpm install --prefix /usr/local
Packed .../greeter/.cxpm/packages/greeter-0.1.0.cxpm.tar
Packed .../greeter/.cxpm/packages/greeter-example-0.1.0.cxpm.tar
Installing greeter into /usr/local with archive
Installing greeter-example into /usr/local with archive

Every member of the workspace is packed and installed, so the example goes along as bin/greeter-example; drop members_append("example") from the manifest to ship the library alone.

Installed:

/usr/local/lib/libgreeter.a
/usr/local/include/greeter/greeter/greeter.hpp
/usr/local/lib/pkgconfig/greeter.pc
/usr/local/lib/cxpm/packages/greeter.json      what was installed, for uninstall

Another project now depends on it with .dependencies_append({"greeter"}), and anything that speaks pkg-config finds it with pkg-config --cflags --libs greeter.

To get a package of your distribution instead of an archive:

cxpm pack --package-manager pacman     # or rpm, deb
sudo cxpm install --package-manager pacman --prefix /usr

cxpm uninstall removes what cxpm install installed, through the same package manager.

Where to go next

  • The cxpm command describes every stage, the manifest API, toolchains, building for another sysroot and confinement.
  • cxpm help <command> lists the options of a command.