Skip to content

Commit 4d576de

Browse files
committed
Merge pull request #175 from aciidb0mb3r/describe_refactor
Refactor describe(), add llbuild tool types
2 parents f99a652 + 51d170c commit 4d576de

File tree

3 files changed

+207
-89
lines changed

3 files changed

+207
-89
lines changed

Sources/Build/YAML.swift

Lines changed: 22 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -8,56 +8,35 @@
88
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
99
*/
1010

11-
import struct Utility.Path
12-
import struct libc.FILE
13-
import func libc.fclose
14-
import POSIX
15-
16-
class YAML {
17-
let path: String
18-
private let fp: UnsafeMutablePointer<FILE>
19-
20-
init(path: String...) throws {
21-
self.path = Path.join(path)
22-
fp = try fopen(self.path, mode: .Write)
23-
}
11+
protocol YAMLRepresentable {
12+
var YAML: String { get }
13+
}
2414

25-
func close() {
26-
fclose(fp)
15+
extension String: YAMLRepresentable {
16+
var YAML: String {
17+
if self == "" { return "\"\"" }
18+
return self
2719
}
20+
}
2821

29-
func write(anys: Any...) throws {
30-
var anys = anys
31-
try fputs(anys.removeFirst() as! String, fp)
32-
if !anys.isEmpty {
33-
try fputs(anys.map(toYAML).joinWithSeparator(""), fp)
34-
}
35-
try fputs("\n", fp)
36-
22+
extension Bool: YAMLRepresentable {
23+
var YAML: String {
24+
if self { return "true" }
25+
return "false"
3726
}
3827
}
3928

40-
private func toYAML(any: Any) -> String {
41-
42-
func quote(input: String) -> String {
43-
for c in input.characters {
44-
if c == "@" || c == " " || c == "-" {
45-
return "\"\(input)\""
29+
extension Array where Element: YAMLRepresentable {
30+
var YAML: String {
31+
func quote(input: String) -> String {
32+
for c in input.characters {
33+
if c == "@" || c == " " || c == "-" {
34+
return "\"\(input)\""
35+
}
4636
}
37+
return input
4738
}
48-
return input
49-
}
50-
51-
switch any {
52-
case let string as String where string == "":
53-
return "\"\""
54-
case let string as String:
55-
return string
56-
case let array as [String]:
57-
return "[" + array.map(quote).joinWithSeparator(", ") + "]"
58-
case let bool as Bool:
59-
return bool ? "true" : "false"
60-
default:
61-
fatalError("Unimplemented YAML type")
39+
let stringArray = self.flatMap { String($0) }
40+
return "[" + stringArray.map(quote).joinWithSeparator(", ") + "]"
6241
}
6342
}

Sources/Build/describe().swift

Lines changed: 59 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import func POSIX.getenv
1212
import func POSIX.mkdir
1313
import PackageType
1414
import Utility
15+
import func POSIX.fopen
16+
import func libc.fclose
1517

1618
/**
1719
- Returns: path to generated YAML for consumption by the llbuild based swift-build-tool
@@ -25,25 +27,20 @@ public func describe(prefix: String, _ conf: Configuration, _ modules: [Module],
2527
let Xcc = Xcc.flatMap{ ["-Xcc", $0] }
2628
let Xld = Xld.flatMap{ ["-Xlinker", $0] }
2729
let prefix = try mkdir(prefix, conf.dirname)
28-
let yaml = try YAML(path: "\(prefix).yaml")
29-
let write = yaml.write
3030

31-
let (buildableTests, buildableNonTests) = (modules.map{$0 as Buildable} + products.map{$0 as Buildable}).partition{$0.isTest}
32-
let (tests, nontests) = (buildableTests.map{$0.targetName}, buildableNonTests.map{$0.targetName})
33-
34-
defer { yaml.close() }
35-
36-
try write("client:")
37-
try write(" name: swift-build")
38-
try write("tools: {}")
39-
try write("targets:")
40-
try write(" default: ", nontests)
41-
try write(" test: ", tests)
42-
try write("commands: ")
31+
var nonTests = [Command]()
32+
var tests = [Command]()
33+
34+
/// Appends the command to appropriate array
35+
func append(command: Command, buildable: Buildable) {
36+
if buildable.isTest {
37+
tests.append(command)
38+
} else {
39+
nonTests.append(command)
40+
}
41+
}
4342

4443
var mkdirs = Set<String>()
45-
46-
4744
let swiftcArgs = Xcc + Xswiftc
4845

4946
for case let module as SwiftModule in modules {
@@ -65,23 +62,22 @@ public func describe(prefix: String, _ conf: Configuration, _ modules: [Module],
6562
#endif
6663

6764
let node = IncrementalNode(module: module, prefix: prefix)
68-
69-
try write(" ", module.targetName, ":")
70-
try write(" tool: swift-compiler")
71-
try write(" executable: ", Resources.path.swiftc)
72-
try write(" module-name: ", module.c99name)
73-
try write(" module-output-path: ", node.moduleOutputPath)
74-
try write(" inputs: ", node.inputs)
75-
try write(" outputs: ", node.outputs)
76-
try write(" import-paths: ", prefix)
77-
try write(" temps-path: ", node.tempsPath)
78-
try write(" objects: ", node.objectPaths)
79-
try write(" other-args: ", args + otherArgs)
80-
try write(" sources: ", module.sources.paths)
81-
82-
// this must be set or swiftc compiles single source file
83-
// modules with a main() for some reason
84-
try write(" is-library: ", module.type == .Library)
65+
let swiftc = SwiftcTool(
66+
inputs: node.inputs,
67+
outputs: node.outputs,
68+
executable: Resources.path.swiftc,
69+
moduleName: module.c99name,
70+
moduleOutputPath: node.moduleOutputPath,
71+
importPaths: prefix,
72+
tempsPath: node.tempsPath,
73+
objects: node.objectPaths,
74+
otherArgs: args + otherArgs,
75+
sources: module.sources.paths,
76+
isLibrary: module.type == .Library) /// this must be set or swiftc compiles single source
77+
/// file modules with a main() for some reason
78+
79+
let command = Command(name: module.targetName, tool: swiftc)
80+
append(command, buildable: module)
8581

8682
for o in node.objectPaths {
8783
mkdirs.insert(o.parentDirectory)
@@ -96,12 +92,14 @@ public func describe(prefix: String, _ conf: Configuration, _ modules: [Module],
9692
args += ["-parse-as-library"]
9793
}
9894

99-
try write(" ", module.targetName, ":")
100-
try write(" tool: shell")
101-
try write(" description: Compiling \(module.name)")
102-
try write(" inputs: ", inputs)
103-
try write(" outputs: ", [productPath, module.targetName])
104-
try write(" args: ", [Resources.path.swiftc, "-o", productPath] + args + module.sources.paths + otherArgs)
95+
let shell = ShellTool(
96+
description: "Compiling \(module.name)",
97+
inputs: inputs,
98+
outputs: [productPath, module.targetName],
99+
args: [Resources.path.swiftc, "-o", productPath] + args + module.sources.paths + otherArgs)
100+
101+
let command = Command(name: module.targetName, tool: shell)
102+
append(command, buildable: module)
105103
}
106104
}
107105

@@ -178,15 +176,30 @@ public func describe(prefix: String, _ conf: Configuration, _ modules: [Module],
178176

179177
let inputs = product.modules.flatMap{ [$0.targetName] + IncrementalNode(module: $0, prefix: prefix).inputs }
180178

181-
try write(" \(product.targetName):")
182-
try write(" tool: shell")
183-
try write(" description: Linking \(product)")
184-
try write(" inputs: ", inputs)
185-
try write(" outputs: ", [product.targetName, outpath])
186-
try write(" args: ", args)
179+
let shell = ShellTool(
180+
description: "Linking \(product)",
181+
inputs: inputs,
182+
outputs: [product.targetName, outpath],
183+
args: args)
184+
185+
let command = Command(name: product.targetName, tool: shell)
186+
append(command, buildable: product)
187187
}
188188

189-
return yaml.path
189+
//Create Targets
190+
let nontestTarget = Target(name: "default", commands: nonTests)
191+
let testTarget = Target(name: "test", commands: tests)
192+
193+
//Generate YAML String for the targets
194+
let yamlString = llbuildYAML(targets: [nontestTarget, testTarget])
195+
196+
//Write YAML to file
197+
let yamlPath = "\(prefix).yaml"
198+
let fp = try fopen(yamlPath, mode: .Write)
199+
defer { fclose(fp) }
200+
try fputs(yamlString, fp)
201+
202+
return yamlPath
190203
}
191204

192205

Sources/Build/llbuild.swift

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/*
2+
This source file is part of the Swift.org open source project
3+
4+
Copyright 2015 - 2016 Apple Inc. and the Swift project authors
5+
Licensed under Apache License v2.0 with Runtime Library Exception
6+
7+
See http://swift.org/LICENSE.txt for license information
8+
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
9+
*/
10+
11+
protocol ToolType {
12+
var name: String { get }
13+
var inputs: [String] { get }
14+
var outputs: [String] { get }
15+
///YAML representation of the tool
16+
var llbuildYAML: String { get }
17+
}
18+
19+
protocol ShellToolType: ToolType {
20+
var description: String { get }
21+
var args: [String] { get }
22+
}
23+
24+
extension ShellToolType {
25+
26+
var name: String {
27+
return "shell"
28+
}
29+
30+
var llbuildYAML: String {
31+
var yaml = ""
32+
yaml += " tool: " + name.YAML + "\n"
33+
yaml += " description: " + description.YAML + "\n"
34+
yaml += " inputs: " + inputs.YAML + "\n"
35+
yaml += " outputs: " + outputs.YAML + "\n"
36+
yaml += " args: " + args.YAML + "\n"
37+
return yaml
38+
}
39+
}
40+
41+
struct ShellTool: ShellToolType {
42+
let description: String
43+
let inputs: [String]
44+
let outputs: [String]
45+
let args: [String]
46+
}
47+
48+
protocol SwiftcToolType: ToolType {
49+
var executable: String { get }
50+
var moduleName: String { get }
51+
var moduleOutputPath: String { get }
52+
var importPaths: String { get }
53+
var tempsPath: String { get }
54+
var objects: [String] { get }
55+
var otherArgs: [String] { get }
56+
var sources: [String] { get }
57+
var isLibrary: Bool { get }
58+
}
59+
60+
extension SwiftcToolType {
61+
62+
var name: String {
63+
return "swift-compiler"
64+
}
65+
66+
var llbuildYAML: String {
67+
var yaml = ""
68+
yaml += " tool: " + name.YAML + "\n"
69+
yaml += " executable: " + executable.YAML + "\n"
70+
yaml += " module-name: " + moduleName.YAML + "\n"
71+
yaml += " module-output-path: " + moduleOutputPath.YAML + "\n"
72+
yaml += " inputs: " + inputs.YAML + "\n"
73+
yaml += " outputs: " + outputs.YAML + "\n"
74+
yaml += " import-paths: " + importPaths.YAML + "\n"
75+
yaml += " temps-path: " + tempsPath.YAML + "\n"
76+
yaml += " objects: " + objects.YAML + "\n"
77+
yaml += " other-args: " + otherArgs.YAML + "\n"
78+
yaml += " sources: " + sources.YAML + "\n"
79+
yaml += " is-library: " + isLibrary.YAML + "\n"
80+
return yaml
81+
}
82+
}
83+
84+
struct SwiftcTool: SwiftcToolType {
85+
let inputs: [String]
86+
let outputs: [String]
87+
let executable: String
88+
let moduleName: String
89+
let moduleOutputPath: String
90+
let importPaths: String
91+
let tempsPath: String
92+
let objects: [String]
93+
let otherArgs: [String]
94+
let sources: [String]
95+
let isLibrary: Bool
96+
}
97+
98+
typealias Command = (name: String, tool: ToolType)
99+
100+
struct Target {
101+
let name: String
102+
let commands: [Command]
103+
}
104+
105+
func llbuildYAML(targets targets: [Target]) -> String {
106+
107+
var yaml = ""
108+
yaml += "client:" + "\n"
109+
yaml += " name: swift-build" + "\n"
110+
yaml += "tools: {}" + "\n"
111+
112+
yaml += "targets:" + "\n"
113+
for target in targets {
114+
yaml += " \(target.name): " + target.commands.map{$0.name}.YAML + "\n"
115+
}
116+
117+
yaml += "commands: " + "\n"
118+
119+
let commands = targets.reduce([Command]()) { $0 + $1.commands }
120+
for command in commands {
121+
yaml += " " + command.name + ":" + "\n"
122+
yaml += command.tool.llbuildYAML
123+
}
124+
125+
return yaml
126+
}

0 commit comments

Comments
 (0)