@@ -87,6 +87,7 @@ extension SwiftPackageCommand {
8787
8888 let buildSystem = try await createBuildSystem (
8989 swiftCommandState,
90+ targets: self . options. targets,
9091 features: features
9192 )
9293
@@ -137,34 +138,46 @@ extension SwiftPackageCommand {
137138
138139 print ( " > Updating manifest. " )
139140 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+ )
148147 }
149148 }
150149
151150 private func createBuildSystem(
152151 _ swiftCommandState: SwiftCommandState ,
152+ targets: Set < String > ? = . none,
153153 features: [ SwiftCompilerFeature ]
154154 ) async throws -> BuildSystem {
155155 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+ }
168181 }
169182
170183 return try await swiftCommandState. createBuildSystem (
@@ -173,34 +186,39 @@ extension SwiftPackageCommand {
173186 toolsBuildParameters: toolsBuildParameters,
174187 // command result output goes on stdout
175188 // ie "swift build" should output to stdout
176- outputStream: TSCBasic . stdoutStream
189+ packageGraphLoader: {
190+ modulesGraph
191+ } ,
192+ outputStream: TSCBasic . stdoutStream,
193+ observabilityScope: swiftCommandState. observabilityScope
177194 )
178195 }
179196
180197 private func updateManifest(
181198 for target: String ,
182- add feature : SwiftCompilerFeature ,
199+ add features : [ SwiftCompilerFeature ] ,
183200 using swiftCommandState: SwiftCommandState
184201 ) {
185202 typealias SwiftSetting = SwiftPackageCommand . AddSetting . SwiftSetting
186203
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+ }
192211 }
193212
194213 do {
195214 try SwiftPackageCommand . AddSetting. editSwiftSettings (
196215 of: target,
197216 using: swiftCommandState,
198- [ setting]
217+ settings,
218+ verbose: !self . globalOptions. logging. quiet
199219 )
200220 } 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. " )
204222 }
205223 }
206224
0 commit comments