How to use the new module disambiguation in Xcode projects?

Swift 5.7 introduced the module disambiguation feature. But the problem I'm having is that how do I use that feature in my Xcode app project? I'm not developing a Swift package, so I don't have the package.swift file. I'm using a package called Regex with a top level class also called Regex, and there seems no way to solve the error of name clashing with the new standard library built in Regex. The WWDC videos only vaguely mentioned this topic, and I can't find any other resources explaining this issue. Am I missing something?

1 Like

Xcode needs to add support for the feature in its package UI. Unfortunately that doesn't seem to have happened this year so perhaps we'll see it next year.

In the meantime, you could try creating a local Package which renames the module and then vends it using @_exported import NewName in a single source file. Then importing the new package may give access to the Regex types under the imported module name, allowing you to disambiguate.

Just because SPM has a feature doesn't mean Xcode's package interface will expose it.

I'm trying to look but Xcode 14b2's package interface just sits on a spinner for me. Cool.

2 Likes

Currently the build system that supports module disambiguation is SwiftPM only (see proposal for more info); a new parameter moduleAliases is introduced and can be used as seen here. The parameter is not yet available on Xcode UI, so access to the user package manifest is needed.

If SwiftPM is not used as a build system, a new compiler flag in 5.7 called -module-alias can directly be applied to a build command line to enable module name disambiguation. For example, if module Foo depends on module Bar, and Bar needs to be renamed as Baz, running the following command lines will allow disambiguation:

swiftc -module-name Baz -module-alias Bar=Baz -o /path/to/Baz.swiftmodule
swiftc -module-name Foo -module-alias Bar=Baz -o /path/to/Foo.swiftmodule

The first line will create Baz.swiftmodule which was originally named Bar, and the second line will compile any references to Bar in module Foo as Baz.

I really like your solution compared to creating my own intermediary package. So for my Xcode project, I can add these commands into the Swift Compiler - Customs Flag section? How would I specify the path to the Swift module? I can't hard code the path because the module itself are in Xcode's derived data folder.

Also, is there no way to customize a package.swift file in an Xcode app project? Especially when the example used the in Swift evolution proposal involves an App. swift-evolution/0339-module-aliasing-for-disambiguation.md at main · apple/swift-evolution · GitHub

No, package dependencies in Xcode are stored in the project file itself, so it's up to Xcode's implementation what properties and behaviors it supports.

As for the path to the swiftmodule files, you may be able to use one of Xcode's computed environment values to provide your DerivedData path. I don't know if that would work though.

You can modify Package.swift if it's the manifest of a package you created; the example App in the proposal is a user-created package.

You might have to use an environment value in your path and add that to search paths as well.