twin binary: build zbar ourselves (#6593) - electrum - Electrum Bitcoin wallet (HTM) git clone https://git.parazyd.org/electrum (DIR) Log (DIR) Files (DIR) Refs (DIR) Submodules --- (DIR) commit fc89c8ffa9b1ab4012331447090b36f6f15b13fc (DIR) parent ea3e3ddbb8280f499bf2535d2a8a63dd174e2e44 (HTM) Author: ghost43 <somber.night@protonmail.com> Date: Tue, 15 Sep 2020 15:35:57 +0000 win binary: build zbar ourselves (#6593) This allows bundling much newer zbar that includes many fixes. related: #6018 This is largely based on https://github.com/Electron-Cash/Electron-Cash/pull/1362 https://github.com/Electron-Cash/Electron-Cash/pull/1363 https://github.com/Electron-Cash/Electron-Cash/pull/1365 https://github.com/Electron-Cash/Electron-Cash/commit/eda015908e9d6ea9a0adfbda9db55b929c0926ba Diffstat: M contrib/build-wine/Dockerfile | 3 +++ M contrib/build-wine/build.sh | 6 ++++++ M contrib/build-wine/deterministic.s… | 2 +- M contrib/build-wine/prepare-wine.sh | 12 ++---------- M contrib/make_libsecp256k1.sh | 2 +- A contrib/make_zbar.sh | 96 +++++++++++++++++++++++++++++++ M electrum/qrscanner.py | 24 ++++++++++++++++-------- 7 files changed, 125 insertions(+), 20 deletions(-) --- (DIR) diff --git a/contrib/build-wine/Dockerfile b/contrib/build-wine/Dockerfile t@@ -17,8 +17,11 @@ RUN apt-get update -q && \ p7zip-full=16.02+dfsg-6 \ make=4.1-9.1ubuntu1 \ mingw-w64=5.0.3-1 \ + mingw-w64-tools=5.0.3-1 \ + win-iconv-mingw-w64-dev=0.0.8-2 \ autotools-dev=20180224.1 \ autoconf=2.69-11 \ + autopoint=0.19.8.1-6ubuntu0.3 \ libtool=2.4.6-2 \ gettext=0.19.8.1-6 (DIR) diff --git a/contrib/build-wine/build.sh b/contrib/build-wine/build.sh t@@ -29,6 +29,12 @@ else "$CONTRIB"/make_libsecp256k1.sh || fail "Could not build libsecp" fi +if [ -f "$PROJECT_ROOT/electrum/libzbar-0.dll" ]; then + info "libzbar already built, skipping" +else + "$CONTRIB"/make_zbar.sh || fail "Could not build zbar" +fi + $here/prepare-wine.sh || fail "prepare-wine failed" info "Resetting modification time in C:\Python..." (DIR) diff --git a/contrib/build-wine/deterministic.spec b/contrib/build-wine/deterministic.spec t@@ -34,6 +34,7 @@ binaries += [b for b in collect_dynamic_libs('PyQt5') if 'qwindowsvista' in b[0] binaries += [('C:/tmp/libsecp256k1-0.dll', '.')] binaries += [('C:/tmp/libusb-1.0.dll', '.')] +binaries += [('C:/tmp/libzbar-0.dll', '.')] datas = [ (home+'electrum/*.json', 'electrum'), t@@ -41,7 +42,6 @@ datas = [ (home+'electrum/wordlist/english.txt', 'electrum/wordlist'), (home+'electrum/locale', 'electrum/locale'), (home+'electrum/plugins', 'electrum/plugins'), - ('C:\\Program Files (x86)\\ZBar\\bin\\', '.'), (home+'electrum/gui/icons', 'electrum/gui/icons'), ] datas += collect_data_files('trezorlib') (DIR) diff --git a/contrib/build-wine/prepare-wine.sh b/contrib/build-wine/prepare-wine.sh t@@ -5,10 +5,6 @@ NSIS_FILENAME=nsis-3.05-setup.exe NSIS_URL=https://downloads.sourceforge.net/project/nsis/NSIS%203/3.05/$NSIS_FILENAME NSIS_SHA256=1a3cc9401667547b9b9327a177b13485f7c59c2303d4b6183e7bc9e6c8d6bfdb -ZBAR_FILENAME=zbarw-20121031-setup.exe -ZBAR_URL=https://downloads.sourceforge.net/project/zbarw/$ZBAR_FILENAME -ZBAR_SHA256=177e32b272fa76528a3af486b74e9cb356707be1c5ace4ed3fcee9723e2c2c02 - LIBUSB_REPO="https://github.com/libusb/libusb.git" LIBUSB_COMMIT="e782eeb2514266f6738e242cdcb18e3ae1ed06fa" # ^ tag v1.0.23 t@@ -63,11 +59,6 @@ $PYTHON -m pip install --no-dependencies --no-warn-script-location -r "$CONTRIB" info "Installing dependencies specific to binaries." $PYTHON -m pip install --no-dependencies --no-warn-script-location -r "$CONTRIB"/deterministic-build/requirements-binaries.txt -info "Installing ZBar." -download_if_not_exist "$CACHEDIR/$ZBAR_FILENAME" "$ZBAR_URL" -verify_hash "$CACHEDIR/$ZBAR_FILENAME" "$ZBAR_SHA256" -wine "$CACHEDIR/$ZBAR_FILENAME" /S - info "Installing NSIS." download_if_not_exist "$CACHEDIR/$NSIS_FILENAME" "$NSIS_URL" verify_hash "$CACHEDIR/$NSIS_FILENAME" "$NSIS_SHA256" t@@ -101,8 +92,9 @@ info "Compiling libusb..." cp "$CACHEDIR/libusb/libusb/.libs/libusb-1.0.dll" $WINEPREFIX/drive_c/tmp/ || fail "Could not copy libusb to its destination" -# copy libsecp dll (already built) +# copy already built DLLs cp "$PROJECT_ROOT/electrum/libsecp256k1-0.dll" $WINEPREFIX/drive_c/tmp/ || fail "Could not copy libsecp to its destination" +cp "$PROJECT_ROOT/electrum/libzbar-0.dll" $WINEPREFIX/drive_c/tmp/ || fail "Could not copy libzbar to its destination" info "Building PyInstaller." (DIR) diff --git a/contrib/make_libsecp256k1.sh b/contrib/make_libsecp256k1.sh t@@ -34,7 +34,7 @@ info "Building $pkgname..." git fetch --all fi git reset --hard - git clean -f -x -q + git clean -dfxq git checkout "${LIBSECP_VERSION}^{commit}" if ! [ -x configure ] ; then (DIR) diff --git a/contrib/make_zbar.sh b/contrib/make_zbar.sh t@@ -0,0 +1,96 @@ +#!/bin/bash + +# This script can be used on Linux hosts to build native libzbar binaries. +# sudo apt-get install pkg-config libx11-dev libx11-6 libv4l-dev libxv-dev libxext-dev libjpeg-dev +# +# It can also be used to cross-compile to Windows: +# $ sudo apt-get install mingw-w64 mingw-w64-tools win-iconv-mingw-w64-dev +# For a Windows x86 (32-bit) target, run: +# $ GCC_TRIPLET_HOST="i686-w64-mingw32" BUILD_TYPE="wine" ./contrib/make_zbar.sh +# Or for a Windows x86_64 (64-bit) target, run: +# $ GCC_TRIPLET_HOST="x86_64-w64-mingw32" BUILD_TYPE="wine" ./contrib/make_zbar.sh + +ZBAR_VERSION="d2893738411be897a04caa42ffc13d1f6107d3c6" + +set -e + +. $(dirname "$0")/build_tools_util.sh || (echo "Could not source build_tools_util.sh" && exit 1) + +here=$(dirname $(realpath "$0" 2> /dev/null || grealpath "$0")) +CONTRIB="$here" +PROJECT_ROOT="$CONTRIB/.." + +pkgname="zbar" +info "Building $pkgname..." + +( + cd $CONTRIB + if [ ! -d zbar ]; then + git clone https://github.com/mchehab/zbar.git + fi + cd zbar + if ! $(git cat-file -e ${ZBAR_VERSION}) ; then + info "Could not find requested version $ZBAR_VERSION in local clone; fetching..." + git fetch --all + fi + git reset --hard + git clean -dfxq + git checkout "${ZBAR_VERSION}^{commit}" + + if [ "$BUILD_TYPE" = "wine" ] ; then + echo "libzbar_la_LDFLAGS += -Wc,-static" >> zbar/Makefile.am + echo "LDFLAGS += -Wc,-static" >> Makefile.am + fi + if ! [ -x configure ] ; then + autoreconf -vfi || fail "Could not run autoreconf for $pkgname. Please make sure you have automake and libtool installed, and try again." + fi + if ! [ -r config.status ] ; then + if [ "$BUILD_TYPE" = "wine" ] ; then + # windows target + ./configure \ + $AUTOCONF_FLAGS \ + --prefix="$here/$pkgname/dist" \ + --with-x=no \ + --enable-pthread=no \ + --enable-doc=no \ + --enable-video=yes \ + --with-directshow=yes \ + --with-jpeg=no \ + --with-python=no \ + --with-gtk=no \ + --with-qt=no \ + --with-java=no \ + --with-imagemagick=no \ + --with-dbus=no \ + --enable-codes=qrcode \ + --disable-dependency-tracking \ + --disable-static \ + --enable-shared || fail "Could not configure $pkgname. Please make sure you have a C compiler installed and try again." + else + # linux target + ./configure \ + $AUTOCONF_FLAGS \ + --prefix="$here/$pkgname/dist" \ + --with-x=yes \ + --enable-pthread=no \ + --enable-doc=no \ + --enable-video=yes \ + --with-jpeg=yes \ + --with-python=no \ + --with-gtk=no \ + --with-qt=no \ + --with-java=no \ + --with-imagemagick=no \ + --with-dbus=no \ + --enable-codes=qrcode \ + --disable-static \ + --enable-shared || fail "Could not configure $pkgname. Please make sure you have a C compiler installed and try again." + fi + fi + make -j4 || fail "Could not build $pkgname" + make install || fail "Could not install $pkgname" + . "$here/$pkgname/dist/lib/libzbar.la" + host_strip "$here/$pkgname/dist/lib/$dlname" + cp -fpv "$here/$pkgname/dist/lib/$dlname" "$PROJECT_ROOT/electrum" || fail "Could not copy the $pkgname binary to its destination" + info "$dlname has been placed in the inner 'electrum' folder." +) (DIR) diff --git a/electrum/qrscanner.py b/electrum/qrscanner.py t@@ -27,6 +27,12 @@ import os import sys import ctypes +from .logging import get_logger + + +_logger = get_logger(__name__) + + if sys.platform == 'darwin': name = 'libzbar.dylib' elif sys.platform in ('windows', 'win32'): t@@ -35,25 +41,27 @@ else: name = 'libzbar.so.0' try: - libzbar = ctypes.cdll.LoadLibrary(name) -except BaseException: - libzbar = None + libzbar = ctypes.cdll.LoadLibrary(os.path.join(os.path.dirname(__file__), name)) +except BaseException as e1: + try: + libzbar = ctypes.cdll.LoadLibrary(name) + except BaseException as e2: + libzbar = None + if sys.platform != 'darwin': + _logger.error(f"failed to load zbar. exceptions: {[e1,e2]!r}") -def scan_barcode_ctypes(device='', timeout=-1, display=True, threaded=False, try_again=True): +def scan_barcode_ctypes(device='', timeout=-1, display=True, threaded=False): if libzbar is None: raise RuntimeError("Cannot start QR scanner; zbar not available.") libzbar.zbar_symbol_get_data.restype = ctypes.c_char_p libzbar.zbar_processor_create.restype = ctypes.POINTER(ctypes.c_int) libzbar.zbar_processor_get_results.restype = ctypes.POINTER(ctypes.c_int) libzbar.zbar_symbol_set_first_symbol.restype = ctypes.POINTER(ctypes.c_int) + # libzbar.zbar_set_verbosity(100) # verbose logs for debugging proc = libzbar.zbar_processor_create(threaded) libzbar.zbar_processor_request_size(proc, 640, 480) if libzbar.zbar_processor_init(proc, device.encode('utf-8'), display) != 0: - if try_again: - # workaround for a bug in "ZBar for Windows" - # libzbar.zbar_processor_init always seem to fail the first time around - return scan_barcode(device, timeout, display, threaded, try_again=False) raise RuntimeError("Can not start QR scanner; initialization failed.") libzbar.zbar_processor_set_visible(proc) if libzbar.zbar_process_one(proc, timeout):