1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#!/bin/bash
# Regenerates GoLib/AtircGo.xcframework for the AT-IRC app.
#
# The framework must contain a SINGLE Go runtime: it is built from the atircgo
# package in the kcp fork, which combines the app's IRC helpers with the kcp
# bridge (kcpios). Never add a second gomobile framework to the app.
#
# Requires gomobile/gobind on PATH, Xcode and git. The kcp fork (branch kcp-ios
# of github.com/johnandersen777/kcp) and socialweb-computer-kcp are fetched at
# the pinned commits below; KCP_IOS_REPO / SOCIALWEB_SRC point at local
# checkouts instead (docs/plans/0001).
set -euo pipefail
cd "$(dirname "$0")"
# The pinned commit of the kcp fork's kcp-ios branch the framework embeds.
KCP_COMMIT="${KCP_COMMIT:-f233e4f2c3daa21f6cee39e6c5f12e679e2d58e9}"
KCP_FORK_URL="${KCP_FORK_URL:-https://github.com/johnandersen777/kcp}"
SOCIALWEB_URL="${SOCIALWEB_URL:-https://github.com/publicdomainrelay/socialweb-computer-kcp}"
SOCIALWEB_SRC_GIVEN="${SOCIALWEB_SRC:-}"
KCP_REPO="${KCP_IOS_REPO:-/tmp/kcp-ios-src}"
SOCIALWEB_SRC="${SOCIALWEB_SRC:-/tmp/socialweb-ios-src}"
# The pinned socialweb-computer-kcp commit the framework embeds.
SOCIALWEB_COMMIT="${SOCIALWEB_COMMIT:-5e6c4e3d6efb3779064f8ae5d64341dffbdb76af}"
SOCIALWEB_MIRROR="${SOCIALWEB_MIRROR:-/tmp/socialweb-ios-mirror}"
export PATH="$(go env GOPATH)/bin:$PATH"
if ! command -v gomobile >/dev/null || ! command -v gobind >/dev/null; then
echo "Missing gomobile/gobind. Install with:" >&2
echo " go install golang.org/x/mobile/cmd/gomobile@latest golang.org/x/mobile/cmd/gobind@latest" >&2
exit 1
fi
# fetch_pin <dir> <url> <commit>: a checkout of exactly that commit.
fetch_pin() {
if [[ "$(git -C "$1" rev-parse HEAD 2>/dev/null)" != "$3" ]]; then
echo "fetching $2 at $3 into $1..."
rm -rf "$1"
git init -q "$1"
git -C "$1" fetch -q --depth 1 "$2" "$3"
git -C "$1" checkout -q --detach FETCH_HEAD
fi
}
if [[ -z "${KCP_IOS_REPO:-}" ]]; then
fetch_pin "${KCP_REPO}" "${KCP_FORK_URL}" "${KCP_COMMIT}"
fi
if [[ -z "${SOCIALWEB_SRC_GIVEN}" ]]; then
fetch_pin "${SOCIALWEB_SRC}" "${SOCIALWEB_URL}" "${SOCIALWEB_COMMIT}"
fi
# socialweb (pkg/embedded) is the pinned commit, archived from git objects
# into a stable mirror, like the wasm build does.
if [[ "${SOCIALWEB_REFRESH:-1}" == "1" || ! -f "${SOCIALWEB_MIRROR}/go.mod" ]]; then
echo "mirroring socialweb source to ${SOCIALWEB_MIRROR}..."
rm -rf "${SOCIALWEB_MIRROR}"
mkdir -p "${SOCIALWEB_MIRROR}"
git -C "${SOCIALWEB_SRC}" -c safe.directory="${SOCIALWEB_SRC}" archive "${SOCIALWEB_COMMIT}" | tar -x -C "${SOCIALWEB_MIRROR}"
fi
# The apiserver factory must come from the patched memory:// copy. The fork's
# go.mod replaces k8s.io/apiserver with /tmp/kcp-patched-modules-native/apiserver
# (produced by this script); gomobile reads go.mod, so keep both in sync.
# The fork's go.mod replaces k8s.io/apiserver with the patched copy under /tmp,
# which does not survive a reboot. Seed it from the module cache: the kcp-dev
# kubernetes staging apiserver at the version the fork's other k8s.io replaces use.
PATCHED_APISERVER=/tmp/kcp-patched-modules-native/apiserver
if [[ ! -d "${PATCHED_APISERVER}" ]]; then
KUBE_FORK_VERSION="$(cd "${KCP_REPO}" && go mod edit -json | python3 -c 'import json,sys; print(next(r["New"]["Version"] for r in json.load(sys.stdin)["Replace"] if r["Old"]["Path"] == "k8s.io/apimachinery"))')"
echo "seeding ${PATCHED_APISERVER} from kcp-dev kubernetes ${KUBE_FORK_VERSION}..."
APISERVER_DIR="$(cd "$(mktemp -d)" && GOFLAGS=-mod=mod go mod download -json "github.com/kcp-dev/kubernetes/staging/src/k8s.io/apiserver@${KUBE_FORK_VERSION}" | python3 -c 'import json,sys; print(json.load(sys.stdin)["Dir"])')"
mkdir -p "$(dirname "${PATCHED_APISERVER}")"
cp -a "${APISERVER_DIR}" "${PATCHED_APISERVER}"
chmod -R u+w "${PATCHED_APISERVER}"
fi
(
cd "${KCP_REPO}"
KCP_PATCH_MODE=native ./scripts/prepare-kcp-patched-modules.sh \
/tmp/kcp-patched-modules-native .go.memory.mod >/dev/null
grep -q 'k8s.io/apiserver => /tmp/kcp-patched-modules-native/apiserver' go.mod || {
echo "go.mod must replace k8s.io/apiserver with the native patched copy" >&2
echo "see docs/plans/0001-ios-embedded-kcp.md" >&2
exit 1
}
GOLIB="$(cd - >/dev/null && pwd)"
# GOLIB_REMOTE_CACHE (default hat-8, empty for none) is an ssh host that
# compiles the pure-Go packages (remote-warm.sh); this build reads them
# from its cache over ssh (cacheprog), so only cgo and the link run here.
# An unreachable host means a local build. Either way GOCACHE is a scratch
# dir deleted afterwards: this Mac keeps no Go build cache.
REMOTE="${GOLIB_REMOTE_CACHE-hat-8}"
RDIR="${GOLIB_REMOTE_DIR:-.tmp/golib-remote}"
SSH=(ssh -o BatchMode=yes -o ConnectTimeout=5)
if [[ -n "${REMOTE}" ]] && ! "${SSH[@]}" "${REMOTE}" true; then
echo "${REMOTE} unreachable; building locally" >&2
REMOTE=""
fi
SCRATCH="$(mktemp -d)"
trap 'rm -rf "${SCRATCH}"' EXIT
export GOCACHE="${SCRATCH}/gocache"
if [[ -n "${REMOTE}" ]]; then
"${SSH[@]}" "${REMOTE}" mkdir -p "${RDIR}/src"
rsync -a --delete --exclude .git -e "${SSH[*]}" "${KCP_REPO}/" "${REMOTE}:${RDIR}/src/kcp/"
rsync -a --delete -e "${SSH[*]}" /tmp/kcp-patched-modules-native/ "${REMOTE}:${RDIR}/src/patched/"
rsync -a --delete --exclude .git -e "${SSH[*]}" "${SOCIALWEB_MIRROR}/" "${REMOTE}:${RDIR}/src/mirror/"
rsync -a --delete -e "${SSH[*]}" "${GOLIB}/cacheprog/" "${REMOTE}:${RDIR}/src/cacheprog/"
"${SSH[@]}" "${REMOTE}" "cd ${RDIR} && sed -i \"s#/tmp/kcp-patched-modules-native#\$PWD/src/patched#; s#${SOCIALWEB_MIRROR}#\$PWD/src/mirror#\" src/kcp/go.mod"
MOBILE="$(go version -m "$(command -v gomobile)" | awk '$1 == "mod" && $2 == "golang.org/x/mobile" {print $3}')"
"${SSH[@]}" "${REMOTE}" bash -s -- "${RDIR}" "$(go env GOVERSION)" "${MOBILE}" < "${GOLIB}/remote-warm.sh"
(cd "${GOLIB}/cacheprog" && go build -o "${SCRATCH}/cacheprog" .)
export GOCACHEPROG="${SCRATCH}/cacheprog -dir ${SCRATCH}/objs -- ${SSH[*]} ${REMOTE} ${RDIR}/bin/cacheprog -serve ${RDIR}/gocache"
fi
# -trimpath: cache keys and the framework do not depend on local paths.
gomobile bind -trimpath -target=ios,iossimulator -ldflags="-s -w" \
-o "${GOLIB}/AtircGo.xcframework" \
github.com/kcp-dev/kcp/contrib/wasm/ios/atircgo
)