]>
Commit | Line | Data |
---|---|---|
36790ab7 XL |
1 | #!/bin/sh |
2 | # Generates Built-Using after a successful cargo build. | |
3 | # Run this in the package top-level directory where debian/ is. | |
4 | ||
5 | set -e | |
6 | ||
7 | 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 -)}" | |
8 | CARGO_REGISTRY="${CARGO_REGISTRY:-debian/cargo_registry}" | |
9 | CARGO_CHANNEL="${CARGO_CHANNEL:-release}" | |
10 | # useful for testing: | |
11 | # CARGO_REGISTRY="$HOME/.cargo/registry/src/github.com-1ecc6299db9ec823" DEB_HOST_RUST_TYPE="." CARGO_CHANNEL=debug | |
12 | ||
13 | CARGO_TARGET_DIR="target/$DEB_HOST_RUST_TYPE/$CARGO_CHANNEL" | |
14 | CARGO_TARGET_DIR_ABS="$(readlink -f "$CARGO_TARGET_DIR")" | |
15 | ||
16 | CPRIGHT_FORMAT="https://www.debian.org/doc/packaging-manuals/copyright-format/1.0" | |
17 | SRCLEFT_LICENSES="$(echo GPL LGPL AGPL GFDL MPL CDDL CPL Artistic Perl QPL | tr ' ' '\n')" | |
18 | pkg_has_srcleft_license() { | |
19 | local pkg="$1" | |
20 | local ver="$2" | |
21 | local f="/usr/share/doc/$pkg/copyright" | |
22 | if ! sed -nre 's ^Format: (.*) \1 gp' "$f" | grep -qiw "$CPRIGHT_FORMAT"; then | |
23 | echo >&2 "$0: abort: Not in machine-readable format: $f" | |
24 | echo 2 | |
25 | elif sed -nre 's ^X-Binary-Requires-Source: (.*) \1 gp' "$f" | grep -qiw yes; then | |
26 | echo 1 | |
27 | elif sed -nre 's ^License: (.*) \1 gp' "$f" | grep -qiwF "$SRCLEFT_LICENSES"; then | |
28 | echo 1 | |
29 | else | |
30 | echo 0 | |
31 | fi | |
32 | } | |
33 | ||
1c8ba851 XL |
34 | dep_files_to_pkgs() { |
35 | xargs -r dpkg -S \ | |
36790ab7 XL |
36 | | sed -nre 's (.*): .* \1 gp' \ |
37 | | xargs -r dpkg-query --show \ | |
38 | | while read pkg ver; do echo "$pkg $ver $(pkg_has_srcleft_license "${pkg%:*}" "$ver")"; done | |
39 | # pkg_has_srcleft_license should be accurate for all rust crates, no need to give a $containing_crate | |
40 | # this is due to nature of crate copyright info, and the debian rust packaging policy | |
41 | } | |
42 | ||
1c8ba851 XL |
43 | rust_dep_files() { |
44 | cat "$CARGO_TARGET_DIR/deps"/*.d \ | |
45 | | sed -nre 's ^\S*/('"$CARGO_REGISTRY"'/[^/]*)/.* '"$(readlink -f "$PWD")/"'\1 gp' \ | |
46 | | sort -u \ | |
47 | | xargs -r readlink -f | |
48 | } | |
49 | ||
50 | rust_libs() { | |
51 | { which rustc; rust_dep_files; } | dep_files_to_pkgs | |
52 | } | |
53 | ||
36790ab7 XL |
54 | gcc_default_searchdirs() { |
55 | gcc -print-search-dirs \ | |
56 | | sed -nre 's ^libraries: (.*) \1 gp' \ | |
57 | | tr ':' '\n' \ | |
58 | | sed -e 's ^= '"$(gcc -print-sysroot)"' g' \ | |
59 | | xargs readlink -m 2>/dev/null # suppress errors caused by early pipe closure | |
60 | } | |
61 | ||
62 | rust_search_lib() { | |
63 | local lib="$1" | |
64 | { | |
65 | cat | |
66 | # rust does not actually search normal paths when linking static libs | |
67 | # - see https://github.com/rust-lang/rust/issues/43118 | |
68 | # - see also `fn link_rlib` in back/link.rs which calls | |
69 | # `pub fn find_library` in back/archive.rs which generates the error message | |
70 | #gcc_default_searchdirs | |
71 | } | while read searchdir; do | |
72 | #echo >&2 "searching $searchdir for static lib $lib" | |
73 | local f="$(readlink -m "$searchdir/lib${lib}.a")" | |
74 | if test -f "$f"; then | |
75 | printf "%s\n" "$f" | |
76 | break | |
77 | fi | |
78 | done | |
79 | } | |
80 | ||
81 | native_libs() { | |
82 | ls -1d "$CARGO_TARGET_DIR/build"/*/output 2>/dev/null | while read output; do | |
8e983617 XL |
83 | sed -nre 's ^cargo:rustc-link-lib=static=(.*) \1 '"$output"' gp' "$output" |
84 | done | while read lib output; do | |
36790ab7 | 85 | local containing_crate="$(basename "$(dirname "$output")")" |
36790ab7 | 86 | test -n "$lib" || continue |
8e983617 | 87 | local libfile="$(sed -nre 's ^cargo:rustc-link-search=native=(.*) \1 gp' "$output" | rust_search_lib "$lib")" |
36790ab7 XL |
88 | local srcleft="" |
89 | test -n "$libfile" || { echo >&2 "$0: abort: could not find static lib '$lib'; rustc should have failed already?"; exit 1; } | |
eecce01b | 90 | echo >&2 "$0: found static lib $lib at $libfile" |
36790ab7 XL |
91 | if [ "${libfile#$CARGO_TARGET_DIR_ABS/}" != "$libfile" ]; then |
92 | # static library source code embedded in crate | |
93 | local srcstat="$(sed -nre 's ^dh-cargo:deb-built-using='"$lib"'=([01]=.*) \1 gp' "$output")" | |
94 | case "$srcstat" in | |
95 | 0=*|1=*) | |
96 | srcleft="${srcstat%%=*}" | |
97 | libfile="${srcstat#*=}" | |
eecce01b | 98 | if [ "$(readlink -f "$libfile")" = "$(readlink -f "$PWD")" ]; then |
daf51491 XL |
99 | # Note that this exception only applies in the case that where you are building |
100 | # the Debian package for $containing_crate itself. In the case where you are | |
101 | # building a Debian package for crate X depending on $containing_crate, the | |
102 | # latter still has to output the dh-cargo:deb-built-using in their build.rs so | |
103 | # that the Debian package for crate X can correctly set Built-Using themselves. | |
36790ab7 XL |
104 | echo >&2 "$0: static library derived from $libfile which is the top-level crate being built, no need to add Built-Using" |
105 | continue | |
106 | fi | |
107 | ;; | |
108 | *) | |
109 | echo >&2 "$0: abort: could not determine source-distribution conditions of ${libfile#$CARGO_TARGET_DIR_ABS/}." | |
110 | 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:" | |
111 | echo >&2 "- \$s is 1 if the license(s) of the included static libs require source distribution alongside binaries, otherwise 0" | |
112 | exit 1 | |
113 | ;; | |
114 | esac | |
115 | fi | |
325e0652 | 116 | local wpkg="$(dpkg -S "$(readlink -f "$libfile")")" |
36790ab7 XL |
117 | test -n "$wpkg" || { echo >&2 "$0: abort: could not find Debian package for file $libfile"; exit 1; } |
118 | local pkgstat="$(echo "$wpkg" | sed -nre 's (.*): .* \1 gp' | xargs -r dpkg-query --show)" | |
119 | local pkg="$(echo "$pkgstat" | cut -f1)" | |
120 | local ver="$(echo "$pkgstat" | cut -f2)" | |
121 | # static library source code embedded in crate (from earlier) | |
122 | if [ -n "$srcleft" ]; then | |
123 | echo "$pkg $ver $srcleft" | |
124 | # static libraries from another Debian package | |
125 | 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 | |
126 | echo "$pkg $ver 0" | |
127 | 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 | |
128 | echo "$pkg $ver 1" | |
129 | else | |
130 | # guess the conditions based on the whole d/copyright file | |
131 | # this loses granularity, e.g. gcc is mostly distributed as GPL-3 but the libbacktrace portion is BSD-3 | |
132 | # to retain granularity the crate package maintainer should patch build.rs as suggested | |
133 | echo >&2 "$0: warning: guessing source-distribution conditions of $libfile, this may be inaccurate." | |
134 | echo >&2 "$0: warning: patch build.rs to suppress the above warning" | |
135 | srcleft="$(pkg_has_srcleft_license "${pkg%:*}" "$ver")" | |
136 | if [ "$srcleft" -gt 1 ]; then | |
137 | echo >&2 "You must patch build.rs of ${containing_crate%-*} to output 'dh-cargo:deb-built-using=$lib=\$s~=\$PAT' where:" | |
138 | echo >&2 "- \$s is 1 if the license(s) of the included static libs require source distribution alongside binaries, otherwise 0" | |
139 | echo >&2 "- \$PAT is an egrep pattern matching the \"\$pkg \$ver\" combinations that satisfy \$s" | |
140 | echo >&2 " for example '$pkg .*' matches the currently-relevant package, $pkg $ver" | |
141 | exit 1 | |
142 | fi | |
143 | echo "$pkg $ver $srcleft" | |
144 | fi | |
145 | done | |
146 | } | |
147 | ||
148 | output() { | |
149 | local binpkg="$1" | |
150 | if [ -z "$binpkg" ]; then | |
151 | cat | |
152 | else | |
153 | local built_using="" | |
154 | local built_using_x="" | |
dd7e39ec | 155 | while read pkg ver srcleft; do |
8bb17ec6 | 156 | local src="$(dpkg-query -f '${source:Package}' --show "$pkg")" |
6645cc59 | 157 | local srcver="$(dpkg-query -f '${source:Version}' --show "$pkg")" |
36790ab7 XL |
158 | case "$srcleft" in |
159 | 2) exit 1;; | |
6645cc59 | 160 | 1) built_using="${built_using}$src (= $srcver), ";; |
36790ab7 | 161 | esac |
6645cc59 | 162 | built_using_x="${built_using_x}$src (= $srcver), " |
36790ab7 XL |
163 | done |
164 | echo "cargo:Built-Using=${built_using%, }" >> "debian/$binpkg.substvars" | |
165 | echo "cargo:X-Cargo-Built-Using=${built_using_x%, }" >> "debian/$binpkg.substvars" | |
166 | fi | |
167 | } | |
168 | ||
169 | native_libs="$(native_libs)" # capture output outside of pipe so set -e works | |
170 | { | |
171 | rust_libs | |
172 | test -z "$native_libs" || echo "$native_libs" | |
dd7e39ec | 173 | } | LC_COLLATE=C.utf-8 sort -u | output "$@" |