-
-
Notifications
You must be signed in to change notification settings - Fork 8
/
compiler.go
205 lines (159 loc) · 5.29 KB
/
compiler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
package main
import (
"os"
"path/filepath"
"runtime"
"strings"
"github.com/codecat/go-libs/log"
)
// LinkType specifies the output build type.
type LinkType int
const (
// LinkExe will create an executable application. Will add the ".exe" suffix on Windows.
LinkExe LinkType = iota
// LinkDll will create a dynamic library. Will add the ".dll" suffix on Windows, and the ".so" suffix on Linux.
LinkDll
// LinkLib will create a static library. Will add the ".lib" suffix on Windows, and the ".a" suffix on Linux.
LinkLib
)
// Compiler contains information about the compiler.
type Compiler interface {
Compile(path, objDir string, options *CompilerOptions) error
Link(objDir, outPath string, outType LinkType, options *CompilerOptions) (string, error)
Clean(name string)
}
// ExceptionType is the way that a compiler's runtime might handle exceptions.
type ExceptionType int
const (
// ExceptionsStandard is the standard way of handling exceptions, and will perform stack unwinding.
ExceptionsStandard ExceptionType = iota
// ExceptionsAll is only supported on Windows, and will allow catching excptions such as access violations and integer divide by zero exceptions.
ExceptionsAll
// ExceptionsMinimal is only supported on Windows, and is similar to ExceptionsAll, except there is no stack unwinding.
ExceptionsMinimal
)
// OptimizeType defines the compiler optimization type.
type OptimizeType int
const (
// OptimizeDefault favors speed for release builds, and disables optimization for debug builds.
OptimizeDefault OptimizeType = iota
// OptimizeNone performs no optimization at all.
OptimizeNone
// OptimizeSize favors size over speed in optimization.
OptimizeSize
// OptimizeSpeed favors sped over size in optimization.
OptimizeSpeed
)
// CPPStandardType defines the C++ standard to use.
type CPPStandardType int
const (
// CPPStandardLatest uses the latest C++ standard available to the compiler.
CPPStandardLatest CPPStandardType = iota
// CPPStandard20 uses the C++20 standard.
CPPStandard20
// CPPStandard17 uses the C++17 standard.
CPPStandard17
// CPPStandard14 uses the C++14 standard.
CPPStandard14
)
// CStandardType defines the C standard to use.
type CStandardType int
const (
// CStandardLatest uses the latest C standard available to the compiler.
CStandardLatest CStandardType = iota
// CStandard11 uses the C17 standard.
CStandard17
// CStandard11 uses the C11 standard.
CStandard11
)
// CompilerOptions contains options used for compiling and linking.
type CompilerOptions struct {
// Static sets whether to build a completely-static binary (eg. no dynamic link libraries are loaded from disk).
Static bool
// Debug configurations will add debug symbols. This will create a pdb file on Windows, and embed debugging information on Linux.
Debug bool
// Verbose compiling means we'll print the actual compiler and linker commands being executed.
Verbose bool
// Strict sets whether to be more strict on warnings.
Strict bool
// Include paths and library links
IncludeDirectories []string
LinkDirectories []string
LinkLibraries []string
// Additional compiler defines
Defines []string
// Additional compiler and linker flags
CompilerFlagsCXX []string
CompilerFlagsCPP []string
CompilerFlagsC []string
LinkerFlags []string
// Specific options
Exceptions ExceptionType
Optimization OptimizeType
CPPStandard CPPStandardType
CStandard CStandardType
}
// CompilerWorkerTask describes a task for the compiler worker
type CompilerWorkerTask struct {
path string
outputDir string
}
func compileWorker(ctx *Context, num int) {
for {
// Get a task
task, ok := <-ctx.CompilerWorkerChannel
if !ok {
break
}
// Log the file we're currently compiling
fileForward := strings.Replace(task.path, "\\", "/", -1)
log.Info("%s", fileForward)
// Invoke the compiler
err := ctx.Compiler.Compile(task.path, task.outputDir, ctx.CompilerOptions)
if err != nil {
log.Error("Failed to compile %s!\n%s", fileForward, err.Error())
ctx.CompilerErrors++
}
}
ctx.CompilerWorkerFinished <- num
}
func performCompilation(ctx *Context) {
// Prepare worker channels
ctx.CompilerWorkerChannel = make(chan CompilerWorkerTask)
ctx.CompilerWorkerFinished = make(chan int)
// Start compiler worker routines
numWorkers := runtime.NumCPU()
if len(ctx.SourceFiles) < numWorkers {
numWorkers = len(ctx.SourceFiles)
}
for i := 0; i < numWorkers; i++ {
go compileWorker(ctx, i)
}
// Compile all the source files
for _, file := range ctx.SourceFiles {
// The output dir will be a sub-folder in the object directory
dir := filepath.Dir(file)
outputDir := filepath.Join(ctx.ObjectPath, dir)
err := os.MkdirAll(outputDir, 0777)
if err != nil {
log.Error("Unable to create output directory %s: %s", outputDir, err.Error())
ctx.CompilerErrors++
continue
}
// Send the task to an available worker
ctx.CompilerWorkerChannel <- CompilerWorkerTask{
path: file,
outputDir: outputDir,
}
}
// Close the worker channel
close(ctx.CompilerWorkerChannel)
// Wait for all workers to finish compiling
for i := 0; i < numWorkers; i++ {
<-ctx.CompilerWorkerFinished
}
}
func performLinking(ctx *Context) (string, error) {
// Invoke the linker
return ctx.Compiler.Link(ctx.ObjectPath, ctx.Name, ctx.Type, ctx.CompilerOptions)
}