~ knotless Search/
↑↓ move↵ open⇧↵ all results

johnandersen777.bsky.social/atirc-ios-client

0
1
main
289 lines · 7.7 KB Raw History

Contributing to AT-IRC

AT-IRC is a SwiftUI iOS client with a small embedded Go library (GoLib). The whole build/test/run loop works from the command line; Xcode is optional.

All commands below are run from the repository root.

Prerequisites

  • macOS with Xcode 27.2 or newer and an iOS 27.2 simulator runtime.

  • Xcode's command-line tools selected:

    xcode-select -p   # should point into /Applications/Xcode.app
    xcodebuild -version
    xcrun simctl list runtimes
    
  • Go 1.27.3+ if you will change GoLib:

    go version
    go install golang.org/x/mobile/cmd/gomobile@latest
    go install golang.org/x/mobile/cmd/gobind@latest
    

    Install both tools. gomobile bind shells out to gobind; installing only gomobile fails with gobind was not found.

The generated Go framework is not checked in. On a fresh clone, build it once before building the app:

./GoLib/build.sh

This writes GoLib/AtircGo.xcframework, which is gitignored. Skipping this step makes the app fail to compile with No such module 'AtircGo' or fail to link with framework not found AtircGo.

Layout

PathContents
AT-IRC/SwiftUI app sources
AT-IRCTests/Swift Testing unit tests
AT-IRCUITests/XCUITest tests
GoLib/Go module, build.sh, and the generated xcframework
docs/golang/Notes on the Go bridge

There is one shared scheme, AT-IRC.

Set up the shell

The examples use these variables. Run this once in the shell you are working in; change DEVICE to any available simulator.

DEVICE="iPhone 17"
DEST="platform=iOS Simulator,name=$DEVICE"
BUNDLE_ID="com.fedfork.irc.AT-IRC"
APP=".build/Build/Products/Debug-iphonesimulator/AT-IRC.app"

Using -derivedDataPath .build keeps build products inside the repository at a predictable path. .build/ is gitignored.

List the available simulators and destinations with:

xcrun simctl list devices available
xcodebuild -showdestinations -project AT-IRC.xcodeproj -scheme AT-IRC

Build from the command line

Debug build for a simulator:

xcodebuild build \
  -project AT-IRC.xcodeproj \
  -scheme AT-IRC \
  -configuration Debug \
  -destination "$DEST" \
  -derivedDataPath .build

For a CI build that does not need a specific simulator, use the generic destination:

xcodebuild build \
  -project AT-IRC.xcodeproj \
  -scheme AT-IRC \
  -configuration Debug \
  -destination 'generic/platform=iOS Simulator' \
  -derivedDataPath .build

The app is always at:

.build/Build/Products/Debug-iphonesimulator/AT-IRC.app

Use -configuration Release for a release build.

Test from the command line

Fast loop: run only the unit tests.

xcodebuild test \
  -project AT-IRC.xcodeproj \
  -scheme AT-IRC \
  -destination "$DEST" \
  -derivedDataPath .build \
  -only-testing:AT-IRCTests

Run only UI tests:

xcodebuild test \
  -project AT-IRC.xcodeproj \
  -scheme AT-IRC \
  -destination "$DEST" \
  -derivedDataPath .build \
  -only-testing:AT-IRCUITests

Run everything (unit + UI):

xcodebuild test \
  -project AT-IRC.xcodeproj \
  -scheme AT-IRC \
  -destination "$DEST" \
  -derivedDataPath .build

Run a single Swift Testing test. The parentheses are part of the identifier, so quote the whole value:

xcodebuild test \
  -project AT-IRC.xcodeproj \
  -scheme AT-IRC \
  -destination "$DEST" \
  -derivedDataPath .build \
  -only-testing:'AT-IRCTests/AT_IRCTests/nickHashMatchesWeeChat()'

To keep a machine-readable result bundle, add -resultBundlePath (the path must not already exist):

rm -rf .build/TestResults.xcresult

xcodebuild test \
  -project AT-IRC.xcodeproj \
  -scheme AT-IRC \
  -destination "$DEST" \
  -derivedDataPath .build \
  -resultBundlePath .build/TestResults.xcresult

xcrun xcresulttool get test-results summary \
  --path .build/TestResults.xcresult

The UI suite includes a launch-performance test and takes about a minute. The unit suite is the fast pre-commit check.

Run and iterate in the simulator

Boot the simulator (and optionally open the Simulator UI):

xcrun simctl bootstatus "$DEVICE" -b
open -a Simulator

Build, install, and relaunch:

xcodebuild build \
  -project AT-IRC.xcodeproj \
  -scheme AT-IRC \
  -configuration Debug \
  -destination "$DEST" \
  -derivedDataPath .build

xcrun simctl install "$DEVICE" "$APP"
xcrun simctl launch --terminate-running-process "$DEVICE" "$BUNDLE_ID"

--terminate-running-process replaces the already-running copy, so the same two simctl commands work for every iteration.

Useful companion commands:

# Stream this app's unified log
xcrun simctl spawn "$DEVICE" log stream --style compact --level debug \
  --predicate 'process == "AT-IRC"'

# Show recent log entries once
xcrun simctl spawn "$DEVICE" log show --last 2m --style compact \
  --predicate 'process == "AT-IRC"'

# Blocking stdout/stderr console (Ctrl-C to stop)
xcrun simctl launch --console-pty --terminate-running-process \
  "$DEVICE" "$BUNDLE_ID"

# Screenshot
xcrun simctl io "$DEVICE" screenshot /tmp/atirc.png

Reset the app without wiping the simulator:

xcrun simctl terminate "$DEVICE" "$BUNDLE_ID" 2>/dev/null || true
xcrun simctl uninstall "$DEVICE" "$BUNDLE_ID"

To clear Keychain and all other simulator state (this erases the whole simulator, so shut it down first):

xcrun simctl shutdown "$DEVICE"
xcrun simctl erase "$DEVICE"

Changing the Go library

Xcode does not track the Go sources and will not regenerate the framework automatically. After editing anything under GoLib/:

./GoLib/build.sh

Then rebuild the app. If you skip this, the app keeps using the previous Go binary, and new exported symbols will not exist in Swift.

gomobile bind generates Objective-C/Swift bindings prefixed with Golib. Interface names that collide with generated class names get a Protocol suffix in Swift (for example GolibCallbackProtocol). Bridge details and type limits are documented in docs/golang/0001-notes.md.

Before you commit

  1. If you changed GoLib/, run ./GoLib/build.sh.

  2. Run the unit tests:

    xcodebuild test \
      -project AT-IRC.xcodeproj \
      -scheme AT-IRC \
      -destination "$DEST" \
      -derivedDataPath .build \
      -only-testing:AT-IRCTests
    
  3. Run the full suite if you changed UI code or UI tests.

  4. Do not commit .build/ or GoLib/AtircGo.xcframework/; both are generated.

Troubleshooting

SymptomFix
No such module 'AtircGo' or framework not found AtircGoRun ./GoLib/build.sh. Confirm GoLib/AtircGo.xcframework exists.
gobind was not foundInstall gomobile and gobind; build.sh adds $(go env GOPATH)/bin to PATH for you.
Unable to find a destination matching ...Run xcrun simctl list devices available and xcodebuild -showdestinations; use the exact device name, or install the iOS 27.2 runtime.
Tests cannot launch the appBoot the simulator explicitly with xcrun simctl bootstatus "$DEVICE" -b and retry.
App still shows old Go behaviorRerun ./GoLib/build.sh, then rebuild. Do a clean build (rm -rf .build) if the stale binary persists.
Installed app does not reflect a new buildReinstall, then launch with --terminate-running-process; uninstall first if needed.
Code-signing errorSimulator builds need no team. Device builds need your own signing team in the target settings.

For device runs, use the device destination and a configured signing team:

xcodebuild test \
  -project AT-IRC.xcodeproj \
  -scheme AT-IRC \
  -destination 'platform=iOS,id=<device-udid>' \
  -derivedDataPath .build \
  -only-testing:AT-IRCTests