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
|
#!/bin/sh
# rustc from a pinned upstream tarball (scripts/rustc.dotslash).
#
# The Rust dist tarball keeps its components in sibling directories, so the
# compiler's default sysroot (rustc/) holds no libstd — it lives under
# rust-std-<triple>/. Point --sysroot at that sibling; the compiler's own
# codegen libraries are still found via rpath, relative to the binary.
set -e
dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
exe=$(dotslash -- fetch "$dir/rustc.dotslash")
# Callers that set their own sysroot win — buck2's rustc_cfg action passes an
# empty --sysroot, and rustc rejects the option being given twice.
for arg in "$@"; do
case $arg in
--sysroot|--sysroot=*) exec "$exe" "$@" ;;
esac
done
root=$(dirname -- "$(dirname -- "$(dirname -- "$exe")")")
host_std=
for std in "$root"/rust-std-*/; do
host_std=${std%/}
break
done
[ -n "$host_std" ] || { echo "scripts/rustc: no rust-std component under $root" >&2; exit 1; }
# Cross-compiling needs one sysroot holding both triples: the host's, for proc
# macros and build scripts, and the target's, for the crate being built. The
# components ship as separate tarballs, so stitch them together as a symlink
# farm — cheap to build, and stable enough to cache across invocations.
#
# buck2 passes rustc its arguments in an @argsfile, so --target is usually not
# in argv at all; look inside those too.
scan_target() {
prev=
for arg in "$@"; do
case $arg in
--target=*-linux-android) echo "${arg#--target=}"; return ;;
*-linux-android) [ "$prev" = "--target" ] && { echo "$arg"; return; } ;;
@*) if [ -f "${arg#@}" ]; then
found=$(sed -n 's/^"\{0,1\}\(--target=\)\{0,1\}\([a-z0-9_]*-linux-android[0-9]*\)"\{0,1\}$/\2/p' \
"${arg#@}" | head -n1)
[ -n "$found" ] && { echo "$found"; return; }
fi ;;
esac
prev=$arg
done
}
android_target=$(scan_target "$@")
if [ -z "$android_target" ]; then
exec "$exe" --sysroot "$host_std" "$@"
fi
std_install=$(dotslash -- fetch "$dir/rust-std-android.dotslash")
target_std=$(dirname -- "$std_install")/rust-std-$android_target
merged=${XDG_CACHE_HOME:-$HOME/.cache}/vidya-rust-sysroot/$(basename -- "$host_std")+$android_target
if [ ! -d "$merged/lib/rustlib/$android_target" ]; then
tmp=$merged.$$
rm -rf -- "$tmp"
mkdir -p -- "$tmp/lib/rustlib"
for entry in "$host_std"/lib/*; do
[ "$(basename -- "$entry")" = rustlib ] && continue
ln -sfn -- "$entry" "$tmp/lib/"
done
for entry in "$host_std"/lib/rustlib/*; do
ln -sfn -- "$entry" "$tmp/lib/rustlib/"
done
ln -sfn -- "$target_std/lib/rustlib/$android_target" "$tmp/lib/rustlib/$android_target"
rm -rf -- "$merged"
mv -- "$tmp" "$merged" 2>/dev/null || rm -rf -- "$tmp"
fi
exec "$exe" --sysroot "$merged" "$@"
|