Skip to content

Commit 5398153

Browse files
authored
New technique for resolving module name conflicts to module alias docs (#8979)
Conflicts can arise due to duplicate module names within a package graph. Module aliases themselves if they are not globally unique can introduce further conflicts. The documentation for the module aliases feature can describe a technique for the naming that can help to reduce the likelihood of further collisions by recommending the use of the package identifier as a qualifier to the alias. As other packages in the graph encounter the collision, this system can help for there to be a broader agreement on the new name, which should lessen the cases where module alias chaining is needed.
1 parent 59f3e8d commit 5398153

File tree

1 file changed

+16
-16
lines changed

1 file changed

+16
-16
lines changed

Documentation/ModuleAliasing.md

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
## Overview
44

5-
The number of package dependencies often grows, with that, a name collision can occur among modules from different packages. Module names such as `Logging` or `Utils` are common examples. In order to resolve the collision, SwiftPM (in 5.7+) introduces a new parameter `moduleAliases`, which allows a user to define new unique names for the conflicting modules without requiring any source code changes.
5+
The number of package dependencies often grows, with that, a name collision can occur among modules from different packages. Module names such as `Logging` or `Utils` are common examples. In order to resolve the collision, SwiftPM (in 5.7+) introduces a new parameter `moduleAliases`, which allows a user to define new unique names for the conflicting modules without requiring any source code changes.
66

77
## How to Use
88

9-
Let's consider the following scenarios to go over how module aliasing can be used.
9+
Let's consider the following scenarios to go over how module aliasing can be used.
1010

1111
### Example 1
1212

@@ -56,16 +56,16 @@ Package manifest `App`
5656
package: "swift-draw"),
5757
.product(name: "Utils",
5858
package: "swift-game",
59-
moduleAliases: ["Utils": "GameUtils"]),
59+
moduleAliases: ["Utils": "SwiftGameUtils"]),
6060
])
6161
]
6262
```
6363

64-
The value for the `moduleAliases` parameter is a dictionary where the key is the original module name in conflict and the value is a user-defined new unique name, in this case `GameUtils`. This will rename the `Utils` module in package `swift-game` as `GameUtils`; the name of the binary will be `GameUtils.swiftmodule`. No source or manifest changes are required by the `swift-game` package.
64+
The value for the `moduleAliases` parameter is a dictionary where the key is the original module name in conflict and the value is a user-defined new unique name, in this case `SwiftGameUtils` to qualify it with the package identifier. This will rename the `Utils` module in package `swift-game` as `SwiftGameUtils`; the name of the binary will be `SwiftGameUtils.swiftmodule`. No source or manifest changes are required by the `swift-game` package.
6565

66-
To use the aliased module, `App` needs to reference the the new name, i.e. `import GameUtils`. Its existing `import Utils` statement will continue to reference the `Utils` module from package `swift-draw`, as expected.
66+
To use the aliased module, `App` needs to reference the the new name, i.e. `import SwiftGameUtils`. Its existing `import Utils` statement will continue to reference the `Utils` module from package `swift-draw`, as expected.
6767

68-
Note that the dependency product names are duplicate, i.e. both have the same name `Utils`, which is by default not allowed. However, this is allowed when module aliasing is used as long as no multiple files with the same product name are created. This means they must all be automatic library types, or at most one of them can be a static library, dylib, an executable, or any other type that creates a file or a directory with the product name.
68+
Note that the dependency product names are duplicate, i.e. both have the same name `Utils`, which is by default not allowed. However, this is allowed when module aliasing is used as long as no files with the same product name are created. This means they must all be automatic library types, or at most one of them can be a static library, dylib, an executable, or any other type that creates a file or a directory with the product name.
6969

7070
### Example 2
7171

@@ -106,24 +106,24 @@ Package manifest `App`
106106
package: "swift-draw"),
107107
.product(name: "Game",
108108
package: "swift-game",
109-
moduleAliases: ["Utils": "GameUtils"]),
109+
moduleAliases: ["Utils": "SwiftGameUtils"]),
110110
])
111111
]
112112
```
113113

114-
The `Utils` module from `swift-game` is renamed as `GameUtils`, and all the references to `Utils` in source files of `Game` are compiled as `GameUtils`. Similar to Example 1, no source or manifest changes are required by the `swift-game` package.
114+
The `Utils` module from `swift-game` is renamed as `SwiftGameUtils`, and all the references to `Utils` in source files of `Game` are compiled as `SwiftGameUtils`. Similar to Example 1, no source or manifest changes are required by the `swift-game` package. Since the package identifier is unique to the package, using it as the prefix for the new module alias should prevent collisions.
115115

116-
If more aliases need to be defined, they can be added with a comma delimiter, per below.
116+
If more aliases need to be defined, they can be added with a comma delimiter, per below.
117117

118118
```
119-
moduleAliases: ["Utils": "GameUtils", "Logging": "GameLogging"]),
119+
moduleAliases: ["Utils": "SwiftGameUtils", "Logging": "SwiftGameLogging"]),
120120
```
121121

122122
## Override Module Aliases
123123

124-
If module alias values defined upstream are conflicting downstream, they can be overridden by chaining; add an entry to the `moduleAliases` parameter downstream using the conflicting alias value as a key and provide a unique value.
124+
If module alias values defined upstream are conflicting downstream, they can be overridden by chaining; add an entry to the `moduleAliases` parameter downstream using the conflicting alias value as a key and provide a unique value. Note that this should be a particularly rare occurrence since prefixing a module alias with its package identifier will usually give it a globally unique alias. However, if this does occur then chaining can be a solution.
125125

126-
To illustrate, the `swift-draw` and `swift-game` packages are modified to have the following dependencies and module aliases.
126+
To illustrate, the `swift-draw` and `swift-game` packages are modified to have the following dependencies and module aliases.
127127

128128
Package manifest `swift-draw`
129129
```
@@ -183,19 +183,19 @@ To override it, the `App` manifest can define its own module aliases per below.
183183
dependencies: [
184184
.product(name: "Draw",
185185
package: "swift-draw",
186-
moduleAliases: ["FooUtils": "DrawUtils"]),
186+
moduleAliases: ["FooUtils": "SwiftDrawUtils"]),
187187
.product(name: "Game",
188188
package: "swift-game",
189-
moduleAliases: ["FooUtils": "GameUtils"]),
189+
moduleAliases: ["FooUtils": "SwiftGameUtils"]),
190190
])
191191
]
192192
```
193-
The `Utils` module from package `a-utils` will be renamed as `DrawUtils`, and `Utils` from package `c-utils` will be renamed as `GameUtils`. Each overridden alias will be applied to all of the targets that depend on each module.
193+
The `Utils` module from package `a-utils` will be renamed as `SwiftDrawUtils`, and `Utils` from package `c-utils` will be renamed as `SwiftGameUtils`. Each overridden alias will be applied to all of the targets that depend on each module.
194194

195195
## Requirements
196196

197197
* A package needs to adopt the swift tools version 5.7 and above to use the `moduleAliases` parameter.
198-
* A module being aliased needs to be a pure Swift module only: no ObjC/C/C++/Asm are supported due to a likely symbol collision. Similarly, use of `@objc(name)` should be avoided.
198+
* A module being aliased needs to be a pure Swift module only: no ObjC/C/C++/Asm are supported due to a likely symbol collision. Similarly, use of `@objc(name)` should be avoided.
199199
* A module being aliased cannot be a prebuilt binary due to the impact on mangling and serialization, i.e. source-based only.
200200
* A module being aliased should not be passed to a runtime call such as `NSClassFromString(...)` that converts (directly or indirectly) String to a type in a module since such call will fail.
201201
* If a target mapped to a module being aliased contains resources, they should be asset catalogs, localized strings, or resources that do not require explicit module names.

0 commit comments

Comments
 (0)