cargo-deb

repository·main·Indexed 20 days ago

https://github.com/kornelski/cargo-deb

A Cargo subcommand that automates the creation of binary Debian packages (.deb) from Rust projects. It allows for custom metadata configuration via [package.metadata.deb] in Cargo.toml, including asset management, debug symbol handling, cross-compilation support, and the definition of multiple package variants.

Tokens
13.6K
Snippets
37
Records
70
Agent score
68%

What's inside cargo-deb

  1. Handle debug symbols in Debian packages

    main

    By default, debug symbols are stripped from binaries.

    To include them, you can:

    1. Enable debug = "line-tables-only" in your [profile.release] section in Cargo.toml.
    2. Use the --separate-debug-symbols or --dbgsym CLI flags during cargo deb.
    3. Set separate-debug-symbols = true in the [package.metadata.deb] table.

    When enabled, debug symbols are packaged as separate files installed at /usr/lib/debug/<build-id-or-path>.debug.

  2. How systemd units interact with cargo-deb variants

    main

    When using the variants feature in cargo-deb, the <package> name in the naming patterns above is replaced by <package>-<variant>.

    If you have overridden the variant name using the name key in the variant-specific metadata table, use that overridden name instead. This allows you to provide different systemd unit files or maintainer scripts for different package variants.

  3. Merge assets in package variants

    main

    When using variants, you can merge the variant's asset list with the parent asset list using the merge-assets option. There are three strategies:

    • merge-assets.append: Appends the variant's assets to the parent list.
    • merge-assets.by.dest: Merges assets by joining on the destination path. Replaces both source path and permissions.
    • merge-assets.by.src: Merges assets by joining on the source path. Replaces both destination path and permissions.

    Note: If both append and a by.* option are used, append is applied first. The special "$auto" entry is not expanded before merging; explicit paths take precedence over "$auto".

    # Example: Merging by destination path
    [package.metadata.deb.variants.mergedest]
    merge-assets.by.dest = [
        ["4.txt", "var/lib/example/merged.txt", "644"]
    ]
  4. Cross-compile Debian packages

    main

    You can build for different architectures using the --target flag. Multiple targets can be specified to build them in parallel.

    Requirements:

    • The target must be installed via rustup (e.g., rustup target add i686-unknown-linux-gnu).
    • The target's system libraries must be installed on the host (e.g., apt-get install libc6-dev-i386).
    • A Linux-compatible linker and system libraries must be available.
    • Cargo must be configured to use a cross-linker in .cargo/config.
    • For C dependencies, you must install the target's sysroot and configure CC_<target>.

    Tip: If cross-compilation requirements are too complex, use cross or cargo zigbuild, then run cargo deb --target=... --no-build.

    Cross-compiled archives are saved in target/debian/*.deb.

    cargo deb --target=i686-unknown-linux-gnu
    cargo deb --target=x86_64-unknown-linux-gnu --target=aarch64-unknown-linux-gnu
  5. Configure separate debug symbols

    main

    To include debug symbols, you must first configure your Rust profile in Cargo.toml:

    [profile.release]
    debug = "line-tables-only"
    # or debug = 1 for fatter debug info

    Note: The dev profile is unsupported. Use --profile to specify other profiles.

    Options for debug symbols:

    1. Separate -dbgsym.ddeb package: Creates a second package containing only the debug files. Requires GNU objcopy.

      cargo deb --dbgsym
    2. Separate debug files in the same package: Removes symbols from executables and places them in /usr/lib/debug/.build-id/* within the same package. Requires GNU objcopy. Use --compress-debug-symbols to reduce disk space.

      cargo deb --separate-debug-symbols --compress-debug-symbols
    cargo deb --dbgsym
  6. Configure automatic systemd unit management

    main

    You can automate the installation, enabling, and lifecycle management of systemd units by using the [package.metadata.deb.systemd-units] table in your Cargo.toml.

    Requirements:

    1. You MUST specify the maintainer-scripts option in [package.metadata.deb]. This can be an empty directory.
    2. If you provide existing maintainer scripts (e.g., postinst, prerm), they MUST contain the #DEBHELPER# token. This token marks the location where cargo-deb will inject the generated shell script fragments for systemd operations.

    How it works:

    • cargo-deb finds matching systemd unit files in the directory specified by unit-scripts (which defaults to your maintainer-scripts directory).
    • It generates shell script fragments for enabling, disabling, starting, stopping, and restarting services.
    • It augments your maintainer scripts by replacing #DEBHELPER# with these fragments.
    [package.metadata.deb]
    maintainer-scripts = "debian/"
    systemd-units = { enable = false }
  7. Install cargo-deb

    main

    Install cargo-deb using cargo install.

    Requirements:

    • Rust 1.76+
    • Optionally: dpkg, dpkg-dev, and liblzma-dev (for LZMA support).

    Troubleshooting:

    • If you encounter compilation errors, run rustup update.
    • If LZMA dependencies cause issues, install without default features: cargo install cargo-deb --no-default-features.
    • If rustup update fails, it is recommended to uninstall your system's Rust/Cargo and install the official version from rustup.rs.
    rustup update
    cargo install cargo-deb
  8. Use cargo-deb to build and install Debian packages

    main

    Run cargo deb from the root directory of your Cargo project to create a .deb package.

    • Output Location: By default, packages are created in target/debian/<project_name>_<version>-1_<arch>.deb. You can specify a custom location using the --output flag.
    • Local Installation: To build and immediately install the package on your local system, use the --install flag.
    • Manual Installation: You can install the generated package using dpkg -i <path_to_deb>.
    cargo deb
    cargo deb --install
  9. Use the $auto magic prefix for assets

    main

    When defining assets in [package.metadata.deb.assets], you can use the special $auto prefix. This tells cargo-deb to automatically include the project's build products (binaries, libraries, etc.) based on the Cargo metadata.

    If you do not specify any assets, cargo-deb defaults to assets = ["$auto"].

    When using $auto, cargo-deb automatically handles:

    • Binaries: Placed in usr/bin with 0o755 permissions.
    • Libraries (cdylib): Placed in the appropriate library directory (e.g., usr/lib/...) with 0o644 permissions. The naming convention (prefix/suffix) adjusts based on whether a rust_target_triple is specified.
    • README: If readme is configured in [package.metadata.deb], it is automatically placed in usr/share/doc/<deb_name>/<readme_filename> with 0o644 permissions.
    # Example of using the default implicit assets
    [package.metadata.deb]
    assets = ['$auto']
  10. Configure systemd unit installation

    main

    If your package installs systemd services, you can configure how they are managed via the systemd_units configuration. This maps to the dh_installsystemd Debian helper.

    For each unit, you can specify:

    • enable: Whether to enable the unit (defaults to true).
    • start: Whether to start the unit (defaults to true).
    • stop_on_upgrade: Whether to stop the unit during an upgrade (defaults to false).
    • restart_after_upgrade: Whether to restart the unit after an upgrade (defaults to true).
  11. Define package assets in Cargo.toml

    main

    Assets are defined in the [package.metadata.deb] section of your Cargo.toml. You can specify assets as a list of paths or as a table for more control.

    Supported asset types include:

    • Files: Copy a file from a source path to a target path in the Debian package.
    • Symlinks: Create a symbolic link at a specific target path pointing to a link name.

    If you specify a directory or a glob pattern as a source path, cargo-deb will expand it to include all files within that directory/pattern. Note that directories themselves are not added as assets; only files are.

    Key configuration options for assets:

    • source_path: The path on your filesystem.
    • target_path: The destination path within the Debian package.
    • chmod: An optional octal mode (e.g., 0o755) to set file permissions.
    • preserve_symlinks: A boolean to determine if existing symlinks should be copied as-is or followed.
  12. Configure Debug Symbol handling

    main

    You can control how debug symbols are handled via CLI flags. Note that some flags conflict:

    • Separate Package: Use --dbgsym to create a .ddeb package.
    • In-package file: Use --separate-debug-symbols to put a .debug file inside the main package.
    • Stripping: Use --strip to remove symbols entirely. Use --no-strip to prevent stripping.
    • Compression: Use --compress-debug-symbols <zstd|zlib|auto> to compress debug sections using objcopy.