Redistribute on Linux
Bundle the SmartSpectra Linux C++ SDK tarball into your own .deb so end users install your app on stock Ubuntu without a Presage apt source.
Validated path for a developer to take the published SmartSpectra Linux C++
SDK release tarball, build their own application against it, and ship a
self-contained .deb that installs on a stock Ubuntu / Mint / Debian host
without configuring a Presage apt source.
This is the only Linux redistribution shape currently supported. Other shapes are not currently validated.
When to use this path
You're a developer who:
- Ships a desktop app to enterprise Linux end-users
- Wants the end-user install to be one
sudo apt install ./your-app.debstep - Cannot ask end-users to configure a Presage apt source
- Targets Debian-family distros — currently Ubuntu 22.04 / 24.04 (Mint 21 / 22), with Debian 11+ as a documented equivalent. arm64 redistribution remains a follow-up
If your end-users run a non-Debian-family distro (Fedora, RHEL, openSUSE, Arch), you're in territory we don't currently validate.
The example app
The public GitHub mirror ships the example as
cpp/samples/debian-app-example/README.md
with its packaging logic in
cpp/samples/debian-app-example/CMakeLists.txt.
It demonstrates every choice this page documents and is a suitable starting
point to copy into your own repository when integrating the SDK into a
redistributable .deb.
Build it standalone against an extracted SDK release tarball:
# 1. Extract the published SDK release tarball
# Use the codename-qualified asset name:
# - Ubuntu 22.04 / Mint 21 / Debian 11+: linux-jammy-amd64
# - Ubuntu 24.04 / Mint 22: linux-noble-amd64
mkdir -p /tmp/sdk
tar -xzf smartspectra-sdk-<version>-linux-<codename>-amd64.tar.gz -C /tmp/sdk
# 2. Choose the example source path for your checkout:
# - Public GitHub mirror: cpp/samples/debian-app-example
cmake -S <example-source-dir> -B /tmp/dae-build \
-DCMAKE_PREFIX_PATH=/tmp/sdk \
-DCMAKE_BUILD_TYPE=Release
cmake --build /tmp/dae-build -j$(nproc)
# 3. Produce the .deb (per-codename revision suffix)
cd /tmp/dae-build
cpack -G DEB
# Produces e.g. debian-app-example_0.1.0-noble1_amd64.deb on Ubuntu 24.04
# or debian-app-example_0.1.0-jammy1_amd64.deb on Ubuntu 22.04 — the
# revision suffix tracks the build-host codename so the same .deb stream
# never serves a mismatched stock-archive Depends set.
# 4. Install on a clean Debian-family container
sudo apt install -y ./debian-app-example_*.debRead the example
CMakeLists.txt
end-to-end —
it's the canonical source for the install layout, CPack DEB config, Depends
manifest reading, and maintainer-script wiring.
Install layout
The .deb installs entirely under /opt/debian-app-example/ (an app-private prefix
per FHS 3.0 §3.12).
Replace debian-app-example with your own app name when you adapt the example.
/opt/<app-name>/
├── bin/
│ └── <app-name> (the executable)
├── lib/
│ ├── libsmartspectra.so (bundled from SDK tarball)
│ └── smartspectra_manifest.json (written at install time)
└── share/
└── smartspectra/
└── graph/
├── models/ (bundled from SDK tarball)
└── ...Plus one file outside the app's prefix, written by postinst:
# /etc/ld.so.conf.d/<app-name>.conf
/opt/<app-name>/libpostrm removes that fragment on remove / purge.
RPATH and per-app ldconfig
Two mechanisms place the bundled libsmartspectra.so on the loader's path
when the end-user launches the binary.
RPATH on the binary. The example binary is linked with
INSTALL_RPATH=$ORIGIN/../lib and INSTALL_RPATH_USE_LINK_PATH=FALSE so the
resulting DT_RUNPATH is exactly $ORIGIN/../lib. From
/opt/<app-name>/bin/<app> this walks to /opt/<app-name>/lib/, where
libsmartspectra.so lives.
ldconfig fragment for libsmartspectra.so. The SDK's shared library has
no embedded DT_RUNPATH / DT_RPATH, and /opt/<app-name>/lib is not on the
loader's default search path, so postinst also registers it with the system
loader cache:
# /etc/ld.so.conf.d/<app-name>.conf
/opt/<app-name>/liband runs ldconfig, so libsmartspectra.so resolves at load time.
postrm removes the ldconfig fragment on remove / purge so the cache no
longer maps libraries to the now-removed prefix.
Model-path resolution
At runtime the SDK locates its own shared-library directory and reads
smartspectra_manifest.json from that directory. The manifest contains a
single absolute path:
{
"resource_root_dir": "/opt/<app-name>/share/smartspectra"
}The SDK joins resource_root_dir with the relative model paths it ships
internally, so model lookups land under
/opt/<app-name>/share/smartspectra/... at runtime.
The example's CMake writes this manifest at install time (not build time) so the recorded prefix matches the actual install location, not the build prefix.
Depends: from SmartSpectraPackageManifest.json
The example does not hard-code its Depends: list. Drift between the
SDK's own apt-resolved dependencies and the example's list would silently
produce a .deb that installs but fails to load the SDK on a stock
container.
Instead, the example reads
<sdk>/share/smartspectra/package/SmartSpectraPackageManifest.json at
CMake-configure time and feeds its debian_depends field straight into
CPACK_DEBIAN_PACKAGE_DEPENDS. The manifest is per-codename, so each
codename produces its own Depends set from the same example source.
A FATAL_ERROR guard in the example's CMake refuses to package if the
manifest is missing or its debian_depends field is empty.
The end-user therefore needs no Presage apt source — every transitive
dependency resolves from the codename's stock archive at
apt install ./<app>.deb time on both jammy and noble. arm64
remains a follow-up.
See also
- Example README:
cpp/samples/debian-app-example/README.md - Example packaging logic:
cpp/samples/debian-app-example/CMakeLists.txt