[pbs-devel] [RFC proxmox-backup] buildsys: build and package statically linked client binary

Fabian Grünbichler f.gruenbichler at proxmox.com
Wed Apr 9 11:09:22 CEST 2025


I think the following going in first and rebasing on top might make
sense:

----8<----
commit 1793d3cd1ee9e1175354350f7c3dde92c9ed4413
Author:     Fabian Grünbichler <f.gruenbichler at proxmox.com>
AuthorDate: Wed Apr 9 10:32:20 2025 +0200
Commit:     Fabian Grünbichler <f.gruenbichler at proxmox.com>
CommitDate: Wed Apr 9 10:32:20 2025 +0200

    build: always set --target
    
    since it affects whether cargo puts build artifacts directly into
    target/debug (or target/release) or into a target-specific
    sub-directory.
    
    the package build will always pass `--target $(DEB_HOST_RUST_TYPE)`,
    since it invokes the cargo wrapper in /usr/share/cargo/bin/cargo, so
    this change unifies the behaviour across plain `make` and `make
    deb`.

    direct calls to `cargo build/test/..` will still work as before.
    
    Signed-off-by: Fabian Grünbichler <f.gruenbichler at proxmox.com>

diff --git a/Makefile b/Makefile
index 428ef40b9..2543b1e37 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,10 @@
 include /usr/share/dpkg/default.mk
+include /usr/share/rustc/architecture.mk
 include defines.mk
 
 PACKAGE := proxmox-backup
 ARCH := $(DEB_BUILD_ARCH)
+export DEB_HOST_RUST_TYPE
 
 SUBDIRS := etc www docs templates
 
@@ -39,10 +41,11 @@ SUBCRATES != cargo metadata --no-deps --format-version=1 \
 STATIC_TARGET ?= x86_64-unknown-linux-gnu
 
 ifeq ($(BUILD_MODE), release)
-CARGO_BUILD_ARGS += --release
+CARGO_BUILD_ARGS += --release --target $(DEB_HOST_RUST_TYPE)
 COMPILEDIR := target/$(DEB_HOST_RUST_TYPE)/release
 STATIC_COMPILEDIR := target/$(STATIC_TARGET)/release
 else
+CARGO_BUILD_ARGS += --target $(DEB_HOST_RUST_TYPE)
 COMPILEDIR := target/$(DEB_HOST_RUST_TYPE)/debug
 STATIC_COMPILEDIR := target/$(STATIC_TARGET)/debug
 endif
 ---->8----

that would allow eliminating STATIC_TARGET altogether, since we can
just use DEB_HOST_RUST_TYPE across the board.

I also have verified this here works (on top of all the rest)

diff --git a/Makefile b/Makefile
index 8a6106671..3b1f945b9 100644
--- a/Makefile
+++ b/Makefile
@@ -243,4 +243,4 @@ proxmox-backup-client-static:
           echo '!<arch>' > $(STATIC_COMPILEDIR)/deps-stubs/libsystemd.a # workaround for to greedy linkage and proxmox-systemd
 	$(CARGO) rustc $(CARGO_BUILD_ARGS)  --package proxmox-backup-client --bin proxmox-backup-client \
           	--target $(DEB_HOST_RUST_TYPE) --target-dir $(STATIC_TARGET_DIR) -- \
-		-C target-feature=+crt-static -C strip=debuginfo -L $(STATIC_COMPILEDIR)/deps-stubs/
+		-C target-feature=+crt-static -L $(STATIC_COMPILEDIR)/deps-stubs/


and will automatically strip the static binary and put the debug
information into the corresponding -dbgsym package (which should then
also be uploaded ;)) - I don't think we want to completely drop
debugging support just because the binary is built statically..

On April 9, 2025 10:18 am, Christian Ebner wrote:
> Build and package the a statically linked binary version of
> proxmox-backup-client to facilitate updates and distribution.
> This provides a mechanism to obtain and repackage the client for
> external parties and Linux distributions.
> 
> The statically linked client is provided as dedicated package,
> conflicting with the regular package. Symlinks are created to invoke
> the client with the regular command name.
> 
> Since the RUSTFLAGS env variables are not preserved when building
> with dpkg-buildpackage, invoke via `cargo rustc` instead which allows
> to set the recquried arguments.
> 
> Credit goes also to Christoph Heiss, as this patch is loosely based
> on his pre-existing work for the proxmox-auto-install-assistant [0],
> which provided a good template.
> 
> [0] https://lore.proxmox.com/pve-devel/20240816161942.2044889-1-c.heiss@proxmox.com/
> 
> Suggested-by: Thomas Lamprecht <t.lamprecht at proxmox.com>
> Signed-off-by: Christian Ebner <c.ebner at proxmox.com>
> ---
> This patch depends on:
> https://lore.proxmox.com/pbs-devel/15f17e0d-e493-40fc-80f2-4538376ea310@proxmox.com/T/
> 
>  Makefile                                    | 24 +++++++++++----------
>  debian/control                              |  9 ++++++++
>  debian/proxmox-backup-client-static.install |  4 ++++
>  debian/proxmox-backup-client-static.links   |  1 +
>  4 files changed, 27 insertions(+), 11 deletions(-)
>  create mode 100644 debian/proxmox-backup-client-static.install
>  create mode 100644 debian/proxmox-backup-client-static.links
> 
> diff --git a/Makefile b/Makefile
> index 428ef40b9..efab87871 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -37,14 +37,15 @@ SUBCRATES != cargo metadata --no-deps --format-version=1 \
>  	| sed -e "s!.*$$PWD/!!g" -e 's/\#.*$$//g' -e 's/)$$//g'
>  
>  STATIC_TARGET ?= x86_64-unknown-linux-gnu
> +STATIC_TARGET_DIR := target/static-build
>  
>  ifeq ($(BUILD_MODE), release)
>  CARGO_BUILD_ARGS += --release
>  COMPILEDIR := target/$(DEB_HOST_RUST_TYPE)/release
> -STATIC_COMPILEDIR := target/$(STATIC_TARGET)/release
> +STATIC_COMPILEDIR := $(STATIC_TARGET_DIR)/$(DEB_HOST_RUST_TYPE)/release
>  else
>  COMPILEDIR := target/$(DEB_HOST_RUST_TYPE)/debug
> -STATIC_COMPILEDIR := target/$(STATIC_TARGET)/debug
> +STATIC_COMPILEDIR := $(STATIC_TARGET_DIR)/$(DEB_HOST_RUST_TYPE)/debug
>  endif
>  
>  ifeq ($(valgrind), yes)
> @@ -64,10 +65,11 @@ CLIENT_DEB=$(PACKAGE)-client_$(DEB_VERSION)_$(ARCH).deb
>  CLIENT_DBG_DEB=$(PACKAGE)-client-dbgsym_$(DEB_VERSION)_$(ARCH).deb
>  RESTORE_DEB=proxmox-backup-file-restore_$(DEB_VERSION)_$(ARCH).deb
>  RESTORE_DBG_DEB=proxmox-backup-file-restore-dbgsym_$(DEB_VERSION)_$(ARCH).deb
> +STATIC_CLIENT_DEB=$(PACKAGE)-client-static_$(DEB_VERSION)_$(ARCH).deb
>  DOC_DEB=$(PACKAGE)-docs_$(DEB_VERSION)_all.deb
>  
>  DEBS=$(SERVER_DEB) $(SERVER_DBG_DEB) $(CLIENT_DEB) $(CLIENT_DBG_DEB) \
> -     $(RESTORE_DEB) $(RESTORE_DBG_DEB)
> +     $(RESTORE_DEB) $(RESTORE_DBG_DEB) $(STATIC_CLIENT_DEB)
>  
>  DSC = rust-$(PACKAGE)_$(DEB_VERSION).dsc
>  
> @@ -199,7 +201,7 @@ $(COMPILED_BINS) $(COMPILEDIR)/dump-catalog-shell-cli $(COMPILEDIR)/docgen: .do-
>  lint:
>  	cargo clippy -- -A clippy::all -D clippy::correctness
>  
> -install: $(COMPILED_BINS)
> +install: $(COMPILED_BINS) proxmox-backup-client-static
>  	install -dm755 $(DESTDIR)$(BINDIR)
>  	install -dm755 $(DESTDIR)$(ZSH_COMPL_DEST)
>  	$(foreach i,$(USR_BIN), \
> @@ -218,25 +220,25 @@ install: $(COMPILED_BINS)
>  	install -m4755 -o root -g root $(COMPILEDIR)/sg-tape-cmd $(DESTDIR)$(LIBEXECDIR)/proxmox-backup/sg-tape-cmd
>  	$(foreach i,$(SERVICE_BIN), \
>  	    install -m755 $(COMPILEDIR)/$(i) $(DESTDIR)$(LIBEXECDIR)/proxmox-backup/ ;)
> +	install -m755 $(STATIC_COMPILEDIR)/proxmox-backup-client $(DESTDIR)$(BINDIR)/proxmox-backup-client-static

you can undo this when installing the binary into the package
afterwards, no need for symlinking then (see below)

>  	$(MAKE) -C www install
>  	$(MAKE) -C docs install
>  	$(MAKE) -C templates install
>  
>  .PHONY: upload
>  upload: UPLOAD_DIST ?= $(DEB_DISTRIBUTION)
> -upload: $(SERVER_DEB) $(CLIENT_DEB) $(RESTORE_DEB) $(DOC_DEB)
> +upload: $(SERVER_DEB) $(CLIENT_DEB) $(RESTORE_DEB) $(DOC_DEB) $(STATIC_CLIENT_DEB)
>  	# check if working directory is clean
>  	git diff --exit-code --stat && git diff --exit-code --stat --staged
> -	tar cf - $(SERVER_DEB) $(SERVER_DBG_DEB) $(DOC_DEB) $(CLIENT_DEB) $(CLIENT_DBG_DEB) \
> +	tar cf - $(SERVER_DEB) $(SERVER_DBG_DEB) $(DOC_DEB) $(CLIENT_DEB) $(CLIENT_DBG_DEB) $(STATIC_CLIENT_DEB) \
>  	  | ssh -X repoman at repo.proxmox.com upload --product pbs --dist $(UPLOAD_DIST)
> -	tar cf - $(CLIENT_DEB) $(CLIENT_DBG_DEB) | ssh -X repoman at repo.proxmox.com upload --product "pve,pmg,pbs-client" --dist $(UPLOAD_DIST)
> +	tar cf - $(CLIENT_DEB) $(CLIENT_DBG_DEB) $(STATIC_CLIENT_DEB) | ssh -X repoman at repo.proxmox.com upload --product "pve,pmg,pbs-client" --dist $(UPLOAD_DIST)

I don't think it makes sense to upload the static client to PVE and PMG,
we probably just want to move the pbs-client target to its own upload
invocation here?

>  	tar cf - $(RESTORE_DEB) $(RESTORE_DBG_DEB) | ssh -X repoman at repo.proxmox.com upload --product "pve" --dist $(UPLOAD_DIST)
>  
>  .PHONY: proxmox-backup-client-static
>  proxmox-backup-client-static:
>  	mkdir -p $(STATIC_COMPILEDIR)/deps-stubs/ && \
>            echo '!<arch>' > $(STATIC_COMPILEDIR)/deps-stubs/libsystemd.a # workaround for to greedy linkage and proxmox-systemd
> -	RUSTFLAGS='-C target-feature=+crt-static -C strip=debuginfo -L $(STATIC_COMPILEDIR)/deps-stubs/' \
> -        $(CARGO) build $(CARGO_BUILD_ARGS) \
> -          --package proxmox-backup-client --bin proxmox-backup-client \
> -          --target $(STATIC_TARGET)
> +	$(CARGO) rustc $(CARGO_BUILD_ARGS)  --package proxmox-backup-client --bin proxmox-backup-client \
> +          	--target $(STATIC_TARGET) --target-dir $(STATIC_TARGET_DIR) -- \
> +		-C target-feature=+crt-static -C strip=debuginfo -L $(STATIC_COMPILEDIR)/deps-stubs/
> diff --git a/debian/control b/debian/control
> index 1a2661858..3bddeecc4 100644
> --- a/debian/control
> +++ b/debian/control
> @@ -205,6 +205,15 @@ Description: Proxmox Backup Client tools
>   This package contains the Proxmox Backup client, which provides a
>   simple command line tool to create and restore backups.
>  
> +Package: proxmox-backup-client-static
> +Architecture: any
> +Depends: qrencode, ${misc:Depends},
> +Conflicts: proxmox-backup-client
> +Provides: proxmox-backup-client

I don't think we need/want this Provides here, unless there is a need
for it that I am missing? it might make apt pull in the static version
by accident, and also doesn't allow to just switch over to the static
variant..

> +Description: Proxmox Backup Client tools (statically linked)
> + This package contains the Proxmox Backup client, which provides a
> + simple command line tool to create and restore backups.
> +
>  Package: proxmox-backup-docs
>  Build-Profiles: <!nodoc>
>  Section: doc
> diff --git a/debian/proxmox-backup-client-static.install b/debian/proxmox-backup-client-static.install
> new file mode 100644
> index 000000000..d83a77f6e
> --- /dev/null
> +++ b/debian/proxmox-backup-client-static.install
> @@ -0,0 +1,4 @@
> +usr/bin/proxmox-backup-client-static

we could just ship the client under the usual name instead, since the
packages conflict anyway..

there's two ways to do this - either convert the .install file to use
dh-exec (see `man dh_install`), or `mv` it manually in d/rules - we
already override dh_auto_install there, so this should be fairly easy to
do:

diff --git a/debian/proxmox-backup-client-static.install b/debian/proxmox-backup-client-static.install
index d83a77f6e..690303a74 100644
--- a/debian/proxmox-backup-client-static.install
+++ b/debian/proxmox-backup-client-static.install
@@ -1,4 +1,3 @@
-usr/bin/proxmox-backup-client-static
 usr/share/man/man1/proxmox-backup-client.1
 usr/share/man/man1/pxar.1
 usr/share/zsh/vendor-completions/_proxmox-backup-client
diff --git a/debian/rules b/debian/rules
index a03fe11ba..be7c93c2e 100755
--- a/debian/rules
+++ b/debian/rules
@@ -47,6 +47,8 @@ override_dh_auto_install:
 	dh_auto_install -- \
 	    PROXY_USER=backup \
 	    LIBDIR=/usr/lib/$(DEB_HOST_MULTIARCH)
+	mkdir -p debian/proxmox-backup-client-static/usr/bin
+	mv debian/tmp/usr/bin/proxmox-backup-client-static debian/proxmox-backup-client-static/usr/bin/proxmox-backup-client
 
 override_dh_installsystemd:
 	dh_installsystemd -pproxmox-backup-server  proxmox-backup-daily-update.timer


> +usr/share/man/man1/proxmox-backup-client.1
> +usr/share/man/man1/pxar.1

we don't build/ship pxar (should we? ;)) so this man page probably
shouldn't be included here..

> +usr/share/zsh/vendor-completions/_proxmox-backup-client

the bash completion is missing..

> diff --git a/debian/proxmox-backup-client-static.links b/debian/proxmox-backup-client-static.links

and drop this then :)

> new file mode 100644
> index 000000000..a26ce008c
> --- /dev/null
> +++ b/debian/proxmox-backup-client-static.links
> @@ -0,0 +1 @@
> +usr/bin/proxmox-backup-client-static usr/bin/proxmox-backup-client




More information about the pbs-devel mailing list