#!/usr/bin/env bash # # Rebuild the vendored Tailscale core when the Go source is newer than the built artefact. # # . scripts/ensure-core.sh ios # or: android # # WHY THIS EXISTS # # Changing modules/officer-net/gocore requires rebuilding the core by hand, per platform, and nothing # enforces it. Forgetting is silent until link or compile time, and the error names a symbol rather # than the cause: # # Android e: Unresolved reference 'loginTo' # iOS error: cannot find 'TailcoreSubnetRoutes' in scope # # iOS is the nastier of the two: the Go compiles cleanly and the failure arrives minutes later, in # Swift, against a vendored xcframework whose headers are simply older than the source beside them. # # It compares mtimes rather than hashes: gomobile takes minutes, and a spurious rebuild is far cheaper # than a stale one. The artefact is touched on success so an unchanged tree does not rebuild twice. set -uo pipefail _ec_platform="${1:?usage: ensure-core.sh }" _ec_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" _ec_gocore="$_ec_root/modules/officer-net/gocore" case "$_ec_platform" in ios) _ec_artifact="$_ec_root/modules/officer-net/ios/libs/TailCore.xcframework" _ec_script="$_ec_root/modules/officer-net/scripts/build-libtailscale-ios.sh" ;; android) _ec_artifact="$_ec_root/modules/officer-net/android/libs/tailcore.aar" _ec_script="$_ec_root/modules/officer-net/scripts/build-libtailscale-android.sh" ;; *) echo "!! ensure-core: unknown platform '$_ec_platform'" >&2 return 1 2>/dev/null || exit 1 ;; esac # Newest input: any Go source, plus the module files that pin tailscale.com itself. _ec_newest_src="$(find "$_ec_gocore" -type f \( -name '*.go' -o -name 'go.mod' -o -name 'go.sum' \) \ -exec stat -f '%m' {} + 2>/dev/null | sort -rn | head -1)" if [[ -e "$_ec_artifact" ]]; then # The xcframework is a directory, and its own mtime is what this script touches. _ec_artifact_mtime="$(stat -f '%m' "$_ec_artifact" 2>/dev/null || echo 0)" else _ec_artifact_mtime=0 fi if [[ -z "${_ec_newest_src:-}" ]]; then echo "ensure-core: no Go sources found — skipping (is gocore missing?)" >&2 elif (( _ec_newest_src > _ec_artifact_mtime )); then if (( _ec_artifact_mtime == 0 )); then echo "==> core artefact missing for $_ec_platform — building it (a few minutes)" else echo "==> gocore is newer than the built core for $_ec_platform — rebuilding (a few minutes)" fi # gomobile lives in ~/go/bin, which is not on PATH in every shell. if PATH="$PATH:$HOME/go/bin" "$_ec_script"; then touch "$_ec_artifact" 2>/dev/null || true echo "==> core rebuilt for $_ec_platform" else echo "!! core rebuild FAILED for $_ec_platform — the app build would link a stale core, stopping." >&2 return 1 2>/dev/null || exit 1 fi else echo "==> core is up to date for $_ec_platform" fi