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