Linux Packaging
This directory contains all files needed to build RPM and Debian packages for xrpld.
Directory layout
package/
build_pkg.sh Staging and build script (called by CMake targets and CI)
rpm/
xrpld.spec RPM spec (xrpld_version/pkg_release passed via rpmbuild --define)
deb/
debian/ Debian control files (control, rules, install, links, conffiles, ...)
shared/
xrpld.service systemd unit file (used by both RPM and DEB)
xrpld.sysusers sysusers.d config (used by both RPM and DEB)
xrpld.tmpfiles tmpfiles.d config (used by both RPM and DEB)
xrpld.logrotate logrotate config (installed to /opt/xrpld/bin/, user activates)
update-xrpld.sh auto-update script (installed to /opt/xrpld/bin/)
update-xrpld-cron cron entry for auto-update (installed to /opt/xrpld/bin/)
test/
smoketest.sh Package install smoke test
check_install_paths.sh Verify install paths and compat symlinks
Prerequisites
Packaging targets and their container images are declared in
.github/scripts/strategy-matrix/linux.json
via a "packaging" field on specific os entries. The image tag is composed
as ghcr.io/xrplf/ci/{distro}-{version}:{compiler}-{cver}-sha-{image_sha} —
the same scheme used by reusable-build-test.yml. Bump image_sha in
linux.json and both CI and local builds pick up the new image with no
workflow edits.
| Package type | Image (derived from linux.json) |
Tool required |
|---|---|---|
| RPM | ghcr.io/xrplf/ci/rhel-9:gcc-12-sha-<git_sha> |
rpmbuild |
| DEB | ghcr.io/xrplf/ci/ubuntu-jammy:gcc-12-sha-<git_sha> |
dpkg-buildpackage, debhelper (>= 13), dh-sequence-systemd |
To print the exact image tags for the current linux.json:
./.github/scripts/strategy-matrix/generate.py --packaging --config=.github/scripts/strategy-matrix/linux.json
Building packages
Via CI
Caller workflows (on-pr.yml, on-tag.yml, on-trigger.yml) call
reusable-strategy-matrix.yml with mode: packaging to generate the matrix of
{pkg_type, artifact_name, container_image} entries, then fan out to
reusable-package.yml per entry. That workflow downloads the pre-built xrpld
binary artifact and calls build_pkg.sh directly — no CMake configure or
build step is needed inside the packaging job.
Locally (mirrors CI)
With an xrpld binary already built at build/xrpld, run the packaging step
inside the same container CI uses. The image tag is derived from linux.json
so you don't need to hardcode a SHA.
# From the repo root.
PKG_TYPE=deb # or rpm
VERSION=2.4.0-local
PKG_RELEASE=1
# Derive the correct image for this package type from linux.json.
IMAGE=$(jq -r --arg pkg "$PKG_TYPE" '
.os[] | select((.packaging // []) | index($pkg)) |
"ghcr.io/xrplf/ci/\(.distro_name)-\(.distro_version):\(.compiler_name)-\(.compiler_version)-sha-\(.image_sha)"
' .github/scripts/strategy-matrix/linux.json)
# Run the packaging in the container.
docker run --rm \
-v "$(pwd):/src" \
-w /src \
"$IMAGE" \
./package/build_pkg.sh "$PKG_TYPE" . build "$VERSION" "$PKG_RELEASE"
# Output:
# build/debbuild/*.deb (DEB + dbgsym .ddeb)
# build/rpmbuild/RPMS/x86_64/*.rpm
Via CMake (host-side target)
If you run CMake configure on a host that has rpmbuild or dpkg-buildpackage
installed natively, you can use the CMake targets directly — no container
needed, but the host toolchain replaces the pinned CI image:
cmake \
-DCMAKE_INSTALL_PREFIX=/opt/xrpld \
-Dxrpld=ON \
-Dxrpld_version=2.4.0-local \
-Dtests=OFF \
..
cmake --build . --target package-rpm # requires rpmbuild
cmake --build . --target package-deb # requires dpkg-buildpackage
The cmake/XrplPackaging.cmake module gates each target on whether the
required tool is present at configure time, so configuring on a host that
lacks one simply omits the corresponding target. CMAKE_INSTALL_PREFIX must
be /opt/xrpld; if it is not, both targets are skipped with a STATUS
message.
How build_pkg.sh works
build_pkg.sh <pkg_type> <src_dir> <build_dir> [version] [pkg_release] stages
all files and invokes the platform build tool. It resolves src_dir and
build_dir to absolute paths, then calls stage_common() to copy the binary,
config files, and shared support files into the staging area.
RPM
- Creates the standard
rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}tree inside the build directory. - Copies
xrpld.specand all source files (binary, configs, service files) intoSOURCES/. - Runs
rpmbuild -bb --define "xrpld_version ..." --define "pkg_release ...". The spec uses manualinstallcommands to place files. - Output:
rpmbuild/RPMS/x86_64/xrpld-*.rpm
DEB
- Creates a staging source tree at
debbuild/source/inside the build directory. - Stages the binary, configs,
README.md, andLICENSE.md. - Copies
package/deb/debian/control files intodebbuild/source/debian/. - Copies shared service/sysusers/tmpfiles into
debian/wheredh_installsystemd,dh_installsysusers, anddh_installtmpfilespick them up automatically. - Generates a minimal
debian/changelog(pre-release versions use~instead of-). - Runs
dpkg-buildpackage -b --no-sign.debian/rulesuses manualinstallcommands. - Output:
debbuild/*.debanddebbuild/*.ddeb(dbgsym package)
Post-build verification
# DEB
dpkg-deb -c debbuild/*.deb | grep -E 'systemd|sysusers|tmpfiles'
lintian -I debbuild/*.deb
# RPM
rpm -qlp rpmbuild/RPMS/x86_64/*.rpm
Reproducibility
The following environment variables improve build reproducibility. They are not
set automatically by build_pkg.sh; set them manually if needed:
export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)
export TZ=UTC
export LC_ALL=C.UTF-8
export GZIP=-n
export DEB_BUILD_OPTIONS="noautodbgsym reproducible=+fixfilepath"