Skip to content

Commit e9aa317

Browse files
authored
Doc updates to module alias overriding (#5587)
1 parent 6245408 commit e9aa317

File tree

1 file changed

+61
-12
lines changed

1 file changed

+61
-12
lines changed

Documentation/ModuleAliasing.md

Lines changed: 61 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,22 @@ Package manifest `swift-game`
3131
}
3232
```
3333

34+
Package manifest `swift-draw`
35+
```
36+
{
37+
name: "swift-draw",
38+
products: [
39+
.library(name: "Utils", targets: ["Utils"]),
40+
],
41+
targets: [
42+
.target(name: "Utils", dependencies: [])
43+
]
44+
}
45+
```
46+
3447
Both `swift-draw` and `swift-game` vend modules with the same name `Utils`, thus causing a conflict. To resolve the collision, a new parameter `moduleAliases` can now be used to disambiguate them.
3548

49+
Package manifest `App`
3650
```
3751
targets: [
3852
.executableTarget(
@@ -51,6 +65,8 @@ The value for the `moduleAliases` parameter is a dictionary where the key is the
5165

5266
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.
5367

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.
69+
5470
### Example 2
5571

5672
`App` imports a module `Utils` from a package `swift-draw`. It wants to add another package dependency `swift-game` and imports a module `Game` vended from the package. The `Game` module imports `Utils` from the same package.
@@ -80,6 +96,7 @@ Similar to Example 1, both packages contain modules with the same name `Utils`,
8096

8197
We can use `moduleAliases` again, as follows.
8298

99+
Package manifest `App`
83100
```
84101
targets: [
85102
.executableTarget(
@@ -104,45 +121,76 @@ If more aliases need to be defined, they can be added with a comma delimiter, pe
104121

105122
## Override Module Aliases
106123

107-
The `moduleAliases` defined in a downstream package will override the `moduleAliases` values defined in an upstream package. This may be useful if the upstream aliases themselves result in a conflict.
124+
If module alias values defined upstream are conflicting downstream, they can be overriden by chaining; add an entry to the `moduleAliases` parameter downstream using the conflicting alias value as a key and provide a unique value.
108125

109-
To illustrate, the `swift-game` package is modified to have the following package dependency.
126+
To illustrate, the `swift-draw` and `swift-game` packages are modified to have the following dependencies and module aliases.
110127

128+
Package manifest `swift-draw`
129+
```
130+
{
131+
name: "swift-draw",
132+
dependencies: [
133+
.package(url: https://.../a-utils.git),
134+
.package(url: https://.../b-utils.git),
135+
],
136+
products: [
137+
.library(name: "Draw", targets: ["Draw"]),
138+
],
139+
targets: [
140+
.target(name: "Draw",
141+
dependencies: [
142+
.product(name: "Utils",
143+
package: "a-utils",
144+
moduleAliases: ["Utils": "FooUtils"]),
145+
.product(name: "Utils",
146+
package: "b-utils",
147+
moduleAliases: ["Utils": "BarUtils"]),
148+
])
149+
]
150+
}
151+
```
152+
Package manifest `swift-game`
111153
```
112154
{
113155
name: "swift-game",
114156
dependencies: [
115-
.package(url: https://.../swift-utils.git),
157+
.package(url: https://.../c-utils.git),
158+
.package(url: https://.../d-utils.git),
116159
],
117160
products: [
118161
.library(name: "Game", targets: ["Game"]),
119162
],
120163
targets: [
121164
.target(name: "Game",
122165
dependencies: [
123-
.product(name: "UtilsInSwift",
124-
package: "swift-utils",
125-
moduleAliases: ["Utils": "SwiftUtils"]),
166+
.product(name: "Utils",
167+
package: "c-utils",
168+
moduleAliases: ["Utils": "FooUtils"]),
169+
.product(name: "Utils",
170+
package: "d-utils",
171+
moduleAliases: ["Utils": "BazUtils"]),
126172
])
127173
]
128174
}
129175
```
130-
The `App` manifest is same as before:
176+
177+
Both packages define `FooUtils` as an alias, thus causing a conflict downstream.
178+
To override it, the `App` manifest can define its own module aliases per below.
131179
```
132180
targets: [
133181
.executableTarget(
134182
name: "App",
135183
dependencies: [
136-
.product(name: "Utils",
137-
package: "swift-draw"),
184+
.product(name: "Draw",
185+
package: "swift-draw",
186+
moduleAliases: ["FooUtils": "DrawUtils"]),
138187
.product(name: "Game",
139188
package: "swift-game",
140-
moduleAliases: ["Utils": "GameUtils"]),
189+
moduleAliases: ["FooUtils": "GameUtils"]),
141190
])
142191
]
143192
```
144-
145-
The alias `SwiftUtils` defined in `swift-game` will be overridden by the value `GameUtils` defined in `App` for the `Utils` module vended by `swift-utils`. The module will be renamed as `GameUtils` and all of the targets that depend on the module will treat it as `GameUtils`.
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 overriden alias will be applied to all of the targets that depend on each module.
146194

147195
## Requirements
148196

@@ -151,3 +199,4 @@ The alias `SwiftUtils` defined in `swift-game` will be overridden by the value `
151199
* A module being aliased cannot be a prebuilt binary due to the impact on mangling and serialization, i.e. source-based only.
152200
* 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.
153201
* 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.
202+
* If a product that a module being aliased belongs to has a conflicting name with another product, at most one of the products can be a non-automatic library type.

0 commit comments

Comments
 (0)