Skip to content

Issues with BranchSDK and Swift macros #941

@jpsim

Description

@jpsim

This is a bit of a tricky one. If I have BranchSDK and Swift macros in my iOS app, everything works fine on the command line, but break in one way or another in rules_xcodeproj.

Here's some sample changes applied to the Lottie iOS example in this repo as a repro case:

--- a/examples/lottie_ios_example/LottieExample/AppDelegate.swift
+++ b/examples/lottie_ios_example/LottieExample/AppDelegate.swift
@@ -2,6 +2,7 @@
 // Copyright © 2022 Airbnb Inc. All rights reserved.
 
 import UIKit
+import BranchSDK
 
 @main
 class AppDelegate: UIResponder, UIApplicationDelegate {
@@ -14,3 +15,27 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
   }
 }
 
+
+import Foundation
+import Dependencies
+import DependenciesMacros
+
+// MARK: - MyDependency
+
+extension DependencyValues {
+    var myDep: MyDependency {
+        get { self[MyDependency.self] }
+        set { self[MyDependency.self] = newValue }
+    }
+}
+
+@DependencyClient
+struct MyDependency: Sendable {
+    var perform: @Sendable () throws -> Void
+}
+
+extension MyDependency: DependencyKey {
+    static let liveValue = MyDependency(perform: {
+        print("Hello from MyDependency")
+    })
+}
--- a/examples/lottie_ios_example/LottieExample/BUILD.bazel
+++ b/examples/lottie_ios_example/LottieExample/BUILD.bazel
@@ -13,7 +13,12 @@ swift_library(
     module_name = "LottieExample",
     tags = ["manual"],
     visibility = ["//visibility:public"],
-    deps = ["@swiftpkg_lottie_spm//:Lottie"],
+    deps = [
+        "@swiftpkg_ios_branch_sdk_spm//:BranchSDK",
+        "@swiftpkg_swift_dependencies//:Dependencies",
+        "@swiftpkg_swift_dependencies//:DependenciesMacros",
+        "@swiftpkg_lottie_spm//:Lottie",
+    ],
 )
 
 ios_application(
--- a/examples/lottie_ios_example/MODULE.bazel
+++ b/examples/lottie_ios_example/MODULE.bazel
@@ -49,6 +49,8 @@ swift_deps.from_file(
 )
 use_repo(
     swift_deps,
+    "swiftpkg_ios_branch_sdk_spm",
     "swiftpkg_lottie_spm",
+    "swiftpkg_swift_dependencies",
 )
 # swift_deps END
--- a/examples/lottie_ios_example/Package.swift
+++ b/examples/lottie_ios_example/Package.swift
@@ -6,5 +6,7 @@ let package = Package(
     name: "lottie_ios_example",
     dependencies: [
         .package(url: "https://github.com/airbnb/lottie-spm", from: "4.4.1"),
+        .package(url: "https://github.com/BranchMetrics/ios-branch-sdk-spm", exact: "3.3.0"),
+        .package(url: "https://github.com/pointfreeco/swift-dependencies", exact: "1.2.1"),
     ]
 )

Everything builds fine with bazel build //LottieExample:iosapp.

However, with Xcode and rules_xcodeproj, I get errors like this:

rules_swift_package_manager~override~swift_deps~swiftpkg_ios_branch_sdk_spm/BranchSDK/module.modulemap:1:8: error: redefinition of module 'BranchSDK'
module "BranchSDK" {
       ^
rules_swift_package_manager~override~swift_deps~swiftpkg_ios_branch_sdk_spm/Framework/module.modulemap:1:18: note: previously defined here
framework module BranchSDK {
                 ^

Similarly, I get the same errors if I build from the command with bazel build --spawn_strategy=standalone //LottieExample:iosapp.

If I follow the instructions in the FAQ to enable sandboxing to work around this, then the BranchSDK module builds but Swift macros break because they violate the sandbox:

$ bazel build --spawn_strategy=sandboxed,remote,worker,local //LottieExample:iosapp
INFO: From Compiling Swift module @@rules_swift_package_manager~override~swift_deps~swiftpkg_swift_dependencies//:DependenciesMacros.rspm:
sandbox-exec: sandbox_apply: Operation not permitted
<unknown>:0: warning: compiler plugin not loaded: '/private/var/tmp/_bazel_jsimard/00d2abe118e4e56c1b7d05adaab0b6c8/execroot/_main/bazel-out/darwin_arm64-opt-exec-ST-13d3ddad9198/bin/external/rules_swift_package_manager~override~swift_deps~swiftpkg_swift_dependencies/DependenciesMacrosPlugin.rspm; failed to initialize
external/rules_swift_package_manager~override~swift_deps~swiftpkg_swift_dependencies/Sources/DependenciesMacros/Macros.swift:118:14: warning: external macro implementation type 'DependenciesMacrosPlugin.DependencyClientMacro' could not be found for macro 'DependencyClient()'
public macro DependencyClient() =
             ^
external/rules_swift_package_manager~override~swift_deps~swiftpkg_swift_dependencies/Sources/DependenciesMacros/Macros.swift:187:14: warning: external macro implementation type 'DependenciesMacrosPlugin.DependencyEndpointMacro' could not be found for macro 'DependencyEndpoint(method:)'
public macro DependencyEndpoint(method: String = "") =
             ^
sandbox-exec: sandbox_apply: Operation not permitted
<unknown>:0: warning: compiler plugin not loaded: '/private/var/tmp/_bazel_jsimard/00d2abe118e4e56c1b7d05adaab0b6c8/execroot/_main/bazel-out/darwin_arm64-opt-exec-ST-13d3ddad9198/bin/external/rules_swift_package_manager~override~swift_deps~swiftpkg_swift_dependencies/DependenciesMacrosPlugin.rspm; failed to initialize
external/rules_swift_package_manager~override~swift_deps~swiftpkg_swift_dependencies/Sources/DependenciesMacros/Macros.swift:118:14: warning: external macro implementation type 'DependenciesMacrosPlugin.DependencyClientMacro' could not be found for macro 'DependencyClient()'
public macro DependencyClient() =
             ^
external/rules_swift_package_manager~override~swift_deps~swiftpkg_swift_dependencies/Sources/DependenciesMacros/Macros.swift:187:14: warning: external macro implementation type 'DependenciesMacrosPlugin.DependencyEndpointMacro' could not be found for macro 'DependencyEndpoint(method:)'
public macro DependencyEndpoint(method: String = "") =
             ^

ERROR: /Users/jsimard/src/rules_swift_package_manager/examples/lottie_ios_example/LottieExample/BUILD.bazel:6:14: Compiling Swift module //LottieExample:LottieExample failed: (Exit 1): worker failed: error executing SwiftCompile command (from target //LottieExample:LottieExample) 
  (cd /private/var/tmp/_bazel_jsimard/00d2abe118e4e56c1b7d05adaab0b6c8/sandbox/darwin-sandbox/152/execroot/_main && \
  exec env - \
    APPLE_SDK_PLATFORM=iPhoneSimulator \
    APPLE_SDK_VERSION_OVERRIDE=17.2 \
    PATH=/bin:/usr/bin:/usr/local/bin \
    SWIFT_AVOID_WARNING_USING_OLD_DRIVER=1 \
    XCODE_VERSION_OVERRIDE=15.2.0.15C500b \
  bazel-out/darwin_arm64-opt-exec-ST-13d3ddad9198/bin/external/rules_swift~1.16.0/tools/worker/worker swiftc @bazel-out/ios_sim_arm64-fastbuild-ios-sim_arm64-min13.0-applebin_ios-ST-91e00ca0df9e/bin/LottieExample/LottieExample.swiftmodule-0.params)
# Configuration: 46ae69df7f021f5ca14c686c812107a06acd0a16562cc65620238f9a52de920b
# Execution platform: @@local_config_platform//:host

Use --sandbox_debug to see verbose messages from the sandbox and retain the sandbox build root for debugging
sandbox-exec: sandbox_apply: Operation not permitted
<unknown>:0: warning: compiler plugin not loaded: '/private/var/tmp/_bazel_jsimard/00d2abe118e4e56c1b7d05adaab0b6c8/execroot/_main/bazel-out/darwin_arm64-opt-exec-ST-13d3ddad9198/bin/external/rules_swift_package_manager~override~swift_deps~swiftpkg_swift_dependencies/DependenciesMacrosPlugin.rspm; failed to initialize
LottieExample/AppDelegate.swift:33:8: error: external macro implementation type 'DependenciesMacrosPlugin.DependencyClientMacro' could not be found for macro 'DependencyClient()'
struct MyDependency: Sendable {
       ^
DependenciesMacros.DependencyClient:1:79: note: 'DependencyClient()' declared here
@attached(member, names: named(init)) @attached(memberAttribute) public macro DependencyClient() = #externalMacro(module: "DependenciesMacrosPlugin", type: "DependencyClientMacro")
                                                                              ^
LottieExample/AppDelegate.swift:34:9: error: external macro implementation type 'DependenciesMacrosPlugin.DependencyClientMacro' could not be found for macro 'DependencyClient()'
    var perform: @Sendable () throws -> Void
        ^
DependenciesMacros.DependencyClient:1:79: note: 'DependencyClient()' declared here
@attached(member, names: named(init)) @attached(memberAttribute) public macro DependencyClient() = #externalMacro(module: "DependenciesMacrosPlugin", type: "DependencyClientMacro")
                                                                              ^
error: emit-module command failed with exit code 1 (use -v to see invocation)
sandbox-exec: sandbox_apply: Operation not permitted
<unknown>:0: warning: compiler plugin not loaded: '/private/var/tmp/_bazel_jsimard/00d2abe118e4e56c1b7d05adaab0b6c8/execroot/_main/bazel-out/darwin_arm64-opt-exec-ST-13d3ddad9198/bin/external/rules_swift_package_manager~override~swift_deps~swiftpkg_swift_dependencies/DependenciesMacrosPlugin.rspm; failed to initialize
LottieExample/AppDelegate.swift:33:8: error: external macro implementation type 'DependenciesMacrosPlugin.DependencyClientMacro' could not be found for macro 'DependencyClient()'
struct MyDependency: Sendable {
       ^
DependenciesMacros.DependencyClient:1:79: note: 'DependencyClient()' declared here
@attached(member, names: named(init)) @attached(memberAttribute) public macro DependencyClient() = #externalMacro(module: "DependenciesMacrosPlugin", type: "DependencyClientMacro")
                                                                              ^
LottieExample/AppDelegate.swift:34:9: error: external macro implementation type 'DependenciesMacrosPlugin.DependencyClientMacro' could not be found for macro 'DependencyClient()'
    var perform: @Sendable () throws -> Void
        ^
DependenciesMacros.DependencyClient:1:79: note: 'DependencyClient()' declared here
@attached(member, names: named(init)) @attached(memberAttribute) public macro DependencyClient() = #externalMacro(module: "DependenciesMacrosPlugin", type: "DependencyClientMacro")
                                                                              ^
error: fatalError

So any way I slice it, I can't get both BranchSDK and Swift macros to be buildable in Xcode.

It's possible that some of this becomes fixable (in rules_swift?) in Swift 5.10 which will include this change: swiftlang/swift#70079

But it seems like the right fix would be to get packages like BranchSDK (and Firebase I imagine) buildable with sandboxing disabled.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions