@@ -14,23 +14,20 @@ import POSIX
14
14
15
15
//FIXME: Incremental builds
16
16
17
- extension Command {
18
- static func compile( clangModule module: ClangModule , configuration conf: Configuration , prefix: 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)
17
+ private extension ClangModule {
25
18
19
+ var basicArgs : [ String ] {
26
20
var args : [ String ] = [ ]
27
- #if os(Linux)
28
- args += [ " -fPIC " ]
29
- #endif
30
- args += [ " -fmodules " , " -fmodule-name= \( module. name) " ]
31
- args += [ " -L \( prefix) " ]
21
+ #if os(Linux)
22
+ args += [ " -fPIC " ]
23
+ #endif
24
+ args += [ " -fmodules " , " -fmodule-name= \( name) " ]
25
+ return args
26
+ }
32
27
33
- for case let dep as ClangModule in module. dependencies {
28
+ var includeFlags : [ String ] {
29
+ var args : [ String ] = [ ]
30
+ for case let dep as ClangModule in dependencies {
34
31
let includeFlag : String
35
32
//add `-iquote` argument to the include directory of every target in the package in the
36
33
//transitive closure of the target being built allowing the use of `#include "..."`
@@ -45,32 +42,93 @@ extension Command {
45
42
includeFlag = " -iquote "
46
43
}
47
44
args += [ includeFlag, dep. path]
48
- args += [ " -l \( dep. c99name) " ] //FIXME: giving path to other module's -fmodule-map-file is not linking that module
49
45
}
46
+ return args
47
+ }
48
+
49
+ var linkFlags : [ String ] {
50
+ var args : [ String ] = [ ]
51
+ for case let dep as ClangModule in dependencies {
52
+ args += [ " -l \( dep. c99name) " ]
53
+ }
54
+ return args
55
+ }
50
56
57
+ func optimizationFlags( conf: Configuration ) -> [ String ] {
51
58
switch conf {
52
59
case . Debug:
53
- args += [ " -g " , " -O0 " ]
60
+ return [ " -g " , " -O0 " ]
54
61
case . Release:
55
- args += [ " -O2 " ]
62
+ return [ " -O2 " ]
63
+ }
64
+ }
65
+ }
66
+
67
+ private extension Sources {
68
+
69
+ func compilePathsForBuildDir( wd: String ) -> [ ( filename: String , source: String , object: String , deps: String ) ] {
70
+ return relativePaths. map { source in
71
+ let path = Path . join ( root, source)
72
+ let object = Path . join ( wd, " \( source) .o " )
73
+ let deps = Path . join ( wd, " \( source) .d " )
74
+ return ( source, path, object, deps)
75
+ }
76
+ }
77
+
78
+ }
79
+
80
+ extension Command {
81
+ static func compile( clangModule module: ClangModule , configuration conf: Configuration , prefix: String ) -> ( [ Command ] , Command ) {
82
+
83
+ let wd = Path . join ( prefix, " \( module. c99name) .build " )
84
+ let mkdir = Command . createDirectory ( wd)
85
+
86
+ ///------------------------------ Compile -----------------------------------------
87
+ var compileCommands = [ Command] ( )
88
+ let dependencies = module. dependencies. map { $0. targetName }
89
+ let basicArgs = module. basicArgs + module. includeFlags + module. optimizationFlags ( conf)
90
+ for path in module. sources. compilePathsForBuildDir ( wd) {
91
+ var args = basicArgs
92
+ args += [ " -MMD " , " -MT " , " dependencies " , " -MF " , path. deps]
93
+ args += [ " -c " , path. source, " -o " , path. object]
94
+
95
+ let node = " < \( module. name) . \( path. filename) > "
96
+
97
+ let clang = ClangTool ( desc: " Compiling \( module. name) \( path. filename) " ,
98
+ inputs: dependencies + [ path. source, mkdir. node] ,
99
+ outputs: [ path. object, node] ,
100
+ args: args,
101
+ deps: path. deps)
102
+
103
+ let command = Command ( node: node, tool: clang)
104
+
105
+ compileCommands. append ( command)
56
106
}
57
107
58
- args += module. sources. paths
59
-
108
+
109
+ ///FIXME: This probably doesn't belong here
110
+ ///------------------------------ Product -----------------------------------------
111
+
112
+ var args = module. basicArgs
113
+ args += module. optimizationFlags ( conf)
114
+ args += [ " -L \( prefix) " ]
115
+ args += module. linkFlags
116
+ args += module. sources. compilePathsForBuildDir ( wd) . map { $0. object}
117
+
60
118
if module. type == . Library {
61
119
args += [ " -shared " ]
62
120
}
63
-
64
- args += [ " -o " , productPath]
65
121
66
- let clang = ShellTool (
67
- description: " Compiling \( module. name) " ,
68
- inputs: inputs,
69
- outputs: [ productPath, module. targetName] ,
70
- args: [ Toolchain . clang] + args)
122
+ let productPath = Path . join ( prefix, module. type == . Library ? " lib \( module. c99name) .so " : module. c99name)
123
+ args += [ " -o " , productPath]
71
124
125
+ let clang = ClangTool ( desc: " Linking \( module. name) " ,
126
+ inputs: dependencies + compileCommands. map { $0. node} + [ mkdir. node] ,
127
+ outputs: [ productPath, module. targetName] ,
128
+ args: args,
129
+ deps: nil )
72
130
let command = Command ( node: module. targetName, tool: clang)
73
131
74
- return ( command, mkdir)
132
+ return ( compileCommands + [ command] , mkdir)
75
133
}
76
134
}
0 commit comments