Go layer (c-archive) provides a localhost TCP proxy through a WireGuard tunnel. Flutter connects gRPC to localhost:PORT, Go forwards via tsnet to heater's Tailscale IP. No VPN entitlement needed — uses userspace netstack. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
150 lines
4.9 KiB
Bash
Executable File
150 lines
4.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Build the Go static library for iOS using go build -buildmode=c-archive.
|
|
#
|
|
# This is the production-grade approach (same as Tailscale's own iOS app).
|
|
# No gomobile dependency — just the standard Go compiler + Xcode SDK.
|
|
#
|
|
# Prerequisites:
|
|
# - Go 1.23+
|
|
# - Xcode with iOS SDK
|
|
#
|
|
# Usage:
|
|
# cd /path/to/tailscale_kit
|
|
# ./build_go.sh
|
|
#
|
|
# Output: ios/TailscaleKit.xcframework (static library xcframework)
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
GO_DIR="$SCRIPT_DIR/ios/Go"
|
|
BUILD_DIR="$SCRIPT_DIR/ios/build"
|
|
OUTPUT="$SCRIPT_DIR/ios/TailscaleKit.xcframework"
|
|
MIN_IOS="14.0"
|
|
|
|
# Omit Tailscale features we don't need — we only use tsnet.Dial() for proxying.
|
|
OMIT_TAGS="ts_omit_ssh,ts_omit_drive,ts_omit_taildrop,ts_omit_serve"
|
|
OMIT_TAGS="$OMIT_TAGS,ts_omit_webclient,ts_omit_capture,ts_omit_appconnectors"
|
|
OMIT_TAGS="$OMIT_TAGS,ts_omit_debug,ts_omit_doctor,ts_omit_portlist,ts_omit_posture"
|
|
OMIT_TAGS="$OMIT_TAGS,ts_omit_cli,ts_omit_kube,ts_omit_aws,ts_omit_bird"
|
|
OMIT_TAGS="$OMIT_TAGS,ts_omit_synology,ts_omit_tpm,ts_omit_tap,ts_omit_conn25"
|
|
OMIT_TAGS="$OMIT_TAGS,ts_omit_qrcodes,ts_omit_relayserver,ts_omit_systray"
|
|
OMIT_TAGS="$OMIT_TAGS,ts_omit_webbrowser,ts_omit_completion,ts_omit_completion_scripts"
|
|
OMIT_TAGS="$OMIT_TAGS,ts_omit_colorable,ts_omit_clientupdate,ts_omit_wakeonlan"
|
|
OMIT_TAGS="$OMIT_TAGS,ts_omit_usermetrics,ts_omit_desktop_sessions,ts_omit_ace"
|
|
OMIT_TAGS="$OMIT_TAGS,ts_omit_acme,ts_omit_hujsonconf,ts_omit_tailnetlock"
|
|
OMIT_TAGS="$OMIT_TAGS,ts_omit_netlog,ts_omit_syspolicy,ts_omit_cachenetmap"
|
|
|
|
rm -rf "$BUILD_DIR" "$OUTPUT"
|
|
mkdir -p "$BUILD_DIR/ios-arm64/Headers" "$BUILD_DIR/ios-arm64-simulator/Headers"
|
|
|
|
cd "$GO_DIR"
|
|
|
|
echo "==> Tidying Go modules..."
|
|
go mod tidy
|
|
|
|
# --- Build for iOS device (arm64) ---
|
|
echo "==> Building for iOS device (arm64)..."
|
|
IPHONEOS_SDK=$(xcrun --sdk iphoneos --show-sdk-path)
|
|
IPHONEOS_CC=$(xcrun --sdk iphoneos --find clang)
|
|
|
|
CGO_ENABLED=1 \
|
|
GOOS=ios \
|
|
GOARCH=arm64 \
|
|
CC="$IPHONEOS_CC" \
|
|
CGO_CFLAGS="-isysroot $IPHONEOS_SDK -arch arm64 -miphoneos-version-min=$MIN_IOS" \
|
|
CGO_LDFLAGS="-isysroot $IPHONEOS_SDK -arch arm64 -miphoneos-version-min=$MIN_IOS" \
|
|
go build \
|
|
-buildmode=c-archive \
|
|
-tags "$OMIT_TAGS" \
|
|
-ldflags="-s -w" \
|
|
-o "$BUILD_DIR/ios-arm64/libtailscale.a" \
|
|
.
|
|
|
|
# Helper: create a framework bundle from a static library
|
|
create_framework() {
|
|
local lib_path="$1"
|
|
local header_path="$2"
|
|
local framework_dir="$3"
|
|
|
|
mkdir -p "$framework_dir/Headers" "$framework_dir/Modules"
|
|
|
|
# Copy the static library as the framework binary
|
|
cp "$lib_path" "$framework_dir/TailscaleKit"
|
|
|
|
# Copy and clean the header (remove Go-internal types)
|
|
cp "$header_path" "$framework_dir/Headers/tailscale.h"
|
|
|
|
# Module map
|
|
cat > "$framework_dir/Modules/module.modulemap" <<'MODMAP'
|
|
framework module TailscaleKit {
|
|
header "tailscale.h"
|
|
export *
|
|
}
|
|
MODMAP
|
|
|
|
# Info.plist
|
|
cat > "$framework_dir/Info.plist" <<PLIST
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
<plist version="1.0">
|
|
<dict>
|
|
<key>CFBundleIdentifier</key>
|
|
<string>com.constellation-heating.TailscaleKit</string>
|
|
<key>CFBundleName</key>
|
|
<string>TailscaleKit</string>
|
|
<key>CFBundleVersion</key>
|
|
<string>1</string>
|
|
<key>CFBundlePackageType</key>
|
|
<string>FMWK</string>
|
|
</dict>
|
|
</plist>
|
|
PLIST
|
|
}
|
|
|
|
create_framework \
|
|
"$BUILD_DIR/ios-arm64/libtailscale.a" \
|
|
"$BUILD_DIR/ios-arm64/libtailscale.h" \
|
|
"$BUILD_DIR/ios-arm64/TailscaleKit.framework"
|
|
|
|
# --- Build for iOS simulator (arm64) ---
|
|
echo "==> Building for iOS simulator (arm64)..."
|
|
SIMULATOR_SDK=$(xcrun --sdk iphonesimulator --show-sdk-path)
|
|
SIMULATOR_CC=$(xcrun --sdk iphonesimulator --find clang)
|
|
|
|
CGO_ENABLED=1 \
|
|
GOOS=ios \
|
|
GOARCH=arm64 \
|
|
CC="$SIMULATOR_CC" \
|
|
CGO_CFLAGS="-isysroot $SIMULATOR_SDK -arch arm64 -miphoneos-version-min=$MIN_IOS -target arm64-apple-ios${MIN_IOS}-simulator" \
|
|
CGO_LDFLAGS="-isysroot $SIMULATOR_SDK -arch arm64 -miphoneos-version-min=$MIN_IOS -target arm64-apple-ios${MIN_IOS}-simulator" \
|
|
go build \
|
|
-buildmode=c-archive \
|
|
-tags "$OMIT_TAGS" \
|
|
-ldflags="-s -w" \
|
|
-o "$BUILD_DIR/ios-arm64-simulator/libtailscale.a" \
|
|
.
|
|
|
|
create_framework \
|
|
"$BUILD_DIR/ios-arm64-simulator/libtailscale.a" \
|
|
"$BUILD_DIR/ios-arm64-simulator/libtailscale.h" \
|
|
"$BUILD_DIR/ios-arm64-simulator/TailscaleKit.framework"
|
|
|
|
# --- Create xcframework from framework bundles ---
|
|
echo "==> Creating xcframework..."
|
|
xcodebuild -create-xcframework \
|
|
-framework "$BUILD_DIR/ios-arm64/TailscaleKit.framework" \
|
|
-framework "$BUILD_DIR/ios-arm64-simulator/TailscaleKit.framework" \
|
|
-output "$OUTPUT"
|
|
|
|
# Clean up build artifacts
|
|
rm -rf "$BUILD_DIR"
|
|
|
|
# Also copy the header to Classes/ for CocoaPods umbrella header
|
|
cp "$OUTPUT/ios-arm64/TailscaleKit.framework/Headers/tailscale.h" "$SCRIPT_DIR/ios/Classes/tailscale.h"
|
|
|
|
echo "==> Built: $OUTPUT"
|
|
du -sh "$OUTPUT"
|
|
echo "==> Device framework:"
|
|
ls -lh "$OUTPUT/ios-arm64/TailscaleKit.framework/TailscaleKit"
|