Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 10 additions & 39 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
# NOTE: every job here fails on a clean checkout until PureSwift/AndroidBluetooth#4 is merged.
# AndroidBluetooth requests the `AndroidManifest` product from `Android`, but it moved to
# `swift-android-native` (PureSwift/Android#40), and SwiftPM validates the whole package graph even
# for dependencies that are conditional on `.android`:
# error: product 'AndroidManifest' required by package 'androidbluetooth' ... not found
# That is a one-line manifest fix upstream, not a problem with this repo.
name: CI

on:
Expand All @@ -19,33 +13,34 @@ concurrency:
jobs:
test:
name: Test
runs-on: macos-15
runs-on: macos-26
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
# Pinned, not latest-stable: WasmKit 0.3.x declares swift-tools-version 6.3, so it needs
# Swift 6.3+. Xcode 26.5 (the macos-26 default) ships Swift 6.2.x and fails with
# "package 'wasmkit' is using Swift tools version 6.3.0 but the installed version is 6.2.4".
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest-stable
xcode-version: '26.6'
- name: Build
run: swift build --build-tests
- name: Test
run: swift test

ios-archive:
name: iOS Archive
runs-on: macos-15
runs-on: macos-26
timeout-minutes: 60
steps:
- uses: actions/checkout@v4
# Pinned, not latest-stable: WasmKit 0.3.x declares swift-tools-version 6.3, so it needs
# Swift 6.3+. Xcode 26.5 (the macos-26 default) ships Swift 6.2.x and fails with
# "package 'wasmkit' is using Swift tools version 6.3.0 but the installed version is 6.2.4".
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest-stable
xcode-version: '26.6'

# WasmKit declares `.treatAllWarnings(as: .error)` for Apple platforms, which conflicts with
# the `-suppress-warnings` Xcode passes to package dependencies:
# error: Conflicting options '-warnings-as-errors' and '-suppress-warnings'
# The setting only reaches package targets from the command line, so it cannot live in the
# xcconfig or the project.
- name: Archive
working-directory: Darwin
run: |
Expand All @@ -56,7 +51,6 @@ jobs:
-archivePath "$RUNNER_TEMP/BluetoothExplorer.xcarchive" \
-skipPackagePluginValidation \
-skipMacroValidation \
SWIFT_SUPPRESS_WARNINGS=NO \
CODE_SIGNING_ALLOWED=NO

- name: Verify archive contents
Expand All @@ -72,26 +66,3 @@ jobs:
name: ios-archive
path: ${{ runner.temp }}/BluetoothExplorer.xcarchive
retention-days: 14

android-package:
name: Android Swift Package
runs-on: macos-15
timeout-minutes: 60
steps:
- uses: actions/checkout@v4
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest-stable

- name: Install Swift Android SDK
run: |
brew install skiptools/skip/skip || (brew update && brew install skiptools/skip/skip)
skip android sdk install --version 6.3.3

# Only the plugin engine is built here. The full app does not yet cross-compile for Android:
# AndroidBluetooth's `@JavaImplementation` macro generates invalid code for its scan callback,
# and WasmKit's SystemExtras target does not compile against the Android sysroot
# (`st_mode` is UInt32 there while swift-system's CInterop.Mode is UInt16). Neither is
# reachable from this target. See Documentation/AndroidSwiftUIMigration.md.
- name: Build plugin engine for Android
run: swift build --swift-sdk swift-6.3.3-RELEASE_android --target BluetoothExplorerPluginEngine
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ playground.xcworkspace
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
# Packages/
# Package.pins
*Package.resolved
# NOTE: Package.resolved is deliberately committed. This is an app, not a library, and several
# dependencies track moving branches (GATT master, AndroidSwiftUI master), so without it every
# clean checkout — including CI — resolves a different graph than the one that was tested.
Darwin/**/Package.resolved
.build/
.swiftpm

Expand Down
20 changes: 0 additions & 20 deletions Darwin/BluetoothExplorer.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@
499CD43A2AC5B799001AE8D8 /* Sources */,
499CD43C2AC5B799001AE8D8 /* Frameworks */,
499CD43E2AC5B799001AE8D8 /* Resources */,
499CD4452AC5B869001AE8D8 /* Run skip gradle */,
499CD44A2AC5B9C6001AE8D8 /* Embed Frameworks */,
);
buildRules = (
Expand Down Expand Up @@ -166,25 +165,6 @@
/* End PBXResourcesBuildPhase section */

/* Begin PBXShellScriptBuildPhase section */
499CD4452AC5B869001AE8D8 /* Run skip gradle */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
name = "Run skip gradle";
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = "/bin/sh -e";
shellScript = "if [ \"${SKIP_ZERO}\" != \"\" ]; then\n echo \"note: skipping skip due to SKIP_ZERO\"\n exit 0\nelif [ \"${ENABLE_PREVIEWS}\" = \"YES\" ]; then\n echo \"note: skipping skip due to ENABLE_PREVIEWS\"\n exit 0\nelif [ \"${ACTION}\" = \"install\" ]; then\n echo \"note: skipping skip due to archive install\"\n exit 0\nelif [ \"${SKIP_ACTION}\" = \"none\" ]; then\n echo \"note: skipping skip due to SKIP_ACTION none\"\n exit 0\nelse\n SKIP_ACTION=\"${SKIP_ACTION:-launch}\"\nfi\nPATH=${BUILD_ROOT}/Release:${BUILD_ROOT}/Debug:${BUILD_ROOT}/../../SourcePackages/artifacts/skip/skip/skip.artifactbundle/macos:${PATH}:${HOMEBREW_PREFIX:-/opt/homebrew}/bin\necho \"note: running gradle build with: $(which skip) gradle -p ${PWD}/../Android ${SKIP_ACTION:-launch}${CONFIGURATION:-Debug}\"\nskip gradle -p ../Android ${SKIP_ACTION:-launch}${CONFIGURATION:-Debug}\n";
};
/* End PBXShellScriptBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
Expand Down
14 changes: 13 additions & 1 deletion Documentation/AndroidSwiftUIMigration.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,19 @@ device or emulator. Notable limitations, each documented in the source:

## Platform status

- **Apple platforms** — the package resolves and every target builds with no Skip involvement.
- **Apple platforms** — working end to end. A clean checkout resolves, builds, tests and archives
with **no mirrors, no environment variables and no extra xcodebuild flags**, and the app runs in
the simulator: the device list populates from `MockCentral`, and all 13 bundled plugins install
into `Documents/Plugins/` on first launch and appear in the Plugins tab.

Two things were needed to get there beyond removing Skip:
- The `AndroidBluetooth` package dependency is temporarily not declared. SwiftPM validates the
whole graph even for `.android`-conditional dependencies, so its `AndroidManifest` bug broke
Apple builds. Restore it with PureSwift/AndroidBluetooth#4.
- WasmKit is taken from a fork that drops `.treatAllWarnings(as: .error)`. Upstream's setting
collides with the `-suppress-warnings` Xcode passes to package dependencies, which made the app
unbuildable in Xcode; the override only works from the command line, so it could not be fixed
from the xcconfig or project.
- **Android** — the dependency wiring is in place, but the Android app build has not been verified
end to end. It additionally needs the two PureSwift PRs above, and the Kotlin JNI peers under
`Sources/BluetoothExplorer/Skip/` (`ScanCallback.kt`, `BluetoothGattCallback.kt`) rehomed into the
Expand Down
176 changes: 176 additions & 0 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 17 additions & 7 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,27 @@ let package = Package(
],
dependencies: [
.package(url: "https://github.com/PureSwift/GATT.git", branch: "master"),
.package(url: "https://github.com/PureSwift/AndroidBluetooth.git", branch: "master"),
// AndroidBluetooth is temporarily not declared. It requests the `AndroidManifest` product
// from `Android`, but that product moved to `swift-android-native`
// (PureSwift/Android#40), and SwiftPM validates the whole package graph even for
// dependencies conditional on `.android` — so simply declaring it breaks Apple-platform
// builds. Restore this together with the `AndroidBluetooth` target dependency below once
// PureSwift/AndroidBluetooth#4 is merged. The Swift sources still guard their use of it
// with `#if os(Android)`, so nothing else has to change.
.package(url: "https://github.com/PureSwift/Bluetooth.git", from: "7.2.0"),
// SwiftUI for Android. Apple platforms use the system SwiftUI instead, so this is only
// linked for .android — see the conditional target dependencies below.
.package(url: "https://github.com/PureSwift/AndroidSwiftUI.git", branch: "master"),
.package(url: "https://github.com/swiftwasm/WasmKit.git", .upToNextMinor(from: "0.3.1"))
// Fork of WasmKit 0.3.1 with one change: upstream declares
// `.treatAllWarnings(as: .error)` for Apple platforms, which collides with the
// `-suppress-warnings` Xcode passes to package dependencies and makes the app fail to build
// in Xcode ("Conflicting options '-warnings-as-errors' and '-suppress-warnings'"). That
// setting only reaches package targets from the command line, so it cannot be overridden
// from the xcconfig or the project. Track upstream and drop the fork once it is fixed there.
.package(
url: "https://github.com/MillerTechnologyPeru/WasmKit.git",
revision: "ba06b7c64b5bc692c19c301ba2ef843c8d0f37c2"
)
],
targets: [
.target(
Expand Down Expand Up @@ -64,11 +79,6 @@ let package = Package(
package: "GATT",
condition: .when(platforms: [.macOS, .iOS, .macCatalyst, .watchOS, .tvOS, .visionOS])
),
.product(
name: "AndroidBluetooth",
package: "AndroidBluetooth",
condition: .when(platforms: [.android])
),
.product(
name: "AndroidSwiftUI",
package: "AndroidSwiftUI",
Expand Down
Loading