Skip to content

Commit 1801715

Browse files
committed
Merge #20619: guix: Quality of life improvements
570e43f guix: Print build params inside/outside of container (Carl Dong) 2f9d1fd guix: Move DISTSRC determination to guix-build.sh (Carl Dong) 0b7cd07 guix: Move OUTDIR determination+creation to guix-build.sh (Carl Dong) d27ff8b guix: Add more sanity checks to guix-build.sh (Carl Dong) 57f9533 guix: Add section headings to guix-build.sh (Carl Dong) 38b7b2e genbuild: Specify rev-parse length (Carl Dong) 036dc74 docs: Point to contrib/guix/README.md in doc/guix.md (Carl Dong) 34f0fda guix: Small updates to README wording (Carl Dong) 402e3a5 guix: Update HOSTS README entry for new architectures (Carl Dong) cfa7ceb guix: Remove README development environment section (Carl Dong) 93b6a85 guix: Add ADDITIONAL_GUIX_{COMMON,TIMEMACHINE}_FLAGS options (Carl Dong) 0f31e24 guix: Add SUBSTITUTE_URLS option (Carl Dong) 444fcfc guix: Make guix honor MAX_JOBS setting (Carl Dong) Pull request description: After live-demo-ing a Guix build (which completed successfully!) on achow101's stream, I realized there were a few quality of life improvements which can be made to improve the user experience of our Guix build process. Here are a few of them. Notable changes: 1. When `MAX_JOBS` is specified, both `guix time-machine` and `guix environment` will now build up to `MAX_JOBS` packages at a time when creating the build environment 2. The instructions for using substitutes were incorrect, and has now been replaced with a `SUBSTITUTE_URLS` environment variable, which works well with shell's IFS splitting rules 3. New `ADDITIONAL_GUIX_{COMMON,TIMEMACHINE}_FLAGS` options, for more granular customization of the build process. 4. README cleanup ACKs for top commit: fanquake: ACK 570e43f - lets move this forward. Tree-SHA512: 4e8ab560522ade5efb5e8736aec0fb1a3f19ae9deb586c1ab87020816876f3f466a950b3f8c04d9fa1d072ae5ee780038c5c9063577049bdd9db17978e11c328
2 parents 7838db1 + 570e43f commit 1801715

File tree

5 files changed

+210
-56
lines changed

5 files changed

+210
-56
lines changed

contrib/guix/README.md

Lines changed: 41 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -40,25 +40,27 @@ Otherwise, follow the [Guix installation guide][guix/bin-install].
4040

4141
Guix allows us to achieve better binary security by using our CPU time to build
4242
everything from scratch. However, it doesn't sacrifice user choice in pursuit of
43-
this: users can decide whether or not to bootstrap and to use substitutes.
43+
this: users can decide whether or not to bootstrap and to use substitutes
44+
(pre-built packages).
4445

4546
After installation, you may want to consider [adding substitute
46-
servers](#speeding-up-builds-with-substitute-servers) to speed up your build if
47-
that fits your security model (say, if you're just testing that this works).
48-
This is skippable if you're using the [Dockerfile][fanquake/guix-docker].
47+
servers](#speeding-up-builds-with-substitute-servers) from which to download
48+
pre-built packages to speed up your build if that fits your security model (say,
49+
if you're just testing that this works). Substitute servers are set up by
50+
default if you're using the [Dockerfile][fanquake/guix-docker].
4951

50-
If you prefer not to use any substitutes, make sure to set
51-
`ADDITIONAL_GUIX_ENVIRONMENT_FLAGS` like the following snippet. The first build
52-
will take a while, but the resulting packages will be cached for future builds.
52+
If you prefer not to use any substitutes, make sure to supply `--no-substitutes`
53+
like in the following snippet. The first build will take a while, but the
54+
resulting packages will be cached for future builds.
5355

5456
```sh
55-
export ADDITIONAL_GUIX_ENVIRONMENT_FLAGS='--no-substitutes'
57+
export ADDITIONAL_GUIX_COMMON_FLAGS='--no-substitutes'
5658
```
5759

5860
Likewise, to perform a bootstrapped build (takes even longer):
5961

6062
```sh
61-
export ADDITIONAL_GUIX_ENVIRONMENT_FLAGS='--bootstrap --no-substitutes'
63+
export ADDITIONAL_GUIX_COMMON_FLAGS='--no-substitutes' ADDITIONAL_GUIX_ENVIRONMENT_FLAGS='--bootstrap'
6264
```
6365

6466
### Using a version of Guix with `guix time-machine` capabilities
@@ -82,17 +84,6 @@ export PATH="${HOME}/.config/guix/current/bin${PATH:+:}$PATH"
8284

8385
## Usage
8486

85-
### As a Development Environment
86-
87-
For a Bitcoin Core depends development environment, simply invoke
88-
89-
```sh
90-
guix environment --manifest=contrib/guix/manifest.scm
91-
```
92-
93-
And you'll land back in your shell with all the build dependencies required for
94-
a `depends` build injected into your environment.
95-
9687
### As a Tool for Deterministic Builds
9788

9889
From the top of a clean Bitcoin Core repository:
@@ -113,10 +104,8 @@ find output/ -type f -print0 | sort -z | xargs -r0 sha256sum
113104
* _**HOSTS**_
114105

115106
Override the space-separated list of platform triples for which to perform a
116-
bootstrappable build. _(defaults to "x86\_64-linux-gnu
117-
arm-linux-gnueabihf aarch64-linux-gnu riscv64-linux-gnu")_
118-
119-
> Windows and OS X platform triplet support are WIP.
107+
bootstrappable build. _(defaults to "x86\_64-linux-gnu arm-linux-gnueabihf
108+
aarch64-linux-gnu riscv64-linux-gnu x86_64-w64-mingw32")_
120109

121110
* _**SOURCES_PATH**_
122111

@@ -147,28 +136,45 @@ find output/ -type f -print0 | sort -z | xargs -r0 sha256sum
147136
string) is interpreted the same way as not setting `V` at all, and that `V=0`
148137
has the same effect as `V=1`.
149138

150-
* _**ADDITIONAL_GUIX_ENVIRONMENT_FLAGS**_
139+
* _**SUBSTITUTE_URLS**_
151140

152-
Additional flags to be passed to `guix environment`. For a fully-bootstrapped
141+
A whitespace-delimited list of URLs from which to download pre-built packages.
142+
A URL is only used if its signing key is authorized (refer to the [substitute
143+
servers section](#speeding-up-builds-with-substitute-servers) for more
144+
details).
145+
146+
* _**ADDITIONAL_GUIX_COMMON_FLAGS**_
147+
148+
Additional flags to be passed to all `guix` commands. For a fully-bootstrapped
153149
build, set this to `--bootstrap --no-substitutes` (refer to the [security
154150
model section](#choosing-your-security-model) for more details). Note that a
155151
fully-bootstrapped build will take quite a long time on the first run.
156152

153+
* _**ADDITIONAL_GUIX_TIMEMACHINE_FLAGS**_
154+
155+
Additional flags to be passed to `guix time-machine`.
156+
157+
* _**ADDITIONAL_GUIX_ENVIRONMENT_FLAGS**_
158+
159+
Additional flags to be passed to the invocation of `guix environment` inside
160+
`guix time-machine`.
161+
157162
## Tips and Tricks
158163

159164
### Speeding up builds with substitute servers
160165

161166
_This whole section is automatically done in the convenience
162167
[Dockerfiles][fanquake/guix-docker]_
163168

164-
For those who are used to life in the fast _(and trustful)_ lane, you can use
165-
[substitute servers][guix/substitutes] to enable binary downloads of packages.
169+
For those who are used to life in the fast _(and trustful)_ lane, you can
170+
specify [substitute servers][guix/substitutes] from which to download pre-built
171+
packages.
166172

167173
> For those who only want to use substitutes from the official Guix build farm
168174
> and have authorized the build farm's signing key during Guix's installation,
169175
> you don't need to do anything.
170176
171-
#### Authorize the signing keys
177+
#### Step 1: Authorize the signing keys
172178

173179
For the official Guix build farm at https://ci.guix.gnu.org, run as root:
174180

@@ -182,7 +188,7 @@ For dongcarl's substitute server at https://guix.carldong.io, run as root:
182188
wget -qO- 'https://guix.carldong.io/signing-key.pub' | guix archive --authorize
183189
```
184190

185-
#### Use the substitute servers
191+
#### Step 2: Specify the substitute servers
186192

187193
The official Guix build farm at https://ci.guix.gnu.org is automatically used
188194
unless the `--no-substitutes` flag is supplied.
@@ -196,7 +202,7 @@ To use dongcarl's substitute server for Bitcoin Core builds after having
196202
[authorized his signing key](#authorize-the-signing-keys):
197203

198204
```
199-
export ADDITIONAL_GUIX_ENVIRONMENT_FLAGS='--substitute-urls="https://guix.carldong.io https://ci.guix.gnu.org"'
205+
export SUBSTITUTE_URLS='https://guix.carldong.io https://ci.guix.gnu.org'
200206
```
201207

202208
## FAQ
@@ -212,9 +218,9 @@ As mentioned at the bottom of [this manual page][guix/bin-install]:
212218
213219
### When will Guix be packaged in debian?
214220

215-
Vagrant Cascadian has been making good progress on this
216-
[here][debian/guix-package]. We have all the pieces needed to put up an APT
217-
repository and will likely put one up soon.
221+
Thanks to Vagrant Cascadian's diligent work, Guix is now [in debian
222+
experimental][debian/guix-experimental]! Hopefully it will make its way into a
223+
release soon.
218224

219225
[b17e]: http://bootstrappable.org/
220226
[r12e/source-date-epoch]: https://reproducible-builds.org/docs/source-date-epoch/
@@ -226,5 +232,5 @@ repository and will likely put one up soon.
226232
[guix/substitute-server-auth]: https://www.gnu.org/software/guix/manual/en/html_node/Substitute-Server-Authorization.html
227233
[guix/time-machine]: https://guix.gnu.org/manual/en/html_node/Invoking-guix-time_002dmachine.html
228234

229-
[debian/guix-package]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=850644
235+
[debian/guix-experimental]: https://packages.debian.org/experimental/guix
230236
[fanquake/guix-docker]: https://github.com/fanquake/core-review/tree/master/guix

contrib/guix/guix-build.sh

Lines changed: 155 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,116 @@
22
export LC_ALL=C
33
set -e -o pipefail
44

5+
###################
6+
## Sanity Checks ##
7+
###################
8+
9+
################
10+
# Check 1: Make sure that we can invoke required tools
11+
################
12+
for cmd in git make guix cat mkdir; do
13+
if ! command -v "$cmd" > /dev/null 2>&1; then
14+
echo "ERR: This script requires that '$cmd' is installed and available in your \$PATH"
15+
exit 1
16+
fi
17+
done
18+
19+
################
20+
# Check 2: Make sure GUIX_BUILD_OPTIONS is empty
21+
################
22+
#
23+
# GUIX_BUILD_OPTIONS is an environment variable recognized by guix commands that
24+
# can perform builds. This seems like what we want instead of
25+
# ADDITIONAL_GUIX_COMMON_FLAGS, but the value of GUIX_BUILD_OPTIONS is actually
26+
# _appended_ to normal command-line options. Meaning that they will take
27+
# precedence over the command-specific ADDITIONAL_GUIX_<CMD>_FLAGS.
28+
#
29+
# This seems like a poor user experience. Thus we check for GUIX_BUILD_OPTIONS's
30+
# existence here and direct users of this script to use our (more flexible)
31+
# custom environment variables.
32+
if [ -n "$GUIX_BUILD_OPTIONS" ]; then
33+
cat << EOF
34+
Error: Environment variable GUIX_BUILD_OPTIONS is not empty:
35+
'$GUIX_BUILD_OPTIONS'
36+
37+
Unfortunately this script is incompatible with GUIX_BUILD_OPTIONS, please unset
38+
GUIX_BUILD_OPTIONS and use ADDITIONAL_GUIX_COMMON_FLAGS to set build options
39+
across guix commands or ADDITIONAL_GUIX_<CMD>_FLAGS to set build options for a
40+
specific guix command.
41+
42+
See contrib/guix/README.md for more details.
43+
EOF
44+
exit 1
45+
fi
46+
47+
################
48+
# Check 3: Make sure that we're not in a dirty worktree
49+
################
50+
if ! git diff-index --quiet HEAD -- && [ -z "$FORCE_DIRTY_WORKTREE" ]; then
51+
cat << EOF
52+
ERR: The current git worktree is dirty, which may lead to broken builds.
53+
54+
Aborting...
55+
56+
Hint: To make your git worktree clean, You may want to:
57+
1. Commit your changes,
58+
2. Stash your changes, or
59+
3. Set the 'FORCE_DIRTY_WORKTREE' environment variable if you insist on
60+
using a dirty worktree
61+
EOF
62+
exit 1
63+
else
64+
GIT_COMMIT=$(git rev-parse --short=12 HEAD)
65+
fi
66+
67+
################
68+
# Check 4: Make sure that build directories do no exist
69+
################
70+
71+
# Default to building for all supported HOSTs (overridable by environment)
72+
export HOSTS="${HOSTS:-x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu riscv64-linux-gnu
73+
x86_64-w64-mingw32}"
74+
75+
DISTSRC_BASE="${DISTSRC_BASE:-${PWD}}"
76+
77+
# Usage: distsrc_for_host HOST
78+
#
79+
# HOST: The current platform triple we're building for
80+
#
81+
distsrc_for_host() {
82+
echo "${DISTSRC_BASE}/distsrc-${GIT_COMMIT}-${1}"
83+
}
84+
85+
# Accumulate a list of build directories that already exist...
86+
hosts_distsrc_exists=""
87+
for host in $HOSTS; do
88+
if [ -e "$(distsrc_for_host "$host")" ]; then
89+
hosts_distsrc_exists+=" ${host}"
90+
fi
91+
done
92+
93+
if [ -n "$hosts_distsrc_exists" ]; then
94+
# ...so that we can print them out nicely in an error message
95+
cat << EOF
96+
ERR: Build directories for this commit already exist for the following platform
97+
triples you're attempting to build, probably because of previous builds.
98+
Please remove, or otherwise deal with them prior to starting another build.
99+
100+
Aborting...
101+
102+
EOF
103+
for host in $hosts_distsrc_exists; do
104+
echo " ${host} '$(distsrc_for_host "$host")'"
105+
done
106+
exit 1
107+
else
108+
mkdir -p "$DISTSRC_BASE"
109+
fi
110+
111+
#########
112+
# Setup #
113+
#########
114+
5115
# Determine the maximum number of jobs to run simultaneously (overridable by
6116
# environment)
7117
MAX_JOBS="${MAX_JOBS:-$(nproc)}"
@@ -16,11 +126,23 @@ SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:-$(git log --format=%at -1)}"
16126
# Execute "$@" in a pinned, possibly older version of Guix, for reproducibility
17127
# across time.
18128
time-machine() {
129+
# shellcheck disable=SC2086
19130
guix time-machine --url=https://github.com/dongcarl/guix.git \
20131
--commit=b066c25026f21fb57677aa34692a5034338e7ee3 \
132+
--max-jobs="$MAX_JOBS" \
133+
${SUBSTITUTE_URLS:+--substitute-urls="$SUBSTITUTE_URLS"} \
134+
${ADDITIONAL_GUIX_COMMON_FLAGS} ${ADDITIONAL_GUIX_TIMEMACHINE_FLAGS} \
21135
-- "$@"
22136
}
23137

138+
# Make sure an output directory exists for our builds
139+
OUTDIR="${OUTDIR:-${PWD}/output}"
140+
[ -e "$OUTDIR" ] || mkdir -p "$OUTDIR"
141+
142+
#########
143+
# Build #
144+
#########
145+
24146
# Function to be called when building for host ${1} and the user interrupts the
25147
# build
26148
int_trap() {
@@ -38,9 +160,9 @@ and untracked files and directories will be wiped, allowing you to start anew.
38160
EOF
39161
}
40162

41-
# Deterministically build Bitcoin Core for HOSTs (overridable by environment)
163+
# Deterministically build Bitcoin Core
42164
# shellcheck disable=SC2153
43-
for host in ${HOSTS=x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu riscv64-linux-gnu x86_64-w64-mingw32}; do
165+
for host in $HOSTS; do
44166

45167
# Display proper warning when the user interrupts the build
46168
trap 'int_trap ${host}' INT
@@ -50,6 +172,19 @@ for host in ${HOSTS=x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu riscv
50172
# for the particular $HOST we're building for
51173
export HOST="$host"
52174

175+
# shellcheck disable=SC2030
176+
cat << EOF
177+
INFO: Building commit ${GIT_COMMIT:?not set} for platform triple ${HOST:?not set}:
178+
...using reference timestamp: ${SOURCE_DATE_EPOCH:?not set}
179+
...running at most ${MAX_JOBS:?not set} jobs
180+
...from worktree directory: '${PWD}'
181+
...bind-mounted in container to: '/bitcoin'
182+
...in build directory: '$(distsrc_for_host "$HOST")'
183+
...bind-mounted in container to: '$(DISTSRC_BASE=/distsrc-base && distsrc_for_host "$HOST")'
184+
...outputting in: '${OUTDIR:?not set}'
185+
...bind-mounted in container to: '/outdir'
186+
EOF
187+
53188
# Run the build script 'contrib/guix/libexec/build.sh' in the build
54189
# container specified by 'contrib/guix/manifest.scm'.
55190
#
@@ -99,20 +234,36 @@ for host in ${HOSTS=x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu riscv
99234
# make the downloaded depends sources available to it. The sources
100235
# should have been downloaded prior to this invocation.
101236
#
102-
# shellcheck disable=SC2086
237+
# ${SUBSTITUTE_URLS:+--substitute-urls="$SUBSTITUTE_URLS"}
238+
#
239+
# fetch substitute from SUBSTITUTE_URLS if they are
240+
# authorized
241+
#
242+
# Depending on the user's security model, it may be desirable to use
243+
# substitutes (pre-built packages) from servers that the user trusts.
244+
# Please read the README.md in the same directory as this file for
245+
# more information.
246+
#
247+
# shellcheck disable=SC2086,SC2031
103248
time-machine environment --manifest="${PWD}/contrib/guix/manifest.scm" \
104249
--container \
105250
--pure \
106251
--no-cwd \
107252
--share="$PWD"=/bitcoin \
253+
--share="$DISTSRC_BASE"=/distsrc-base \
254+
--share="$OUTDIR"=/outdir \
108255
--expose="$(git rev-parse --git-common-dir)" \
109256
${SOURCES_PATH:+--share="$SOURCES_PATH"} \
110-
${ADDITIONAL_GUIX_ENVIRONMENT_FLAGS} \
257+
--max-jobs="$MAX_JOBS" \
258+
${SUBSTITUTE_URLS:+--substitute-urls="$SUBSTITUTE_URLS"} \
259+
${ADDITIONAL_GUIX_COMMON_FLAGS} ${ADDITIONAL_GUIX_ENVIRONMENT_FLAGS} \
111260
-- env HOST="$host" \
112261
MAX_JOBS="$MAX_JOBS" \
113262
SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:?unable to determine value}" \
114263
${V:+V=1} \
115264
${SOURCES_PATH:+SOURCES_PATH="$SOURCES_PATH"} \
265+
DISTSRC="$(DISTSRC_BASE=/distsrc-base && distsrc_for_host "$HOST")" \
266+
OUTDIR=/outdir \
116267
bash -c "cd /bitcoin && bash contrib/guix/libexec/build.sh"
117268
)
118269

0 commit comments

Comments
 (0)