Skip to content

Commit

Permalink
Add visionOS support (#1098)
Browse files Browse the repository at this point in the history
* add compiler directives for visionOS support

* add SPM visionOS support

* add CocoaPods visionOS support

* update Carthage dependencies

* add visionOS support when using the Xcode project

* extend test script to include visionOS

* fix cocoapods support by modifying dependencies directly

* do not break older Swift version support by creating a swift 5.9 explicit Package.swift file

* skip tests on visionOS if it's not present

* fix build issues below Xcode 15

* skip visionOS cocoapod validation if visionOS is not present

* move TARGET_OS_VISION definition to umbrella header

* bump CwlPreconditionTesting to 2.2.0

* link CwlPreconditionTesting on visionOS

* add visionOS for to dependencies array

* add CI execution for visionOS with Xcode 15.2

* remove visionOS testing on Xcode 15.2

* it looks like the visionOS simulator is not created by default on the used macOS image
  • Loading branch information
stonko1994 authored Jan 17, 2024
1 parent 29c8d41 commit 52c7526
Show file tree
Hide file tree
Showing 10 changed files with 151 additions and 36 deletions.
3 changes: 2 additions & 1 deletion Nimble.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Pod::Spec.new do |s|
s.osx.deployment_target = "10.15"
s.tvos.deployment_target = "13.0"
s.watchos.deployment_target = "7.0"
s.visionos.deployment_target = "1.0"
s.source = { :git => "https://github.com/Quick/Nimble.git",
:tag => "v#{s.version}" }

Expand All @@ -34,7 +35,7 @@ Pod::Spec.new do |s|
'OTHER_SWIFT_FLAGS' => '$(inherited) -suppress-warnings',
}

[s.osx, s.ios].each do |platform|
[s.osx, s.ios, s.visionos].each do |platform|
platform.dependency 'CwlPreconditionTesting', '~> 2.1.0'
end

Expand Down
12 changes: 6 additions & 6 deletions Nimble.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 53;
objectVersion = 55;
objects = {

/* Begin PBXAggregateTarget section */
Expand Down Expand Up @@ -143,7 +143,7 @@
89C297CE2A92AB34002A143F /* AsyncPromiseTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89C297CD2A92AB34002A143F /* AsyncPromiseTest.swift */; };
89D8AC852B3211C600410644 /* CwlCatchException in Frameworks */ = {isa = PBXBuildFile; productRef = 89D8AC842B3211C600410644 /* CwlCatchException */; };
89D8AC872B3211EA00410644 /* CwlPosixPreconditionTesting in Frameworks */ = {isa = PBXBuildFile; platformFilters = (tvos, watchos, ); productRef = 89D8AC862B3211EA00410644 /* CwlPosixPreconditionTesting */; };
89D8AC892B3211EA00410644 /* CwlPreconditionTesting in Frameworks */ = {isa = PBXBuildFile; platformFilters = (driverkit, ios, maccatalyst, macos, ); productRef = 89D8AC882B3211EA00410644 /* CwlPreconditionTesting */; };
89D8AC892B3211EA00410644 /* CwlPreconditionTesting in Frameworks */ = {isa = PBXBuildFile; platformFilters = (driverkit, ios, maccatalyst, macos, xros, ); productRef = 89D8AC882B3211EA00410644 /* CwlPreconditionTesting */; };
89EEF5A52A03293100988224 /* AsyncMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89EEF5A42A03293100988224 /* AsyncMatcher.swift */; };
89EEF5B72A032C3200988224 /* AsyncPredicateTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89EEF5B22A032C2500988224 /* AsyncPredicateTest.swift */; };
89EEF5C02A06211C00988224 /* AsyncHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89EEF5BB2A06210D00988224 /* AsyncHelpers.swift */; };
Expand Down Expand Up @@ -1183,10 +1183,10 @@
PRODUCT_NAME = Nimble;
SDKROOT = macosx;
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator macosx watchos watchsimulator";
SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator macosx watchos watchsimulator xros xrsimulator";
SUPPORTS_MACCATALYST = YES;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
TARGETED_DEVICE_FAMILY = "1,2,3,4";
TARGETED_DEVICE_FAMILY = "1,2,3,4,7";
};
name = Debug;
};
Expand Down Expand Up @@ -1225,12 +1225,12 @@
PRODUCT_NAME = Nimble;
SDKROOT = macosx;
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator macosx watchos watchsimulator";
SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator macosx watchos watchsimulator xros xrsimulator";
SUPPORTS_MACCATALYST = YES;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
TARGETED_DEVICE_FAMILY = "1,2,3,4";
TARGETED_DEVICE_FAMILY = "1,2,3,4,7";
};
name = Release;
};
Expand Down
42 changes: 20 additions & 22 deletions Package.resolved
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
{
"object": {
"pins": [
{
"package": "CwlCatchException",
"repositoryURL": "https://github.com/mattgallagher/CwlCatchException.git",
"state": {
"branch": null,
"revision": "f809deb30dc5c9d9b78c872e553261a61177721a",
"version": "2.0.0"
}
},
{
"package": "CwlPreconditionTesting",
"repositoryURL": "https://github.com/mattgallagher/CwlPreconditionTesting.git",
"state": {
"branch": null,
"revision": "c21f7bab5ca8eee0a9998bbd17ca1d0eb45d4688",
"version": "2.1.0"
}
"pins" : [
{
"identity" : "cwlcatchexception",
"kind" : "remoteSourceControl",
"location" : "https://github.com/mattgallagher/CwlCatchException.git",
"state" : {
"revision" : "3b123999de19bf04905bc1dfdb76f817b0f2cc00",
"version" : "2.1.2"
}
]
},
"version": 1
},
{
"identity" : "cwlpreconditiontesting",
"kind" : "remoteSourceControl",
"location" : "https://github.com/mattgallagher/CwlPreconditionTesting.git",
"state" : {
"revision" : "dc9af4781f2afdd1e68e90f80b8603be73ea7abc",
"version" : "2.2.0"
}
}
],
"version" : 2
}
65 changes: 65 additions & 0 deletions [email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// swift-tools-version:5.9
import PackageDescription

let package = Package(
name: "Nimble",
platforms: [
.macOS(.v10_15), .iOS(.v13), .tvOS(.v13), .watchOS(.v6), .visionOS(.v1)
],
products: [
.library(
name: "Nimble",
targets: {
var targets: [String] = ["Nimble"]
#if os(macOS)
targets.append("NimbleObjectiveC")
#endif
return targets
}()
),
],
dependencies: [
.package(url: "https://github.com/mattgallagher/CwlPreconditionTesting.git", .upToNextMajor(from: "2.2.0")),
],
targets: {
var testHelperDependencies: [PackageDescription.Target.Dependency] = ["Nimble"]
#if os(macOS)
testHelperDependencies.append("NimbleObjectiveC")
#endif
var targets: [Target] = [
.target(
name: "Nimble",
dependencies: [
.product(name: "CwlPreconditionTesting", package: "CwlPreconditionTesting",
condition: .when(platforms: [.macOS, .iOS, .macCatalyst, .visionOS])),
.product(name: "CwlPosixPreconditionTesting", package: "CwlPreconditionTesting",
condition: .when(platforms: [.tvOS, .watchOS]))
],
exclude: ["Info.plist"]
),
.target(
name: "NimbleSharedTestHelpers",
dependencies: testHelperDependencies
),
.testTarget(
name: "NimbleTests",
dependencies: ["Nimble", "NimbleSharedTestHelpers"],
exclude: ["Info.plist"]
),
]
#if os(macOS)
targets.append(contentsOf: [
.target(
name: "NimbleObjectiveC",
dependencies: ["Nimble"]
),
.testTarget(
name: "NimbleObjectiveCTests",
dependencies: ["NimbleObjectiveC", "Nimble", "NimbleSharedTestHelpers"]
)
])
#endif
return targets
}(),
swiftLanguageVersions: [.v5]
)
4 changes: 2 additions & 2 deletions Sources/Nimble/Adapters/NimbleXCTestHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class NimbleXCTestUnavailableHandler: AssertionHandler {
private var stashed_swift_reportFatalErrorsToDebugger: Bool = false

@objc public func testCaseWillStart(_ testCase: XCTestCase) {
#if (os(macOS) || os(iOS)) && !SWIFT_PACKAGE
#if (os(macOS) || os(iOS) || os(visionOS)) && !SWIFT_PACKAGE
stashed_swift_reportFatalErrorsToDebugger = _swift_reportFatalErrorsToDebugger
_swift_reportFatalErrorsToDebugger = false
#endif
Expand All @@ -56,7 +56,7 @@ class NimbleXCTestUnavailableHandler: AssertionHandler {
@objc public func testCaseDidFinish(_ testCase: XCTestCase) {
currentTestCase = nil

#if (os(macOS) || os(iOS)) && !SWIFT_PACKAGE
#if (os(macOS) || os(iOS) || os(visionOS)) && !SWIFT_PACKAGE
_swift_reportFatalErrorsToDebugger = stashed_swift_reportFatalErrorsToDebugger
#endif
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/Nimble/Matchers/BeginWith.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public func beginWith(_ startingElement: Any) -> Matcher<NMBOrderedCollection> {
return Matcher.simple("begin with <\(startingElement)>") { actualExpression in
guard let collection = try actualExpression.evaluate() else { return .fail }
guard collection.count > 0 else { return .doesNotMatch }
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) || os(visionOS)
let collectionValue = collection.object(at: 0) as AnyObject
#else
guard let collectionValue = collection.object(at: 0) as? NSObject else {
Expand Down
2 changes: 1 addition & 1 deletion Sources/Nimble/Matchers/EndWith.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public func endWith(_ endingElement: Any) -> Matcher<NMBOrderedCollection> {
guard let collection = try actualExpression.evaluate() else { return .fail }

guard collection.count > 0 else { return MatcherStatus(bool: false) }
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) || os(visionOS)
let collectionValue = collection.object(at: collection.count - 1) as AnyObject
#else
guard let collectionValue = collection.object(at: collection.count - 1) as? NSObject else {
Expand Down
2 changes: 1 addition & 1 deletion Sources/Nimble/Matchers/ThrowAssertion.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// swiftlint:disable all
#if canImport(CwlPreconditionTesting) && (os(macOS) || os(iOS))
#if canImport(CwlPreconditionTesting) && (os(macOS) || os(iOS) || os(visionOS))
import CwlPreconditionTesting
#elseif canImport(CwlPosixPreconditionTesting)
import CwlPosixPreconditionTesting
Expand Down
9 changes: 8 additions & 1 deletion Sources/Nimble/Nimble.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
#import <Foundation/Foundation.h>

// When running below Xcode 15, TARGET_OS_VISION is not defined. Since the project has TREAT_WARNINGS_AS_ERROS enabled
// we need to workaround this warning.
#ifndef TARGET_OS_VISION
#define TARGET_OS_VISION 0
#endif /* TARGET_OS_VISION */

#import <Nimble/NMBExceptionCapture.h>
#import <Nimble/NMBStringify.h>
#import <Nimble/DSL.h>

#if TARGET_OS_OSX || TARGET_OS_IOS
#if TARGET_OS_OSX || TARGET_OS_IOS || TARGET_OS_VISION
#if COCOAPODS
#import <CwlMachBadInstructionHandler/CwlMachBadInstructionHandler.h>
#import <CwlCatchExceptionSupport/CwlCatchException.h>
Expand Down
46 changes: 45 additions & 1 deletion test
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,17 @@ if which xcodebuild > /dev/null; then
LATEST_WATCHOS_SDK_VERSION=`xcodebuild -showsdks | grep -e '-sdk watchos' | cut -d ' ' -f 2 | ruby -e 'puts STDIN.read.chomp.split("\n").last'`
LATEST_WATCHOS_VERSION=`xcrun simctl list | grep ^watchOS | ruby -e 'puts /\(([0-9.]+).*\)/.match(STDIN.read.chomp.split("\n").last).to_a[1]'`
LATEST_MACOS_SDK_VERSION=`xcodebuild -showsdks | grep -e '-sdk macosx' | cut -d ' ' -f 2 | ruby -e 'puts STDIN.read.chomp.split("\n").last'`
LATEST_VISIONOS_SDK_VERSION=`xcodebuild -showsdks | grep -e '-sdk xros' | cut -d ' ' -f 2 | ruby -e 'puts STDIN.read.chomp.split("\n").last'`
LATEST_VISIONOS_VERSION=`xcrun simctl list | grep ^visionOS | ruby -e 'puts /\(([0-9.]+).*\)/.match(STDIN.read.chomp.split("\n").last).to_a[1]'`
BUILD_IOS_SDK_VERSION=${NIMBLE_BUILD_IOS_SDK_VERSION:-$LATEST_IOS_SDK_VERSION}
RUNTIME_IOS_VERSION=${NIMBLE_RUNTIME_IOS_VERSION:-$LATEST_IOS_VERSION}
BUILD_TVOS_SDK_VERSION=${NIMBLE_BUILD_TVOS_SDK_VERSION:-$LATEST_TVOS_SDK_VERSION}
RUNTIME_TVOS_VERSION=${NIMBLE_RUNTIME_TVOS_VERSION:-$LATEST_TVOS_VERSION}
BUILD_WATCHOS_SDK_VERSION=${NIMBLE_BUILD_WATCHOS_SDK_VERSION:-$LATEST_WATCHOS_SDK_VERSION}
RUNTIME_WATCHOS_VERSION=${NIMBLE_RUNTIME_WATCHOS_VERSION:-$LATEST_WATCHOS_VERSION}
BUILD_MACOS_SDK_VERSION=${NIMBLE_BUILD_MACOS_SDK_VERSION:-$LATEST_MACOS_SDK_VERSION}
BUILD_VISIONOS_SDK_VERSION=${NIMBLE_BUILD_VISIONOS_SDK_VERSION:-$LATEST_VISIONOS_SDK_VERSION}
RUNTIME_VISIONOS_VERSION=${NIMBLE_RUNTIME_VISIONOS_VERSION:-$LATEST_VISIONOS_VERSION}
fi

set -e
Expand Down Expand Up @@ -51,6 +55,11 @@ function print_env {
echo " Building with watchOS SDK: `color_if_overridden $BUILD_WATCHOS_SDK_VERSION $NIMBLE_BUILD_WATCHOS_SDK_VERSION`"
echo " Running with watchOS: `color_if_overridden $RUNTIME_WATCHOS_VERSION $NIMBLE_RUNTIME_WATCHOS_VERSION`"
echo
echo " visionOS:"
echo " Latest visionOS SDK: $LATEST_VISIONOS_SDK_VERSION"
echo " Building with visionOS SDK: `color_if_overridden $BUILD_VISIONOS_SDK_VERSION $NIMBLE_BUILD_VISIONOS_SDK_VERSION`"
echo " Running with visionOS: `color_if_overridden $RUNTIME_VISIONOS_VERSION $NIMBLE_RUNTIME_VISIONOS_VERSION`"
echo
echo " macOS:"
echo " Latest macOS SDK: $LATEST_MACOS_SDK_VERSION"
echo " Building with macOS SDK: `color_if_overridden $BUILD_MACOS_SDK_VERSION $NIMBLE_BUILD_MACOS_SDK_VERSION`"
Expand Down Expand Up @@ -85,6 +94,18 @@ function test_watchos {
run set -o pipefail && xcodebuild -project Nimble.xcodeproj -scheme "Nimble" -configuration "Debug" -sdk "watchsimulator$BUILD_WATCHOS_SDK_VERSION" -destination "name=Apple Watch Series 6 (40mm),OS=$RUNTIME_WATCHOS_VERSION" OTHER_SWIFT_FLAGS='$(inherited) -suppress-warnings' build-for-testing test-without-building | xcpretty
}

function test_visionos {
if [[ -z $LATEST_VISIONOS_SDK_VERSION ]]; then
echo "visionOS is not supported on this machine"
return
fi

run set -o pipefail && xcodebuild -project Nimble.xcodeproj -scheme "Nimble" -configuration "Debug" -destination "generic/platform=visionOS" OTHER_SWIFT_FLAGS='$(inherited) -suppress-warnings' build | xcpretty

run osascript -e 'tell app "Simulator" to quit'
run set -o pipefail && xcodebuild -project Nimble.xcodeproj -scheme "Nimble" -configuration "Debug" -sdk "xrsimulator$BUILD_VISIONOS_SDK_VERSION" -destination "name=Apple Vision Pro),OS=$RUNTIME_VISIONOS_VERSION" OTHER_SWIFT_FLAGS='$(inherited) -suppress-warnings' build-for-testing test-without-building | xcpretty
}

function test_macos {
run set -o pipefail && xcodebuild -project Nimble.xcodeproj -scheme "Nimble" -configuration "Debug" -sdk "macosx$BUILD_MACOS_SDK_VERSION" OTHER_SWIFT_FLAGS='$(inherited) -suppress-warnings' build-for-testing test-without-building | xcpretty
}
Expand Down Expand Up @@ -116,11 +137,28 @@ function test_xcode_spm_watchos {
run set -o pipefail && xcodebuild -scheme "Nimble" -configuration "Debug" -sdk "watchsimulator$BUILD_WATCHOS_SDK_VERSION" -destination "name=Apple Watch Series 6 (40mm),OS=$RUNTIME_WATCHOS_VERSION" OTHER_SWIFT_FLAGS='$(inherited) -suppress-warnings' build-for-testing test-without-building | xcpretty
}

function test_xcode_spm_visionos {
if [[ -z $LATEST_VISIONOS_SDK_VERSION ]]; then
echo "visionOS is not supported on this machine"
return
fi

run osascript -e 'tell app "Simulator" to quit'
mv Nimble.xcodeproj Nimble.xcodeproj.bak
trap 'mv Nimble.xcodeproj.bak Nimble.xcodeproj' EXIT
run set -o pipefail && xcodebuild -scheme "Nimble" -configuration "Debug" -sdk "xrsimulator$BUILD_WATCHOS_SDK_VERSION" -destination "name=Apple Vision Pro,OS=$RUNTIME_WATCHOS_VERSION" OTHER_SWIFT_FLAGS='$(inherited) -suppress-warnings' build-for-testing test-without-building | xcpretty
}

function test_podspec {
PLATFORMS="ios,tvos,watchos,macos"
if [[ ! -z $LATEST_VISIONOS_SDK_VERSION ]]; then
PLATFORMS="$PLATFORMS,visionos"
fi

echo "Gathering CocoaPods installation information..."
run bundle exec pod --version
echo "Linting podspec..."
run bundle exec pod lib lint Nimble.podspec --skip-import-validation --verbose
run bundle exec pod lib lint Nimble.podspec --skip-import-validation --verbose --platforms=$PLATFORMS
}

function test_carthage {
Expand All @@ -147,12 +185,14 @@ function test() {
test_ios
test_tvos
test_watchos
test_visionos

if xcodebuild --help 2>&1 | grep xcframework > /dev/null; then
test_xcode_spm_macos
test_xcode_spm_ios
test_xcode_spm_tvos
test_xcode_spm_watchos
test_xcode_spm_visionos
else
echo "Not testing with Swift Package Manager version of Xcode because it requires at least Xcode 11"
fi
Expand Down Expand Up @@ -189,6 +229,8 @@ function help {
echo " tvos_xcodespm - Runs the tests as an tvOS device using the Swift Package Manager version of Xcode"
echo " watchos - Runs the tests as an watchOS device"
echo " watchos_xcodespm - Runs the tests as an watchOS device using the Swift Package Manager version of Xcode"
echo " visionos - Runs the tests as an visionOS device"
echo " visionos_xcodespm - Runs the tests as an visionOS device using the Swift Package Manager version of Xcode"
echo " podspec - Runs pod lib lint against the podspec to detect breaking changes"
echo " carthage - Runs verifyies that the carthage artifacts build"
echo " swiftpm - Runs the tests built by the Swift Package Manager"
Expand All @@ -209,6 +251,8 @@ function main {
tvos_xcodespm) test_xcode_spm_tvos ;;
watchos) test_watchos ;;
watchos_xcodespm) test_xcode_spm_watchos ;;
visionos) test_visionos ;;
visionos_xcodespm) test_xcode_spm_visionos ;;
macos) test_macos ;;
macos_xcodespm) test_xcode_spm_macos ;;
podspec) test_podspec ;;
Expand Down

0 comments on commit 52c7526

Please sign in to comment.