#!/usr/bin/env bash set -eu ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)" HELPER_DIR="${ROOT_DIR}/tunnel-helper" BUNDLED_DIR="${ROOT_DIR}/src-tauri/bundled" HOST_OS="$(uname -s)" TARGET="${1:-}" if [ -z "${TARGET}" ]; then echo "usage: build-tunnel-helper.sh " exit 1 fi case "${TARGET}" in x86_64-pc-windows-msvc) OUTPUT_DIR="${BUNDLED_DIR}/windows-x64" OUTPUT_NAME="nexavpn-tunnel-helper.exe" ;; aarch64-apple-darwin) OUTPUT_DIR="${BUNDLED_DIR}/macos-arm64" OUTPUT_NAME="nexavpn-tunnel-helper" ;; x86_64-apple-darwin) OUTPUT_DIR="${BUNDLED_DIR}/macos-x64" OUTPUT_NAME="nexavpn-tunnel-helper" ;; *) echo "unsupported target: ${TARGET}" exit 1 ;; esac if [ "${TARGET}" = "x86_64-pc-windows-msvc" ]; then case "${HOST_OS}" in MINGW64_NT*|MSYS_NT*|CYGWIN_NT*) ;; Linux) if ! cargo xwin --version >/dev/null 2>&1; then echo "Linux cross-builds for Windows require cargo-xwin." echo "Install it with:" echo " cargo install --locked cargo-xwin" exit 1 fi ;; *) echo "Windows x64 helper builds are supported on Windows or on Linux with cargo-xwin." echo "Current host: ${HOST_OS}" echo "Install the target with:" echo " rustup target add x86_64-pc-windows-msvc" exit 1 ;; esac fi if [ "${TARGET}" = "aarch64-apple-darwin" ] || [ "${TARGET}" = "x86_64-apple-darwin" ]; then if [ "${HOST_OS}" != "Darwin" ]; then echo "macOS helper builds must run on macOS." echo "Current host: ${HOST_OS}" echo "Use a Mac, then install the target with:" echo " rustup target add ${TARGET}" exit 1 fi fi if ! command -v rustup >/dev/null 2>&1; then echo "rustup is required to verify/install Rust targets." exit 1 fi if ! rustup target list --installed | grep -qx "${TARGET}"; then echo "Rust target ${TARGET} is not installed." echo "Install it with:" echo " rustup target add ${TARGET}" exit 1 fi mkdir -p "${OUTPUT_DIR}" rm -f "${OUTPUT_DIR}/${OUTPUT_NAME}" if [ "${HOST_OS}" = "Linux" ] && [ "${TARGET}" = "x86_64-pc-windows-msvc" ]; then cargo xwin build --manifest-path "${HELPER_DIR}/Cargo.toml" --release --target "${TARGET}" --xwin-arch x86_64 else cargo build --manifest-path "${HELPER_DIR}/Cargo.toml" --release --target "${TARGET}" fi install -m 755 "${HELPER_DIR}/target/${TARGET}/release/${OUTPUT_NAME}" "${OUTPUT_DIR}/${OUTPUT_NAME}" if [ "${TARGET}" = "x86_64-pc-windows-msvc" ]; then if ! command -v curl >/dev/null 2>&1; then echo "curl is required to bundle the official WireGuard Windows MSI." exit 1 fi MSI_URL="${NEXAVPN_WIREGUARD_WINDOWS_MSI_URL:-}" if [ -z "${MSI_URL}" ]; then INDEX_HTML="$(curl -fsSL https://download.wireguard.com/windows-client/)" MSI_NAME="$(printf '%s' "${INDEX_HTML}" | grep -oE 'wireguard-amd64-[0-9.]+\.msi' | sort -uV | tail -n 1)" if [ -z "${MSI_NAME}" ]; then echo "Unable to discover the latest official WireGuard Windows MSI." exit 1 fi MSI_URL="https://download.wireguard.com/windows-client/${MSI_NAME}" fi echo "Bundling WireGuard Windows runtime from ${MSI_URL}" rm -f "${OUTPUT_DIR}/wireguard-installer.msi" curl -fsSL "${MSI_URL}" -o "${OUTPUT_DIR}/wireguard-installer.msi" fi if [ "${TARGET}" = "aarch64-apple-darwin" ] || [ "${TARGET}" = "x86_64-apple-darwin" ]; then WG_BIN="$(command -v wg || true)" WG_QUICK_BIN="$(command -v wg-quick || true)" if [ -z "${WG_BIN}" ] || [ -z "${WG_QUICK_BIN}" ]; then echo "macOS bundle requires wg and wg-quick to be installed on the build machine." echo "Install them with:" echo " brew install wireguard-tools" exit 1 fi rm -f "${OUTPUT_DIR}/wg" "${OUTPUT_DIR}/wg-quick" install -m 755 "$(realpath "${WG_BIN}")" "${OUTPUT_DIR}/wg" install -m 755 "$(realpath "${WG_QUICK_BIN}")" "${OUTPUT_DIR}/wg-quick" chmod -R u+rwX,go+rX "${OUTPUT_DIR}" fi echo "Bundled ${OUTPUT_NAME} into ${OUTPUT_DIR}"