Skip to content

Commit 464d9d3

Browse files
authored
Merge pull request #78879 from rintaro/xcodegen-commandline
[XcodeGen] Handle 'rule' declarations and generate command line args
2 parents 7c685ba + 8d2ac00 commit 464d9d3

File tree

9 files changed

+403
-300
lines changed

9 files changed

+403
-300
lines changed

utils/swift-xcodegen/Sources/SwiftXcodeGen/BuildArgs/RunnableTargets.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ struct RunnableTargets {
2222
private var targets: [RunnableTarget] = []
2323

2424
init(from buildDir: RepoBuildDir) throws {
25-
for rule in try buildDir.ninjaFile.buildRules {
25+
for rule in try buildDir.ninjaFile.buildEdges {
2626
tryAddTarget(rule, buildDir: buildDir)
2727
}
2828
}
@@ -59,7 +59,7 @@ extension RunnableTargets {
5959
}
6060

6161
private mutating func tryAddTarget(
62-
_ rule: NinjaBuildFile.BuildRule, buildDir: RepoBuildDir
62+
_ rule: NinjaBuildFile.BuildEdge, buildDir: RepoBuildDir
6363
) {
6464
guard let (name, path) = getRunnablePath(for: rule.outputs),
6565
addedPaths.insert(path).inserted else { return }

utils/swift-xcodegen/Sources/SwiftXcodeGen/BuildArgs/SwiftDriverUtils.swift

-126
This file was deleted.

utils/swift-xcodegen/Sources/SwiftXcodeGen/BuildArgs/SwiftTargets.swift

+24-50
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ struct SwiftTargets {
2424

2525
init(for buildDir: RepoBuildDir) throws {
2626
log.debug("[*] Reading Swift targets from build.ninja")
27-
for rule in try buildDir.ninjaFile.buildRules {
27+
for rule in try buildDir.ninjaFile.buildEdges {
2828
try tryAddTarget(for: rule, buildDir: buildDir)
2929
}
3030
targets.sort(by: { $0.name < $1.name })
@@ -65,33 +65,17 @@ struct SwiftTargets {
6565
}
6666

6767
private mutating func computeBuildArgs(
68-
for rule: NinjaBuildFile.BuildRule
68+
for edge: NinjaBuildFile.BuildEdge,
69+
in ninja: NinjaBuildFile
6970
) throws -> BuildArgs? {
70-
var buildArgs = BuildArgs(for: .swiftc)
71-
if let commandAttr = rule.attributes[.command] {
72-
// We have a custom command, parse it looking for a swiftc invocation.
73-
let command = try CommandParser.parseKnownCommandOnly(commandAttr.value)
74-
guard let command, command.executable.knownCommand == .swiftc else {
75-
return nil
76-
}
77-
buildArgs += command.args
78-
} else if rule.attributes[.flags] != nil {
79-
// Ninja separates out other arguments we need, splice them back in.
80-
for key: NinjaBuildFile.Attribute.Key in [.flags, .includes, .defines] {
81-
guard let attr = rule.attributes[key] else { continue }
82-
buildArgs.append(attr.value)
83-
}
84-
// Add a module name argument if one is specified, validating to
85-
// ensure it's correct since we currently have some targets with
86-
// invalid module names, e.g swift-plugin-server.
87-
if let moduleName = rule.attributes[.swiftModuleName]?.value,
88-
moduleName.isValidSwiftIdentifier {
89-
buildArgs.append("-module-name \(moduleName)")
90-
}
91-
} else {
71+
let commandLine = try ninja.commandLine(for: edge)
72+
let command = try CommandParser.parseKnownCommandOnly(commandLine)
73+
guard let command, command.executable.knownCommand == .swiftc else {
9274
return nil
9375
}
9476

77+
var buildArgs = BuildArgs(for: .swiftc, args: command.args)
78+
9579
// Only include known flags for now.
9680
buildArgs = buildArgs.filter { arg in
9781
if arg.flag != nil {
@@ -125,17 +109,9 @@ struct SwiftTargets {
125109
}
126110

127111
func getSources(
128-
from rule: NinjaBuildFile.BuildRule, buildDir: RepoBuildDir
112+
from edge: NinjaBuildFile.BuildEdge, buildDir: RepoBuildDir
129113
) throws -> SwiftTarget.Sources {
130-
// If we have SWIFT_SOURCES defined, use it, otherwise check the rule
131-
// inputs.
132-
let files: [AnyPath]
133-
if let sourcesStr = rule.attributes[.swiftSources]?.value {
134-
files = try CommandParser.parseArguments(sourcesStr, for: .swiftc)
135-
.compactMap(\.value).map(AnyPath.init)
136-
} else {
137-
files = rule.inputs.map(AnyPath.init)
138-
}
114+
let files: [AnyPath] = edge.inputs.map(AnyPath.init)
139115

140116
// Split the files into repo sources and external sources. Repo sources
141117
// are those under the repo path, external sources are outside that path,
@@ -166,29 +142,29 @@ struct SwiftTargets {
166142
}
167143

168144
private mutating func tryAddTarget(
169-
for rule: NinjaBuildFile.BuildRule,
145+
for edge: NinjaBuildFile.BuildEdge,
170146
buildDir: RepoBuildDir
171147
) throws {
172148
// Phonies are only used to track aliases.
173-
if rule.isPhony {
174-
for output in rule.outputs {
175-
outputAliases[output, default: []] += rule.inputs
149+
if edge.isPhony {
150+
for output in edge.outputs {
151+
outputAliases[output, default: []] += edge.inputs
176152
}
177153
return
178154
}
179155

180156
// Ignore build rules that don't have object file or swiftmodule outputs.
181-
let forBuild = rule.outputs.contains(
157+
let forBuild = edge.outputs.contains(
182158
where: { $0.hasExtension(.o) }
183159
)
184-
let forModule = rule.outputs.contains(
160+
let forModule = edge.outputs.contains(
185161
where: { $0.hasExtension(.swiftmodule) }
186162
)
187163
guard forBuild || forModule else {
188164
return
189165
}
190-
let primaryOutput = rule.outputs.first!
191-
let sources = try getSources(from: rule, buildDir: buildDir)
166+
let primaryOutput = edge.outputs.first!
167+
let sources = try getSources(from: edge, buildDir: buildDir)
192168
let repoSources = sources.repoSources
193169
let externalSources = sources.externalSources
194170

@@ -198,32 +174,30 @@ struct SwiftTargets {
198174
return
199175
}
200176

201-
guard let buildArgs = try computeBuildArgs(for: rule) else { return }
177+
guard let buildArgs = try computeBuildArgs(for: edge, in: buildDir.ninjaFile) else { return }
202178

203179
// Pick up the module name from the arguments, or use an explicitly
204180
// specified module name if we have one. The latter might be invalid so
205181
// may not be part of the build args (e.g 'swift-plugin-server'), but is
206182
// fine for generation.
207-
let moduleName = buildArgs.lastValue(for: .moduleName) ??
208-
rule.attributes[.swiftModuleName]?.value
183+
let moduleName = buildArgs.lastValue(for: .moduleName) ?? edge.bindings[.swiftModuleName]
209184
guard let moduleName else {
210185
log.debug("! Skipping Swift target with output \(primaryOutput); no module name")
211186
return
212187
}
213-
let moduleLinkName = rule.attributes[.swiftLibraryName]?.value ??
214-
buildArgs.lastValue(for: .moduleLinkName)
188+
let moduleLinkName = buildArgs.lastValue(for: .moduleLinkName) ?? edge.bindings[.swiftLibraryName]
215189
let name = moduleLinkName ?? moduleName
216190

217191
// Add the dependencies. We track dependencies for any input files, along
218192
// with any recorded swiftmodule dependencies.
219193
dependenciesByTargetName.withValue(for: name, default: []) { deps in
220194
deps.formUnion(
221-
rule.inputs.filter {
195+
edge.inputs.filter {
222196
$0.hasExtension(.swiftmodule) || $0.hasExtension(.o)
223197
}
224198
)
225199
deps.formUnion(
226-
rule.dependencies.filter { $0.hasExtension(.swiftmodule) }
200+
edge.dependencies.filter { $0.hasExtension(.swiftmodule) }
227201
)
228202
}
229203

@@ -258,7 +232,7 @@ struct SwiftTargets {
258232
targets.append(target)
259233
return target
260234
}()
261-
for output in rule.outputs {
235+
for output in edge.outputs {
262236
targetsByOutput[output] = target
263237
}
264238
if buildRule == nil || target.buildRule == nil {

0 commit comments

Comments
 (0)