mirror of
https://github.com/XRPLF/rippled.git
synced 2026-07-23 15:10:34 +00:00
219 lines
9.5 KiB
Markdown
219 lines
9.5 KiB
Markdown
# 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 the CMake `package` target and CI)
|
|
rpm/
|
|
xrpld.spec RPM spec
|
|
debian/ Debian control files (control, rules, copyright, xrpld.docs, xrpld.links, source/format)
|
|
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 /etc/logrotate.d/xrpld)
|
|
```
|
|
|
|
## Prerequisites
|
|
|
|
Packaging targets and their container images are declared in
|
|
[`.github/scripts/strategy-matrix/linux.json`](../.github/scripts/strategy-matrix/linux.json)
|
|
under `package_configs`, one entry per distro. Today only `linux/amd64` is
|
|
emitted. Each entry pins its full container image in an `image` field; to move
|
|
to a new image, edit that field and both CI and local builds pick it up. The
|
|
package format (deb or rpm) is inferred at build time from the container's
|
|
package manager (`apt-get` -> deb, `dnf`/`yum` -> rpm).
|
|
|
|
| Package type | Image (`package_configs.<distro>[].image` in `linux.json`) | Tools required |
|
|
| ------------ | ---------------------------------------------------------- | --------------------------------------------------- |
|
|
| RPM | `ghcr.io/xrplf/xrpld/packaging-rhel:sha-<sha>` | `rpmbuild` |
|
|
| DEB | `ghcr.io/xrplf/xrpld/packaging-debian:sha-<sha>` | `dpkg-buildpackage`, debhelper with compat level 13 |
|
|
|
|
To print the full packaging matrix (artifact names and images) for the current
|
|
`linux.json`:
|
|
|
|
```bash
|
|
./.github/scripts/strategy-matrix/generate.py --packaging
|
|
```
|
|
|
|
## Building packages
|
|
|
|
### Via CI
|
|
|
|
Caller workflows (`on-pr.yml`, `on-tag.yml`, `on-trigger.yml`) call
|
|
`reusable-package.yml`. That workflow generates its own packaging matrix from
|
|
`package_configs` in `linux.json` (via `generate.py --packaging`) and fans out
|
|
one job per distro. Each job downloads the pre-built `xrpld` binary artifact and
|
|
runs in that distro's container, so the package format follows from the
|
|
container's package manager. The packaging script derives the package version
|
|
from the downloaded binary's `xrpld --version` output; 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.
|
|
|
|
```bash
|
|
# From the repo root. Each distro's container image is the `image` field of its
|
|
# package_configs entry in linux.json; the package format is inferred from the
|
|
# container's package manager. Example for the rpm-producing image (use
|
|
# .package_configs.debian[0].image for the deb image):
|
|
IMAGE=$(jq -r '.package_configs.rhel[0].image' .github/scripts/strategy-matrix/linux.json)
|
|
|
|
PKG_RELEASE=1
|
|
|
|
docker run --rm \
|
|
-v "$(pwd):/src" \
|
|
-w /src \
|
|
"${IMAGE}" \
|
|
./package/build_pkg.sh --pkg-release "${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 target directly — no container
|
|
needed, but the host toolchain replaces the pinned CI image:
|
|
|
|
```bash
|
|
cmake \
|
|
-Dxrpld=ON \
|
|
-Dpkg_release=1 \
|
|
-Dtests=OFF \
|
|
..
|
|
|
|
cmake --build . --target package # deb on Debian/Ubuntu, rpm on RHEL
|
|
```
|
|
|
|
The `cmake/XrplPackaging.cmake` module defines the `package` target only if at
|
|
least one of `rpmbuild` / `dpkg-buildpackage` is present; `build_pkg.sh` then
|
|
infers the package format from the host's package manager. The packaging script
|
|
installs to FHS-standard paths (`/usr/bin`, `/etc/xrpld`, etc.) regardless of
|
|
`CMAKE_INSTALL_PREFIX`.
|
|
|
|
The package version is not a CMake input on this path: `build_pkg.sh` derives it
|
|
from the just-built `xrpld` binary's `xrpld --version` output. The package
|
|
release defaults to 1 and is overridable with `-Dpkg_release=N`.
|
|
|
|
## How `build_pkg.sh` works
|
|
|
|
`build_pkg.sh` derives the `xrpld` software version from
|
|
`${BUILD_DIR}/xrpld --version` in both package formats.
|
|
|
|
The binary's version is already SemVer-validated by `BuildInfo`.
|
|
`build_pkg.sh` converts pre-release versions such as `3.2.0-b1` or
|
|
`3.2.0-rc1` from `-` to `~` for package metadata so pre-releases sort before
|
|
the final release. If that normalized package version still contains `-`,
|
|
packaging fails because RPM forbids `-` in `Version`, and Debian uses `-` as
|
|
the upstream/revision separator.
|
|
|
|
`pkg_version` is the normalized package metadata version derived inside
|
|
`build_pkg.sh` from the binary-reported `xrpld` version (`-` pre-release
|
|
separator converted to `~`). It is not a separate user input.
|
|
|
|
`PKG_RELEASE` is a different value: the package release iteration for that
|
|
`xrpld` version. RPM receives the normalized `pkg_version` and `PKG_RELEASE` as
|
|
the `pkg_version` and `pkg_release` macros for its `Version` and `Release`
|
|
values; DEB writes them as `${pkg_version}-${PKG_RELEASE}` in
|
|
`debian/changelog`.
|
|
|
|
With `PKG_RELEASE=1`, the package metadata becomes:
|
|
|
|
| Input version | RPM version/release | Debian version |
|
|
| ------------------ | ---------------------------- | -------------------- |
|
|
| `3.2.0` | `3.2.0-1%{?dist}` | `3.2.0-1` |
|
|
| `3.2.0-b0+abc1234` | `3.2.0~b0+abc1234-1%{?dist}` | `3.2.0~b0+abc1234-1` |
|
|
| `3.2.0-b1` | `3.2.0~b1-1%{?dist}` | `3.2.0~b1-1` |
|
|
| `3.2.0-rc1` | `3.2.0~rc1-1%{?dist}` | `3.2.0~rc1-1` |
|
|
|
|
The Debian changelog entry carries the repository component: final releases use
|
|
`stable`, `b0` builds, including `b0+metadata`, use `develop`, and `bN`/`rcN`
|
|
pre-releases use `unstable`.
|
|
Build metadata on a final release, such as `3.2.0+abc123`, is rejected.
|
|
|
|
The RPM path intentionally uses `~` in `Version`, matching the Debian
|
|
pre-release ordering convention, so RPM filenames/NVRs begin with forms like
|
|
`xrpld-3.2.0~b1-...` and `xrpld-3.2.0~rc1-...` instead of encoding
|
|
pre-releases with an older `0.<release>.<suffix>` RPM `Release` value.
|
|
|
|
The package format (`deb` or `rpm`) is inferred from the host's package
|
|
manager (`apt-get` -> deb, `dnf`/`yum` -> rpm). Hosts without one of those
|
|
fail early.
|
|
|
|
Flags are for explicit invocation; environment variables are intended for
|
|
CMake/CI integration. The CI workflow and the CMake `package` target both invoke
|
|
`build_pkg.sh` with no flags; CMake supplies `SRC_DIR`, `BUILD_DIR`, and
|
|
`PKG_RELEASE` via env, while CI supplies `BUILD_DIR` and `PKG_RELEASE` via env
|
|
and lets the script use defaults for the rest.
|
|
|
|
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, and invokes the platform build tool.
|
|
|
|
### RPM
|
|
|
|
1. Creates the standard `rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}` tree inside the build directory.
|
|
2. Copies `xrpld.spec` and all shared source files (binary, configs, service files) into `SOURCES/`.
|
|
3. Runs `rpmbuild -bb`, passing the normalized package metadata version as the
|
|
`pkg_version` RPM macro and `PKG_RELEASE` as the `pkg_release` RPM macro.
|
|
The spec uses manual `install` commands to place files, disables `dwz`, and
|
|
writes uncompressed RPM payloads while generating debuginfo packages.
|
|
4. Output: `rpmbuild/RPMS/x86_64/xrpld-*.rpm`
|
|
|
|
The uncompressed RPM payload setting is intentionally unconditional for
|
|
generated RPMs. It trades larger RPM artifacts for much shorter package
|
|
build/validation time, which keeps RPM package validation in the same rough time
|
|
class as Debian package validation.
|
|
|
|
RPM upgrades intentionally do not restart a running `xrpld` service. The spec
|
|
uses `%systemd_postun`, matching Debian's `dh_installsystemd
|
|
--no-stop-on-upgrade` behavior; operators pick up the new binary on the next
|
|
service restart.
|
|
|
|
### DEB
|
|
|
|
1. Creates a staging source tree at `debbuild/source/` inside the build directory.
|
|
2. Stages the binary, configs, `README.md`, and `LICENSE.md`.
|
|
3. Copies `package/debian/` control files into `debbuild/source/debian/`.
|
|
4. Copies shared service/sysusers/tmpfiles into `debian/` where `dh_installsystemd`, `dh_installsysusers`, and `dh_installtmpfiles` pick them up automatically.
|
|
5. Generates a minimal `debian/changelog` using `${pkg_version}-${PKG_RELEASE}`,
|
|
where `pkg_version` is derived from the binary-reported `xrpld` version.
|
|
6. Runs `dpkg-buildpackage -b --no-sign -d` (`-d` skips the build-dependency check, since the binary is already built). `debian/rules` uses manual `install` commands.
|
|
7. Output: `debbuild/*.deb` and `debbuild/*.ddeb` (dbgsym package)
|
|
|
|
## Post-build verification
|
|
|
|
```bash
|
|
# DEB
|
|
dpkg-deb -c debbuild/*.deb | grep -E 'systemd|sysusers|tmpfiles'
|
|
lintian -I debbuild/*.deb
|
|
|
|
# RPM
|
|
rpm -qlp rpmbuild/RPMS/x86_64/*.rpm
|
|
```
|
|
|
|
## Reproducibility
|
|
|
|
`build_pkg.sh` already defaults `SOURCE_DATE_EPOCH` to the latest git commit
|
|
time, or the current time outside a git tree, and exports it (override with
|
|
`--source-date-epoch` / `SOURCE_DATE_EPOCH`); the RPM spec clamps file
|
|
modification times to it via `%build_mtime_policy`. The remaining variables
|
|
below further improve reproducibility but are _not_ set by the script — export
|
|
them yourself if needed:
|
|
|
|
```bash
|
|
export TZ=UTC
|
|
export LC_ALL=C.UTF-8
|
|
export GZIP=-n
|
|
export DEB_BUILD_OPTIONS="noautodbgsym reproducible=+fixfilepath"
|
|
```
|