Skip to content

Commit 0d03048

Browse files
committed
Merge pull request #229 from aciidb0mb3r/c_incremental
Incremental 🛠 for C targets
2 parents f57a878 + 0479046 commit 0d03048

File tree

3 files changed

+108
-34
lines changed

3 files changed

+108
-34
lines changed

Sources/Build/Command.compile(ClangModule).swift

Lines changed: 83 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,19 @@ import PackageType
1212
import Utility
1313
import POSIX
1414

15-
//FIXME: Incremental builds
16-
17-
extension Command {
18-
static func compile(clangModule module: ClangModule, externalModules: Set<Module>, configuration conf: Configuration, prefix: String, CC: String) -> (Command, Command) {
19-
20-
let wd = Path.join(prefix, "\(module.c99name).build")
21-
let mkdir = Command.createDirectory(wd)
22-
23-
let inputs = module.dependencies.map{ $0.targetName } + module.sources.paths + [mkdir.node]
24-
let productPath = Path.join(prefix, module.type == .Library ? "lib\(module.c99name).so" : module.c99name)
25-
15+
private extension ClangModule {
16+
var basicArgs: [String] {
2617
var args: [String] = []
27-
#if os(Linux)
28-
args += ["-fPIC"]
29-
#endif
30-
args += ["-fmodules", "-fmodule-name=\(module.name)"]
31-
args += ["-L\(prefix)"]
18+
#if os(Linux)
19+
args += ["-fPIC"]
20+
#endif
21+
args += ["-fmodules", "-fmodule-name=\(name)"]
22+
return args
23+
}
3224

33-
for case let dep as ClangModule in module.dependencies {
25+
func includeFlagsWithExternalModules(externalModules: Set<Module>) -> [String] {
26+
var args: [String] = []
27+
for case let dep as ClangModule in dependencies {
3428
let includeFlag: String
3529
//add `-iquote` argument to the include directory of every target in the package in the
3630
//transitive closure of the target being built allowing the use of `#include "..."`
@@ -39,32 +33,89 @@ extension Command {
3933

4034
includeFlag = externalModules.contains(dep) ? "-I" : "-iquote"
4135
args += [includeFlag, dep.path]
42-
args += ["-l\(dep.c99name)"] //FIXME: giving path to other module's -fmodule-map-file is not linking that module
4336
}
37+
return args
38+
}
39+
40+
var linkFlags: [String] {
41+
var args: [String] = []
42+
for case let dep as ClangModule in dependencies {
43+
args += ["-l\(dep.c99name)"]
44+
}
45+
return args
46+
}
4447

48+
func optimizationFlags(conf: Configuration) -> [String] {
4549
switch conf {
4650
case .Debug:
47-
args += ["-g", "-O0"]
51+
return ["-g", "-O0"]
4852
case .Release:
49-
args += ["-O2"]
53+
return ["-O2"]
5054
}
55+
}
56+
}
57+
58+
private extension Sources {
59+
func compilePathsForBuildDir(wd: String) -> [(filename: String, source: String, object: String, deps: String)] {
60+
return relativePaths.map { source in
61+
let path = Path.join(root, source)
62+
let object = Path.join(wd, "\(source).o")
63+
let deps = Path.join(wd, "\(source).d")
64+
return (source, path, object, deps)
65+
}
66+
}
67+
}
68+
69+
extension Command {
70+
static func compile(clangModule module: ClangModule, externalModules: Set<Module>, configuration conf: Configuration, prefix: String, CC: String) -> ([Command], Command) {
71+
72+
let wd = Path.join(prefix, "\(module.c99name).build")
73+
let mkdir = Command.createDirectory(wd)
74+
75+
///------------------------------ Compile -----------------------------------------
76+
var compileCommands = [Command]()
77+
let dependencies = module.dependencies.map{ $0.targetName }
78+
let basicArgs = module.basicArgs + module.includeFlagsWithExternalModules(externalModules) + module.optimizationFlags(conf)
79+
for path in module.sources.compilePathsForBuildDir(wd) {
80+
var args = basicArgs
81+
args += ["-MD", "-MT", "dependencies", "-MF", path.deps]
82+
args += ["-c", path.source, "-o", path.object]
83+
84+
let clang = ClangTool(desc: "Compiling \(module.name) \(path.filename)",
85+
inputs: dependencies + [path.source, mkdir.node],
86+
outputs: [path.object],
87+
args: [CC] + args,
88+
deps: path.deps)
89+
90+
let command = Command(node: path.object, tool: clang)
91+
92+
compileCommands.append(command)
93+
}
94+
95+
96+
///FIXME: This probably doesn't belong here
97+
///------------------------------ Product -----------------------------------------
98+
99+
var args = module.basicArgs
100+
args += module.optimizationFlags(conf)
101+
args += ["-L\(prefix)"]
102+
args += module.linkFlags
103+
args += module.sources.compilePathsForBuildDir(wd).map{$0.object}
51104

52-
args += module.sources.paths
53-
54105
if module.type == .Library {
55106
args += ["-shared"]
56107
}
57-
58-
args += ["-o", productPath]
59108

60-
let clang = ShellTool(
61-
description: "Compiling \(module.name)",
62-
inputs: inputs,
63-
outputs: [productPath, module.targetName],
64-
args: [CC] + args)
65-
66-
let command = Command(node: module.targetName, tool: clang)
109+
let productPath = Path.join(prefix, module.type == .Library ? "lib\(module.c99name).so" : module.c99name)
110+
args += ["-o", productPath]
111+
112+
let shell = ShellTool(description: "Linking \(module.name)",
113+
inputs: dependencies + compileCommands.map{$0.node} + [mkdir.node],
114+
outputs: [productPath, module.targetName],
115+
args: [CC] + args)
116+
117+
let command = Command(node: module.targetName, tool: shell)
67118

68-
return (command, mkdir)
119+
return (compileCommands + [command], mkdir)
69120
}
70121
}

Sources/Build/ToolProtocol.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,26 @@ struct MkdirTool: ToolProtocol {
110110
return yaml
111111
}
112112
}
113+
114+
struct ClangTool: ToolProtocol {
115+
let desc: String
116+
let inputs: [String]
117+
let outputs: [String]
118+
let args: [String]
119+
let deps: String?
120+
121+
var name: String { return "clang" }
122+
123+
var YAMLDescription: String {
124+
var yaml = ""
125+
yaml += " tool: " + name.YAML + "\n"
126+
yaml += " description: " + desc.YAML + "\n"
127+
yaml += " inputs: " + inputs.YAML + "\n"
128+
yaml += " outputs: " + outputs.YAML + "\n"
129+
yaml += " args: " + args.joined(separator: " ").YAML + "\n"
130+
if let deps = deps {
131+
yaml += " deps: " + deps.YAML + "\n"
132+
}
133+
return yaml
134+
}
135+
}

Sources/Build/describe().swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@ public func describe(prefix: String, _ conf: Configuration, _ modules: [Module],
5454
}
5555

5656
let (compile, mkdir) = Command.compile(clangModule: module, externalModules: externalModules, configuration: conf, prefix: prefix, CC: CC)
57-
commands.append(compile)
57+
commands += compile
5858
commands.append(mkdir)
59-
targets.main.cmds.append(compile)
59+
targets.main.cmds += compile
6060

6161
case is CModule:
6262
continue

0 commit comments

Comments
 (0)