Skip to content

Commit 570d769

Browse files
committed
guix: Build support for Windows
1 parent 0d71395 commit 570d769

File tree

3 files changed

+244
-104
lines changed

3 files changed

+244
-104
lines changed

contrib/guix/guix-build.sh

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,26 +20,32 @@ time-machine() {
2020
}
2121

2222
# Deterministically build Bitcoin Core for HOSTs (overriable by environment)
23-
for host in ${HOSTS=x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu riscv64-linux-gnu}; do
23+
for host in ${HOSTS=x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu riscv64-linux-gnu x86_64-w64-mingw32}; do
2424

2525
# Display proper warning when the user interrupts the build
2626
trap 'echo "** INT received while building ${host}, you may want to clean up the relevant output and distsrc-* directories before rebuilding"' INT
2727

28-
# Run the build script 'contrib/guix/libexec/build.sh' in the build
29-
# container specified by 'contrib/guix/manifest.scm'
30-
# shellcheck disable=SC2086
31-
time-machine environment --manifest="${PWD}/contrib/guix/manifest.scm" \
32-
--container \
33-
--pure \
34-
--no-cwd \
35-
--share="$PWD"=/bitcoin \
36-
${SOURCES_PATH:+--share="$SOURCES_PATH"} \
37-
${ADDITIONAL_GUIX_ENVIRONMENT_FLAGS} \
38-
-- env HOST="$host" \
39-
MAX_JOBS="$MAX_JOBS" \
40-
SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:?unable to determine value}" \
41-
${V:+V=1} \
42-
${SOURCES_PATH:+SOURCES_PATH="$SOURCES_PATH"} \
43-
bash -c "cd /bitcoin && bash contrib/guix/libexec/build.sh"
28+
(
29+
# Required for 'contrib/guix/manifest.scm' to output the right manifest
30+
# for the particular $HOST we're building for
31+
export HOST="$host"
32+
33+
# Run the build script 'contrib/guix/libexec/build.sh' in the build
34+
# container specified by 'contrib/guix/manifest.scm'.
35+
# shellcheck disable=SC2086
36+
time-machine environment --manifest="${PWD}/contrib/guix/manifest.scm" \
37+
--container \
38+
--pure \
39+
--no-cwd \
40+
--share="$PWD"=/bitcoin \
41+
${SOURCES_PATH:+--share="$SOURCES_PATH"} \
42+
${ADDITIONAL_GUIX_ENVIRONMENT_FLAGS} \
43+
-- env HOST="$host" \
44+
MAX_JOBS="$MAX_JOBS" \
45+
SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:?unable to determine value}" \
46+
${V:+V=1} \
47+
${SOURCES_PATH:+SOURCES_PATH="$SOURCES_PATH"} \
48+
bash -c "cd /bitcoin && bash contrib/guix/libexec/build.sh"
49+
)
4450

4551
done

contrib/guix/libexec/build.sh

Lines changed: 145 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -36,23 +36,41 @@ store_path() {
3636
--expression='s|"[[:space:]]*$||'
3737
}
3838

39-
# Determine output paths to use in CROSS_* environment variables
40-
CROSS_GLIBC="$(store_path glibc-cross-${HOST})"
41-
CROSS_GLIBC_STATIC="$(store_path glibc-cross-${HOST} static)"
42-
CROSS_KERNEL="$(store_path linux-libre-headers-cross-${HOST})"
43-
CROSS_GCC="$(store_path gcc-cross-${HOST})"
44-
CROSS_GCC_LIBS=( "${CROSS_GCC}/lib/gcc/${HOST}"/* ) # This expands to an array of directories...
45-
CROSS_GCC_LIB="${CROSS_GCC_LIBS[0]}" # ...we just want the first one (there should only be one)
46-
4739
# Set environment variables to point Guix's cross-toolchain to the right
4840
# includes/libs for $HOST
49-
#
50-
# NOTE: CROSS_C_INCLUDE_PATH is missing ${CROSS_GCC_LIB}/include-fixed, because
51-
# the limits.h in it is missing a '#include_next <limits.h>'
52-
#
53-
export CROSS_C_INCLUDE_PATH="${CROSS_GCC_LIB}/include:${CROSS_GLIBC}/include:${CROSS_KERNEL}/include"
54-
export CROSS_CPLUS_INCLUDE_PATH="${CROSS_GCC}/include/c++:${CROSS_GCC}/include/c++/${HOST}:${CROSS_GCC}/include/c++/backward:${CROSS_C_INCLUDE_PATH}"
55-
export CROSS_LIBRARY_PATH="${CROSS_GCC}/lib:${CROSS_GCC}/${HOST}/lib:${CROSS_GCC_LIB}:${CROSS_GLIBC}/lib:${CROSS_GLIBC_STATIC}/lib"
41+
case "$HOST" in
42+
*mingw*)
43+
# Determine output paths to use in CROSS_* environment variables
44+
CROSS_GLIBC="$(store_path "mingw-w64-x86_64-winpthreads")"
45+
CROSS_GCC="$(store_path "gcc-cross-${HOST}")"
46+
CROSS_GCC_LIBS=( "${CROSS_GCC}/lib/gcc/${HOST}"/* ) # This expands to an array of directories...
47+
CROSS_GCC_LIB="${CROSS_GCC_LIBS[0]}" # ...we just want the first one (there should only be one)
48+
49+
NATIVE_GCC="$(store_path gcc-glibc-2.27-toolchain)"
50+
export LIBRARY_PATH="${NATIVE_GCC}/lib:${NATIVE_GCC}/lib64"
51+
export CPATH="${NATIVE_GCC}/include"
52+
53+
export CROSS_C_INCLUDE_PATH="${CROSS_GCC_LIB}/include:${CROSS_GCC_LIB}/include-fixed:${CROSS_GLIBC}/include"
54+
export CROSS_CPLUS_INCLUDE_PATH="${CROSS_GCC}/include/c++:${CROSS_GCC}/include/c++/${HOST}:${CROSS_GCC}/include/c++/backward:${CROSS_C_INCLUDE_PATH}"
55+
export CROSS_LIBRARY_PATH="${CROSS_GCC}/lib:${CROSS_GCC}/${HOST}/lib:${CROSS_GCC_LIB}:${CROSS_GLIBC}/lib"
56+
;;
57+
*linux*)
58+
CROSS_GLIBC="$(store_path glibc-cross-${HOST})"
59+
CROSS_GLIBC_STATIC="$(store_path glibc-cross-${HOST} static)"
60+
CROSS_KERNEL="$(store_path linux-libre-headers-cross-${HOST})"
61+
CROSS_GCC="$(store_path gcc-cross-${HOST})"
62+
CROSS_GCC_LIBS=( "${CROSS_GCC}/lib/gcc/${HOST}"/* ) # This expands to an array of directories...
63+
CROSS_GCC_LIB="${CROSS_GCC_LIBS[0]}" # ...we just want the first one (there should only be one)
64+
65+
# NOTE: CROSS_C_INCLUDE_PATH is missing ${CROSS_GCC_LIB}/include-fixed, because
66+
# the limits.h in it is missing a '#include_next <limits.h>'
67+
export CROSS_C_INCLUDE_PATH="${CROSS_GCC_LIB}/include:${CROSS_GLIBC}/include:${CROSS_KERNEL}/include"
68+
export CROSS_CPLUS_INCLUDE_PATH="${CROSS_GCC}/include/c++:${CROSS_GCC}/include/c++/${HOST}:${CROSS_GCC}/include/c++/backward:${CROSS_C_INCLUDE_PATH}"
69+
export CROSS_LIBRARY_PATH="${CROSS_GCC}/lib:${CROSS_GCC}/${HOST}/lib:${CROSS_GCC_LIB}:${CROSS_GLIBC}/lib:${CROSS_GLIBC_STATIC}/lib"
70+
;;
71+
*)
72+
exit 1 ;;
73+
esac
5674

5775
# Sanity check CROSS_*_PATH directories
5876
IFS=':' read -ra PATHS <<< "${CROSS_C_INCLUDE_PATH}:${CROSS_CPLUS_INCLUDE_PATH}:${CROSS_LIBRARY_PATH}"
@@ -74,16 +92,20 @@ export GUIX_LD_WRAPPER_DISABLE_RPATH=yes
7492
[ -e /usr/bin/env ] || ln -s --no-dereference "$(command -v env)" /usr/bin/env
7593

7694
# Determine the correct value for -Wl,--dynamic-linker for the current $HOST
77-
glibc_dynamic_linker=$(
78-
case "$HOST" in
79-
i686-linux-gnu) echo /lib/ld-linux.so.2 ;;
80-
x86_64-linux-gnu) echo /lib64/ld-linux-x86-64.so.2 ;;
81-
arm-linux-gnueabihf) echo /lib/ld-linux-armhf.so.3 ;;
82-
aarch64-linux-gnu) echo /lib/ld-linux-aarch64.so.1 ;;
83-
riscv64-linux-gnu) echo /lib/ld-linux-riscv64-lp64d.so.1 ;;
84-
*) exit 1 ;;
85-
esac
86-
)
95+
case "$HOST" in
96+
*linux*)
97+
glibc_dynamic_linker=$(
98+
case "$HOST" in
99+
i686-linux-gnu) echo /lib/ld-linux.so.2 ;;
100+
x86_64-linux-gnu) echo /lib64/ld-linux-x86-64.so.2 ;;
101+
arm-linux-gnueabihf) echo /lib/ld-linux-armhf.so.3 ;;
102+
aarch64-linux-gnu) echo /lib/ld-linux-aarch64.so.1 ;;
103+
riscv64-linux-gnu) echo /lib/ld-linux-riscv64-lp64d.so.1 ;;
104+
*) exit 1 ;;
105+
esac
106+
)
107+
;;
108+
esac
87109

88110
# Environment variables for determinism
89111
export QT_RCC_TEST=1
@@ -111,7 +133,8 @@ make -C depends --jobs="$MAX_JOBS" HOST="$HOST" \
111133
x86_64_linux_RANLIB=x86_64-linux-gnu-ranlib \
112134
x86_64_linux_NM=x86_64-linux-gnu-nm \
113135
x86_64_linux_STRIP=x86_64-linux-gnu-strip \
114-
qt_config_opts_i686_linux='-platform linux-g++ -xplatform bitcoin-linux-g++'
136+
qt_config_opts_i686_linux='-platform linux-g++ -xplatform bitcoin-linux-g++' \
137+
mingw32_CFLAGS='-DMINGW_HAS_SECURE_API=1 -pipe'
115138

116139

117140
###########################
@@ -136,11 +159,26 @@ DISTNAME="$(basename "$SOURCEDIST" '.tar.gz')"
136159
# Binary Tarball Building #
137160
###########################
138161

139-
# Similar flags to Gitian
140-
CONFIGFLAGS="--enable-glibc-back-compat --enable-reduce-exports --disable-bench --disable-gui-tests"
141-
HOST_CFLAGS="-O2 -g -ffile-prefix-map=${PWD}=."
142-
HOST_CXXFLAGS="-O2 -g -ffile-prefix-map=${PWD}=."
143-
HOST_LDFLAGS="-Wl,--as-needed -Wl,--dynamic-linker=$glibc_dynamic_linker -static-libstdc++"
162+
# CONFIGFLAGS
163+
CONFIGFLAGS="--enable-reduce-exports --disable-bench --disable-gui-tests"
164+
case "$HOST" in
165+
*linux*) CONFIGFLAGS+=" --enable-glibc-back-compat" ;;
166+
esac
167+
168+
# CFLAGS
169+
HOST_CFLAGS="-O2 -g"
170+
case "$HOST" in
171+
*linux*) HOST_CFLAGS+=" -ffile-prefix-map=${PWD}=." ;;
172+
*mingw*) HOST_CFLAGS+=" -fno-ident" ;;
173+
esac
174+
175+
# CXXFLAGS
176+
HOST_CXXFLAGS="$HOST_CFLAGS"
177+
178+
# LDFLAGS
179+
case "$HOST" in
180+
*linux*) HOST_LDFLAGS="-Wl,--as-needed -Wl,--dynamic-linker=$glibc_dynamic_linker -static-libstdc++" ;;
181+
esac
144182

145183
# Make $HOST-specific native binaries from depends available in $PATH
146184
export PATH="${BASEPREFIX}/${HOST}/native/bin:${PATH}"
@@ -160,7 +198,7 @@ export PATH="${BASEPREFIX}/${HOST}/native/bin:${PATH}"
160198
${CONFIGFLAGS} \
161199
CFLAGS="${HOST_CFLAGS}" \
162200
CXXFLAGS="${HOST_CXXFLAGS}" \
163-
LDFLAGS="${HOST_LDFLAGS}"
201+
${HOST_LDFLAGS:+LDFLAGS="${HOST_LDFLAGS}"}
164202

165203
sed -i.old 's/-lstdc++ //g' config.status libtool src/univalue/config.status src/univalue/libtool
166204

@@ -169,9 +207,21 @@ export PATH="${BASEPREFIX}/${HOST}/native/bin:${PATH}"
169207

170208
# Perform basic ELF security checks on a series of executables.
171209
make -C src --jobs=1 check-security ${V:+V=1}
172-
# Check that executables only contain allowed gcc, glibc and libstdc++
173-
# version symbols for Linux distro back-compatibility.
174-
make -C src --jobs=1 check-symbols ${V:+V=1}
210+
211+
case "$HOST" in
212+
*linux*)
213+
# Check that executables only contain allowed gcc, glibc and libstdc++
214+
# version symbols for Linux distro back-compatibility.
215+
make -C src --jobs=1 check-symbols ${V:+V=1}
216+
;;
217+
esac
218+
219+
# Make the os-specific installers
220+
case "$HOST" in
221+
*mingw*)
222+
make deploy ${V:+V=1}
223+
;;
224+
esac
175225

176226
# Setup the directory where our Bitcoin Core build for HOST will be
177227
# installed. This directory will also later serve as the input for our
@@ -180,9 +230,21 @@ export PATH="${BASEPREFIX}/${HOST}/native/bin:${PATH}"
180230
mkdir -p "${INSTALLPATH}"
181231
# Install built Bitcoin Core to $INSTALLPATH
182232
make install DESTDIR="${INSTALLPATH}" ${V:+V=1}
233+
234+
case "$HOST" in
235+
*mingw*)
236+
cp -f --target-directory="$OUTDIR" ./*-setup-unsigned.exe
237+
;;
238+
esac
183239
(
184240
cd installed
185241

242+
case "$HOST" in
243+
*mingw*)
244+
mv --target-directory="$DISTNAME"/lib/ "$DISTNAME"/bin/*.dll
245+
;;
246+
esac
247+
186248
# Prune libtool and object archives
187249
find . -name "lib*.la" -delete
188250
find . -name "lib*.a" -delete
@@ -196,19 +258,56 @@ export PATH="${BASEPREFIX}/${HOST}/native/bin:${PATH}"
196258
find "${DISTNAME}/lib" -type f -print0
197259
} | xargs -0 -n1 -P"$MAX_JOBS" -I{} "${DISTSRC}/contrib/devtools/split-debug.sh" {} {} {}.dbg
198260

199-
cp "${DISTSRC}/doc/README.md" "${DISTNAME}/"
261+
case "$HOST" in
262+
*mingw*)
263+
cp "${DISTSRC}/doc/README_windows.txt" "${DISTNAME}/readme.txt"
264+
;;
265+
*linux*)
266+
cp "${DISTSRC}/doc/README.md" "${DISTNAME}/"
267+
;;
268+
esac
200269

201270
# Finally, deterministically produce {non-,}debug binary tarballs ready
202271
# for release
203-
find "${DISTNAME}" -not -name "*.dbg" -print0 \
204-
| sort --zero-terminated \
205-
| tar --create --no-recursion --mode='u+rw,go+r-w,a+X' --null --files-from=- \
206-
| gzip -9n > "${OUTDIR}/${DISTNAME}-${HOST}.tar.gz" \
207-
|| ( rm -f "${OUTDIR}/${DISTNAME}-${HOST}.tar.gz" && exit 1 )
208-
find "${DISTNAME}" -name "*.dbg" -print0 \
209-
| sort --zero-terminated \
210-
| tar --create --no-recursion --mode='u+rw,go+r-w,a+X' --null --files-from=- \
211-
| gzip -9n > "${OUTDIR}/${DISTNAME}-${HOST}-debug.tar.gz" \
212-
|| ( rm -f "${OUTDIR}/${DISTNAME}-${HOST}-debug.tar.gz" && exit 1 )
272+
case "$HOST" in
273+
*mingw*)
274+
find "${DISTNAME}" -not -name "*.dbg" \
275+
| sort \
276+
| zip -X@ "${OUTDIR}/${DISTNAME}-${HOST//x86_64-w64-mingw32/win64}.zip" \
277+
|| ( rm -f "${OUTDIR}/${DISTNAME}-${HOST//x86_64-w64-mingw32/win64}.zip" && exit 1 )
278+
find "${DISTNAME}" -name "*.dbg" \
279+
| sort \
280+
| zip -X@ "${OUTDIR}/${DISTNAME}-${HOST//x86_64-w64-mingw32/win64}-debug.zip" \
281+
|| ( rm -f "${OUTDIR}/${DISTNAME}-${HOST//x86_64-w64-mingw32/win64}-debug.zip" && exit 1 )
282+
;;
283+
*linux*)
284+
find "${DISTNAME}" -not -name "*.dbg" -print0 \
285+
| sort --zero-terminated \
286+
| tar --create --no-recursion --mode='u+rw,go+r-w,a+X' --null --files-from=- \
287+
| gzip -9n > "${OUTDIR}/${DISTNAME}-${HOST}.tar.gz" \
288+
|| ( rm -f "${OUTDIR}/${DISTNAME}-${HOST}.tar.gz" && exit 1 )
289+
find "${DISTNAME}" -name "*.dbg" -print0 \
290+
| sort --zero-terminated \
291+
| tar --create --no-recursion --mode='u+rw,go+r-w,a+X' --null --files-from=- \
292+
| gzip -9n > "${OUTDIR}/${DISTNAME}-${HOST}-debug.tar.gz" \
293+
|| ( rm -f "${OUTDIR}/${DISTNAME}-${HOST}-debug.tar.gz" && exit 1 )
294+
;;
295+
esac
213296
)
214297
)
298+
299+
case "$HOST" in
300+
*mingw*)
301+
cp -rf --target-directory=. contrib/windeploy
302+
(
303+
cd ./windeploy
304+
mkdir unsigned
305+
cp --target-directory=unsigned/ "$OUTDIR"/bitcoin-*-setup-unsigned.exe
306+
find . -print0 \
307+
| sort --zero-terminated \
308+
| tar --create --no-recursion --mode='u+rw,go+r-w,a+X' --null --files-from=- \
309+
| gzip -9n > "${OUTDIR}/${DISTNAME}-win-unsigned.tar.gz" \
310+
|| ( rm -f "${OUTDIR}/${DISTNAME}-win-unsigned.tar.gz" && exit 1 )
311+
)
312+
;;
313+
esac

0 commit comments

Comments
 (0)