Swift Package used in tests cannot build for arm64 architecture

Recently in our large enterprise app workspace, we have added many new locally-declared Swift packages, one of which, "CombineTestExtensions", declares some custom extensions to XCTest for use in testing with Combine—however, CombineTestExtensions itself is declared as a "target" in SPM (not as a "testTarget"), because it contains no actual tests that should run (it's just used by other test targets).

This setup builds fine for the simulator, however, it has it impossible to build our AllUnitTests scheme when the target is a physical iOS device (arm64, iPad Air 2). We get the following compiler errors when the compiler tries to build CombineTestExtensions:

Undefined symbol: _swift_FORCE_LOAD$XCTestSwiftSupport
Undefined symbol: XCTest.XCTFail(
: Swift.String, file: Swift.StaticString, line: Swift.UInt) -> ()

So I tried to explicitly link XCTest by adding .linkerSettings([.linkedFramework("XCTest")]) to the CombineTestExtensions target. However this merely changes the error to:

'/Applications/Xcode-12.3.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest.framework/XCTest' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. file '/Applications/Xcode-12.3.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest.framework/XCTest' for architecture arm64

Also tried .linkerSettings([.linkedLibrary("XCTestSwiftSupport")]) but that doesn't work either. It just leads to the error:

'/Applications/Xcode-12.3.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/lib/libXCTestSwiftSupport.dylib' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. file '/Applications/Xcode-12.3.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/lib/libXCTestSwiftSupport.dylib' for architecture arm64

Obviously, I can't rebuild XCTest or XCTestSwiftSupport with bitcode enabled.

So... how do I disable bitcode for the CombineTestExtensions target?

I tried this, but it does nothing:

        cSettings: [.define("ENABLE_BITCODE", to: "NO")],

For the record, how do you know which Xcode build settings are cSettings, which ones are cxxSettings, which ones are swiftSettings, which ones are linkerSettings, and which ones of those can only be set using unsafeFlags? Is there a list somewhere? I have googled high and low to find such a list but this seems to be purely the domain of tribal knowledge.

Side note: for Swift 6, could we please please please update SPM so that, rather than all these settings being strings you have to know in advance, instead, each possible setting is an enum case or a variable on a struct with doc comments, e.g.:

enum SwiftSettings {
    /// Explicitly defines whether bitcode is enabled for the target (default is true)
    case isBitCodeEnabled(Bool)
    // .. all the other possible settings
}

or

struct SwiftSettings {
    /// Whether or not bitcode is enabled for this package. (default is true)
    let isBitcodeEnabled: Bool = true
    // .. all the other possible settings
}

Thanks!

Note: I asked about how to change the ENABLE_BITCODE setting for Swift Packages back in December but nobody ever answered. Post link

Finally determined that making the CombineTestExtensions package product not be explicitly declared as .dynamic solves the build errors as long as the targets that import it are, themselves, declared as a testTarget and not a target.

1 Like