Skip to content
17 changes: 8 additions & 9 deletions bloom/generators/debian/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -401,15 +401,14 @@ def generate_substitutions_from_package(

# Build-type specific substitutions.
build_type = package.get_build_type()
if build_type == 'catkin':
pass
elif build_type == 'cmake':
pass
elif build_type == 'meson':
pass
elif build_type == 'ament_cmake':
pass
elif build_type == 'ament_python':
if build_type in (
'ament_cmake',
'ament_python',
'cargo',
'catkin',
'cmake',
'meson',
):
# Don't set the install-scripts flag if it's already set in setup.cfg.
package_path = os.path.abspath(os.path.dirname(package.filename))
setup_cfg_path = os.path.join(package_path, 'setup.cfg')
Expand Down
7 changes: 7 additions & 0 deletions bloom/generators/debian/templates/cargo/changelog.em
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@[for change_version, change_date, changelog, main_name, main_email in changelogs]@(Package) (@(change_version)@(DebianInc)@(Distribution)) @(Distribution); urgency=high

@(changelog)

-- @(main_name) <@(main_email)> @(change_date)

@[end for]
1 change: 1 addition & 0 deletions bloom/generators/debian/templates/cargo/compat.em
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@(debhelper_version)
14 changes: 14 additions & 0 deletions bloom/generators/debian/templates/cargo/control.em
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Source: @(Package)
Section: misc
Priority: optional
Maintainer: @(Maintainer)
Build-Depends: debhelper (>= @(debhelper_version).0.0), @(', '.join(sorted(set(BuildDepends) | {'cargo', 'cargo-auditable', 'dh-cargo', 'python3-pallet-patcher', 'rustc'})))
Homepage: @(Homepage)
Standards-Version: 4.6.0
Comment thread
cottsay marked this conversation as resolved.

Package: @(Package)
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, @(', '.join(Depends))
@[if Conflicts]Conflicts: @(', '.join(Conflicts))@\n@[end if]@
@[if Replaces]Replaces: @(', '.join(Replaces))@\n@[end if]@
Description: @(Description)
11 changes: 11 additions & 0 deletions bloom/generators/debian/templates/cargo/copyright.em
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Format: Bloom subset of https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: @(Name)
@[if BugTracker]Upstream-Contact: @(BugTracker)@\n@[end if]@
@[if Source]Source: @(Source)@\n@[end if]@
@[for License, Text in Licenses]@

Files: See file headers in repository for details
Copyright: See package copyright in source code for details
License: @(License)
@(Text)
@[end for]@
3 changes: 3 additions & 0 deletions bloom/generators/debian/templates/cargo/gbp.conf.em
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[git-buildpackage]
upstream-tag=@(release_tag)
upstream-tree=tag
101 changes: 101 additions & 0 deletions bloom/generators/debian/templates/cargo/rules.em
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Sample debian/rules that uses debhelper.
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of dh-make.

# Uncomment this to turn on verbose mode.
export DH_VERBOSE=1
# TODO: remove the LDFLAGS override. It's here to avoid esoteric problems
# of this sort:
# https://code.ros.org/trac/ros/ticket/2977
# https://code.ros.org/trac/ros/ticket/3842
export LDFLAGS=
export PKG_CONFIG_PATH=@(InstallationPrefix)/lib/pkgconfig
# Explicitly enable -DNDEBUG, see:
# https://github.com/ros-infrastructure/bloom/issues/327
export DEB_CXXFLAGS_MAINT_APPEND=-DNDEBUG
Comment thread
Blast545 marked this conversation as resolved.

DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)

%:
dh $@@ -v --buildsystem=cargo --builddirectory=.obj-$(DEB_HOST_GNU_TYPE)

override_dh_auto_configure:
# dh-cargo's configure step expects these two files to exist, even when
# we aren't vendoring dependencies. Touching an empty cargo-checksum.json
# and Cargo.lock is the canonical workaround (see Debian wiki: Rust Packaging).
touch debian/cargo-checksum.json Cargo.lock
Comment thread
Blast545 marked this conversation as resolved.
# In case we're installing to a non-standard location, look for a setup.sh
# in the install tree and source it. It will set things like
# CMAKE_PREFIX_PATH, PKG_CONFIG_PATH, and PYTHONPATH.
if [ -f "@(InstallationPrefix)/setup.sh" ]; then . "@(InstallationPrefix)/setup.sh"; fi && \
dh_auto_configure
# Generate a pallet-patcher config so that, once we have a viable
# vendoring solution, we can point cargo to local deps
pallet-patcher --output-format=toml Cargo.toml @(InstallationPrefix)/share/cargo/registry > pallet-patcher.toml

override_dh_auto_clean:
dh_auto_clean
rm -f debian/cargo-checksum.json pallet-patcher.toml

override_dh_auto_build:
# In case we're installing to a non-standard location, look for a setup.sh
# in the install tree and source it. It will set things like
# CMAKE_PREFIX_PATH, PKG_CONFIG_PATH, and PYTHONPATH.
if [ -f "@(InstallationPrefix)/setup.sh" ]; then . "@(InstallationPrefix)/setup.sh"; fi
# Call cargo directly to avoid the dh-cargo Python wrapper interfering
# with registry resolution when dependencies are pre-fetched offline.
# `cargo auditable` is a drop-in wrapper that embeds a compressed JSON
# dependency list into a `.dep-v0` linker section of every produced
# binary. Tools like `cargo audit bin`, trivy, grype, syft, and
# `rust-audit-info` can read it back. URLs and local paths are redacted
# by design, so no `/work/...` style paths leak into shipped artifacts.
cargo auditable build --release --config pallet-patcher.toml

override_dh_auto_test:
# In case we're installing to a non-standard location, look for a setup.sh
# in the install tree and source it. It will set things like
# CMAKE_PREFIX_PATH, PKG_CONFIG_PATH, and PYTHONPATH.
echo -- Running tests. Even if one of them fails the build is not canceled.
if [ -f "@(InstallationPrefix)/setup.sh" ]; then . "@(InstallationPrefix)/setup.sh"; fi
cargo test --config pallet-patcher.toml || true

override_dh_auto_install:

@cottsay cottsay May 8, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By overriding dh-cargo's install we're missing out on this whole section, which is responsible for installing the unpacked crate to <prefix>/share/cargo/registry/

https://github.com/deepin-community/dh-cargo/blob/00d6ee3b093ef085d02302bc9fc1e4bdc821fc14/cargo.pm#L177-L186

(sorry I couldn't figure out how to link to dh-cargo's actual upstream source code, but this fork/mirror seems to work)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately the output path is hard-coded in that snippet, so I wonder if the best thing to do is maybe to let the install happen to /usr/share/cargo/registry and then blindly move the results (if any) to @(InstallationPrefix)/share/cargo/registry.

@Blast545 Blast545 May 21, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's no simple way to rely on their code to do what they do with our custom naming/path needs, so I think we can just try to go on our own route. At least for the proof of concept

# Classify the crate's targets ourselves rather than rely on dh-cargo's
# libpkg/binpkg dispatch, which keys on Debian package-name heuristics
# (librust-*-dev vs. others) that bloom-generated ROS package names don't
# satisfy. We then run whichever of the two install branches apply:
# - HAS_LIB: lay down the unpacked crate source under
# <prefix>/share/cargo/registry/<name>-<version>/ so downstream ROS
# Rust packages can resolve this crate via pallet-patcher. Mirrors
# dh-cargo cargo.pm:install() libpkg branch.
# - HAS_BIN: run `cargo auditable install`, which wraps cargo and
# embeds a compressed JSON SBOM into each binary's .dep-v0 ELF
# section. Tools that read it: cargo audit bin, trivy, grype, syft,
# osv-scanner, rust-audit-info. --no-track suppresses .crates.toml.
set -e ; \
if [ -f "@(InstallationPrefix)/setup.sh" ]; then . "@(InstallationPrefix)/setup.sh"; fi ; \
META=$$(cargo metadata --no-deps --format-version 1) ; \
CRATE_NAME=$$(printf '%s' "$$META" | python3 -c "import sys,json;print(json.load(sys.stdin)['packages'][0]['name'])") ; \
CRATE_VER=$$(printf '%s' "$$META" | python3 -c "import sys,json;print(json.load(sys.stdin)['packages'][0]['version'])") ; \
HAS_LIB=$$(printf '%s' "$$META" | python3 -c "import sys,json;p=json.load(sys.stdin)['packages'][0];L={'lib','rlib','dylib','cdylib','staticlib','proc-macro'};print(int(any(k in L for t in p['targets'] for k in t['kind'])))") ; \
HAS_BIN=$$(printf '%s' "$$META" | python3 -c "import sys,json;p=json.load(sys.stdin)['packages'][0];print(int(any('bin' in t['kind'] for t in p['targets'])))") ; \
Comment on lines +84 to +85

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if there's a simpler way to detect if a specific package has libraries or is it only binary.

if [ "$$HAS_LIB" = "1" ]; then \
TARGET="$(CURDIR)/debian/@(Package)@(InstallationPrefix)/share/cargo/registry/$$CRATE_NAME-$$CRATE_VER" ; \
install -d "$$TARGET" ; \
find . -mindepth 1 -maxdepth 1 \
\! -name target \! -name debian \! -name .git \
\! -name '.obj-*' \! -name 'pallet-patcher.toml' \
-exec cp -a -t "$$TARGET" {} + ; \
rm -rf "$$TARGET/target" ; \
cp debian/cargo-checksum.json "$$TARGET/.cargo-checksum.json" ; \
[ -z "$$SOURCE_DATE_EPOCH" ] || touch -d@@$$SOURCE_DATE_EPOCH "$$TARGET/Cargo.toml" ; \
fi ; \
if [ "$$HAS_BIN" = "1" ]; then \
cargo auditable install --path . --config pallet-patcher.toml \
--root "$(CURDIR)/debian/@(Package)@(InstallationPrefix)" \
--no-track ; \
fi
1 change: 1 addition & 0 deletions bloom/generators/debian/templates/cargo/source/format.em
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.0 (@(format))
6 changes: 6 additions & 0 deletions bloom/generators/debian/templates/cargo/source/options.em
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@[if format and format == 'quilt']@
# Automatically add upstream changes to the quilt overlay.
# http://manpages.ubuntu.com/manpages/trusty/man1/dpkg-source.1.html
# This supports reusing the orig.tar.gz for debian increments.
auto-commit
@[end if]
Loading