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?
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.
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.
Hi all,
Just adding a note that I've tried to incorporate these suggestions into my Xcode-based iOS project, to no avail.
Has anyone had any progress or insights on this in the last few years?
I tried incorporating the above swiftc
commands into the SPM Package.swift
(via swiftSettings
and unsafeFlags
of various configurations) and Xcode (via Other Swift Flags
) but couldn't figure out the correct machination.
Usecase is a third-party SPM package which uses:
- the module name
Experiment
- implements a type named
Experiment
...and I want to implement a type named Experiment
in my own project.
I'm observing the Swift compiler preferring to always disambiguate to my project's namespace, preventing me from ever being able to address the SPM module's implementation.
What flag did you pass? You could add -module-alias Experiment=ThirdPartyExperiment
to OTHER_SWIFT_FLAGS
if it's an Xcode project, or add the following to Package.swift
if SPM.
Target(
name: "MyTarget",
dependencies: [
.product(name: "Experiment", package: "third-party", moduleAliases: ["Experiment": "ThirdPartyExperiment"]),
])
And then import ThirdPartyExperiment
in source file to distinguish it from your local Experiment
target.