electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

build.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"/*