One package.cpp per project

A package manager for C++, written in C++.

Describe a project in a package.cpp. cxpm builds, tests, packs and installs it, and fetches what it depends on from git repositories or from a package index.

Experimental and at an early stage · it already builds, tests, packs and installs itself.

cxpm — a session in a project directory
$ cxpm
cxpm — index https://01.dev.soft-forge.dev/cxpm/index
# help lists the commands, Tab completes, Ctrl-D leaves.
cxpm demo> search cx
cxpm 0.2.0  A package manager and build tool for C and C++
cxpm demo> dependency add zlib@>=1.2
Added zlib >= 1.2 to package.cpp
cxpm demo> build
cxpm demo> publish
target per project
1
lifecycle commands
7
package formats: archive, pacman, rpm, deb
4
other build systems needed
0

Why cxpm

What cxpm is, and who it is for

For people who write C and C++ and want one tool between the source and an installed package: no separate build language, no generator step, and dependencies that are declared instead of found by accident.

The problem

A C++ project is usually described in a second language, and a target sees whatever happens to be installed on the machine that builds it.

The manifest is C++

A project is described in a package.cpp, as Swift does with Package.swift. A package.json with the same fields works where no C++ is wanted.

Only what is declared

A target gets include paths and libraries from the dependencies it declares, and from nowhere else. Builds run against a sysroot.

Four places a dependency comes from

Another project of the same workspace, a git repository, a package the index publishes, or a package of the sysroot.

From source to a native package

fetch, configure, build, test, pack, install and uninstall. Each runs the stages before it that it needs. Packages are archives, or pacman, rpm and deb packages.

A package index

The index maps a name and a version to a commit of a repository. Nothing but that entry is uploaded; the code stays in the repository.

Walkthrough

From an empty directory to a published package

Four steps, each one a command you can run today.

  1. Create a project

    cxpm project create writes a package.cpp and a first source. The manifest is ordinary C++: one target, with its name, version, type, sources and dependencies.

    package.cpp
    $ cxpm project create demo
    $ cd demo
    // package.cpp
    auto target = Target()
        .name_set("demo")
        .version_set("0.1.0")
        .type_set("executable")
        .sources_append({"src/*.cpp"})
        .create();
    auto project = Project().target_set(target).create();
  2. Build, test, pack, install

    Everything a project produces is under .cxpm/. cxpm test builds the project and then builds and runs its tests projects. cxpm install packs it and installs the package with the toolchain's package manager.

    terminal
    $ cxpm build
    $ cxpm test
    $ cxpm pack --package-manager rpm
    $ cxpm install --prefix ~/.local
  3. Add a dependency

    cxpm dependency add writes the dependency into the manifest and fetches it. A name is looked up in the index; dependency remove, list and sync do the rest.

    terminal
    $ cxpm dependency add fmt
    $ cxpm dependency add "zlib@>=1.2"
    $ cxpm dependency add https://example.org/team/json.git#v3
    $ cxpm dependency list
    fmt >= 10.2.0
    zlib >= 1.2
    json  https://example.org/team/json.git#v3
  4. Publish

    Log in to the index once, by confirming a code on Soft Forge Payments, then publish from the top of the repository. cxpm sends the name, the version, the repository's address and the commit.

    terminal
    $ cxpm login
    $ cxpm whoami
    $ cxpm publish
    $ cxpm search greeter

Reference

Commands

cxpm help <command> shows a command's options.

fetchDownloads the dependencies, resolves the ones the index publishes and pins them in .cxpm/lock.json.
configureResolves the toolchain and the dependencies again.
build, testBuilds a project; builds and runs its tests projects.
pack, install, uninstallPacks a project for a package manager, installs the package, removes it.
dependency add | remove | list | syncEdits the dependencies in the manifest and fetches them.
searchLists the packages of the index, or the ones matching a text.
login, logout, whoamiStores, forgets and shows the account used with an index.
publishPublishes the project's version as a commit of its repository.
project create, generateCreates a project; writes a starter manifest.
replOpens a session over these commands.
serveServes a package index over HTTP.

Install

Build it from source

Needs a C++23 compiler (GCC 14 or newer), pkg-config and git. bwrap is optional: with it, manifests and build steps run confined.

cxpm builds itself
$ git clone --recurse-submodules https://github.com/arthurafarias/cxpm
$ cd cxpm
$ ./cxpm-build.sh --install --prefix ~/.local
# or as a package of your distribution
$ ./cxpm-build.sh --prefix /usr --package-manager rpm
$ sudo rpm -i .cxpm/packages/*.rpm

Describe C++ projects in C++.

One manifest per project, dependencies that are declared, and a package index that points at commits.