Installer: add cross-compiled Qt wallet support (win64, win32, armhf, aarch64) with --qt-target; update tests and docs
This commit is contained in:
@@ -0,0 +1,166 @@
|
|||||||
|
Installer (Ubuntu)
|
||||||
|
==================
|
||||||
|
|
||||||
|
Overview
|
||||||
|
---------------------
|
||||||
|
The Agrarian installer is `installer/agrarian-installer.sh`. It automates the Ubuntu build steps by:
|
||||||
|
|
||||||
|
- Building the deterministic `depends/` prefix (`make -C depends HOST=... USE_WALLET=... -j...`).
|
||||||
|
- Configuring the project with the depends `config.site` and prefix.
|
||||||
|
- Building the daemon and CLI utilities (via `--action daemon` or `--action all`).
|
||||||
|
- Building the Qt wallet on Linux hosts (via `--action qt`, or `--action all` when Qt is enabled).
|
||||||
|
- Cross-compiling Qt wallets for Windows and Linux ARM targets (via `--action qt --qt-target ...`).
|
||||||
|
|
||||||
|
It does not:
|
||||||
|
|
||||||
|
- Install system packages (it only checks for required toolchains and prints an `apt-get` command if missing).
|
||||||
|
- Run `make install` or copy binaries into `/usr/local`.
|
||||||
|
- Package platform installers (e.g., Windows/macOS/ARM Qt wallet bundles).
|
||||||
|
- Run or configure the daemon after the build.
|
||||||
|
|
||||||
|
Quick Start (Ubuntu/Debian)
|
||||||
|
---------------------
|
||||||
|
Clone the repo and enter it (standard `git clone` workflow), then:
|
||||||
|
|
||||||
|
Show installer help:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./installer/agrarian-installer.sh --help
|
||||||
|
```
|
||||||
|
|
||||||
|
Build the daemon (runs depends, configure, then `make -C src agrariand`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./installer/agrarian-installer.sh --action daemon
|
||||||
|
```
|
||||||
|
|
||||||
|
Build the Qt wallet on Linux (runs depends Qt target when `HOST` is Linux, then `make -C src/qt agrarian-qt`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./installer/agrarian-installer.sh --action qt
|
||||||
|
```
|
||||||
|
|
||||||
|
Build Qt wallets for cross targets (examples):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./installer/agrarian-installer.sh --action qt --qt-target win64
|
||||||
|
./installer/agrarian-installer.sh --action qt --qt-target win32
|
||||||
|
./installer/agrarian-installer.sh --action qt --qt-target armhf
|
||||||
|
./installer/agrarian-installer.sh --action qt --qt-target aarch64
|
||||||
|
./installer/agrarian-installer.sh --action qt --qt-target all
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected outputs:
|
||||||
|
|
||||||
|
- Depends prefix: `depends/<host-triplet>/`
|
||||||
|
- Daemon: `src/agrariand`
|
||||||
|
- CLI utilities (when using `--action all` or a full top-level build): `src/agrarian-cli`, `src/agrarian-tx`
|
||||||
|
- Qt wallet (Linux): `src/qt/agrarian-qt`
|
||||||
|
- Qt wallet (Windows): `src/qt/agrarian-qt.exe`
|
||||||
|
|
||||||
|
Run the daemon:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./src/agrariand
|
||||||
|
```
|
||||||
|
|
||||||
|
Common Installer Options
|
||||||
|
---------------------
|
||||||
|
`--action <depends|daemon|qt|all>`
|
||||||
|
|
||||||
|
- `depends` builds only the `depends/` prefix.
|
||||||
|
- `daemon` builds the daemon (`src/agrariand`). If depends are missing, the installer builds them first.
|
||||||
|
- `qt` builds the Qt wallet (`src/qt/agrarian-qt`). If depends are missing, the installer builds them first.
|
||||||
|
- `all` builds depends and then runs top-level `make` in the repo root.
|
||||||
|
|
||||||
|
`--qt-target <native|win64|win32|armhf|aarch64|all>`
|
||||||
|
|
||||||
|
- `native` uses `--host` as-is (default).
|
||||||
|
- `win64` maps to `x86_64-w64-mingw32`.
|
||||||
|
- `win32` maps to `i686-w64-mingw32`.
|
||||||
|
- `armhf` maps to `arm-linux-gnueabihf`.
|
||||||
|
- `aarch64` maps to `aarch64-unknown-linux-gnu`.
|
||||||
|
- `all` builds native + all cross targets listed above.
|
||||||
|
|
||||||
|
`--host <triplet>`
|
||||||
|
|
||||||
|
- Sets the build host triplet (default: `x86_64-pc-linux-gnu`).
|
||||||
|
- Passed to `depends` as `HOST=<triplet>`.
|
||||||
|
|
||||||
|
`--wallet <0|1>`
|
||||||
|
|
||||||
|
- Controls wallet support.
|
||||||
|
- Passed to `depends` as `USE_WALLET=<0|1>`.
|
||||||
|
- When `--wallet 0`, the installer also adds `--disable-wallet` during `configure`.
|
||||||
|
|
||||||
|
`--dry-run`
|
||||||
|
|
||||||
|
- Prints the commands the installer would run, without executing them.
|
||||||
|
|
||||||
|
`NO_QT=1` in depends
|
||||||
|
|
||||||
|
- The installer does not expose `NO_QT`.
|
||||||
|
- If you need to skip Qt in depends, run it manually:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make -C depends HOST=x86_64-pc-linux-gnu NO_QT=1
|
||||||
|
```
|
||||||
|
|
||||||
|
Troubleshooting
|
||||||
|
---------------------
|
||||||
|
Boost library naming/layout (the `-mt` suffix)
|
||||||
|
|
||||||
|
- Depends builds may produce Boost libs with suffixes like `libboost_thread-gcc-mt-1_64.a`.
|
||||||
|
- The installer checks for `libboost_thread*.a` and `libboost_system*.a`, so it tolerates `-mt` and versioned names.
|
||||||
|
- If you are configuring manually, keep `--with-boost=<depends-prefix>` (the installer sets this for you) to avoid system Boost fallback.
|
||||||
|
|
||||||
|
`config.site` and PATH pitfalls
|
||||||
|
|
||||||
|
- The installer configures with `CONFIG_SITE=depends/<host>/share/config.site`.
|
||||||
|
- That `config.site` prepends `depends/<host>/native/bin` to `PATH`. Do not overwrite `PATH` with a minimal value; ensure `/usr/bin` and other system paths remain available.
|
||||||
|
- If `config.site` is missing, rebuild depends:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./installer/agrarian-installer.sh --action depends
|
||||||
|
```
|
||||||
|
|
||||||
|
Qt pkg-config files missing in the depends prefix
|
||||||
|
|
||||||
|
The installer requires these `.pc` files in `depends/<host>/(lib|share)/pkgconfig`:
|
||||||
|
|
||||||
|
- `Qt5Core.pc`
|
||||||
|
- `Qt5Gui.pc`
|
||||||
|
- `Qt5Network.pc`
|
||||||
|
- `Qt5Widgets.pc`
|
||||||
|
|
||||||
|
Fix by rebuilding depends with Qt enabled:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./installer/agrarian-installer.sh --action qt
|
||||||
|
```
|
||||||
|
|
||||||
|
Forcing rebuilds
|
||||||
|
|
||||||
|
- Use `--reset-depends` to delete `depends/work`, `depends/built`, and `depends/<host>`, then re-run the installer action you need.
|
||||||
|
- If you need a fresh depends build without deleting the prefix, re-run the depends build (same command the installer prints on failure):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make -C depends HOST=<host> USE_WALLET=<wallet> -j<JOBS>
|
||||||
|
```
|
||||||
|
|
||||||
|
Qt Cross-Compilation Packages (Ubuntu/Debian)
|
||||||
|
---------------------
|
||||||
|
Install the common Linux build tools (from `depends/README.md`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt-get install make automake cmake curl g++-multilib libtool binutils-gold bsdmainutils pkg-config python3 patch
|
||||||
|
```
|
||||||
|
|
||||||
|
Then install toolchains per target:
|
||||||
|
|
||||||
|
- win64: `g++-mingw-w64-x86-64` (see `doc/build-windows.md`)
|
||||||
|
- win32: `g++-mingw-w64-i686` (see `doc/build-windows.md`)
|
||||||
|
- armhf: `g++-arm-linux-gnueabihf` and `binutils-arm-linux-gnueabihf`
|
||||||
|
- aarch64: `g++-aarch64-linux-gnu` and `binutils-aarch64-linux-gnu`
|
||||||
|
|
||||||
|
If any toolchain binaries are missing, the installer prints a single `apt-get install` command that includes the required packages for the selected Qt targets.
|
||||||
+304
-24
@@ -6,6 +6,7 @@ REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
|||||||
|
|
||||||
HOST="x86_64-pc-linux-gnu"
|
HOST="x86_64-pc-linux-gnu"
|
||||||
ACTION="all"
|
ACTION="all"
|
||||||
|
QT_TARGET="native"
|
||||||
WALLET="1"
|
WALLET="1"
|
||||||
JOBS="$(nproc)"
|
JOBS="$(nproc)"
|
||||||
DO_UPDATE=0
|
DO_UPDATE=0
|
||||||
@@ -13,6 +14,8 @@ RESET_DEPENDS=0
|
|||||||
ASSUME_YES=0
|
ASSUME_YES=0
|
||||||
USER_LOG_PATH=""
|
USER_LOG_PATH=""
|
||||||
TEST_MODE="${AGRARIAN_INSTALLER_TEST_MODE:-0}"
|
TEST_MODE="${AGRARIAN_INSTALLER_TEST_MODE:-0}"
|
||||||
|
DRY_RUN="0"
|
||||||
|
SUPPORTED_HOSTS=()
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
cat <<'USAGE'
|
cat <<'USAGE'
|
||||||
@@ -24,12 +27,15 @@ Options:
|
|||||||
--host <triplet> Build host triplet (default: x86_64-pc-linux-gnu)
|
--host <triplet> Build host triplet (default: x86_64-pc-linux-gnu)
|
||||||
--action <depends|daemon|qt|all>
|
--action <depends|daemon|qt|all>
|
||||||
Action to run (default: all)
|
Action to run (default: all)
|
||||||
|
--qt-target <native|win64|win32|armhf|aarch64|all>
|
||||||
|
Qt wallet target (default: native)
|
||||||
--wallet <0|1> Enable wallet-related dependencies/build flags (default: 1)
|
--wallet <0|1> Enable wallet-related dependencies/build flags (default: 1)
|
||||||
--jobs <n> Parallel build jobs (default: nproc)
|
--jobs <n> Parallel build jobs (default: nproc)
|
||||||
--update Run git pull --rebase before build
|
--update Run git pull --rebase before build
|
||||||
--reset-depends Remove depends/work, depends/built, depends/<host>
|
--reset-depends Remove depends/work, depends/built, depends/<host>
|
||||||
--yes Assume yes for prompts
|
--yes Assume yes for prompts
|
||||||
--log <path> Log output path
|
--log <path> Log output path
|
||||||
|
--dry-run Print commands without executing them
|
||||||
-h, --help Show this help
|
-h, --help Show this help
|
||||||
USAGE
|
USAGE
|
||||||
}
|
}
|
||||||
@@ -39,6 +45,12 @@ fail() {
|
|||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
join_by() {
|
||||||
|
local IFS="$1"
|
||||||
|
shift
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
check_ubuntu() {
|
check_ubuntu() {
|
||||||
if [[ ! -r /etc/os-release ]]; then
|
if [[ ! -r /etc/os-release ]]; then
|
||||||
fail "Cannot verify OS (missing /etc/os-release); Ubuntu is required"
|
fail "Cannot verify OS (missing /etc/os-release); Ubuntu is required"
|
||||||
@@ -71,13 +83,110 @@ confirm() {
|
|||||||
|
|
||||||
run_cmd() {
|
run_cmd() {
|
||||||
echo "+ $*"
|
echo "+ $*"
|
||||||
if [[ "$TEST_MODE" == "1" ]]; then
|
if is_dry_run; then
|
||||||
echo "[test-mode] skipped"
|
echo "[dry-run] skipped"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
"$@"
|
"$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
detect_supported_hosts() {
|
||||||
|
local host_dir="${REPO_ROOT}/depends/hosts"
|
||||||
|
local name
|
||||||
|
local skip
|
||||||
|
local generic
|
||||||
|
local known_generics=("default" "linux" "mingw32" "darwin")
|
||||||
|
|
||||||
|
[[ -d "${host_dir}" ]] || fail "Missing depends hosts directory: ${host_dir}"
|
||||||
|
|
||||||
|
SUPPORTED_HOSTS=()
|
||||||
|
for path in "${host_dir}"/*.mk; do
|
||||||
|
[[ -f "${path}" ]] || continue
|
||||||
|
name="$(basename "${path}" .mk)"
|
||||||
|
skip=0
|
||||||
|
for generic in "${known_generics[@]}"; do
|
||||||
|
if [[ "${name}" == "${generic}" ]]; then
|
||||||
|
skip=1
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
(( skip == 0 )) && SUPPORTED_HOSTS+=("${name}")
|
||||||
|
done
|
||||||
|
|
||||||
|
((${#SUPPORTED_HOSTS[@]} > 0)) || fail "No supported host definitions found in ${host_dir}"
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_supported_host() {
|
||||||
|
local host="$1"
|
||||||
|
local supported
|
||||||
|
supported="$(join_by ", " "${SUPPORTED_HOSTS[@]}")"
|
||||||
|
if [[ ! " ${SUPPORTED_HOSTS[*]} " =~ [[:space:]]${host}[[:space:]] ]]; then
|
||||||
|
fail "Unsupported host '${host}'. Supported hosts: ${supported}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
add_missing_toolchain() {
|
||||||
|
local tool="$1"
|
||||||
|
local package="$2"
|
||||||
|
|
||||||
|
if ! command -v "${tool}" >/dev/null 2>&1; then
|
||||||
|
MISSING_TOOLS+=("${tool}")
|
||||||
|
MISSING_PACKAGES+=("${package}")
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
check_toolchains_for_host() {
|
||||||
|
local host="$1"
|
||||||
|
case "${host}" in
|
||||||
|
x86_64-w64-mingw32)
|
||||||
|
add_missing_toolchain "x86_64-w64-mingw32-g++" "g++-mingw-w64-x86-64"
|
||||||
|
;;
|
||||||
|
i686-w64-mingw32)
|
||||||
|
add_missing_toolchain "i686-w64-mingw32-g++" "g++-mingw-w64-i686"
|
||||||
|
;;
|
||||||
|
arm-linux-gnueabihf)
|
||||||
|
add_missing_toolchain "arm-linux-gnueabihf-g++" "g++-arm-linux-gnueabihf"
|
||||||
|
add_missing_toolchain "arm-linux-gnueabihf-ar" "binutils-arm-linux-gnueabihf"
|
||||||
|
;;
|
||||||
|
aarch64-unknown-linux-gnu)
|
||||||
|
add_missing_toolchain "aarch64-linux-gnu-g++" "g++-aarch64-linux-gnu"
|
||||||
|
add_missing_toolchain "aarch64-linux-gnu-ar" "binutils-aarch64-linux-gnu"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_toolchains_for_hosts() {
|
||||||
|
local hosts=("$@")
|
||||||
|
local unique_packages=()
|
||||||
|
local host
|
||||||
|
local pkg
|
||||||
|
|
||||||
|
MISSING_TOOLS=()
|
||||||
|
MISSING_PACKAGES=()
|
||||||
|
|
||||||
|
for host in "${hosts[@]}"; do
|
||||||
|
check_toolchains_for_host "${host}"
|
||||||
|
done
|
||||||
|
|
||||||
|
if ((${#MISSING_TOOLS[@]} == 0)); then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
for pkg in "${MISSING_PACKAGES[@]}"; do
|
||||||
|
if [[ ! " ${unique_packages[*]} " =~ [[:space:]]${pkg}[[:space:]] ]]; then
|
||||||
|
unique_packages+=("${pkg}")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "ERROR: Missing required cross toolchain binaries:" >&2
|
||||||
|
printf ' - %s\n' "${MISSING_TOOLS[@]}" >&2
|
||||||
|
echo "Install with:" >&2
|
||||||
|
echo " sudo apt-get update && sudo apt-get install -y $(join_by " " "${unique_packages[@]}")" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
ensure_configure() {
|
ensure_configure() {
|
||||||
if [[ ! -x "${REPO_ROOT}/configure" ]]; then
|
if [[ ! -x "${REPO_ROOT}/configure" ]]; then
|
||||||
run_cmd "${REPO_ROOT}/autogen.sh"
|
run_cmd "${REPO_ROOT}/autogen.sh"
|
||||||
@@ -98,17 +207,27 @@ reset_depends_paths() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
build_depends() {
|
build_depends() {
|
||||||
local args=("HOST=${HOST}" "-j${JOBS}")
|
local host="$1"
|
||||||
if [[ "$WALLET" == "0" ]]; then
|
local args=("HOST=${host}" "USE_WALLET=${WALLET}" "-j${JOBS}")
|
||||||
args+=("USE_WALLET=0")
|
run_cmd make -C "${REPO_ROOT}/depends" "${args[@]}"
|
||||||
fi
|
}
|
||||||
|
|
||||||
|
build_depends_qt() {
|
||||||
|
local host="$1"
|
||||||
|
local args=("HOST=${host}" "USE_WALLET=${WALLET}" "-j${JOBS}" "qt")
|
||||||
run_cmd make -C "${REPO_ROOT}/depends" "${args[@]}"
|
run_cmd make -C "${REPO_ROOT}/depends" "${args[@]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
ensure_depends_prereqs() {
|
ensure_depends_prereqs() {
|
||||||
local prefix="${REPO_ROOT}/depends/${HOST}"
|
local host="$1"
|
||||||
|
local prefix="${REPO_ROOT}/depends/${host}"
|
||||||
local missing=()
|
local missing=()
|
||||||
|
|
||||||
|
if is_dry_run; then
|
||||||
|
echo "[dry-run] skipping depends prefix checks for ${host}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
[[ -f "${prefix}/share/config.site" ]] || missing+=("${prefix}/share/config.site")
|
[[ -f "${prefix}/share/config.site" ]] || missing+=("${prefix}/share/config.site")
|
||||||
[[ -f "${prefix}/include/boost/thread.hpp" ]] || missing+=("${prefix}/include/boost/thread.hpp")
|
[[ -f "${prefix}/include/boost/thread.hpp" ]] || missing+=("${prefix}/include/boost/thread.hpp")
|
||||||
|
|
||||||
@@ -127,41 +246,172 @@ ensure_depends_prereqs() {
|
|||||||
if (( ${#missing[@]} > 0 )); then
|
if (( ${#missing[@]} > 0 )); then
|
||||||
echo "ERROR: depends prefix is missing required files:" >&2
|
echo "ERROR: depends prefix is missing required files:" >&2
|
||||||
printf ' - %s\n' "${missing[@]}" >&2
|
printf ' - %s\n' "${missing[@]}" >&2
|
||||||
echo "Fix: make -C ${REPO_ROOT}/depends HOST=${HOST} USE_WALLET=${WALLET} -j${JOBS}" >&2
|
echo "Fix: make -C ${REPO_ROOT}/depends HOST=${host} USE_WALLET=${WALLET} -j${JOBS}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_qt_pkgconfig_prereqs() {
|
||||||
|
local host="$1"
|
||||||
|
local prefix="${REPO_ROOT}/depends/${host}"
|
||||||
|
local missing=()
|
||||||
|
local module
|
||||||
|
local found_path
|
||||||
|
|
||||||
|
if is_dry_run; then
|
||||||
|
echo "[dry-run] skipping Qt pkg-config checks for ${host}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
for module in Qt5Core Qt5Gui Qt5Network Qt5Widgets; do
|
||||||
|
found_path=""
|
||||||
|
if [[ -f "${prefix}/lib/pkgconfig/${module}.pc" ]]; then
|
||||||
|
found_path="${prefix}/lib/pkgconfig/${module}.pc"
|
||||||
|
elif [[ -f "${prefix}/share/pkgconfig/${module}.pc" ]]; then
|
||||||
|
found_path="${prefix}/share/pkgconfig/${module}.pc"
|
||||||
|
fi
|
||||||
|
[[ -n "${found_path}" ]] || missing+=("${module}.pc in ${prefix}/(lib|share)/pkgconfig")
|
||||||
|
done
|
||||||
|
|
||||||
|
if (( ${#missing[@]} > 0 )); then
|
||||||
|
echo "ERROR: Qt pkg-config files are missing from depends prefix:" >&2
|
||||||
|
printf ' - %s\n' "${missing[@]}" >&2
|
||||||
|
echo "Fix: make -C ${REPO_ROOT}/depends HOST=${host} USE_WALLET=${WALLET} -j${JOBS} qt" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
configure_project() {
|
configure_project() {
|
||||||
local mode="$1"
|
local mode="$1"
|
||||||
local config_site="${REPO_ROOT}/depends/${HOST}/share/config.site"
|
local host="$2"
|
||||||
local cfg_args=("--prefix=${REPO_ROOT}/depends/${HOST}")
|
local config_site="${REPO_ROOT}/depends/${host}/share/config.site"
|
||||||
|
local cfg_args=(
|
||||||
|
"--build=${host}"
|
||||||
|
"--host=${host}"
|
||||||
|
"--prefix=${REPO_ROOT}/depends/${host}"
|
||||||
|
"--with-boost=${REPO_ROOT}/depends/${host}"
|
||||||
|
)
|
||||||
|
|
||||||
[[ "$WALLET" == "0" ]] && cfg_args+=("--disable-wallet")
|
[[ "$WALLET" == "0" ]] && cfg_args+=("--disable-wallet")
|
||||||
[[ "$mode" == "daemon" ]] && cfg_args+=("--without-gui")
|
[[ "$mode" == "daemon" ]] && cfg_args+=("--without-gui")
|
||||||
|
|
||||||
ensure_configure
|
ensure_configure
|
||||||
ensure_depends_prereqs
|
ensure_depends_prereqs "${host}"
|
||||||
run_cmd env CONFIG_SITE="${config_site}" "${REPO_ROOT}/configure" "${cfg_args[@]}"
|
run_cmd env CONFIG_SITE="${config_site}" "${REPO_ROOT}/configure" "${cfg_args[@]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
build_daemon() {
|
build_daemon() {
|
||||||
configure_project daemon
|
configure_project daemon "${HOST}"
|
||||||
run_cmd make -C "${REPO_ROOT}/src" "-j${JOBS}" agrariand
|
run_cmd make -C "${REPO_ROOT}/src" "-j${JOBS}" agrariand
|
||||||
}
|
}
|
||||||
|
|
||||||
build_qt() {
|
qt_target_host() {
|
||||||
configure_project qt
|
local target="$1"
|
||||||
|
case "${target}" in
|
||||||
|
native)
|
||||||
|
echo "${HOST}"
|
||||||
|
;;
|
||||||
|
win64)
|
||||||
|
echo "x86_64-w64-mingw32"
|
||||||
|
;;
|
||||||
|
win32)
|
||||||
|
echo "i686-w64-mingw32"
|
||||||
|
;;
|
||||||
|
armhf)
|
||||||
|
echo "arm-linux-gnueabihf"
|
||||||
|
;;
|
||||||
|
aarch64)
|
||||||
|
echo "aarch64-unknown-linux-gnu"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
qt_target_output() {
|
||||||
|
local host="$1"
|
||||||
|
if [[ "${host}" == *mingw32 ]]; then
|
||||||
|
echo "${REPO_ROOT}/src/qt/agrarian-qt.exe"
|
||||||
|
else
|
||||||
|
echo "${REPO_ROOT}/src/qt/agrarian-qt"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
qt_target_list() {
|
||||||
|
local target="$1"
|
||||||
|
case "${target}" in
|
||||||
|
all)
|
||||||
|
echo "native win64 win32 armhf aarch64"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "${target}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
build_qt_for_host() {
|
||||||
|
local target="$1"
|
||||||
|
local host="$2"
|
||||||
|
local prefix="${REPO_ROOT}/depends/${host}"
|
||||||
|
local output_path
|
||||||
|
|
||||||
|
output_path="$(qt_target_output "${host}")"
|
||||||
|
|
||||||
|
echo "Qt wallet build target:"
|
||||||
|
echo " target: ${target}"
|
||||||
|
echo " host: ${host}"
|
||||||
|
echo " depends prefix: ${prefix}"
|
||||||
|
echo " output: ${output_path}"
|
||||||
|
|
||||||
|
build_depends_qt "${host}"
|
||||||
|
ensure_qt_pkgconfig_prereqs "${host}"
|
||||||
|
configure_project qt "${host}"
|
||||||
run_cmd make -C "${REPO_ROOT}/src/qt" "-j${JOBS}" agrarian-qt
|
run_cmd make -C "${REPO_ROOT}/src/qt" "-j${JOBS}" agrarian-qt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
build_qt() {
|
||||||
|
local target
|
||||||
|
local host
|
||||||
|
local qt_targets
|
||||||
|
local unique_hosts=()
|
||||||
|
local entry
|
||||||
|
|
||||||
|
qt_targets="$(qt_target_list "${QT_TARGET}")"
|
||||||
|
for target in ${qt_targets}; do
|
||||||
|
host="$(qt_target_host "${target}")"
|
||||||
|
if [[ -z "${host}" ]]; then
|
||||||
|
fail "Invalid --qt-target value: ${target}"
|
||||||
|
fi
|
||||||
|
for entry in "${unique_hosts[@]}"; do
|
||||||
|
if [[ "${entry}" == "${host}" ]]; then
|
||||||
|
host=""
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
[[ -n "${host}" ]] && unique_hosts+=("${host}")
|
||||||
|
done
|
||||||
|
|
||||||
|
ensure_toolchains_for_hosts "${unique_hosts[@]}"
|
||||||
|
|
||||||
|
for target in ${qt_targets}; do
|
||||||
|
host="$(qt_target_host "${target}")"
|
||||||
|
build_qt_for_host "${target}" "${host}"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
build_all() {
|
build_all() {
|
||||||
configure_project all
|
configure_project all "${HOST}"
|
||||||
run_cmd make -C "${REPO_ROOT}" "-j${JOBS}"
|
run_cmd make -C "${REPO_ROOT}" "-j${JOBS}"
|
||||||
}
|
}
|
||||||
|
|
||||||
needs_depends() {
|
needs_depends() {
|
||||||
[[ ! -f "${REPO_ROOT}/depends/${HOST}/share/config.site" ]]
|
local host="$1"
|
||||||
|
[[ ! -f "${REPO_ROOT}/depends/${host}/share/config.site" ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
is_dry_run() {
|
||||||
|
[[ "${TEST_MODE}" == "1" || "${DRY_RUN}" == "1" ]]
|
||||||
}
|
}
|
||||||
|
|
||||||
while [[ $# -gt 0 ]]; do
|
while [[ $# -gt 0 ]]; do
|
||||||
@@ -176,6 +426,11 @@ while [[ $# -gt 0 ]]; do
|
|||||||
ACTION="$2"
|
ACTION="$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
|
--qt-target)
|
||||||
|
[[ $# -ge 2 ]] || fail "Missing value for --qt-target"
|
||||||
|
QT_TARGET="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
--wallet)
|
--wallet)
|
||||||
[[ $# -ge 2 ]] || fail "Missing value for --wallet"
|
[[ $# -ge 2 ]] || fail "Missing value for --wallet"
|
||||||
WALLET="$2"
|
WALLET="$2"
|
||||||
@@ -203,6 +458,11 @@ while [[ $# -gt 0 ]]; do
|
|||||||
USER_LOG_PATH="$2"
|
USER_LOG_PATH="$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
|
--dry-run)
|
||||||
|
DRY_RUN=1
|
||||||
|
TEST_MODE=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
-h|--help)
|
-h|--help)
|
||||||
usage
|
usage
|
||||||
exit 0
|
exit 0
|
||||||
@@ -218,6 +478,11 @@ case "$ACTION" in
|
|||||||
*) fail "Invalid --action: ${ACTION}" ;;
|
*) fail "Invalid --action: ${ACTION}" ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
case "$QT_TARGET" in
|
||||||
|
native|win64|win32|armhf|aarch64|all) ;;
|
||||||
|
*) fail "Invalid --qt-target: ${QT_TARGET}" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
case "$WALLET" in
|
case "$WALLET" in
|
||||||
0|1) ;;
|
0|1) ;;
|
||||||
*) fail "Invalid --wallet value: ${WALLET} (expected 0 or 1)" ;;
|
*) fail "Invalid --wallet value: ${WALLET} (expected 0 or 1)" ;;
|
||||||
@@ -241,14 +506,32 @@ echo "Agrarian installer"
|
|||||||
echo " repo: ${REPO_ROOT}"
|
echo " repo: ${REPO_ROOT}"
|
||||||
echo " host: ${HOST}"
|
echo " host: ${HOST}"
|
||||||
echo " action: ${ACTION}"
|
echo " action: ${ACTION}"
|
||||||
|
echo " qt_target: ${QT_TARGET}"
|
||||||
echo " wallet: ${WALLET}"
|
echo " wallet: ${WALLET}"
|
||||||
echo " jobs: ${JOBS}"
|
echo " jobs: ${JOBS}"
|
||||||
echo " update: ${DO_UPDATE}"
|
echo " update: ${DO_UPDATE}"
|
||||||
echo " reset_depends: ${RESET_DEPENDS}"
|
echo " reset_depends: ${RESET_DEPENDS}"
|
||||||
echo " test_mode: ${TEST_MODE}"
|
echo " dry_run: $(is_dry_run && echo 1 || echo 0)"
|
||||||
echo " log: ${LOG_PATH}"
|
echo " log: ${LOG_PATH}"
|
||||||
|
|
||||||
check_ubuntu
|
check_ubuntu
|
||||||
|
detect_supported_hosts
|
||||||
|
|
||||||
|
if [[ "${ACTION}" != "qt" && "${QT_TARGET}" != "native" ]]; then
|
||||||
|
fail "--qt-target is only supported with --action qt"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${ACTION}" == "qt" ]]; then
|
||||||
|
qt_targets="$(qt_target_list "${QT_TARGET}")"
|
||||||
|
for target in ${qt_targets}; do
|
||||||
|
host="$(qt_target_host "${target}")"
|
||||||
|
[[ -n "${host}" ]] || fail "Invalid --qt-target value: ${target}"
|
||||||
|
ensure_supported_host "${host}"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
ensure_supported_host "${HOST}"
|
||||||
|
ensure_toolchains_for_hosts "${HOST}"
|
||||||
|
fi
|
||||||
|
|
||||||
confirm "Proceed with selected installer action?"
|
confirm "Proceed with selected installer action?"
|
||||||
|
|
||||||
@@ -263,22 +546,19 @@ fi
|
|||||||
|
|
||||||
case "$ACTION" in
|
case "$ACTION" in
|
||||||
depends)
|
depends)
|
||||||
build_depends
|
build_depends "${HOST}"
|
||||||
;;
|
;;
|
||||||
daemon)
|
daemon)
|
||||||
if needs_depends; then
|
if needs_depends "${HOST}"; then
|
||||||
build_depends
|
build_depends "${HOST}"
|
||||||
fi
|
fi
|
||||||
build_daemon
|
build_daemon
|
||||||
;;
|
;;
|
||||||
qt)
|
qt)
|
||||||
if needs_depends; then
|
|
||||||
build_depends
|
|
||||||
fi
|
|
||||||
build_qt
|
build_qt
|
||||||
;;
|
;;
|
||||||
all)
|
all)
|
||||||
build_depends
|
build_depends "${HOST}"
|
||||||
build_all
|
build_all
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
+79
-9
@@ -32,6 +32,20 @@ exit 0
|
|||||||
SH
|
SH
|
||||||
chmod +x "${FAKE_BIN}/make"
|
chmod +x "${FAKE_BIN}/make"
|
||||||
|
|
||||||
|
for tool in \
|
||||||
|
x86_64-w64-mingw32-g++ \
|
||||||
|
i686-w64-mingw32-g++ \
|
||||||
|
aarch64-linux-gnu-gcc \
|
||||||
|
aarch64-linux-gnu-g++ \
|
||||||
|
arm-linux-gnueabihf-gcc \
|
||||||
|
arm-linux-gnueabihf-g++; do
|
||||||
|
cat > "${FAKE_BIN}/${tool}" <<'SH'
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
exit 0
|
||||||
|
SH
|
||||||
|
chmod +x "${FAKE_BIN}/${tool}"
|
||||||
|
done
|
||||||
|
|
||||||
assert_file_nonempty() {
|
assert_file_nonempty() {
|
||||||
local path="$1"
|
local path="$1"
|
||||||
local i
|
local i
|
||||||
@@ -45,9 +59,32 @@ assert_file_nonempty() {
|
|||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
seed_fake_depends_prefix() {
|
||||||
|
local host="$1"
|
||||||
|
local prefix="${WORK_REPO}/depends/${host}"
|
||||||
|
mkdir -p "${prefix}/share" "${prefix}/include/boost" "${prefix}/lib" "${prefix}/lib/pkgconfig"
|
||||||
|
: > "${prefix}/share/config.site"
|
||||||
|
: > "${prefix}/include/boost/thread.hpp"
|
||||||
|
: > "${prefix}/include/db_cxx.h"
|
||||||
|
: > "${prefix}/lib/libboost_thread.a"
|
||||||
|
: > "${prefix}/lib/libboost_system.a"
|
||||||
|
: > "${prefix}/lib/pkgconfig/Qt5Core.pc"
|
||||||
|
: > "${prefix}/lib/pkgconfig/Qt5Gui.pc"
|
||||||
|
: > "${prefix}/lib/pkgconfig/Qt5Network.pc"
|
||||||
|
: > "${prefix}/lib/pkgconfig/Qt5Widgets.pc"
|
||||||
|
}
|
||||||
|
|
||||||
echo "[test 1] help output works"
|
echo "[test 1] help output works"
|
||||||
bash "${WORK_REPO}/installer/agrarian-installer.sh" --help > "${LOG_DIR}/help.out"
|
bash "${WORK_REPO}/installer/agrarian-installer.sh" --help > "${LOG_DIR}/help.out"
|
||||||
rg -q -- "--action <depends|daemon|qt|all>" "${LOG_DIR}/help.out"
|
rg -q -- "--action <depends|daemon|qt|all>" "${LOG_DIR}/help.out"
|
||||||
|
rg -q -- "--qt-target <native|win64|win32|armhf|aarch64|all>" "${LOG_DIR}/help.out"
|
||||||
|
rg -q -- "--host <triplet>" "${LOG_DIR}/help.out"
|
||||||
|
rg -q -- "--wallet <0|1>" "${LOG_DIR}/help.out"
|
||||||
|
rg -q -- "--jobs <n>" "${LOG_DIR}/help.out"
|
||||||
|
rg -q -- "--reset-depends" "${LOG_DIR}/help.out"
|
||||||
|
rg -q -- "--update" "${LOG_DIR}/help.out"
|
||||||
|
rg -q -- "--yes" "${LOG_DIR}/help.out"
|
||||||
|
rg -q -- "--dry-run" "${LOG_DIR}/help.out"
|
||||||
|
|
||||||
echo "[test 2] depends build for x86_64-pc-linux-gnu succeeds"
|
echo "[test 2] depends build for x86_64-pc-linux-gnu succeeds"
|
||||||
DEPENDS_LOG="${LOG_DIR}/depends.log"
|
DEPENDS_LOG="${LOG_DIR}/depends.log"
|
||||||
@@ -58,25 +95,42 @@ PATH="${FAKE_BIN}:${PATH}" AGRARIAN_FAKE_MAKE_LOG="${FAKE_MAKE_LOG}" bash "${WOR
|
|||||||
--yes \
|
--yes \
|
||||||
--log "${DEPENDS_LOG}"
|
--log "${DEPENDS_LOG}"
|
||||||
assert_file_nonempty "${DEPENDS_LOG}"
|
assert_file_nonempty "${DEPENDS_LOG}"
|
||||||
rg -q -- "-C ${WORK_REPO}/depends HOST=x86_64-pc-linux-gnu -j2" "${FAKE_MAKE_LOG}"
|
rg -q -- "-C ${WORK_REPO}/depends HOST=x86_64-pc-linux-gnu USE_WALLET=1 -j2" "${FAKE_MAKE_LOG}"
|
||||||
|
|
||||||
echo "[test 3] can run twice with --reset-depends"
|
echo "[test 3] wallet=0 maps to USE_WALLET=0 for depends"
|
||||||
for i in 1 2; do
|
DEPENDS_W0_LOG="${LOG_DIR}/depends-wallet0.log"
|
||||||
RESET_LOG="${LOG_DIR}/reset-${i}.log"
|
PATH="${FAKE_BIN}:${PATH}" AGRARIAN_FAKE_MAKE_LOG="${FAKE_MAKE_LOG}" bash "${WORK_REPO}/installer/agrarian-installer.sh" \
|
||||||
AGRARIAN_INSTALLER_TEST_MODE=1 bash "${WORK_REPO}/installer/agrarian-installer.sh" \
|
--action depends \
|
||||||
|
--host x86_64-pc-linux-gnu \
|
||||||
|
--wallet 0 \
|
||||||
|
--jobs 2 \
|
||||||
|
--yes \
|
||||||
|
--log "${DEPENDS_W0_LOG}"
|
||||||
|
assert_file_nonempty "${DEPENDS_W0_LOG}"
|
||||||
|
rg -q -- "-C ${WORK_REPO}/depends HOST=x86_64-pc-linux-gnu USE_WALLET=0 -j2" "${FAKE_MAKE_LOG}"
|
||||||
|
|
||||||
|
echo "[test 4] reset-depends only removes allowed paths"
|
||||||
|
mkdir -p "${WORK_REPO}/depends/work" "${WORK_REPO}/depends/built" "${WORK_REPO}/depends/x86_64-pc-linux-gnu" "${WORK_REPO}/user-runtime-data"
|
||||||
|
: > "${WORK_REPO}/user-runtime-data/keep-me"
|
||||||
|
RESET_LOG="${LOG_DIR}/reset.log"
|
||||||
|
PATH="${FAKE_BIN}:${PATH}" AGRARIAN_INSTALLER_TEST_MODE=1 bash "${WORK_REPO}/installer/agrarian-installer.sh" \
|
||||||
--action depends \
|
--action depends \
|
||||||
--host x86_64-pc-linux-gnu \
|
--host x86_64-pc-linux-gnu \
|
||||||
--jobs 2 \
|
--jobs 2 \
|
||||||
--reset-depends \
|
--reset-depends \
|
||||||
--yes \
|
--yes \
|
||||||
--log "${RESET_LOG}"
|
--log "${RESET_LOG}"
|
||||||
assert_file_nonempty "${RESET_LOG}"
|
assert_file_nonempty "${RESET_LOG}"
|
||||||
done
|
[[ ! -d "${WORK_REPO}/depends/work" ]]
|
||||||
|
[[ ! -d "${WORK_REPO}/depends/built" ]]
|
||||||
|
[[ ! -d "${WORK_REPO}/depends/x86_64-pc-linux-gnu" ]]
|
||||||
|
[[ -f "${WORK_REPO}/user-runtime-data/keep-me" ]]
|
||||||
|
|
||||||
echo "[test 4] all actions produce logs and return 0"
|
echo "[test 5] all actions produce logs and return 0"
|
||||||
|
seed_fake_depends_prefix "x86_64-pc-linux-gnu"
|
||||||
for action in depends daemon qt all; do
|
for action in depends daemon qt all; do
|
||||||
ACTION_LOG="${LOG_DIR}/${action}.log"
|
ACTION_LOG="${LOG_DIR}/${action}.log"
|
||||||
AGRARIAN_INSTALLER_TEST_MODE=1 bash "${WORK_REPO}/installer/agrarian-installer.sh" \
|
PATH="${FAKE_BIN}:${PATH}" AGRARIAN_INSTALLER_TEST_MODE=1 bash "${WORK_REPO}/installer/agrarian-installer.sh" \
|
||||||
--action "${action}" \
|
--action "${action}" \
|
||||||
--host x86_64-pc-linux-gnu \
|
--host x86_64-pc-linux-gnu \
|
||||||
--jobs 2 \
|
--jobs 2 \
|
||||||
@@ -85,4 +139,20 @@ for action in depends daemon qt all; do
|
|||||||
assert_file_nonempty "${ACTION_LOG}"
|
assert_file_nonempty "${ACTION_LOG}"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
echo "[test 6] dry-run qt win64 prints expected commands"
|
||||||
|
QT_DRY_LOG="${LOG_DIR}/qt-win64-dry.log"
|
||||||
|
PATH="${FAKE_BIN}:${PATH}" bash "${WORK_REPO}/installer/agrarian-installer.sh" \
|
||||||
|
--action qt \
|
||||||
|
--qt-target win64 \
|
||||||
|
--jobs 2 \
|
||||||
|
--yes \
|
||||||
|
--dry-run \
|
||||||
|
--log "${QT_DRY_LOG}"
|
||||||
|
assert_file_nonempty "${QT_DRY_LOG}"
|
||||||
|
rg -q -- "\\+ make -C ${WORK_REPO}/depends HOST=x86_64-w64-mingw32 USE_WALLET=1 -j2 qt" "${QT_DRY_LOG}"
|
||||||
|
rg -q -- "CONFIG_SITE=${WORK_REPO}/depends/x86_64-w64-mingw32/share/config.site" "${QT_DRY_LOG}"
|
||||||
|
rg -q -- "--build=x86_64-w64-mingw32" "${QT_DRY_LOG}"
|
||||||
|
rg -q -- "--host=x86_64-w64-mingw32" "${QT_DRY_LOG}"
|
||||||
|
rg -q -- "\\+ make -C ${WORK_REPO}/src/qt -j2 agrarian-qt" "${QT_DRY_LOG}"
|
||||||
|
|
||||||
echo "All installer tests passed."
|
echo "All installer tests passed."
|
||||||
|
|||||||
Reference in New Issue
Block a user