cxpm docs

How cxpm is linked

cxpm installs software into sysroots and is itself meant to be dropped into one, so it cannot lean on whatever C++ runtime the host happens to have. This page records what is linked statically, what is not, and why.

The decision

Binary Linkage Why
cxpm libstdc++ and libgcc static, glibc dynamic Runs on any machine with a compatible glibc, with no C++ runtime installed
cxpm-descriptor-sandbox Fully dynamic, always It dlopens plugins that were built against the shared libstdc++

Static C++ runtime, dynamic glibc

applications/cxpm/package.cpp passes -static-libstdc++ -static-libgcc as raw options. The result depends on glibc only:

$ ldd applications/cxpm/.cxpm/build/cxpm/cxpm
        linux-vdso.so.1
        libm.so.6 => /usr/lib/libm.so.6
        libc.so.6 => /usr/lib/libc.so.6
        /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2

It removes the dependency that actually breaks in practice, a libstdc++.so.6 older than the compiler that built cxpm, and keeps glibc dynamic, which is what glibc itself is designed for.

Those two flags are the one place where cxpm’s own manifest is tied to GCC and Clang: there is no neutral option for them yet.

Changing it

The linkage is part of the manifest, so changing it is an edit to applications/cxpm/package.cpp:

  • Shared runtime, for a distribution whose policy forbids static copies of libstdc++: remove the two flags.
  • Fully static: replace them with -static. This is not the default because a statically linked glibc still loads libnss_* modules with dlopen to resolve host and user names, and those must match the glibc the binary was linked with; fetch and the package index client resolve host names. A fully static cxpm belongs with a libc designed for it, such as musl.

What makes a fully static build possible at all is that cxpm never calls dlopen: every compiled package.cpp/toolchain.cpp is loaded by the sandbox helper.

The sandbox helper stays dynamic

cxpm-descriptor-sandbox is the process that loads a compiled manifest or toolchain plugin. Those plugins are ordinary shared objects, compiled by the host C++ compiler against the shared libstdc++. If the helper carried its own static copy of the runtime, the process would hold two C++ runtimes at once (two allocators, two sets of std::string internals, two unwinders) and passing a descriptor across the plugin boundary would be undefined behaviour. So the helper is linked dynamically and uses the same libstdc++ the plugins do.

Checking it

ldd applications/cxpm/.cxpm/build/cxpm/cxpm          # no libstdc++.so, no libgcc_s.so
ldd applications/cxpm-descriptor-sandbox/.cxpm/build/cxpm-descriptor-sandbox/cxpm-descriptor-sandbox
                                                     # libstdc++.so.6 present, on purpose

CI makes the first check on the installed binary.