diff --git a/.bazelrc b/.bazelrc index 6838046..34db17a 100644 --- a/.bazelrc +++ b/.bazelrc @@ -30,6 +30,10 @@ build:clang --host_cxxopt="-fno-exceptions" build:clang --cxxopt="-fvisibility=hidden" build:clang --host_cxxopt="-fvisibility=hidden" +# iOS setup +build:ios --ios_multi_cpus=sim_arm64 +build:ios --@rules_apple//apple/build_settings:ios_simulator_device="iPhone 16 Pro" + # Platform-specific options for each supported platform. build:remote_linux_x64 --extra_execution_platforms=//platform/linux_x64 build:remote_linux_x64 --host_platform=//platform/linux_x64 @@ -42,6 +46,9 @@ build:remote_macos_arm64 --platforms=//platform/macos_arm64 build:remote_macos_arm64 --macos_minimum_os=14 build:remote_macos_arm64 --action_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1 build:remote_macos_arm64 --host_action_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1 +build:remote_macos_arm64 --xcode_version_config=//platform/macos_arm64:installed_xcodes +# Disable workers: Builds fail with remote swift workers +build:remote_macos_arm64 --experimental_remote_mark_tool_inputs=false build:remote_windows_x64 --host_platform=//platform/windows_x64 build:remote_windows_x64 --platforms=//platform/windows_x64 diff --git a/MODULE.bazel b/MODULE.bazel index 207b8a9..c35488b 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -51,6 +51,7 @@ bazel_dep(name = "platforms", version = "1.1.0") bazel_dep(name = "protobuf", version = "35.0") bazel_dep(name = "apple_support", version = "2.6.1") bazel_dep(name = "rules_cc", version = "0.2.19") +bazel_dep(name = "rules_apple", version = "5.0.0-rc2") bazel_dep( name = "googleapis", version = "0.0.0-20260525-ef19b7b7", diff --git a/README.md b/README.md index ba3de5e..7042036 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,13 @@ locally before attempting remote execution. bazel build //... ``` +- `ios`: + + ``` + # --config=ios is needed to properly set up the device simulators for testing + bazel build --config=ios //ios:all + ``` + - `swift`: ```sh @@ -81,6 +88,14 @@ locally before attempting remote execution. bazel test //... ``` +- `ios`: + + This will only work on a macOS device with XCode (and the necessary iPhone simulators) installed. + + ```sh + bazel test --config=ios //ios:all + ``` + - `swift`: ```sh @@ -141,6 +156,14 @@ isn't enabled in your `.bazelrc.user` file. bazel build //... ``` +- `ios`: + + These can only be built remotely on a macOS worker with the matching XCode installed. + + ```sh + bazel build --config=ios --config=remote_macos_arm64 --config=opal //ios:all + ``` + - `swift`: ```sh @@ -161,6 +184,16 @@ isn't enabled in your `.bazelrc.user` file. bazel test //... ``` +- `ios`: + + These can only be tested remotely on a macOS worker with the matching XCode installed. + + **NOTE:** Currently, `ios_ui_test` on a remote cluster is not working due to a permissions mismatch). + + ```sh + bazel test --config=ios --config=remote_macos_arm64 //ios:all + ``` + - `swift`: ```sh diff --git a/infra/test-all.py b/infra/test-all.py index 88af3a9..7a62415 100644 --- a/infra/test-all.py +++ b/infra/test-all.py @@ -5,9 +5,11 @@ import sys def main(): - # All targets that can run in any environment. + # All targets that can run in any environment, except ios examples. targets = [ "//...", + # TODO: Add testing configuration for ios tests. + "-//ios/...", ] for key in ("ARCH", "OPAL_RPC_CREDENTIALS", "OS", "REMOTE_EXECUTION"): diff --git a/ios/BUILD.bazel b/ios/BUILD.bazel new file mode 100644 index 0000000..ab1fdf9 --- /dev/null +++ b/ios/BUILD.bazel @@ -0,0 +1,50 @@ +load("@rules_apple//apple:ios.bzl", "ios_application", "ios_ui_test", "ios_unit_test") +load("@rules_swift//swift:swift.bzl", "swift_library") + +swift_library( + name = "HelloAppLibrary", + srcs = ["HelloApp.swift"], + tags = ["manual"], +) + +ios_application( + name = "HelloApp", + bundle_id = "com.engflow.helloapp", + families = [ + "iphone", + "ipad", + ], + minimum_os_version = "26.0", + deps = [":HelloAppLibrary"], +) + +swift_library( + name = "HelloTestLib", + testonly = True, + srcs = ["HelloTest.swift"], + tags = ["manual"], +) + +ios_unit_test( + name = "HelloTest", + minimum_os_version = "26.0", + deps = [":HelloTestLib"], +) + +swift_library( + name = "HelloAppUITestLib", + testonly = True, + srcs = [ + "HelloAppUITest.swift", + ], + module_name = "HelloAppUITest", + tags = ["manual"], +) + +ios_ui_test( + name = "HelloAppUITest", + minimum_os_version = "26.0", + runner = "@rules_apple//apple/testing/default_runner:ios_xctestrun_ordered_runner", + test_host = ":HelloApp", + deps = [":HelloAppUITestLib"], +) diff --git a/ios/HelloApp.swift b/ios/HelloApp.swift new file mode 100644 index 0000000..2e1f9bd --- /dev/null +++ b/ios/HelloApp.swift @@ -0,0 +1,23 @@ +import SwiftUI + +@main +struct HelloApp: App { + var body: some Scene { + WindowGroup { + ContentView() + } + } +} + +struct ContentView: View { + var body: some View { + VStack { + Image(systemName: "globe") + .imageScale(.large) + .foregroundStyle(.tint) + Text("Hello, world!") + .accessibility(identifier: "HELLO_WORLD") + } + .padding() + } +} diff --git a/ios/HelloAppUITest.swift b/ios/HelloAppUITest.swift new file mode 100644 index 0000000..3f5a8a5 --- /dev/null +++ b/ios/HelloAppUITest.swift @@ -0,0 +1,22 @@ +import XCTest + +class HelloAppUITest: XCTestCase { + var application: XCUIApplication! + + override func setUp() { + super.setUp() + continueAfterFailure = false + application = .init() + application.launch() + } + + override func tearDown() { + application.terminate() + application = nil + } + + func testIsActive() { + XCTAssertTrue(application.staticTexts["HELLO_WORLD"].exists) + } +} + diff --git a/ios/HelloTest.swift b/ios/HelloTest.swift new file mode 100644 index 0000000..a7d764e --- /dev/null +++ b/ios/HelloTest.swift @@ -0,0 +1,10 @@ +import Testing + +@Suite +struct HelloTest { + @Test + func example() { + print("Hello from HelloTest") + #expect(1 + 1 == 2) + } +} diff --git a/platform/macos_arm64/BUILD b/platform/macos_arm64/BUILD index c5e8303..3888f67 100644 --- a/platform/macos_arm64/BUILD +++ b/platform/macos_arm64/BUILD @@ -1,5 +1,10 @@ +load("@apple_support//xcode:available_xcodes.bzl", "available_xcodes") +load("@apple_support//xcode:xcode_config.bzl", "xcode_config") +load("@apple_support//xcode:xcode_version.bzl", "xcode_version") + package(default_visibility = ["//visibility:public"]) +# The platform definition for a remote mac worker. platform( name = "macos_arm64", constraint_values = [ @@ -10,3 +15,38 @@ platform( "Pool": "macos_arm_m2", }, ) + +# The XCode installed on the remote worker. +xcode_version( + name = "version26_5_0_17F42", + aliases = [ + "26.5.0", + "26.5", + "17F42", + "26.5.0.17F42", + "26", + ], + default_ios_sdk_version = "26.5", + default_macos_sdk_version = "26.5", + default_tvos_sdk_version = "26.5", + default_visionos_sdk_version = "26.5", + default_watchos_sdk_version = "26.5", + version = "26.5.0.17F42", +) + +xcode_config( + name = "installed_xcodes", + default = ":version26_5_0_17F42", + versions = [ + ":version26_5_0_17F42", + ], +) + +available_xcodes( + name = "available_xcodes", + default = ":version26_5_0_17F42", + versions = [ + ":version26_5_0_17F42", + ], +) +