-
Notifications
You must be signed in to change notification settings - Fork 146
/
Copy pathtoolset.js
224 lines (207 loc) · 6.75 KB
/
toolset.js
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
'use strict'
const TargetOptions = require('./targetOptions')
const environment = require('./environment')
const assert = require('assert')
const CMLog = require('./cmLog')
const { findVisualStudio } = environment.isWin ? require('./import/find-visualstudio') : {}
class Toolset {
constructor(options) {
this.options = options || {}
this.targetOptions = new TargetOptions(this.options)
this.generator = options.generator
this.toolset = options.toolset
this.platform = options.platform
this.target = options.target
this.cCompilerPath = options.cCompilerPath
this.cppCompilerPath = options.cppCompilerPath
this.compilerFlags = []
this.linkerFlags = []
this.makePath = null
this.log = new CMLog(this.options)
this._initialized = false
}
async initialize(install) {
if (!this._initialized) {
if (environment.isWin) {
await this.initializeWin(install)
} else {
this.initializePosix(install)
}
this._initialized = true
}
}
initializePosix(install) {
if (!this.cCompilerPath || !this.cppCompilerPath) {
// 1: Compiler
if (!environment.isGPPAvailable && !environment.isClangAvailable) {
if (environment.isOSX) {
throw new Error(
"C++ Compiler toolset is not available. Install Xcode Commandline Tools from Apple Dev Center, or install Clang with homebrew by invoking: 'brew install llvm --with-clang --with-asan'.",
)
} else {
throw new Error(
"C++ Compiler toolset is not available. Install proper compiler toolset with your package manager, eg. 'sudo apt-get install g++'.",
)
}
}
if (this.options.preferClang && environment.isClangAvailable) {
if (install) {
this.log.info('TOOL', 'Using clang++ compiler, because preferClang option is set, and clang++ is available.')
}
this.cppCompilerPath = this.cppCompilerPath || 'clang++'
this.cCompilerPath = this.cCompilerPath || 'clang'
} else if (this.options.preferGnu && environment.isGPPAvailable) {
if (install) {
this.log.info('TOOL', 'Using g++ compiler, because preferGnu option is set, and g++ is available.')
}
this.cppCompilerPath = this.cppCompilerPath || 'g++'
this.cCompilerPath = this.cCompilerPath || 'gcc'
}
}
// if it's already set because of options...
if (this.generator) {
if (install) {
this.log.info('TOOL', 'Using ' + this.generator + ' generator, as specified from commandline.')
}
}
// 2: Generator
else if (environment.isOSX) {
if (this.options.preferXcode) {
if (install) {
this.log.info('TOOL', 'Using Xcode generator, because preferXcode option is set.')
}
this.generator = 'Xcode'
} else if (this.options.preferMake && environment.isMakeAvailable) {
if (install) {
this.log.info(
'TOOL',
'Using Unix Makefiles generator, because preferMake option is set, and make is available.',
)
}
this.generator = 'Unix Makefiles'
} else if (environment.isNinjaAvailable) {
if (install) {
this.log.info('TOOL', 'Using Ninja generator, because ninja is available.')
}
this.generator = 'Ninja'
} else {
if (install) {
this.log.info('TOOL', 'Using Unix Makefiles generator.')
}
this.generator = 'Unix Makefiles'
}
} else {
if (this.options.preferMake && environment.isMakeAvailable) {
if (install) {
this.log.info(
'TOOL',
'Using Unix Makefiles generator, because preferMake option is set, and make is available.',
)
}
this.generator = 'Unix Makefiles'
} else if (environment.isNinjaAvailable) {
if (install) {
this.log.info('TOOL', 'Using Ninja generator, because ninja is available.')
}
this.generator = 'Ninja'
} else {
if (install) {
this.log.info('TOOL', 'Using Unix Makefiles generator.')
}
this.generator = 'Unix Makefiles'
}
}
// 3: Flags
if (environment.isOSX) {
if (install) {
this.log.verbose('TOOL', 'Setting default OSX compiler flags.')
}
this.compilerFlags.push('-D_DARWIN_USE_64_BIT_INODE=1')
this.compilerFlags.push('-D_LARGEFILE_SOURCE')
this.compilerFlags.push('-D_FILE_OFFSET_BITS=64')
this.linkerFlags.push('-undefined dynamic_lookup')
}
this.compilerFlags.push('-DBUILDING_NODE_EXTENSION')
// 4: Build target
if (this.options.target) {
this.log.info('TOOL', 'Building only the ' + this.options.target + ' target, as specified from the command line.')
}
}
async initializeWin(install) {
if (!this.generator) {
const foundVsInfo = await this._getTopSupportedVisualStudioGenerator()
if (foundVsInfo) {
if (install) {
this.log.info('TOOL', `Using ${foundVsInfo.generator} generator.`)
}
this.generator = foundVsInfo.generator
const isAboveVS16 = foundVsInfo.versionMajor >= 16
// The CMake Visual Studio Generator does not support the Win64 or ARM suffix on
// the generator name. Instead the generator platform must be set explicitly via
// the platform parameter
if (!this.platform && isAboveVS16) {
switch (this.targetOptions.arch) {
case 'ia32':
case 'x86':
this.platform = 'Win32'
break
case 'x64':
this.platform = 'x64'
break
case 'arm':
this.platform = 'ARM'
break
case 'arm64':
this.platform = 'ARM64'
break
default:
this.log.warn('TOOL', 'Unknown NodeJS architecture: ' + this.targetOptions.arch)
break
}
}
} else {
throw new Error('There is no Visual C++ compiler installed. Install Visual C++ Build Toolset or Visual Studio.')
}
} else {
// if it's already set because of options...
if (install) {
this.log.info('TOOL', 'Using ' + this.options.generator + ' generator, as specified from commandline.')
}
}
this.linkerFlags.push('/DELAYLOAD:NODE.EXE')
if (this.targetOptions.isX86) {
if (install) {
this.log.verbose('TOOL', 'Setting SAFESEH:NO linker flag.')
}
this.linkerFlags.push('/SAFESEH:NO')
}
}
async _getTopSupportedVisualStudioGenerator() {
const CMake = require('./cMake')
assert(environment.isWin)
const selectedVs = await findVisualStudio(environment.runtimeVersion, this.options.msvsVersion)
if (!selectedVs) return null
const list = await CMake.getGenerators(this.options, this.log)
for (const gen of list) {
const found = gen.startsWith(`Visual Studio ${selectedVs.versionMajor}`)
if (!found) {
continue
}
// unlike previous versions "Visual Studio 16 2019" and onwards don't end with arch name
const isAboveVS16 = selectedVs.versionMajor >= 16
if (!isAboveVS16) {
const is64Bit = gen.endsWith('Win64')
if ((this.targetOptions.isX86 && is64Bit) || (this.targetOptions.isX64 && !is64Bit)) {
continue
}
}
return {
...selectedVs,
generator: gen,
}
}
// Nothing matched
return null
}
}
module.exports = Toolset