@@ -87,6 +87,7 @@ extension SwiftPackageCommand {
87
87
88
88
let buildSystem = try await createBuildSystem (
89
89
swiftCommandState,
90
+ targets: self . options. targets,
90
91
features: features
91
92
)
92
93
@@ -137,34 +138,46 @@ extension SwiftPackageCommand {
137
138
138
139
print ( " > Updating manifest. " )
139
140
for module in modules. map ( \. module) {
140
- print ( " > Adding feature(s) to ' \( module. name) '. " )
141
- for feature in features {
142
- self . updateManifest (
143
- for: module. name,
144
- add: feature,
145
- using: swiftCommandState
146
- )
147
- }
141
+ swiftCommandState. observabilityScope. emit ( debug: " Adding feature(s) to ' \( module. name) '. " )
142
+ self . updateManifest (
143
+ for: module. name,
144
+ add: features,
145
+ using: swiftCommandState
146
+ )
148
147
}
149
148
}
150
149
151
150
private func createBuildSystem(
152
151
_ swiftCommandState: SwiftCommandState ,
152
+ targets: Set < String > ? = . none,
153
153
features: [ SwiftCompilerFeature ]
154
154
) async throws -> BuildSystem {
155
155
let toolsBuildParameters = try swiftCommandState. toolsBuildParameters
156
- var destinationBuildParameters = try swiftCommandState. productsBuildParameters
157
-
158
- // Inject feature settings as flags. This is safe and not as invasive
159
- // as trying to update manifest because in adoption mode the features
160
- // can only produce warnings.
161
- for feature in features {
162
- destinationBuildParameters. flags. swiftCompilerFlags. append ( contentsOf: [
163
- " -Xfrontend " ,
164
- " -enable- \( feature. upcoming ? " upcoming " : " experimental " ) -feature " ,
165
- " -Xfrontend " ,
166
- " \( feature. name) :migrate " ,
167
- ] )
156
+ let destinationBuildParameters = try swiftCommandState. productsBuildParameters
157
+
158
+ let modulesGraph = try await swiftCommandState. loadPackageGraph ( )
159
+
160
+ let addFeaturesToModule = { ( module: ResolvedModule ) in
161
+ for feature in features {
162
+ module. underlying. buildSettings. add ( . init( values: [
163
+ " -Xfrontend " ,
164
+ " -enable- \( feature. upcoming ? " upcoming " : " experimental " ) -feature " ,
165
+ " -Xfrontend " ,
166
+ " \( feature. name) :migrate " ,
167
+ ] ) , for: . OTHER_SWIFT_FLAGS)
168
+ }
169
+ }
170
+
171
+ if let targets {
172
+ targets. lazy. compactMap {
173
+ modulesGraph. module ( for: $0)
174
+ } . forEach ( addFeaturesToModule)
175
+ } else {
176
+ for package in modulesGraph. rootPackages {
177
+ package . modules. filter {
178
+ $0. type != . plugin
179
+ } . forEach ( addFeaturesToModule)
180
+ }
168
181
}
169
182
170
183
return try await swiftCommandState. createBuildSystem (
@@ -173,34 +186,39 @@ extension SwiftPackageCommand {
173
186
toolsBuildParameters: toolsBuildParameters,
174
187
// command result output goes on stdout
175
188
// ie "swift build" should output to stdout
176
- outputStream: TSCBasic . stdoutStream
189
+ packageGraphLoader: {
190
+ modulesGraph
191
+ } ,
192
+ outputStream: TSCBasic . stdoutStream,
193
+ observabilityScope: swiftCommandState. observabilityScope
177
194
)
178
195
}
179
196
180
197
private func updateManifest(
181
198
for target: String ,
182
- add feature : SwiftCompilerFeature ,
199
+ add features : [ SwiftCompilerFeature ] ,
183
200
using swiftCommandState: SwiftCommandState
184
201
) {
185
202
typealias SwiftSetting = SwiftPackageCommand . AddSetting . SwiftSetting
186
203
187
- let setting : ( SwiftSetting , String ) = switch feature {
188
- case . upcoming( name: let name, migratable: _, enabledIn: _) :
189
- ( . upcomingFeature, " \( name) " )
190
- case . experimental( name: let name, migratable: _) :
191
- ( . experimentalFeature, " \( name) " )
204
+ let settings : [ ( SwiftSetting , String ) ] = features. map {
205
+ switch $0 {
206
+ case . upcoming( name: let name, migratable: _, enabledIn: _) :
207
+ ( . upcomingFeature, " \( name) " )
208
+ case . experimental( name: let name, migratable: _) :
209
+ ( . experimentalFeature, " \( name) " )
210
+ }
192
211
}
193
212
194
213
do {
195
214
try SwiftPackageCommand . AddSetting. editSwiftSettings (
196
215
of: target,
197
216
using: swiftCommandState,
198
- [ setting]
217
+ settings,
218
+ verbose: !self . globalOptions. logging. quiet
199
219
)
200
220
} catch {
201
- print (
202
- " ! Couldn't update manifest due to - \( error) ; Please add '.enable \( feature. upcoming ? " Upcoming " : " Experimental " ) Feature( \" \( feature. name) \" )' to target ' \( target) ' settings manually. "
203
- )
221
+ swiftCommandState. observabilityScope. emit ( error: " Could not update manifest for ' \( target) ' ( \( error) ). Please enable ' \( features. map ( \. name) . joined ( separator: " , " ) ) ' features manually. " )
204
222
}
205
223
}
206
224
0 commit comments