tbuild.sh - electrum - Electrum Bitcoin wallet
HTML git clone https://git.parazyd.org/electrum
DIR Log
DIR Files
DIR Refs
DIR Submodules
---
tbuild.sh (10330B)
---
1 #!/bin/bash
2
3 set -e
4
5 PROJECT_ROOT="$(dirname "$(readlink -e "$0")")/../../.."
6 CONTRIB="$PROJECT_ROOT/contrib"
7 CONTRIB_APPIMAGE="$CONTRIB/build-linux/appimage"
8 DISTDIR="$PROJECT_ROOT/dist"
9 BUILDDIR="$CONTRIB_APPIMAGE/build/appimage"
10 APPDIR="$BUILDDIR/electrum.AppDir"
11 CACHEDIR="$CONTRIB_APPIMAGE/.cache/appimage"
12 PIP_CACHE_DIR="$CACHEDIR/pip_cache"
13
14 export GCC_STRIP_BINARIES="1"
15
16 # pinned versions
17 # note: compiling python 3.8.x requires at least glibc 2.27,
18 # which is first available on ubuntu 18.04
19 PYTHON_VERSION=3.7.9
20 PKG2APPIMAGE_COMMIT="eb8f3acdd9f11ab19b78f5cb15daa772367daf15"
21 SQUASHFSKIT_COMMIT="ae0d656efa2d0df2fcac795b6823b44462f19386"
22
23
24 VERSION=`git describe --tags --dirty --always`
25 APPIMAGE="$DISTDIR/electrum-$VERSION-x86_64.AppImage"
26
27 . "$CONTRIB"/build_tools_util.sh
28
29 rm -rf "$BUILDDIR"
30 mkdir -p "$APPDIR" "$CACHEDIR" "$PIP_CACHE_DIR" "$DISTDIR"
31
32 # potential leftover from setuptools that might make pip put garbage in binary
33 rm -rf "$PROJECT_ROOT/build"
34
35
36 info "downloading some dependencies."
37 download_if_not_exist "$CACHEDIR/functions.sh" "https://raw.githubusercontent.com/AppImage/pkg2appimage/$PKG2APPIMAGE_COMMIT/functions.sh"
38 verify_hash "$CACHEDIR/functions.sh" "78b7ee5a04ffb84ee1c93f0cb2900123773bc6709e5d1e43c37519f590f86918"
39
40 download_if_not_exist "$CACHEDIR/appimagetool" "https://github.com/AppImage/AppImageKit/releases/download/12/appimagetool-x86_64.AppImage"
41 verify_hash "$CACHEDIR/appimagetool" "d918b4df547b388ef253f3c9e7f6529ca81a885395c31f619d9aaf7030499a13"
42
43 download_if_not_exist "$CACHEDIR/Python-$PYTHON_VERSION.tar.xz" "https://www.python.org/ftp/python/$PYTHON_VERSION/Python-$PYTHON_VERSION.tar.xz"
44 verify_hash "$CACHEDIR/Python-$PYTHON_VERSION.tar.xz" "91923007b05005b5f9bd46f3b9172248aea5abc1543e8a636d59e629c3331b01"
45
46
47
48 info "building python."
49 tar xf "$CACHEDIR/Python-$PYTHON_VERSION.tar.xz" -C "$BUILDDIR"
50 (
51 cd "$BUILDDIR/Python-$PYTHON_VERSION"
52 LC_ALL=C export BUILD_DATE=$(date -u -d "@$SOURCE_DATE_EPOCH" "+%b %d %Y")
53 LC_ALL=C export BUILD_TIME=$(date -u -d "@$SOURCE_DATE_EPOCH" "+%H:%M:%S")
54 # Patch taken from Ubuntu http://archive.ubuntu.com/ubuntu/pool/main/p/python3.7/python3.7_3.7.6-1.debian.tar.xz
55 patch -p1 < "$CONTRIB_APPIMAGE/patches/python-3.7-reproducible-buildinfo.diff"
56 ./configure \
57 --cache-file="$CACHEDIR/python.config.cache" \
58 --prefix="$APPDIR/usr" \
59 --enable-ipv6 \
60 --enable-shared \
61 -q
62 make -j4 -s || fail "Could not build Python"
63 make -s install > /dev/null || fail "Could not install Python"
64 # When building in docker on macOS, python builds with .exe extension because the
65 # case insensitive file system of macOS leaks into docker. This causes the build
66 # to result in a different output on macOS compared to Linux. We simply patch
67 # sysconfigdata to remove the extension.
68 # Some more info: https://bugs.python.org/issue27631
69 sed -i -e 's/\.exe//g' "$APPDIR"/usr/lib/python3.7/_sysconfigdata*
70 )
71
72
73 info "Building squashfskit"
74 git clone "https://github.com/squashfskit/squashfskit.git" "$BUILDDIR/squashfskit"
75 (
76 cd "$BUILDDIR/squashfskit"
77 git checkout "${SQUASHFSKIT_COMMIT}^{commit}"
78 make -C squashfs-tools mksquashfs || fail "Could not build squashfskit"
79 )
80 MKSQUASHFS="$BUILDDIR/squashfskit/squashfs-tools/mksquashfs"
81
82
83 "$CONTRIB"/make_libsecp256k1.sh || fail "Could not build libsecp"
84 cp -f "$PROJECT_ROOT/electrum/libsecp256k1.so.0" "$APPDIR/usr/lib/libsecp256k1.so.0" || fail "Could not copy libsecp to its destination"
85
86
87 appdir_python() {
88 env \
89 PYTHONNOUSERSITE=1 \
90 LD_LIBRARY_PATH="$APPDIR/usr/lib:$APPDIR/usr/lib/x86_64-linux-gnu${LD_LIBRARY_PATH+:$LD_LIBRARY_PATH}" \
91 "$APPDIR/usr/bin/python3.7" "$@"
92 }
93
94 python='appdir_python'
95
96
97 info "installing pip."
98 "$python" -m ensurepip
99
100 break_legacy_easy_install
101
102
103 info "preparing electrum-locale."
104 (
105 cd "$PROJECT_ROOT"
106 git submodule update --init
107
108 pushd "$CONTRIB"/deterministic-build/electrum-locale
109 if ! which msgfmt > /dev/null 2>&1; then
110 fail "Please install gettext"
111 fi
112 for i in ./locale/*; do
113 dir="$PROJECT_ROOT/electrum/$i/LC_MESSAGES"
114 mkdir -p $dir
115 msgfmt --output-file="$dir/electrum.mo" "$i/electrum.po" || true
116 done
117 popd
118 )
119
120
121 info "Installing build dependencies."
122 "$python" -m pip install --no-dependencies --no-binary :all: --no-warn-script-location \
123 --cache-dir "$PIP_CACHE_DIR" -r "$CONTRIB/deterministic-build/requirements-build-appimage.txt"
124
125 info "installing electrum and its dependencies."
126 # note: we prefer compiling C extensions ourselves, instead of using binary wheels,
127 # hence "--no-binary :all:" flags. However, we specifically allow
128 # - PyQt5, as it's harder to build from source
129 # - cryptography, as building it would need openssl 1.1, not available on ubuntu 16.04
130 "$python" -m pip install --no-dependencies --no-binary :all: --no-warn-script-location \
131 --cache-dir "$PIP_CACHE_DIR" -r "$CONTRIB/deterministic-build/requirements.txt"
132 "$python" -m pip install --no-dependencies --no-binary :all: --only-binary pyqt5,cryptography --no-warn-script-location \
133 --cache-dir "$PIP_CACHE_DIR" -r "$CONTRIB/deterministic-build/requirements-binaries.txt"
134 "$python" -m pip install --no-dependencies --no-binary :all: --no-warn-script-location \
135 --cache-dir "$PIP_CACHE_DIR" -r "$CONTRIB/deterministic-build/requirements-hw.txt"
136
137 "$python" -m pip install --no-dependencies --no-warn-script-location \
138 --cache-dir "$PIP_CACHE_DIR" "$PROJECT_ROOT"
139
140 # was only needed during build time, not runtime
141 "$python" -m pip uninstall -y Cython
142
143
144 info "copying zbar"
145 cp "/usr/lib/x86_64-linux-gnu/libzbar.so.0" "$APPDIR/usr/lib/libzbar.so.0"
146
147
148 info "desktop integration."
149 cp "$PROJECT_ROOT/electrum.desktop" "$APPDIR/electrum.desktop"
150 cp "$PROJECT_ROOT/electrum/gui/icons/electrum.png" "$APPDIR/electrum.png"
151
152
153 # add launcher
154 cp "$CONTRIB_APPIMAGE/apprun.sh" "$APPDIR/AppRun"
155
156 info "finalizing AppDir."
157 (
158 export PKG2AICOMMIT="$PKG2APPIMAGE_COMMIT"
159 . "$CACHEDIR/functions.sh"
160
161 cd "$APPDIR"
162 # copy system dependencies
163 copy_deps; copy_deps; copy_deps
164 move_lib
165
166 # apply global appimage blacklist to exclude stuff
167 # move usr/include out of the way to preserve usr/include/python3.7m.
168 mv usr/include usr/include.tmp
169 delete_blacklisted
170 mv usr/include.tmp usr/include
171 ) || fail "Could not finalize AppDir"
172
173 info "Copying additional libraries"
174 (
175 # On some systems it can cause problems to use the system libusb (on AppImage excludelist)
176 cp -f /usr/lib/x86_64-linux-gnu/libusb-1.0.so "$APPDIR/usr/lib/libusb-1.0.so" || fail "Could not copy libusb"
177 # some distros lack libxkbcommon-x11
178 cp -f /usr/lib/x86_64-linux-gnu/libxkbcommon-x11.so.0 "$APPDIR"/usr/lib/x86_64-linux-gnu || fail "Could not copy libxkbcommon-x11"
179 )
180
181 info "stripping binaries from debug symbols."
182 # "-R .note.gnu.build-id" also strips the build id
183 # "-R .comment" also strips the GCC version information
184 strip_binaries()
185 {
186 chmod u+w -R "$APPDIR"
187 {
188 printf '%s\0' "$APPDIR/usr/bin/python3.7"
189 find "$APPDIR" -type f -regex '.*\.so\(\.[0-9.]+\)?$' -print0
190 } | xargs -0 --no-run-if-empty --verbose strip -R .note.gnu.build-id -R .comment
191 }
192 strip_binaries
193
194 remove_emptydirs()
195 {
196 find "$APPDIR" -type d -empty -print0 | xargs -0 --no-run-if-empty rmdir -vp --ignore-fail-on-non-empty
197 }
198 remove_emptydirs
199
200
201 info "removing some unneeded stuff to decrease binary size."
202 rm -rf "$APPDIR"/usr/{share,include}
203 PYDIR="$APPDIR"/usr/lib/python3.7
204 rm -rf "$PYDIR"/{test,ensurepip,lib2to3,idlelib,turtledemo}
205 rm -rf "$PYDIR"/{ctypes,sqlite3,tkinter,unittest}/test
206 rm -rf "$PYDIR"/distutils/{command,tests}
207 rm -rf "$PYDIR"/config-3.7m-x86_64-linux-gnu
208 rm -rf "$PYDIR"/site-packages/{opt,pip,setuptools,wheel}
209 rm -rf "$PYDIR"/site-packages/Cryptodome/SelfTest
210 rm -rf "$PYDIR"/site-packages/{psutil,qrcode,websocket}/tests
211 for component in connectivity declarative help location multimedia quickcontrols2 serialport webengine websockets xmlpatterns ; do
212 rm -rf "$PYDIR"/site-packages/PyQt5/Qt/translations/qt${component}_*
213 rm -rf "$PYDIR"/site-packages/PyQt5/Qt/resources/qt${component}_*
214 done
215 rm -rf "$PYDIR"/site-packages/PyQt5/Qt/{qml,libexec}
216 rm -rf "$PYDIR"/site-packages/PyQt5/{pyrcc.so,pylupdate.so,uic}
217 rm -rf "$PYDIR"/site-packages/PyQt5/Qt/plugins/{bearer,gamepads,geometryloaders,geoservices,playlistformats,position,renderplugins,sceneparsers,sensors,sqldrivers,texttospeech,webview}
218 for component in Bluetooth Concurrent Designer Help Location NetworkAuth Nfc Positioning PositioningQuick Qml Quick Sensors SerialPort Sql Test Web Xml ; do
219 rm -rf "$PYDIR"/site-packages/PyQt5/Qt/lib/libQt5${component}*
220 rm -rf "$PYDIR"/site-packages/PyQt5/Qt${component}*
221 done
222 rm -rf "$PYDIR"/site-packages/PyQt5/Qt.so
223
224 # these are deleted as they were not deterministic; and are not needed anyway
225 find "$APPDIR" -path '*/__pycache__*' -delete
226 # note that *.dist-info is needed by certain packages.
227 # e.g. see https://gitlab.com/python-devs/importlib_metadata/issues/71
228 for f in "$PYDIR"/site-packages/importlib_metadata-*.dist-info; do mv "$f" "$(echo "$f" | sed s/\.dist-info/\.dist-info2/)"; done
229 rm -rf "$PYDIR"/site-packages/*.dist-info/
230 rm -rf "$PYDIR"/site-packages/*.egg-info/
231 for f in "$PYDIR"/site-packages/importlib_metadata-*.dist-info2; do mv "$f" "$(echo "$f" | sed s/\.dist-info2/\.dist-info/)"; done
232
233
234 find -exec touch -h -d '2000-11-11T11:11:11+00:00' {} +
235
236
237 info "creating the AppImage."
238 (
239 cd "$BUILDDIR"
240 cp "$CACHEDIR/appimagetool" "$CACHEDIR/appimagetool_copy"
241 # zero out "appimage" magic bytes, as on some systems they confuse the linker
242 sed -i 's|AI\x02|\x00\x00\x00|' "$CACHEDIR/appimagetool_copy"
243 chmod +x "$CACHEDIR/appimagetool_copy"
244 "$CACHEDIR/appimagetool_copy" --appimage-extract
245 # We build a small wrapper for mksquashfs that removes the -mkfs-fixed-time option
246 # that mksquashfs from squashfskit does not support. It is not needed for squashfskit.
247 cat > ./squashfs-root/usr/lib/appimagekit/mksquashfs << EOF
248 #!/bin/sh
249 args=\$(echo "\$@" | sed -e 's/-mkfs-fixed-time 0//')
250 "$MKSQUASHFS" \$args
251 EOF
252 env VERSION="$VERSION" ARCH=x86_64 SOURCE_DATE_EPOCH=1530212462 ./squashfs-root/AppRun --no-appstream --verbose "$APPDIR" "$APPIMAGE"
253 )
254
255
256 info "done."
257 ls -la "$DISTDIR"
258 sha256sum "$DISTDIR"/*