-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcommonNativeUtils.gradle
230 lines (203 loc) · 9.94 KB
/
commonNativeUtils.gradle
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
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
// Settings and methods for visual studio.
////////////////////////////////////////////////////////////////
// Set up the default compiler options for a C++ project
def addDefaultCPPOptions(Project prj, Boolean suppressConsoleDef=false) {
prj.tasks.withType(CppCompile).configureEach { task ->
// TODO - make this depend upon the target
//task.macros.put("NDEBUG", null)
task.compilerArgs.addAll toolChain.map { toolChain ->
if (toolChain in VisualCpp) {
return [
'/D_CRT_SECURE_NO_WARNINGS', '/wd4996',
'/nologo',
// TODO for non-debug use:
//'/MT',
// for debug, use:
'/MTd',
'/EHsc',
'/DWIN32',
'/D_WIN32_WINNT=0x0601',
'/W3', '/WX',
// We'd like to be able to do a build time analysis, intellisense will work,
// but you have to open every source file in the IDE to get that to scan it all, which is impractical.
// Since Gradle only sends compilation errors to stdout, not warnings, we either need to someone get the entire
// compiler output to stdout, or cause all warnings to be errors.
// Comment this line back in to get all analysis warnings in the VS error list panel, but turning this on for an
// existing codebase will cause a lot of issues that need to be fixed (unless you turn it on
// only on demand) and may prevent other projects from being built (based on dependencies), so leave it off normally.
// Ideally turn this on by some command line switch, VS doesn't seem to let us control the analyze command as it does
// for debug or release.
//'/analyze',
// TODO: There is also this solution at https://stackoverflow.com/questions/44126969/gradle-compiler-output-when-building-c-c-code/44691786#44691786.
// It sends the compiler output from the build\tmp directory to gradle stdout.
// TODO - make this depend upon the target, debug or release
//'/DNDEBUG',
'/DEBUG', '/D_DEBUG',
// Tell some of the modules in SourceT to use a relative include path for siglib.
'/DUSE_REL_SIGLIB_PATH',
]
}
return [] // Always return at least an empty array, otherwise all the previous settings will be wiped out.
}
if(suppressConsoleDef == false) {
task.compilerArgs.addAll toolChain.map { toolChain ->
if (toolChain in VisualCpp) {
return ['/D_CONSOLE']
}
return [] // Always return at least an empty array, otherwise all the previous settings will be wiped out.
}
}
}
}
////////////////////////////////////////////////////////////////
def addVSCompilerOption(Project prj, String newOption) {
prj.tasks.withType(CppCompile).configureEach { task ->
// There must be a simpler way to do this than using map.
task.compilerArgs.addAll toolChain.map { toolChain ->
if (toolChain in VisualCpp) {
return [ newOption ]
}
return [] // Always return at least an empty array, otherwise all the previous settings will be wiped out.
}
}
}
////////////////////////////////////////////////////////////////
def AddVSExeLinkOption(Project prj, String newOption) {
prj.tasks.withType(LinkExecutable).configureEach{ task->
task.linkerArgs.addAll toolChain.map { tc ->
if (tc in VisualCpp) {
return [
newOption
]
}
return [] // Always return at least an empty array, otherwise all the previous settings will be wiped out.
}
}
}
////////////////////////////////////////////////////////////////
def AddVSDllLinkOption(Project prj, String newOption) {
prj.tasks.withType(LinkSharedLibrary).configureEach{ task->
task.linkerArgs.addAll toolChain.map { tc ->
if (tc in VisualCpp) {
return [
newOption
]
}
return [] // Always return at least an empty array, otherwise all the previous settings will be wiped out.
}
}
}
////////////////////////////////////////////////////////////////
def addDefaultCPPLibraryOptions(Project prj, CppLibrary lib, Boolean suppressConsoleDef=false) {
lib.targetMachines = [prj.machines.windows.x86, prj.machines.linux.x86_64]
addDefaultCPPOptions(prj, suppressConsoleDef)
}
////////////////////////////////////////////////////////////////
def addDefaultCPPApplicationOptions(Project prj, CppApplication app, Boolean suppressConsoleDef=false) {
app.targetMachines = [prj.machines.windows.x86, prj.machines.linux.x86_64]
addDefaultCPPOptions(prj, suppressConsoleDef)
// Add Windows specific linker options
app.binaries.configureEach {
if (toolChain instanceof VisualCpp) {
linkTask.get().linkerArgs.addAll( [
"iphlpapi.lib",
"kernel32.lib",
"user32.lib",
"gdi32.lib",
"winspool.lib",
"comdlg32.lib",
"advapi32.lib",
"shell32.lib",
"ole32.lib",
"oleaut32.lib",
"odbc32.lib",
"odbccp32.lib",
"ws2_32.lib",
"wsock32.lib"
])
}
}
}
////////////////////////////////////////////////////////////////
def addWindowsResourceFile(Project prj, CppApplication app, String dir=".") {
app.binaries.whenElementFinalized { bin ->
def compileResources = prj.tasks.register("compileResources${bin.name.capitalize()}", WindowsResourceCompile) {
targetPlatform = bin.compileTask.get().targetPlatform
toolChain = bin.toolChain
source.from prj.fileTree(dir: "${dir}", includes: ["*.rc"])
// For some as yet not understood reason, if you just run "rc /v /l 0x409 Version.rc" in a VS command prompt, it works,
// but when Gradle runs the command, rc.exe can't find the standard include files, so we have to use the INCLUDE env var.
includes.from file(System.getenv('INCLUDE'))
compilerArgs.addAll toolChain.map({ NativeToolChain toolChain ->
if (toolChain instanceof VisualCpp) {
return [ "/v", "/l", "0x409" ]
}
return [] // Always return at least an empty array, otherwise all the previous settings will be wiped out.
}).get()
it.outputDir = prj.layout.buildDirectory.dir("windows-resources/${bin.name}").get().asFile
}
bin.linkTask.get().configure {
dependsOn compileResources
source.from compileResources.map({ return prj.fileTree(dir: it.outputDir, includes: ["**/*.res","**/*.obj"]) })
linkerArgs.addAll toolChain.map { NativeToolChain toolChain ->
if (toolChain instanceof VisualCpp) {
return ["user32.lib"]
}
return [] // Always return at least an empty array, otherwise all the previous settings will be wiped out.
}
}
}
}
////////////////////////////////////////////////////////////////
// For some reason when run under gradle, the compiler isn't locating the AFX stuff by default,
// although if you just run the same command (get it from gradle build --debug redirected to a file),
// from the same command prompt, it works.
def addAFXOptions(Project prj) {
addVSCompilerOption(prj, '/I' + System.getenv('VCToolsInstallDir') + 'atlmfc\\include')
AddVSExeLinkOption(prj, "/LIBPATH:" + System.getenv('VCToolsInstallDir') + 'atlmfc\\lib\\x86')
AddVSExeLinkOption(prj, "/subsystem:windows")
}
////////////////////////////////////////////////////////////////
// Tasks to show compiler options and output
// from https://stackoverflow.com/questions/44126969/gradle-compiler-output-when-building-c-c-code/44691786#44691786
task showCompilerOptions {
doLast {
println '\n-----------------------------------------------------\n'
println 'Compiler options:'
FileTree tree = fileTree('build').include('**/options.txt')
// Iterate over the contents of a tree
tree.each {File file ->
println 'Content of file ' + file + ':\n'
println file.text
println '------\n'
}
}
}
task showCompilerOutput {
dependsOn showCompilerOptions
doLast {
println '\n-----------------------------------------------------\n'
println 'Compiler output:'
FileTree tree = fileTree('build').include('**/output.txt')
// Iterate over the contents of a tree
tree.each {File file ->
println 'Content of file ' + file + ':\n'
println file.text
println '------\n'
}
}
}
// We need to "convert" our groovy method(s) to Closures, otherwise they won't be visible in
// other Gradle files.
// We wouldn't have to do this if these methods were in the root Gradle file, but this way
// we can refactor things to keep the root Gradle file cleaner.
// See https://stackoverflow.com/questions/18715137/extract-common-methods-from-gradle-build-script
ext {
addDefaultCPPLibraryOptions = this.&addDefaultCPPLibraryOptions
addDefaultCPPApplicationOptions = this.&addDefaultCPPApplicationOptions
addWindowsResourceFile = this.&addWindowsResourceFile
addAFXOptions = this.&addAFXOptions
}