codesign.sh raw
1 #!/usr/bin/env bash
2 # Copyright (c) 2021-present The Bitcoin Core developers
3 # Distributed under the MIT software license, see the accompanying
4 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 export LC_ALL=C
6 set -e -o pipefail
7
8 # Environment variables for determinism
9 export TAR_OPTIONS="--owner=0 --group=0 --numeric-owner --mtime='@${SOURCE_DATE_EPOCH}' --sort=name"
10 export TZ=UTC
11
12 # Although Guix _does_ set umask when building its own packages (in our case,
13 # this is all packages in manifest.scm), it does not set it for `guix
14 # shell`. It does make sense for at least `guix shell --container`
15 # to set umask, so if that change gets merged upstream and we bump the
16 # time-machine to a commit which includes the aforementioned change, we can
17 # remove this line.
18 #
19 # This line should be placed before any commands which creates files.
20 umask 0022
21
22 if [ -n "$V" ]; then
23 # Print both unexpanded (-v) and expanded (-x) forms of commands as they are
24 # read from this file.
25 set -vx
26 # Set VERBOSE for CMake-based builds
27 export VERBOSE="$V"
28 fi
29
30 # Check that required environment variables are set
31 cat << EOF
32 Required environment variables as seen inside the container:
33 CODESIGNING_TARBALL: ${CODESIGNING_TARBALL:?not set}
34 DETACHED_SIGS_REPO: ${DETACHED_SIGS_REPO:?not set}
35 DIST_ARCHIVE_BASE: ${DIST_ARCHIVE_BASE:?not set}
36 DISTNAME: ${DISTNAME:?not set}
37 HOST: ${HOST:?not set}
38 SOURCE_DATE_EPOCH: ${SOURCE_DATE_EPOCH:?not set}
39 DISTSRC: ${DISTSRC:?not set}
40 OUTDIR: ${OUTDIR:?not set}
41 EOF
42
43 ACTUAL_OUTDIR="${OUTDIR}"
44 OUTDIR="${DISTSRC}/output"
45
46 git_head_version() {
47 local recent_tag
48 if recent_tag="$(git -C "$1" describe --exact-match HEAD 2> /dev/null)"; then
49 echo "${recent_tag#v}"
50 else
51 git -C "$1" rev-parse --short=12 HEAD
52 fi
53 }
54
55 CODESIGNATURE_GIT_ARCHIVE="${DIST_ARCHIVE_BASE}/${DISTNAME}-codesignatures-$(git_head_version "$DETACHED_SIGS_REPO").tar.gz"
56
57 # Create the codesignature tarball if not already there
58 if [ ! -e "$CODESIGNATURE_GIT_ARCHIVE" ]; then
59 mkdir -p "$(dirname "$CODESIGNATURE_GIT_ARCHIVE")"
60 git -C "$DETACHED_SIGS_REPO" archive --output="$CODESIGNATURE_GIT_ARCHIVE" HEAD
61 fi
62
63 mkdir -p "$OUTDIR"
64
65 mkdir -p "$DISTSRC"
66 (
67 cd "$DISTSRC"
68
69 tar -xf "$CODESIGNING_TARBALL"
70
71 mkdir -p codesignatures
72 tar -C codesignatures -xf "$CODESIGNATURE_GIT_ARCHIVE"
73
74 case "$HOST" in
75 *mingw*)
76 # Apply detached codesignatures
77 WORKDIR=".tmp"
78 mkdir -p ${WORKDIR}
79 cp -r --target-directory="${WORKDIR}" "unsigned/${DISTNAME}"
80 find "${WORKDIR}/${DISTNAME}" -name "*.exe" -type f -exec rm {} \;
81 find unsigned/ -name "*.exe" -type f | while read -r bin
82 do
83 bin_base="$(realpath --relative-to=unsigned/ "${bin}")"
84 mkdir -p "${WORKDIR}/$(dirname "${bin_base}")"
85 osslsigncode attach-signature \
86 -in "${bin}" \
87 -out "${WORKDIR}/${bin_base/-unsigned}" \
88 -CAfile "$GUIX_ENVIRONMENT/etc/ssl/certs/ca-certificates.crt" \
89 -sigin codesignatures/win/"${bin_base}".pem
90 done
91
92 # Move installer to outdir
93 cd "${WORKDIR}"
94 find . -name "*setup.exe" -print0 \
95 | xargs -0r mv --target-directory="${OUTDIR}"
96
97 # Make .zip from binaries
98 find "${DISTNAME}" -print0 \
99 | xargs -0r touch --no-dereference --date="@${SOURCE_DATE_EPOCH}"
100 find "${DISTNAME}" \
101 | sort \
102 | zip -X@ "${OUTDIR}/${DISTNAME}-${HOST//x86_64-w64-mingw32/win64}.zip" \
103 || ( rm -f "${OUTDIR}/${DISTNAME}-${HOST//x86_64-w64-mingw32/win64}.zip" && exit 1 )
104 ;;
105 *darwin*)
106 case "$HOST" in
107 arm64*) ARCH="arm64" ;;
108 x86_64*) ARCH="x86_64" ;;
109 esac
110
111 # Apply detached codesignatures (in-place)
112 signapple apply dist/Bitcoin-Qt.app codesignatures/osx/"${HOST}"/dist/Bitcoin-Qt.app
113 find "${DISTNAME}" \( -wholename "*/bin/*" -o -wholename "*/libexec/*" \) -type f | while read -r bin
114 do
115 signapple apply "${bin}" "codesignatures/osx/${HOST}/${bin}.${ARCH}sign"
116 done
117
118 # Make a .zip from dist/
119 cd dist/
120 find . -print0 \
121 | xargs -0r touch --no-dereference --date="@${SOURCE_DATE_EPOCH}"
122 find . | sort \
123 | zip -X@ "${OUTDIR}/${DISTNAME}-${HOST}.zip"
124 cd ..
125
126 # Make a .tar.gz from bins
127 find "${DISTNAME}" -print0 \
128 | sort --zero-terminated \
129 | tar --create --no-recursion --mode='u+rw,go+r-w,a+X' --null --files-from=- \
130 | gzip -9n > "${OUTDIR}/${DISTNAME}-${HOST}.tar.gz" \
131 || ( rm -f "${OUTDIR}/${DISTNAME}-${HOST}.tar.gz" && exit 1 )
132 ;;
133 *)
134 exit 1
135 ;;
136 esac
137 ) # $DISTSRC
138
139 rm -rf "$ACTUAL_OUTDIR"
140 mv --no-target-directory "$OUTDIR" "$ACTUAL_OUTDIR" \
141 || ( rm -rf "$ACTUAL_OUTDIR" && exit 1 )
142
143 (
144 tmp="$(mktemp)"
145 cd /outdir-base
146 {
147 echo "$CODESIGNING_TARBALL"
148 echo "$CODESIGNATURE_GIT_ARCHIVE"
149 find "$ACTUAL_OUTDIR" -type f
150 } | xargs realpath --relative-base="$PWD" \
151 | xargs sha256sum \
152 | sort -k2 \
153 > "$tmp";
154 mv "$tmp" "$ACTUAL_OUTDIR"/SHA256SUMS.part
155 )
156