"Missing required module 'X" error in Xcode after setting language version to Swift 6

We're using CocoaPods in our project and we noticed the compiler fails to build some modules with "Missing required module 'x'" error when built in Swift 6.

I've set up a demo project with some repro steps where there is a CoreFeatureFramework framework that depends on LoggerFramework, a dynamic framework that depends on the external library CocoaLumberjack.

After running pod install, if we try to build, the error only appears when the Swift Language version is set to Swift 6 but not when is set to Swift 5. It seems the issue can be solved by manually adding the search path for CocoaLumberjack in the CoreFeatureFramework build settings or if we add CocoaLumberjack as a dependency of CoreFeatureFramework in the Podfile.

This issue arises as our team is migrating the project from Swift 5 to Swift 6. We have numerous pod dependencies, and almost all modules are affected after setting the language version to Swift 6, resulting in errors and blocking the build.

We'd like to understand the reason behind this behavior and ask for any suggestions on how to deal with this issue.

SE-0444 (MemberImportVisibility) made this problem. It is source breaking. The reason behind it is outlined in the proposal, but the gist of it is:

  • modules should now be explicitly imported in every file where used
  • it fixes previous leaky behavior of modules, preventing some confusing errors

I think this is a great addition to the language, albeit breaking previous code that was using modules that were leaked into files/projects.

3 Likes

@RandomHashTags, thank you for the response!

We're not sure if that is actually what's causing the issue we're seeing. If I understand correctly, with SE-0444, it now prevents leaky member visibility to files that don't directly import the member's source module or directly import a module that re-exports such module.

That said, in our example we're seeing the issue as soon as we import the module, not when using any of its members. For example, in a scenario where A depends on B and B depends on C, we'll see the issue "Missing required module 'C'" in A as soon as we import B and try to build.

However, we found out this only happens if C is publicly imported in B (which is the default in Swift 5 & 6 according to SE-0409). So, if in our example we use the internal access modifier to import C in B:

// Module B
internal import C

This get rids of the error. However, there are places where we'll need to import modules publicly, in which case it'll require us to add C to the search paths of A. This wasn't required before and we noticed it only occurs when we try to build in Swift 6.

So, if SE-0444 is causing this issue I'd like to get a better understanding on how it's doing that. I noticed that MemberImportVisibility is under the // Swift 7 section at Features.def, so it's unclear to me if this flag is enabled by default when building in Swift 6. I also tried adding -enable-experimental-feature MemberImportVisibility when building in Swift 5 but didn't see a difference either, the target built successfully.

So, my current thought is that this particular issue might be related to SE-0409 and some other change introduced in Swift 6 instead. I think it's not SE-0409 alone since I'm also not seeing any changes when only adding -enable-experimental-feature AccessLevelOnImport and building in Swift 5.

I'm currently building the project on a M1 Max, Xcode 16.1 and using:
swift-driver version: 1.115 Apple Swift version 6.0.2 (swiftlang-6.0.2.1.2 clang-1600.0.26.4)

I'll appreciate if you could provide further guidance on the root cause of this issue as we'd like to get a better understanding on what's happening so we can know what the appropriate solution will be for us.

I'm no expert in using CocoaPods, but I did release an iOS App using them years ago. I've been using the Swift Package Manager ever since due to numerous problems I was having with no solution when working with Xcode and third-party dependencies. I've only had bad experiences with CocoaPods.

Access control of imports is new in Swift 6 and I do not recommend using them unless you know for an absolute certainty that they're what you need.

I always use the Swift Package Manager to manage modules, dependencies, platform requirements, and other project settings. It is pretty straightforward when you learn how to use it.

I am confident that your issues will disappear or become a lot easier to fix by switching your project to use the Swift Package Manager. I'm sure others here, including myself, would help you getting things setupor watch a YouTube tutorial :).

@osv I am encountering a similar issue while migrating to Swift 6 with the TrueTime framework, which internally relies on the CTrueTime library. Have you found a solution to this? I seem to have hit a dead end and would appreciate any guidance.