Skip to content

build: implement ios builds#77

Open
gBasil wants to merge 1 commit intoByteNess:mainfrom
gBasil:build/ios
Open

build: implement ios builds#77
gBasil wants to merge 1 commit intoByteNess:mainfrom
gBasil:build/ios

Conversation

@gBasil
Copy link

@gBasil gBasil commented Mar 19, 2026

I finally got iOS builds working! It turns out that only Keyring needed changes, and that go-keychain didn't need to be touched. I tested it on an iOS device and it works.

For posterity, my build command (against the basic example in the README) is:

SDKROOT=$(xcrun --sdk iphoneos --show-sdk-path) \
IPHONEOS_DEPLOYMENT_TARGET=10.0 \
GOOS=ios GOARCH=arm64 CGO_ENABLED=1 \
go build

The one thing in this PR I'm not certain about is is the change I made in keychain_darwin.go. Strangely, that changed is needed for compilation, as despite compiling for iOS, the Darwin file would seemingly be evaluated too, and Go would be unable to find the macOS-only symbols present there and error.

This was referenced Mar 19, 2026
@gBasil
Copy link
Author

gBasil commented Mar 20, 2026

The one unfortunate thing is that I've been unable to get it to build for older iOS versions (though it builds fine for newer ones). Changing SDKROOT to point to an SDK for iOS 14.5 and building causes this build error:

# example/hello
/opt/homebrew/Cellar/go/1.26.0/libexec/pkg/tool/darwin_arm64/link: running cc failed: exit status 1
/usr/bin/cc -Wl,-S -o $WORK/b001/exe/a.out -Qunused-arguments /var/folders/11/vf0w_3yx1pn3s6psnmvpm52c0000gn/T/go-link-4092325464/go.o /var/folders/11/vf0w_3yx1pn3s6psnmvpm52c0000gn/T/go-link-4092325464/000000.o /var/folders/11/vf0w_3yx1pn3s6psnmvpm52c0000gn/T/go-link-4092325464/000001.o /var/folders/11/vf0w_3yx1pn3s6psnmvpm52c0000gn/T/go-link-4092325464/000002.o /var/folders/11/vf0w_3yx1pn3s6psnmvpm52c0000gn/T/go-link-4092325464/000003.o /var/folders/11/vf0w_3yx1pn3s6psnmvpm52c0000gn/T/go-link-4092325464/000004.o /var/folders/11/vf0w_3yx1pn3s6psnmvpm52c0000gn/T/go-link-4092325464/000005.o /var/folders/11/vf0w_3yx1pn3s6psnmvpm52c0000gn/T/go-link-4092325464/000006.o /var/folders/11/vf0w_3yx1pn3s6psnmvpm52c0000gn/T/go-link-4092325464/000007.o /var/folders/11/vf0w_3yx1pn3s6psnmvpm52c0000gn/T/go-link-4092325464/000008.o /var/folders/11/vf0w_3yx1pn3s6psnmvpm52c0000gn/T/go-link-4092325464/000009.o /var/folders/11/vf0w_3yx1pn3s6psnmvpm52c0000gn/T/go-link-4092325464/000010.o /var/folders/11/vf0w_3yx1pn3s6psnmvpm52c0000gn/T/go-link-4092325464/000011.o /var/folders/11/vf0w_3yx1pn3s6psnmvpm52c0000gn/T/go-link-4092325464/000012.o /var/folders/11/vf0w_3yx1pn3s6psnmvpm52c0000gn/T/go-link-4092325464/000013.o /var/folders/11/vf0w_3yx1pn3s6psnmvpm52c0000gn/T/go-link-4092325464/000014.o /var/folders/11/vf0w_3yx1pn3s6psnmvpm52c0000gn/T/go-link-4092325464/000015.o /var/folders/11/vf0w_3yx1pn3s6psnmvpm52c0000gn/T/go-link-4092325464/000016.o /var/folders/11/vf0w_3yx1pn3s6psnmvpm52c0000gn/T/go-link-4092325464/000017.o -O2 -g -framework CoreFoundation -framework CoreFoundation -framework CoreFoundation -framework Security -framework CoreFoundation -framework Security -lresolv -O2 -g -framework CoreFoundation -O2 -g -ldl -framework CoreFoundation -framework Security
Undefined symbols for architecture arm64:
  "_SecTrustCopyCertificateChain", referenced from:
      _runtime.text in go.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

It seems to be related to this issue in the Go repo, which mentions this change where the crypto library moves to a newer API, that according to Apple's documentation is available in iOS 15.0+, which would restrict compilation to those versions. I've tried downgrading Go and the crypto version, but I still run into the same issue.

Copy link

@mbevc1 mbevc1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your contribution and I'm glad to hear you got it going.

Just a side note - Darwin keychain backend has tests. The iOS file adds new backend logic with no corresponding test file. Even a stub that only compiles and skips on non-iOS would help CI catch regressions in the future.

Comment on lines +27 to +28
// Set the isAccessibleWhenUnlocked to the boolean value of
// KeychainAccessibleWhenUnlocked is a shorthand for setting the accessibility value.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this part of the same sentance, reads a bit weird 🤔

passwordFunc PromptFunc

isSynchronizable bool
isAccessibleWhenUnlocked bool
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem to be initialised?

The keychain struct includes isSynchronizable, and Set does check it — but the init() function that constructs the struct never sets it from cfg. Looking at the Darwin implementation, cfg.KeychainSynchronizable is presumably used to populate this field. The iOS init currently omits this, meaning isSynchronizable will always be false even if a caller configures it. This looks like an oversight.

@@ -0,0 +1,191 @@
//go:build ios && cgo
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You comment notes that iOS 15.0+ is effectively required due to a Go runtime dependency on SecTrustCopyCertificateChain. This is a meaningful constraint for downstream users, but it's not captured anywhere in the code (no comment, no doc, no README update). It would be worth at minimum adding a comment near the build tag, e.g.:

//go:build ios && cgo
// NOTE: Due to Go's crypto library requiring SecTrustCopyCertificateChain,
// this requires iOS 15.0 or later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants