File: dh-cargo-built-using

package info (click to toggle)
dh-cargo 30
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 52 kB
  • sloc: sh: 192; perl: 159; makefile: 2
file content (173 lines) | stat: -rwxr-xr-x 7,408 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#!/bin/sh
# Generates Built-Using after a successful cargo build.
# Run this in the package top-level directory where debian/ is.

set -e

DEB_HOST_RUST_TYPE="${DEB_HOST_RUST_TYPE:-$(printf "include /usr/share/rustc/architecture.mk\nall:\n\techo \$(DEB_HOST_RUST_TYPE)\n" | make --no-print-directory -sf -)}"
CARGO_REGISTRY="${CARGO_REGISTRY:-debian/cargo_registry}"
CARGO_CHANNEL="${CARGO_CHANNEL:-release}"
# useful for testing:
# CARGO_REGISTRY="$HOME/.cargo/registry/src/github.com-1ecc6299db9ec823" DEB_HOST_RUST_TYPE="." CARGO_CHANNEL=debug

CARGO_TARGET_DIR="target/$DEB_HOST_RUST_TYPE/$CARGO_CHANNEL"
CARGO_TARGET_DIR_ABS="$(readlink -f "$CARGO_TARGET_DIR")"

CPRIGHT_FORMAT="https://www.debian.org/doc/packaging-manuals/copyright-format/1.0"
SRCLEFT_LICENSES="$(echo GPL LGPL AGPL GFDL MPL CDDL CPL Artistic Perl QPL | tr ' ' '\n')"
pkg_has_srcleft_license() {
	local pkg="$1"
	local ver="$2"
	local f="/usr/share/doc/$pkg/copyright"
	if ! sed -nre 's	^Format: (.*)	\1	gp' "$f" | grep -qiw "$CPRIGHT_FORMAT"; then
		echo >&2 "$0: abort: Not in machine-readable format: $f"
		echo 2
	elif sed -nre 's	^X-Binary-Requires-Source: (.*)	\1	gp' "$f" | grep -qiw yes; then
		echo 1
	elif sed -nre 's	^License: (.*)	\1	gp' "$f" | grep -qiwF "$SRCLEFT_LICENSES"; then
		echo 1
	else
		echo 0
	fi
}

dep_files_to_pkgs() {
	xargs -r dpkg -S \
	| sed -nre 's	(.*): .*	\1	gp' \
	| xargs -r dpkg-query --show \
	| while read pkg ver; do echo "$pkg $ver $(pkg_has_srcleft_license "${pkg%:*}" "$ver")"; done
	# pkg_has_srcleft_license should be accurate for all rust crates, no need to give a $containing_crate
	# this is due to nature of crate copyright info, and the debian rust packaging policy
}

rust_dep_files() {
	cat "$CARGO_TARGET_DIR/deps"/*.d \
	| sed -nre 's	^\S*/('"$CARGO_REGISTRY"'/[^/]*)/.*	'"$(readlink -f "$PWD")/"'\1	gp' \
	| sort -u \
	| xargs -r readlink -f
}

rust_libs() {
	{ which rustc; rust_dep_files; } | dep_files_to_pkgs
}

gcc_default_searchdirs() {
	gcc -print-search-dirs \
	| sed -nre 's	^libraries: (.*)	\1	gp' \
	| tr ':' '\n' \
	| sed -e 's	^=	'"$(gcc -print-sysroot)"'	g' \
	| xargs readlink -m 2>/dev/null # suppress errors caused by early pipe closure
}

rust_search_lib() {
	local lib="$1"
	{
	cat
	# rust does not actually search normal paths when linking static libs
	# - see https://github.com/rust-lang/rust/issues/43118
	# - see also `fn link_rlib` in back/link.rs which calls
	#   `pub fn find_library` in back/archive.rs which generates the error message
	#gcc_default_searchdirs
	} | while read searchdir; do
		#echo >&2 "searching $searchdir for static lib $lib"
		local f="$(readlink -m "$searchdir/lib${lib}.a")"
		if test -f "$f"; then
			printf "%s\n" "$f"
			break
		fi
	done
}

native_libs() {
	ls -1d "$CARGO_TARGET_DIR/build"/*/output 2>/dev/null | while read output; do
		sed -nre 's	^cargo:rustc-link-lib=static=(.*)	\1 '"$output"'	gp' "$output"
	done | while read lib output; do
		local containing_crate="$(basename "$(dirname "$output")")"
		test -n "$lib" || continue
		local libfile="$(sed -nre 's	^cargo:rustc-link-search=native=(.*)	\1	gp' "$output" | rust_search_lib "$lib")"
		local srcleft=""
		test -n "$libfile" || { echo >&2 "$0: abort: could not find static lib '$lib'; rustc should have failed already?"; exit 1; }
		echo >&2 "$0: found static lib $lib at $libfile"
		if [ "${libfile#$CARGO_TARGET_DIR_ABS/}" != "$libfile" ]; then
			# static library source code embedded in crate
			local srcstat="$(sed -nre 's	^dh-cargo:deb-built-using='"$lib"'=([01]=.*)	\1	gp' "$output")"
			case "$srcstat" in
			0=*|1=*)
				srcleft="${srcstat%%=*}"
				libfile="${srcstat#*=}"
				if [ "$(readlink -f "$libfile")" = "$(readlink -f "$PWD")" ]; then
					# Note that this exception only applies in the case that where you are building
					# the Debian package for $containing_crate itself. In the case where you are
					# building a Debian package for crate X depending on $containing_crate, the
					# latter still has to output the dh-cargo:deb-built-using in their build.rs so
					# that the Debian package for crate X can correctly set Built-Using themselves.
					echo >&2 "$0: static library derived from $libfile which is the top-level crate being built, no need to add Built-Using"
					continue
				fi
				;;
			*)
				echo >&2 "$0: abort: could not determine source-distribution conditions of ${libfile#$CARGO_TARGET_DIR_ABS/}."
				echo >&2 "You must patch build.rs of ${containing_crate%-*} to output 'println!(\"dh-cargo:deb-built-using=$lib=\$s={}\", env::var(\"CARGO_MANIFEST_DIR\").unwrap());' where:"
				echo >&2 "- \$s is 1 if the license(s) of the included static libs require source distribution alongside binaries, otherwise 0"
				exit 1
				;;
			esac
		fi
		local wpkg="$(dpkg -S "$(readlink -f "$libfile")")"
		test -n "$wpkg" || { echo >&2 "$0: abort: could not find Debian package for file $libfile"; exit 1; }
		local pkgstat="$(echo "$wpkg" | sed -nre 's	(.*): .*	\1	gp' | xargs -r dpkg-query --show)"
		local pkg="$(echo "$pkgstat" | cut -f1)"
		local ver="$(echo "$pkgstat" | cut -f2)"
		# static library source code embedded in crate (from earlier)
		if [ -n "$srcleft" ]; then
			echo "$pkg $ver $srcleft"
		# static libraries from another Debian package
		elif sed -nre 's	^dh-cargo:deb-built-using='"$lib"'=0~=(.*)	\1	gp' "$output" | { echo "${pkg%:*} $ver" | grep -qExf /dev/fd/3; } 3<&0; then
			echo "$pkg $ver 0"
		elif sed -nre 's	^dh-cargo:deb-built-using='"$lib"'=1~=(.*)	\1	gp' "$output" | { echo "${pkg%:*} $ver" | grep -qExf /dev/fd/3; } 3<&0; then
			echo "$pkg $ver 1"
		else
			# guess the conditions based on the whole d/copyright file
			# this loses granularity, e.g. gcc is mostly distributed as GPL-3 but the libbacktrace portion is BSD-3
			# to retain granularity the crate package maintainer should patch build.rs as suggested
			echo >&2 "$0: warning: guessing source-distribution conditions of $libfile, this may be inaccurate."
			echo >&2 "$0: warning: patch build.rs to suppress the above warning"
			srcleft="$(pkg_has_srcleft_license "${pkg%:*}" "$ver")"
			if [ "$srcleft" -gt 1 ]; then
				echo >&2 "You must patch build.rs of ${containing_crate%-*} to output 'dh-cargo:deb-built-using=$lib=\$s~=\$PAT' where:"
				echo >&2 "- \$s is 1 if the license(s) of the included static libs require source distribution alongside binaries, otherwise 0"
				echo >&2 "- \$PAT is an egrep pattern matching the \"\$pkg \$ver\" combinations that satisfy \$s"
				echo >&2 "  for example '$pkg .*' matches the currently-relevant package, $pkg $ver"
				exit 1
			fi
			echo "$pkg $ver $srcleft"
		fi
	done
}

output() {
	local binpkg="$1"
	if [ -z "$binpkg" ]; then
		cat
	else
		local built_using=""
		local built_using_x=""
		while read pkg ver srcleft; do
			local src="$(dpkg-query -f '${source:Package}' --show "$pkg")"
			local srcver="$(dpkg-query -f '${source:Version}' --show "$pkg")"
			case "$srcleft" in
			2)	exit 1;;
			1)	built_using="${built_using}$src (= $srcver), ";;
			esac
			built_using_x="${built_using_x}$src (= $srcver), "
		done
		echo "cargo:Built-Using=${built_using%, }" >> "debian/$binpkg.substvars"
		echo "cargo:X-Cargo-Built-Using=${built_using_x%, }" >> "debian/$binpkg.substvars"
	fi
}

native_libs="$(native_libs)" # capture output outside of pipe so set -e works
{
rust_libs
test -z "$native_libs" || echo "$native_libs"
} | LC_ALL=C.utf-8 sort -u | output "$@"