|
| 1 | +#!/usr/bin/env bash |
| 2 | +# Copyright (c) Stack Wallet developers |
| 3 | +# Distributed under the MIT software license, see the accompanying |
| 4 | +# file COPYING or https://opensource.org/licenses/MIT. |
| 5 | +# |
| 6 | +# guix-build — Outer orchestrator for reproducible Stack Wallet builds. |
| 7 | +# |
| 8 | +# Usage: ./guix-build [--app stack_wallet|stack_duo|campfire] |
| 9 | +# [--jobs N] |
| 10 | +# [--version X.Y.Z] |
| 11 | +# [--build-number NNN] |
| 12 | + |
| 13 | +set -euo pipefail |
| 14 | + |
| 15 | +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" |
| 16 | +source "${SCRIPT_DIR}/libexec/prelude.bash" |
| 17 | + |
| 18 | +################ |
| 19 | +# CLI args # |
| 20 | +################ |
| 21 | + |
| 22 | +while [ $# -gt 0 ]; do |
| 23 | + case "$1" in |
| 24 | + --app) APP_NAME_ID="$2"; shift 2 ;; |
| 25 | + --jobs) JOBS="$2"; shift 2 ;; |
| 26 | + --version) APP_VERSION="$2"; shift 2 ;; |
| 27 | + --build-number) APP_BUILD_NUMBER="$2"; shift 2 ;; |
| 28 | + --hosts) HOSTS="$2"; shift 2 ;; |
| 29 | + --help|-h) |
| 30 | + echo "Usage: guix-build [--app NAME] [--jobs N] [--version X.Y.Z] [--build-number NNN]" |
| 31 | + exit 0 |
| 32 | + ;; |
| 33 | + *) die "Unknown option: $1" ;; |
| 34 | + esac |
| 35 | +done |
| 36 | + |
| 37 | +auto_detect_version |
| 38 | +compute_source_date_epoch |
| 39 | + |
| 40 | +# Compute commit hash outside the container (source .git is not mounted). |
| 41 | +if [ -d "${SOURCE_DIR}/.git" ]; then |
| 42 | + BUILT_COMMIT_HASH="$(git -C "${SOURCE_DIR}" log -1 --pretty=format:"%H")" |
| 43 | +else |
| 44 | + BUILT_COMMIT_HASH="0000000000000000000000000000000000000000" |
| 45 | +fi |
| 46 | + |
| 47 | +export APP_NAME_ID APP_VERSION APP_BUILD_NUMBER JOBS SOURCE_DATE_EPOCH BUILT_COMMIT_HASH |
| 48 | + |
| 49 | +################ |
| 50 | +# Validate # |
| 51 | +################ |
| 52 | + |
| 53 | +log_info "=== Stack Wallet Guix Build ===" |
| 54 | +log_info "App: ${APP_NAME_ID}" |
| 55 | +log_info "Version: ${APP_VERSION}+${APP_BUILD_NUMBER}" |
| 56 | +log_info "Jobs: ${JOBS}" |
| 57 | +log_info "Hosts: ${HOSTS}" |
| 58 | +log_info "Source: ${SOURCE_DIR}" |
| 59 | +log_info "SOURCE_DATE_EPOCH: ${SOURCE_DATE_EPOCH}" |
| 60 | +log_info "Output: ${OUTDIR}" |
| 61 | + |
| 62 | +# Verify pre-fetched caches exist. |
| 63 | +for cache_dir in "$PUB_CACHE_DIR" "$CARGO_CACHE_DIR" "$FLUTTER_SDK_DIR" "$RUST_DIR" "${BASE_CACHE}/native-sources"; do |
| 64 | + if [ ! -d "$cache_dir" ]; then |
| 65 | + die "Missing cache directory: ${cache_dir} |
| 66 | +Run supplementary/deps/fetch-pub-deps.sh and fetch-cargo-deps.sh first." |
| 67 | + fi |
| 68 | +done |
| 69 | + |
| 70 | +# Verify Flutter SDK is present. |
| 71 | +if [ ! -x "${FLUTTER_SDK_DIR}/flutter/bin/flutter" ]; then |
| 72 | + die "Flutter SDK not found at ${FLUTTER_SDK_DIR}/flutter" |
| 73 | +fi |
| 74 | + |
| 75 | +# Verify at least the default Rust toolchain. |
| 76 | +if [ ! -x "${RUST_DIR}/${RUST_VERSION_DEFAULT}/bin/rustc" ]; then |
| 77 | + die "Rust ${RUST_VERSION_DEFAULT} not found at ${RUST_DIR}/${RUST_VERSION_DEFAULT}" |
| 78 | +fi |
| 79 | + |
| 80 | +# Verify source directory. |
| 81 | +if [ ! -f "${SOURCE_DIR}/pubspec.yaml" ]; then |
| 82 | + die "Source directory does not look like a Stack Wallet checkout: ${SOURCE_DIR}" |
| 83 | +fi |
| 84 | + |
| 85 | +################ |
| 86 | +# Build loop # |
| 87 | +################ |
| 88 | + |
| 89 | +mkdir -p "$OUTDIR" |
| 90 | + |
| 91 | +for HOST in $HOSTS; do |
| 92 | + log_info "--- Building for ${HOST} ---" |
| 93 | + |
| 94 | + HOST_OUTDIR="${OUTDIR}/${HOST}" |
| 95 | + mkdir -p "$HOST_OUTDIR" |
| 96 | + |
| 97 | + # NOTE: guix shell --container --pure strips the environment. |
| 98 | + # We use env inside the container to inject required variables. |
| 99 | + # The guix scripts tree is mounted at /sw/guix since it lives |
| 100 | + # outside the main source directory. |
| 101 | + guix shell \ |
| 102 | + --container \ |
| 103 | + --pure \ |
| 104 | + --emulate-fhs \ |
| 105 | + --manifest="${SCRIPT_DIR}/manifest.scm" \ |
| 106 | + --expose="${SOURCE_DIR}=/sw/src" \ |
| 107 | + --expose="${SCRIPT_DIR}=/sw/guix" \ |
| 108 | + --share="${HOST_OUTDIR}=/sw/output" \ |
| 109 | + --share="${PUB_CACHE_DIR}=/sw/pub-cache" \ |
| 110 | + --expose="${CARGO_CACHE_DIR}=/sw/cargo-cache" \ |
| 111 | + --share="${FLUTTER_SDK_DIR}=/sw/flutter-sdk" \ |
| 112 | + --expose="${RUST_DIR}=/sw/rust" \ |
| 113 | + --expose="${BASE_CACHE}/native-sources=/sw/native-sources" \ |
| 114 | + --no-cwd \ |
| 115 | + -- env \ |
| 116 | + HOME="/tmp" \ |
| 117 | + HOST="$HOST" \ |
| 118 | + JOBS="$JOBS" \ |
| 119 | + SOURCE_DATE_EPOCH="$SOURCE_DATE_EPOCH" \ |
| 120 | + APP_NAME_ID="$APP_NAME_ID" \ |
| 121 | + APP_VERSION="$APP_VERSION" \ |
| 122 | + APP_BUILD_NUMBER="$APP_BUILD_NUMBER" \ |
| 123 | + RUST_VERSION_DEFAULT="$RUST_VERSION_DEFAULT" \ |
| 124 | + RUST_VERSION_MWC="$RUST_VERSION_MWC" \ |
| 125 | + RUST_VERSION_FROSTDART="$RUST_VERSION_FROSTDART" \ |
| 126 | + BUILT_COMMIT_HASH="$BUILT_COMMIT_HASH" \ |
| 127 | + bash /sw/guix/libexec/build.sh \ |
| 128 | + 2>&1 | tee "${HOST_OUTDIR}/build.log" \ |
| 129 | + || die "Build failed for ${HOST}. See ${HOST_OUTDIR}/build.log" |
| 130 | + |
| 131 | + log_info "Build complete for ${HOST}" |
| 132 | + log_info "Output: ${HOST_OUTDIR}" |
| 133 | +done |
| 134 | + |
| 135 | +################ |
| 136 | +# Summary # |
| 137 | +################ |
| 138 | + |
| 139 | +log_info "=== All builds complete ===" |
| 140 | +log_info "Output directory: ${OUTDIR}" |
| 141 | + |
| 142 | +# Collect all SHA256SUMS.part files. |
| 143 | +SUMS_FILE="${OUTDIR}/SHA256SUMS" |
| 144 | +: > "$SUMS_FILE" |
| 145 | +for HOST in $HOSTS; do |
| 146 | + PART="${OUTDIR}/${HOST}/SHA256SUMS.part" |
| 147 | + if [ -f "$PART" ]; then |
| 148 | + cat "$PART" >> "$SUMS_FILE" |
| 149 | + fi |
| 150 | +done |
| 151 | + |
| 152 | +if [ -s "$SUMS_FILE" ]; then |
| 153 | + log_info "Combined SHA256SUMS:" |
| 154 | + cat "$SUMS_FILE" |
| 155 | +fi |
0 commit comments