Xcode 12.5b2 - unit testing target compile error with SPM dependency

I'm unsure if this is an Xcode-specific bug or a bug with SPM, but I'm trying out the new beta to see if the new support for dynamic linking of SPM dependencies would solve an issue I've been having trying to move some unit testing support code into a package library.

This Package.swift demonstrates my scenario - CasePaths is the actual dependency I'm having trouble with but I don't know if the issue lies with that or elsewhere:

let package = Package(
    name: "MyLibrary",
    platforms: [.iOS(.v13), .macOS(.v10_15)],
    products: [
        .library(
            name: "MyLibrary",
            targets: ["MyLibrary"]
        ),
        .library(
            name: "MyLibraryTestHelpers",
            targets: ["MyLibraryTestHelpers"]
        )
    ],
    dependencies: [
        .package(url: "https://github.com/pointfreeco/swift-case-paths", from: "0.1.2")
    ],
    targets: [
        .target(
            name: "MyLibrary",
            dependencies: [
                .product(name: "CasePaths", package: "swift-case-paths")
            ]
        ),
        .target(
            name: "MyLibraryTestHelpers",
            dependencies: ["MyLibrary"] // also uses XCTest but I think that's fine?
        ),
        .testTarget(
            name: "MyLibraryTests",
            dependencies: ["MyLibrary"]
        )
    ]
)

This is a local package alongside an iOS app target in an Xcode workspace. The app target (MyApp) has a dependency on MyLibrary and the app's unit test bundle (MyAppTests) has a dependency on MyLibraryTestHelpers. I was never able to get this to work in previous Xcode versions due to the diamond dependency problem and I'm hoping the new dynamic linking feature in 12.5b2 solves this but I can't even get that far.

Here's what does work:

  • I can use the MyLibrary Xcode scheme to successfully compile MyLibrary in isolation.
  • I can use the MyLibrary Xcode scheme to successfully compile and run all of the tests (in the MyLibraryTests test target) for MyLibrary.
  • I can build my app target using the app's scheme - it builds all of its dependencies, including MyLibrary without issue.

What I cannot do is compile MyAppTests - it immediately fails trying to compile MyLibrary (which it implicitly depends on through its dependency on MyLibraryTestHelpers) with the error, No such module "CasePaths".

I don't understand why it cannot find the CasePaths module when trying to compile MyLibrary in this scenario, when it compiles fine in all other scenarios.

While trying to get this work I also frequently ran into "The build system has crashed, please re-open your workspace" errors but I put this down to general beta instability.

2 Likes

This is still failing in 12.5b3 - is this an Xcode or an SPM bug?

Update: I may have found a workaround. If I remove the dependency on "MyLibrary" from "MyLibraryTestHelpers" (so it has no dependencies), then I can build my app for testing and run my unit tests just fine.

Of course, this means I can no longer compile "MyLibraryTestHelpers" in isolation using the Xcode scheme for that library - it complains about "No such module" because its trying to import MyLibrary and I'm no longer including it in its dependencies.

I feel like it should be declaring the modules it depends on but doing that prevents me from building my app test target. Removing them flips it around. I can probably live with this but there must be either a bug or I'm missing something obvious.

I've tried setting MyLibrary as dynamic to see if that solves the problem but then I just run into a code signing issue like this: Xcode 12.5 and automatic dynamic linking of products

2 Likes

I'm running into exactly the same problem, like, exactly! Would love to see a fix for this :slightly_smiling_face:

I'm seeing the same issue in 12.5 release. Removing the dependency as suggested by @lukeredpath works. Has this been reported as a bug?

Same problem here, though in my app with 3rd party packages imported via Xcode Packages menu. Should work fine on earlier versions, but I only discovered this after upgrading my codebase to Xcode 12.5

Any recommendations?

I join the chorus.

Setup:

  • Xcode project for an iOS app Foo
  • app has Sentry has swift package dependency
  • unit test target in the same project of the app
  • when trying to do @testable import Foo I get Missing required module 'Sentry'

Sorry, I had missed this thread so far.

Does adding a dependency from the unit test target to the "missing" package product work?

I am not sure I understand what you mean.

I managed to have a sample project at this repo https://github.com/codedbypm/Foo which has my same error.

If you check it out and run the tests you will see the error in the unit test file missing package Sentry.
I am sure this can help: commenting import Sentry out from FooApp.swift makes the unit tests build green.

Thanks for the example.

What I meant and what seems to work for the example is adding the "Sentry" library product explicitly as a linked library to "FooTests".

Oh jeez. I knew it was was something small and trivial. That fixes indeed the sample project.
Tomorrow I will try the same with my current work app and will report.
Many thanks for now!

Hmm, this doesn’t seem like the same problem as what I originally reported.

Sadly this is still a problem. I’ve had to give up on linking this test library to my app test target as it just breaks dependency resolution. I’m guessing it’s something to do with the way app test targets are embedded in the app as a test host.

I’m now just copying the files from my test library into my app test target directly and only using the library version for my SPM test targets.

Simple question: since you mentioned embedding in your host app, have you tried to build and run your unit test bundle without a host app? If your setup allow that, of course

No because our tests aren’t set up that way right now and I don’t even know if they will run outside of a test host.

Anyone have any luck determining the root cause here? I am running into the same (or something very similar) in my large project. I'm currently working on getting our app tests running with the "AppTestHelper" library supplied via SPM-- but then ran into this.

I'm up to Xcode 13.2 now.

I just stumbled upon this thread because I am seeing the same behavior currently in Xcode 13.3. Any idea for a workaround?

1 Like

I think my team is seeing this in Xcode 14.1. It's been incredibly frustrating trying to debug this, as Xcode really doesn't log much that I can see to help diagnose or fix package issues when they arise.

Did you have any luck fixing or working around this, Mike?

1 Like

Hi Tony! Sorry I missed this earlier. I don't remember with 100% certainty, but I think we worked around this by moving the problematic tests fully into SPM as a .testTarget(), which works fine.

1 Like

@NeoNacho Thanks for your response! Do you know why this is needed? My unit tests doesn't use any code from the Swift package, should it still be needed?

@lukeredpath I think I am running into the same issue as yours, and have noticed something peculiar about how the library gets compiled in the test target.
Looking at the build log, the Emitting module for MyLibrary phase fails with the No such module error. The invoked command is fairly long but when breaking down I clearly saw some paths were wrongly defined (some output omitted for clarity):

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-frontend
[...]
-I /my/path/to/DerivedData/App-acbcde/Build/Products/Debug-iphonesimulator/PackageFrameworks
-F /my/path/to/DerivedData/App-abcde/Products/Debug-iphonesimulator/PackageFrameworks/PackageFrameworks

For reasons I do not understand yet, PackageFrameworks is incorrectly appended in those paths, so the folders pointing to the existing modules are empty and the command fails. I verified that adjusting the path manually and executing the command again completes without errors.

I believe if we could figure out a way to correct these paths the whole test target compilation would succeed, but I have to admit I don't really know where to start investigating this issue. I may open a new thread since you already seem to have found a workaround.

Also running into this. Same as @erudel, I can remove PackageFrameworks from the path and the build command succeeds. @erudel did you find a workaround for this?