tMerge pull request #5042 from SomberNight/appimage - electrum - Electrum Bitcoin wallet
HTML git clone https://git.parazyd.org/electrum
DIR Log
DIR Files
DIR Refs
DIR Submodules
---
DIR commit 76ff2f53c504b8dc9e7a5fce3e25634267e1ec02
DIR parent ca931f476fc20e0c2003d4eb4fcafceb85e3972e
HTML Author: ThomasV <thomasv@electrum.org>
Date: Mon, 4 Feb 2019 19:16:15 +0100
Merge pull request #5042 from SomberNight/appimage
binaries for Linux: AppImage
Diffstat:
M .travis.yml | 11 +++++++++++
A contrib/build-linux/appimage/Docke… | 25 +++++++++++++++++++++++++
A contrib/build-linux/appimage/READM… | 41 +++++++++++++++++++++++++++++++
A contrib/build-linux/appimage/appru… | 11 +++++++++++
A contrib/build-linux/appimage/build… | 197 +++++++++++++++++++++++++++++++
M contrib/build-wine/prepare-wine.sh | 56 ++-----------------------------
A contrib/build_tools_util.sh | 69 ++++++++++++++++++++++++++++++
M contrib/osx/base.sh | 16 ++--------------
8 files changed, 359 insertions(+), 67 deletions(-)
---
DIR diff --git a/.travis.yml b/.travis.yml
t@@ -70,6 +70,17 @@ jobs:
script: ./contrib/osx/make_osx
after_script: ls -lah dist && md5 dist/*
after_success: true
+ - name: "AppImage build"
+ sudo: true
+ language: c
+ python: false
+ services:
+ - docker
+ install:
+ - sudo docker build --no-cache -t electrum-appimage-builder-img ./contrib/build-linux/appimage/
+ script:
+ - sudo docker run --name electrum-appimage-builder-cont -v $PWD:/opt/electrum --rm --workdir /opt/electrum/contrib/build-linux/appimage electrum-appimage-builder-img ./build.sh
+ after_success: true
- stage: release check
install:
- git fetch --all --tags
DIR diff --git a/contrib/build-linux/appimage/Dockerfile b/contrib/build-linux/appimage/Dockerfile
t@@ -0,0 +1,25 @@
+FROM ubuntu:14.04@sha256:cac55e5d97fad634d954d00a5c2a56d80576a08dcc01036011f26b88263f1578
+
+ENV LC_ALL=C.UTF-8 LANG=C.UTF-8
+
+RUN apt-get update -q && \
+ apt-get install -qy \
+ git \
+ wget \
+ make \
+ autotools-dev \
+ autoconf \
+ libtool \
+ xz-utils \
+ libssl-dev \
+ zlib1g-dev \
+ libffi6 \
+ libffi-dev \
+ libusb-1.0-0-dev \
+ libudev-dev \
+ gettext \
+ libzbar0 \
+ && \
+ rm -rf /var/lib/apt/lists/* && \
+ apt-get autoremove -y && \
+ apt-get clean
DIR diff --git a/contrib/build-linux/appimage/README.md b/contrib/build-linux/appimage/README.md
t@@ -0,0 +1,41 @@
+AppImage binary for Electrum
+============================
+
+This assumes an Ubuntu host, but it should not be too hard to adapt to another
+similar system. The docker commands should be executed in the project's root
+folder.
+
+1. Install Docker
+
+ ```
+ $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
+ $ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
+ $ sudo apt-get update
+ $ sudo apt-get install -y docker-ce
+ ```
+
+2. Build image
+
+ ```
+ $ sudo docker build --no-cache -t electrum-appimage-builder-img contrib/build-linux/appimage
+ ```
+
+3. Build binary
+
+ ```
+ $ sudo docker run -it \
+ --name electrum-appimage-builder-cont \
+ -v $PWD:/opt/electrum \
+ --rm \
+ --workdir /opt/electrum/contrib/build-linux/appimage \
+ electrum-appimage-builder-img \
+ ./build.sh
+ ```
+
+4. The generated binary is in `./dist`.
+
+
+## FAQ
+
+### How can I see what is included in the AppImage?
+Execute the binary as follows: `./electrum*.AppImage --appimage-extract`
DIR diff --git a/contrib/build-linux/appimage/apprun.sh b/contrib/build-linux/appimage/apprun.sh
t@@ -0,0 +1,11 @@
+#!/bin/bash
+
+set -e
+
+APPDIR="$(dirname "$(readlink -e "$0")")"
+
+export LD_LIBRARY_PATH="${APPDIR}/usr/lib/:${APPDIR}/usr/lib/x86_64-linux-gnu${LD_LIBRARY_PATH+:$LD_LIBRARY_PATH}"
+export PATH="${APPDIR}/usr/bin:${PATH}"
+export LDFLAGS="-L${APPDIR}/usr/lib/x86_64-linux-gnu -L${APPDIR}/usr/lib"
+
+exec "${APPDIR}/usr/bin/python3.6" -s "${APPDIR}/usr/bin/electrum" "$@"
DIR diff --git a/contrib/build-linux/appimage/build.sh b/contrib/build-linux/appimage/build.sh
t@@ -0,0 +1,197 @@
+#!/bin/bash
+
+set -e
+
+PROJECT_ROOT="$(dirname "$(readlink -e "$0")")/../../.."
+CONTRIB="$PROJECT_ROOT/contrib"
+DISTDIR="$PROJECT_ROOT/dist"
+BUILDDIR="$CONTRIB/build-linux/appimage/build/appimage"
+APPDIR="$BUILDDIR/electrum.AppDir"
+CACHEDIR="$CONTRIB/build-linux/appimage/.cache/appimage"
+
+# pinned versions
+PYTHON_VERSION=3.6.8
+PKG2APPIMAGE_COMMIT="83483c2971fcaa1cb0c1253acd6c731ef8404381"
+LIBSECP_VERSION="452d8e4d2a2f9f1b5be6b02e18f1ba102e5ca0b4"
+
+
+VERSION=`git describe --tags --dirty --always`
+APPIMAGE="$DISTDIR/electrum-$VERSION-x86_64.AppImage"
+
+rm -rf "$BUILDDIR"
+mkdir -p "$APPDIR" "$CACHEDIR" "$DISTDIR"
+
+
+. "$CONTRIB"/build_tools_util.sh
+
+
+info "downloading some dependencies."
+download_if_not_exist "$CACHEDIR/functions.sh" "https://raw.githubusercontent.com/AppImage/pkg2appimage/$PKG2APPIMAGE_COMMIT/functions.sh"
+verify_hash "$CACHEDIR/functions.sh" "a73a21a6c1d1e15c0a9f47f017ae833873d1dc6aa74a4c840c0b901bf1dcf09c"
+
+download_if_not_exist "$CACHEDIR/appimagetool" "https://github.com/probonopd/AppImageKit/releases/download/11/appimagetool-x86_64.AppImage"
+verify_hash "$CACHEDIR/appimagetool" "c13026b9ebaa20a17e7e0a4c818a901f0faba759801d8ceab3bb6007dde00372"
+
+download_if_not_exist "$CACHEDIR/Python-$PYTHON_VERSION.tar.xz" "https://www.python.org/ftp/python/$PYTHON_VERSION/Python-$PYTHON_VERSION.tar.xz"
+verify_hash "$CACHEDIR/Python-$PYTHON_VERSION.tar.xz" "35446241e995773b1bed7d196f4b624dadcadc8429f26282e756b2fb8a351193"
+
+
+
+info "building python."
+tar xf "$CACHEDIR/Python-$PYTHON_VERSION.tar.xz" -C "$BUILDDIR"
+(
+ cd "$BUILDDIR/Python-$PYTHON_VERSION"
+ export SOURCE_DATE_EPOCH=1530212462
+ ./configure \
+ --cache-file="$CACHEDIR/python.config.cache" \
+ --prefix="$APPDIR/usr" \
+ --enable-ipv6 \
+ --enable-shared \
+ --with-threads \
+ -q
+ make -s
+ make -s install > /dev/null
+)
+
+
+info "building libsecp256k1."
+(
+ git clone https://github.com/bitcoin-core/secp256k1 "$CACHEDIR"/secp256k1 || (cd "$CACHEDIR"/secp256k1 && git pull)
+ cd "$CACHEDIR"/secp256k1
+ git reset --hard "$LIBSECP_VERSION"
+ git clean -f -x -q
+ export SOURCE_DATE_EPOCH=1530212462
+ ./autogen.sh
+ echo "LDFLAGS = -no-undefined" >> Makefile.am
+ ./configure \
+ --prefix="$APPDIR/usr" \
+ --enable-module-recovery \
+ --enable-experimental \
+ --enable-module-ecdh \
+ --disable-jni \
+ -q
+ make -s
+ make -s install > /dev/null
+)
+
+
+appdir_python() {
+ env \
+ PYTHONNOUSERSITE=1 \
+ LD_LIBRARY_PATH="$APPDIR/usr/lib:$APPDIR/usr/lib/x86_64-linux-gnu${LD_LIBRARY_PATH+:$LD_LIBRARY_PATH}" \
+ "$APPDIR/usr/bin/python3.6" "$@"
+}
+
+python='appdir_python'
+
+
+info "installing pip."
+"$python" -m ensurepip
+
+
+info "preparing electrum-locale."
+(
+ cd "$PROJECT_ROOT"
+ git submodule update --init
+
+ pushd "$CONTRIB"/deterministic-build/electrum-locale
+ if ! which msgfmt > /dev/null 2>&1; then
+ echo "Please install gettext"
+ exit 1
+ fi
+ for i in ./locale/*; do
+ dir="$PROJECT_ROOT/electrum/$i/LC_MESSAGES"
+ mkdir -p $dir
+ msgfmt --output-file="$dir/electrum.mo" "$i/electrum.po" || true
+ done
+ popd
+)
+
+
+info "installing electrum and its dependencies."
+mkdir -p "$CACHEDIR/pip_cache"
+"$python" -m pip install --cache-dir "$CACHEDIR/pip_cache" -r "$CONTRIB/deterministic-build/requirements.txt"
+"$python" -m pip install --cache-dir "$CACHEDIR/pip_cache" -r "$CONTRIB/deterministic-build/requirements-binaries.txt"
+"$python" -m pip install --cache-dir "$CACHEDIR/pip_cache" -r "$CONTRIB/deterministic-build/requirements-hw.txt"
+"$python" -m pip install --cache-dir "$CACHEDIR/pip_cache" "$PROJECT_ROOT"
+
+
+info "copying zbar"
+cp "/usr/lib/libzbar.so.0" "$APPDIR/usr/lib/libzbar.so.0"
+
+
+info "desktop integration."
+cp "$PROJECT_ROOT/electrum.desktop" "$APPDIR/electrum.desktop"
+cp "$PROJECT_ROOT/icons/electrum.png" "$APPDIR/electrum.png"
+
+
+# add launcher
+cp "$CONTRIB/build-linux/appimage/apprun.sh" "$APPDIR/AppRun"
+
+info "finalizing AppDir."
+(
+ export PKG2AICOMMIT="$PKG2APPIMAGE_COMMIT"
+ . "$CACHEDIR/functions.sh"
+
+ cd "$APPDIR"
+ # copy system dependencies
+ # note: temporarily move PyQt5 out of the way so
+ # we don't try to bundle its system dependencies.
+ mv "$APPDIR/usr/lib/python3.6/site-packages/PyQt5" "$BUILDDIR"
+ copy_deps; copy_deps; copy_deps
+ move_lib
+ mv "$BUILDDIR/PyQt5" "$APPDIR/usr/lib/python3.6/site-packages"
+
+ # apply global appimage blacklist to exclude stuff
+ # move usr/include out of the way to preserve usr/include/python3.6m.
+ mv usr/include usr/include.tmp
+ delete_blacklisted
+ mv usr/include.tmp usr/include
+)
+
+
+info "stripping binaries from debug symbols."
+strip_binaries()
+{
+ chmod u+w -R "$APPDIR"
+ {
+ printf '%s\0' "$APPDIR/usr/bin/python3.6"
+ find "$APPDIR" -type f -regex '.*\.so\(\.[0-9.]+\)?$' -print0
+ } | xargs -0 --no-run-if-empty --verbose -n1 strip
+}
+strip_binaries
+
+remove_emptydirs()
+{
+ find "$APPDIR" -type d -empty -print0 | xargs -0 --no-run-if-empty rmdir -vp --ignore-fail-on-non-empty
+}
+remove_emptydirs
+
+
+info "removing some unneeded stuff to decrease binary size."
+rm -rf "$APPDIR"/usr/lib/python3.6/test
+rm -rf "$APPDIR"/usr/lib/python3.6/config-3.6m-x86_64-linux-gnu
+rm -rf "$APPDIR"/usr/lib/python3.6/site-packages/PyQt5/Qt/translations/qtwebengine_locales
+rm -rf "$APPDIR"/usr/lib/python3.6/site-packages/PyQt5/Qt/resources/qtwebengine_*
+rm -rf "$APPDIR"/usr/lib/python3.6/site-packages/PyQt5/Qt/qml
+rm -rf "$APPDIR"/usr/lib/python3.6/site-packages/PyQt5/Qt/lib/libQt5Web*
+rm -rf "$APPDIR"/usr/lib/python3.6/site-packages/PyQt5/Qt/lib/libQt5Designer*
+rm -rf "$APPDIR"/usr/lib/python3.6/site-packages/PyQt5/Qt/lib/libQt5Qml*
+rm -rf "$APPDIR"/usr/lib/python3.6/site-packages/PyQt5/Qt/lib/libQt5Quick*
+rm -rf "$APPDIR"/usr/lib/python3.6/site-packages/PyQt5/Qt/lib/libQt5Location*
+rm -rf "$APPDIR"/usr/lib/python3.6/site-packages/PyQt5/Qt/lib/libQt5Test*
+rm -rf "$APPDIR"/usr/lib/python3.6/site-packages/PyQt5/Qt/lib/libQt5Xml*
+
+
+info "creating the AppImage."
+(
+ cd "$BUILDDIR"
+ chmod +x "$CACHEDIR/appimagetool"
+ "$CACHEDIR/appimagetool" --appimage-extract
+ env VERSION="$VERSION" ./squashfs-root/AppRun --no-appstream --verbose "$APPDIR" "$APPIMAGE"
+)
+
+
+info "done."
+ls -la "$DISTDIR"
+sha256sum "$DISTDIR"/*
DIR diff --git a/contrib/build-wine/prepare-wine.sh b/contrib/build-wine/prepare-wine.sh
t@@ -24,62 +24,12 @@ PYHOME="c:/$PYTHON_FOLDER"
PYTHON="wine $PYHOME/python.exe -OO -B"
-# based on https://superuser.com/questions/497940/script-to-verify-a-signature-with-gpg
-verify_signature() {
- local file=$1 keyring=$2 out=
- if out=$(gpg --no-default-keyring --keyring "$keyring" --status-fd 1 --verify "$file" 2>/dev/null) &&
- echo "$out" | grep -qs "^\[GNUPG:\] VALIDSIG "; then
- return 0
- else
- echo "$out" >&2
- exit 1
- fi
-}
-
-verify_hash() {
- local file=$1 expected_hash=$2
- actual_hash=$(sha256sum $file | awk '{print $1}')
- if [ "$actual_hash" == "$expected_hash" ]; then
- return 0
- else
- echo "$file $actual_hash (unexpected hash)" >&2
- rm "$file"
- exit 1
- fi
-}
-
-download_if_not_exist() {
- local file_name=$1 url=$2
- if [ ! -e $file_name ] ; then
- wget -O $PWD/$file_name "$url"
- fi
-}
-
-# https://github.com/travis-ci/travis-build/blob/master/lib/travis/build/templates/header.sh
-retry() {
- local result=0
- local count=1
- while [ $count -le 3 ]; do
- [ $result -ne 0 ] && {
- echo -e "\nThe command \"$@\" failed. Retrying, $count of 3.\n" >&2
- }
- ! { "$@"; result=$?; }
- [ $result -eq 0 ] && break
- count=$(($count + 1))
- sleep 1
- done
-
- [ $count -gt 3 ] && {
- echo -e "\nThe command \"$@\" failed 3 times.\n" >&2
- }
-
- return $result
-}
-
# Let's begin!
-here=$(dirname $(readlink -e $0))
+here="$(dirname "$(readlink -e "$0")")"
set -e
+. $here/../build_tools_util.sh
+
wine 'wineboot'
# HACK to work around https://bugs.winehq.org/show_bug.cgi?id=42474#c22
DIR diff --git a/contrib/build_tools_util.sh b/contrib/build_tools_util.sh
t@@ -0,0 +1,69 @@
+#!/usr/bin/env bash
+
+RED='\033[0;31m'
+BLUE='\033[0;34m'
+YELLOW='\033[0;33m'
+NC='\033[0m' # No Color
+function info {
+ printf "\r💬 ${BLUE}INFO:${NC} ${1}\n"
+}
+function fail {
+ printf "\r🗯 ${RED}ERROR:${NC} ${1}\n"
+ exit 1
+}
+function warn {
+ printf "\r⚠️ ${YELLOW}WARNING:${NC} ${1}\n"
+}
+
+
+# based on https://superuser.com/questions/497940/script-to-verify-a-signature-with-gpg
+function verify_signature() {
+ local file=$1 keyring=$2 out=
+ if out=$(gpg --no-default-keyring --keyring "$keyring" --status-fd 1 --verify "$file" 2>/dev/null) &&
+ echo "$out" | grep -qs "^\[GNUPG:\] VALIDSIG "; then
+ return 0
+ else
+ echo "$out" >&2
+ exit 1
+ fi
+}
+
+function verify_hash() {
+ local file=$1 expected_hash=$2
+ actual_hash=$(sha256sum $file | awk '{print $1}')
+ if [ "$actual_hash" == "$expected_hash" ]; then
+ return 0
+ else
+ echo "$file $actual_hash (unexpected hash)" >&2
+ rm "$file"
+ exit 1
+ fi
+}
+
+function download_if_not_exist() {
+ local file_name=$1 url=$2
+ if [ ! -e $file_name ] ; then
+ wget -O $file_name "$url"
+ fi
+}
+
+# https://github.com/travis-ci/travis-build/blob/master/lib/travis/build/templates/header.sh
+function retry() {
+ local result=0
+ local count=1
+ while [ $count -le 3 ]; do
+ [ $result -ne 0 ] && {
+ echo -e "\nThe command \"$@\" failed. Retrying, $count of 3.\n" >&2
+ }
+ ! { "$@"; result=$?; }
+ [ $result -eq 0 ] && break
+ count=$(($count + 1))
+ sleep 1
+ done
+
+ [ $count -gt 3 ] && {
+ echo -e "\nThe command \"$@\" failed 3 times.\n" >&2
+ }
+
+ return $result
+}
DIR diff --git a/contrib/osx/base.sh b/contrib/osx/base.sh
t@@ -1,19 +1,7 @@
#!/usr/bin/env bash
-RED='\033[0;31m'
-BLUE='\033[0,34m'
-YELLOW='\033[0;33m'
-NC='\033[0m' # No Color
-function info {
- printf "\r💬 ${BLUE}INFO:${NC} ${1}\n"
-}
-function fail {
- printf "\r🗯 ${RED}ERROR:${NC} ${1}\n"
- exit 1
-}
-function warn {
- printf "\r⚠️ ${YELLOW}WARNING:${NC} ${1}\n"
-}
+. $(dirname "$0")/../build_tools_util.sh
+
function DoCodeSignMaybe { # ARGS: infoName fileOrDirName codesignIdentity
infoName="$1"