summaryrefslogtreecommitdiff
path: root/maint/reproducible-build
blob: 1b3e7df12b78d66059e7c3ee918e6b69aeb575e4 (plain)
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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#!/usr/bin/env bash
#
# This script is run inside a docker container as part of our
# reproducible build process.
#
set -xeuo pipefail
if [ ! -f /.dockerenv ]; then
    echo Not running inside Docker, build will probably not be reproducible
    echo Use docker_reproducible_build instead to get the right environment
fi
if [ $# -eq 0 ]; then
	echo usage : "$0" '<linux|windows|macos|android...>'
	exit 1
fi

: "${CARGO:=cargo}" # quotes are just to placate shellcheck

linux=""
windows=""
macos=""
android=""
while [ "$#" -ne 0 ]; do
	case "$1" in
	linux)   linux=1;;
	windows) windows=1;;
	macos)   macos=1;;
	android) android=1;;
	*)
		echo "unknown target : $1" >&2
		exit 1;;
	esac
	shift
done

here=$(pwd)

## fix the target architecture to get reproducible builds
## the architecture was chosen as old enough that it should cover most usage
## while still supporting useful features like AES-NI. Older architectures
## won't be able to execute the resulting binary.
if [ -z $android ]; then
  export CFLAGS="-march=westmere"
  export RUSTFLAGS="-C target-cpu=westmere"
fi
export SOURCE_DATE_EPOCH="0"

## force build to run in a fixed location. Necessary because the build path
## is somehow captured when compiling.
cp -a "$here" /arti
cd /arti

cargo_build () {
	$CARGO build --locked "$@"
}
cargo_build_arti () {
	cargo_build -p arti --release --features full,static "$@"
}

echo "android: '$android'"
if [ -z $android ]; then
  ## add missing dependencies
  apk add perl make git musl-dev
fi

if [ -n "$linux" ]; then
	## no additional dependencies specifically for Linux

	## Build targeting x86_64-unknown-linux-musl to get a static binary
	## feature "static" enable compiling some C dependencies instead of linking
	## to system libraries. It is required to get a well behaving result.
	cargo_build_arti --target x86_64-unknown-linux-musl
	mv /arti/target/x86_64-unknown-linux-musl/release/arti "$here"/arti-linux
fi
if [ -n "$android" ]; then
  cargo ndk --target aarch64-linux-android build --locked -p arti --release --features full,static
  mv target/aarch64-linux-android/release/arti "$here"/arti-android-aarch64
  "$ANDROID_NDK_ROOT"/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip "$here"/arti-android-aarch64
  cargo ndk --target armv7-linux-androideabi build --locked -p arti --release --features full,static
  mv target/armv7-linux-androideabi/release/arti "$here"/arti-android-armv7
  "$ANDROID_NDK_ROOT"/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip "$here"/arti-android-armv7
fi
if [ -n "$windows" ]; then
	apk add mingw-w64-gcc
	rustup target add x86_64-pc-windows-gnu

	## Same tweaks as for Linux, plus don't insert compilation timestamp into PE headers
	RUSTFLAGS="$RUSTFLAGS -C link-arg=-Wl,--no-insert-timestamp" \
		cargo_build_arti --target x86_64-pc-windows-gnu
	mv /arti/target/x86_64-pc-windows-gnu/release/arti.exe "$here"/arti-windows.exe
fi
if [ -n "$macos" ]; then
	apk add bash cmake patch clang libc-dev libxml2-dev openssl-dev musl-fts-dev build-base python3 bsd-compat-headers xz
	rustup target add x86_64-apple-darwin

	# Architecture note: the "o64" tool prefix here chooses the right
	# defaults for x86_64-apple-darwin.
	#
	# At some point, we should switch all the "o64" prefixes to to
	# "o64a" for aarch64.

	# This is the version of OSX that we try to build against.
	export MACOSX_DEPLOYMENT_TARGET="10.14"

	mkdir -p .cargo
	# (note: "ar" seems to be unused here. We could probably remove it?)
	cat > .cargo/config << EOF
[target.x86_64-apple-darwin]
linker = "o64-clang++"
EOF

	# Here we explain hw oto find the SDK we want.  This
	# originally comes from apple upstream as a '.dmg'.  The copy
	# below is an extacted '.pkg' in a cache maintained by the TB
	# team.
	#
	# To upgrade the SDK:
	#   - Make sure that OSX_SDK_URL is a .pkg file in buid-sources.tbb.tpo.
	#   - Set OSX_SDK_VERSION to the versions of that SDK.
	#   - Set OSX_PKG_SHA256 to the sha256 digest of that SDK's pkg file.
	#   - Make sure that OSX_PKG is the base-name of that pkg file.
	#
	# This SDK doesn't need to be the most recent or the oldest;
	# it does have to be at least as recent as our MACOSX_DEPLOYMENT_TARGET.
	OSX_SDK_URL=https://build-sources.tbb.torproject.org/CLTools_macOSNMOS_SDK-15.5.pkg
	OSX_SDK_VERSION=15.5
	OSX_PKG="CLTools_macOSNMOS_SDK-${OSX_SDK_VERSION}.pkg"
	OSX_PKG_SHA256=ba3453d62b3d2babf67f3a4a44e8073d6555c85f114856f4390a1f53bd76e24a
	OSX_SDK="MacOSX${OSX_SDK_VERSION}.sdk.tar.xz"

	## don't compile clang if it's already here (CI cache?)
	## Make sure that it was built from the right SDK too.
	if [ ! -x "/arti/osxcross-${OSX_SDK_VERSION}/target/bin/o64-clang" ]; then
		# Step 1: Fetch locally cached OSX Command-line tools pkg file.
		wget -nc "${OSX_SDK_URL}"
		echo "${OSX_PKG_SHA256} ${OSX_PKG}" > ./sdk-checksum
		sha256sum -c ./sdk-checksum

		# Step 2: Extract the CommandLineTools directory from that package file,
		# using a tool from the tor-browser-build repo.
		rm -rf ./tor-browser-build/
		git clone --depth 1 --sparse --filter=blob:none \
		    https://gitlab.torproject.org/tpo/applications/tor-browser-build.git
		cd ./tor-browser-build
		git sparse-checkout set projects/macosx-toolchain
		cd ./projects/macosx-toolchain
		patch < tools.diff
		python3 unpack-sdk.py \
			"../../../${OSX_PKG}" \
			"Library/Developer/" \
			"../../.."
		cd ../../..
		# (Kludge: Remove the link from e.g. MacOSX15.sdk to MacOSX15.5.sdk,
		# so we don't get duplicate package files in step 3 below.)
		rm CommandLineTools/SDKs/MacOSX[0-9][0-9].sdk

		# Step 3: Clone osxcross and build a package from the CommandLineTools
		git clone https://github.com/tpoechtrager/osxcross "osxcross-${OSX_SDK_VERSION}"
		cd "osxcross-${OSX_SDK_VERSION}"
		XCODE_TOOLS_DIR=../CommandLineTools ./tools/gen_sdk_package_tools.sh
		mv "${OSX_SDK}" ./tarballs

		# Step 4: Build the osxcross toolchain using that package.
		# (Todo: We could save time by building only the arch we want.)
		UNATTENDED=yes OSX_VERSION_MIN="$MACOSX_DEPLOYMENT_TARGET" ./build.sh

		# Step 5: copy it to gitlab build-dir so it may get cached
		cp -R /arti/"osxcross-${OSX_SDK_VERSION}" "$here"
		cd ..
	fi

	PATH="/arti/osxcross-${OSX_SDK_VERSION}/target/bin:$PATH" \
		CC=o64-clang \
		CXX=o64-clang++ \
		cargo_build_arti --target x86_64-apple-darwin

	mv /arti/target/x86_64-apple-darwin/release/arti "$here"/arti-macos
fi

git config --global --add safe.directory /arti

set +x
echo "branch       :" "$(git rev-parse --abbrev-ref HEAD)"
echo "commit       :" "$(git rev-parse HEAD)"
[ -z "$linux" ]   || echo "Linux hash   :" "$(sha256sum "$here"/arti-linux       | cut -d " " -f 1)"
[ -z "$android" ]   || echo -e "Android hash   :" "\n$(sha256sum "$here"/arti-android* | cut -d " " -f 1)"
[ -z "$windows" ] || echo "Windows hash :" "$(sha256sum "$here"/arti-windows.exe | cut -d " " -f 1)"
[ -z "$macos" ]   || echo "MacOS hash   :" "$(sha256sum "$here"/arti-macos       | cut -d " " -f 1)"