build-electrum-git.sh (3665B)
1 #!/bin/bash 2 3 NAME_ROOT=electrum 4 5 export PYTHONDONTWRITEBYTECODE=1 6 7 8 # Let's begin! 9 set -e 10 11 . "$CONTRIB"/build_tools_util.sh 12 13 pushd $WINEPREFIX/drive_c/electrum 14 15 VERSION=`git describe --tags --dirty --always` 16 info "Last commit: $VERSION" 17 18 # Load electrum-locale for this release 19 git submodule update --init 20 21 pushd ./contrib/deterministic-build/electrum-locale 22 if ! which msgfmt > /dev/null 2>&1; then 23 fail "Please install gettext" 24 fi 25 for i in ./locale/*; do 26 dir=$WINEPREFIX/drive_c/electrum/electrum/$i/LC_MESSAGES 27 mkdir -p $dir 28 msgfmt --output-file=$dir/electrum.mo $i/electrum.po || true 29 done 30 popd 31 32 find -exec touch -d '2000-11-11T11:11:11+00:00' {} + 33 popd 34 35 36 # Install frozen dependencies 37 $WINE_PYTHON -m pip install --no-dependencies --no-warn-script-location \ 38 --cache-dir "$WINE_PIP_CACHE_DIR" -r "$CONTRIB"/deterministic-build/requirements.txt 39 40 $WINE_PYTHON -m pip install --no-dependencies --no-warn-script-location \ 41 --cache-dir "$WINE_PIP_CACHE_DIR" -r "$CONTRIB"/deterministic-build/requirements-binaries.txt 42 43 $WINE_PYTHON -m pip install --no-dependencies --no-warn-script-location \ 44 --cache-dir "$WINE_PIP_CACHE_DIR" -r "$CONTRIB"/deterministic-build/requirements-hw.txt 45 46 pushd $WINEPREFIX/drive_c/electrum 47 # see https://github.com/pypa/pip/issues/2195 -- pip makes a copy of the entire directory 48 info "Pip installing Electrum. This might take a long time if the project folder is large." 49 $WINE_PYTHON -m pip install --no-dependencies --no-warn-script-location . 50 popd 51 52 53 rm -rf dist/ 54 55 # build standalone and portable versions 56 info "Running pyinstaller..." 57 wine "$WINE_PYHOME/scripts/pyinstaller.exe" --noconfirm --ascii --clean --name $NAME_ROOT-$VERSION -w deterministic.spec 58 59 # set timestamps in dist, in order to make the installer reproducible 60 pushd dist 61 find -exec touch -d '2000-11-11T11:11:11+00:00' {} + 62 popd 63 64 info "building NSIS installer" 65 # $VERSION could be passed to the electrum.nsi script, but this would require some rewriting in the script itself. 66 wine "$WINEPREFIX/drive_c/Program Files (x86)/NSIS/makensis.exe" /DPRODUCT_VERSION=$VERSION electrum.nsi 67 68 cd dist 69 mv electrum-setup.exe $NAME_ROOT-$VERSION-setup.exe 70 cd .. 71 72 info "Padding binaries to 8-byte boundaries, and fixing COFF image checksum in PE header" 73 # note: 8-byte boundary padding is what osslsigncode uses: 74 # https://github.com/mtrojnar/osslsigncode/blob/6c8ec4427a0f27c145973450def818e35d4436f6/osslsigncode.c#L3047 75 ( 76 cd dist 77 for binary_file in ./*.exe; do 78 info ">> fixing $binary_file..." 79 # code based on https://github.com/erocarrera/pefile/blob/bbf28920a71248ed5c656c81e119779c131d9bd4/pefile.py#L5877 80 python3 <<EOF 81 pe_file = "$binary_file" 82 with open(pe_file, "rb") as f: 83 binary = bytearray(f.read()) 84 pe_offset = int.from_bytes(binary[0x3c:0x3c+4], byteorder="little") 85 checksum_offset = pe_offset + 88 86 checksum = 0 87 88 # Pad data to 8-byte boundary. 89 remainder = len(binary) % 8 90 binary += bytes(8 - remainder) 91 92 for i in range(len(binary) // 4): 93 if i == checksum_offset // 4: # Skip the checksum field 94 continue 95 dword = int.from_bytes(binary[i*4:i*4+4], byteorder="little") 96 checksum = (checksum & 0xffffffff) + dword + (checksum >> 32) 97 if checksum > 2 ** 32: 98 checksum = (checksum & 0xffffffff) + (checksum >> 32) 99 100 checksum = (checksum & 0xffff) + (checksum >> 16) 101 checksum = (checksum) + (checksum >> 16) 102 checksum = checksum & 0xffff 103 checksum += len(binary) 104 105 # Set the checksum 106 binary[checksum_offset : checksum_offset + 4] = int.to_bytes(checksum, byteorder="little", length=4) 107 108 with open(pe_file, "wb") as f: 109 f.write(binary) 110 EOF 111 done 112 ) 113 114 sha256sum dist/electrum*.exe