@dry-software/cmake-js 7.3.1 → 7.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/cMake.js DELETED
@@ -1,362 +0,0 @@
1
- 'use strict'
2
- const which = require('which')
3
- const fs = require('fs-extra')
4
- const path = require('path')
5
- const environment = require('./environment')
6
- const Dist = require('./dist')
7
- const CMLog = require('./cmLog')
8
- const TargetOptions = require('./targetOptions')
9
- const processHelpers = require('./processHelpers')
10
- const locateNAN = require('./locateNAN')
11
- const locateNodeApi = require('./locateNodeApi')
12
- const npmConfigData = require('rc')('npm')
13
- const Toolset = require('./toolset')
14
- const headers = require('node-api-headers')
15
-
16
- class CMake {
17
- get path() {
18
- return this.options.cmakePath || 'cmake'
19
- }
20
- get isAvailable() {
21
- if (this._isAvailable === null) {
22
- this._isAvailable = CMake.isAvailable(this.options)
23
- }
24
- return this._isAvailable
25
- }
26
-
27
- constructor(options) {
28
- this.options = options || {}
29
- this.log = new CMLog(this.options)
30
- this.dist = new Dist(this.options)
31
- this.projectRoot = path.resolve(this.options.directory || process.cwd())
32
- this.workDir = path.resolve(this.options.out || path.join(this.projectRoot, 'build'))
33
- this.config = this.options.config || (this.options.debug ? 'Debug' : 'Release')
34
- this.buildDir = path.join(this.workDir, this.config)
35
- this._isAvailable = null
36
- this.targetOptions = new TargetOptions(this.options)
37
- this.toolset = new Toolset(this.options)
38
- this.cMakeOptions = this.options.cMakeOptions || {}
39
- this.extraCMakeArgs = this.options.extraCMakeArgs || []
40
- this.silent = !!options.silent
41
- }
42
- static isAvailable(options) {
43
- options = options || {}
44
- try {
45
- if (options.cmakePath) {
46
- const stat = fs.lstatSync(options.cmakePath)
47
- return !stat.isDirectory()
48
- } else {
49
- which.sync('cmake')
50
- return true
51
- }
52
- } catch (e) {
53
- // Ignore
54
- }
55
- return false
56
- }
57
- static async getGenerators(options, log) {
58
- const arch = ' [arch]'
59
- options = options || {}
60
- const gens = []
61
- if (CMake.isAvailable(options)) {
62
- // try parsing machine-readable capabilities (available since CMake 3.7)
63
- try {
64
- const stdout = await processHelpers.execFile([options.cmakePath || 'cmake', '-E', 'capabilities'])
65
- const capabilities = JSON.parse(stdout)
66
- return capabilities.generators.map((x) => x.name)
67
- } catch (error) {
68
- if (log) {
69
- log.verbose('TOOL', 'Failed to query CMake capabilities (CMake is probably older than 3.7)')
70
- }
71
- }
72
-
73
- // fall back to parsing help text
74
- const stdout = await processHelpers.execFile([options.cmakePath || 'cmake', '--help'])
75
- const hasCr = stdout.includes('\r\n')
76
- const output = hasCr ? stdout.split('\r\n') : stdout.split('\n')
77
- let on = false
78
- output.forEach(function (line, i) {
79
- if (on) {
80
- const parts = line.split('=')
81
- if (
82
- (parts.length === 2 && parts[0].trim()) ||
83
- (parts.length === 1 && i !== output.length - 1 && output[i + 1].trim()[0] === '=')
84
- ) {
85
- let gen = parts[0].trim()
86
- if (gen.endsWith(arch)) {
87
- gen = gen.substr(0, gen.length - arch.length)
88
- }
89
- gens.push(gen)
90
- }
91
- }
92
- if (line.trim() === 'Generators') {
93
- on = true
94
- }
95
- })
96
- } else {
97
- throw new Error('CMake is not installed. Install CMake.')
98
- }
99
- return gens
100
- }
101
- verifyIfAvailable() {
102
- if (!this.isAvailable) {
103
- throw new Error(
104
- "CMake executable is not found. Please use your system's package manager to install it, or you can get installers from there: http://cmake.org.",
105
- )
106
- }
107
- }
108
- async getConfigureCommand() {
109
- // Create command:
110
- let command = [this.path, this.projectRoot, '--no-warn-unused-cli']
111
-
112
- const D = []
113
-
114
- // CMake.js watermark
115
- D.push({ CMAKE_JS_VERSION: environment.cmakeJsVersion })
116
-
117
- // Build configuration:
118
- D.push({ CMAKE_BUILD_TYPE: this.config })
119
- if (environment.isWin) {
120
- D.push({ CMAKE_RUNTIME_OUTPUT_DIRECTORY: this.workDir })
121
- } else if (this.workDir.endsWith(this.config)) {
122
- D.push({ CMAKE_LIBRARY_OUTPUT_DIRECTORY: this.workDir })
123
- } else {
124
- D.push({ CMAKE_LIBRARY_OUTPUT_DIRECTORY: this.buildDir })
125
- }
126
-
127
- // In some configurations MD builds will crash upon attempting to free memory.
128
- // This tries to encourage MT builds which are larger but less likely to have this crash.
129
- D.push({ CMAKE_MSVC_RUNTIME_LIBRARY: 'MultiThreaded$<$<CONFIG:Debug>:Debug>' })
130
-
131
- // Includes:
132
- const includesString = await this.getCmakeJsIncludeString()
133
- D.push({ CMAKE_JS_INC: includesString })
134
-
135
- // Sources:
136
- const srcsString = this.getCmakeJsSrcString()
137
- D.push({ CMAKE_JS_SRC: srcsString })
138
-
139
- // Runtime:
140
- D.push({ NODE_RUNTIME: this.targetOptions.runtime })
141
- D.push({ NODE_RUNTIMEVERSION: this.targetOptions.runtimeVersion })
142
- D.push({ NODE_ARCH: this.targetOptions.arch })
143
-
144
- if (environment.isOSX) {
145
- if (this.targetOptions.arch) {
146
- let xcodeArch = this.targetOptions.arch
147
- if (xcodeArch === 'x64') xcodeArch = 'x86_64'
148
- D.push({ CMAKE_OSX_ARCHITECTURES: xcodeArch })
149
- }
150
- }
151
-
152
- // Custom options
153
- for (const [key, value] of Object.entries(this.cMakeOptions)) {
154
- D.push({ [key]: value })
155
- }
156
-
157
- // Toolset:
158
- await this.toolset.initialize(false)
159
-
160
- const libsString = this.getCmakeJsLibString()
161
- D.push({ CMAKE_JS_LIB: libsString })
162
-
163
- if (environment.isWin) {
164
- const nodeLibDefPath = this.getNodeLibDefPath()
165
- if (nodeLibDefPath) {
166
- const nodeLibPath = path.join(this.workDir, 'node.lib')
167
- D.push({ CMAKE_JS_NODELIB_DEF: nodeLibDefPath })
168
- D.push({ CMAKE_JS_NODELIB_TARGET: nodeLibPath })
169
- }
170
- }
171
-
172
- if (this.toolset.generator) {
173
- command.push('-G', this.toolset.generator)
174
- }
175
- if (this.toolset.platform) {
176
- command.push('-A', this.toolset.platform)
177
- }
178
- if (this.toolset.toolset) {
179
- command.push('-T', this.toolset.toolset)
180
- }
181
- if (this.toolset.cppCompilerPath) {
182
- D.push({ CMAKE_CXX_COMPILER: this.toolset.cppCompilerPath })
183
- }
184
- if (this.toolset.cCompilerPath) {
185
- D.push({ CMAKE_C_COMPILER: this.toolset.cCompilerPath })
186
- }
187
- if (this.toolset.compilerFlags.length) {
188
- D.push({ CMAKE_CXX_FLAGS: this.toolset.compilerFlags.join(' ') })
189
- }
190
- if (this.toolset.linkerFlags.length) {
191
- D.push({ CMAKE_SHARED_LINKER_FLAGS: this.toolset.linkerFlags.join(' ') })
192
- }
193
- if (this.toolset.makePath) {
194
- D.push({ CMAKE_MAKE_PROGRAM: this.toolset.makePath })
195
- }
196
-
197
- // Load NPM config
198
- for (const [key, value] of Object.entries(npmConfigData)) {
199
- if (key.startsWith('cmake_')) {
200
- const sk = key.substr(6)
201
- if (sk && value) {
202
- D.push({ [sk]: value })
203
- }
204
- }
205
- }
206
-
207
- command = command.concat(
208
- D.map(function (p) {
209
- return '-D' + Object.keys(p)[0] + '=' + Object.values(p)[0]
210
- }),
211
- )
212
-
213
- return command.concat(this.extraCMakeArgs)
214
- }
215
- getCmakeJsLibString() {
216
- const libs = []
217
- if (environment.isWin) {
218
- const nodeLibDefPath = this.getNodeLibDefPath()
219
- if (nodeLibDefPath) {
220
- libs.push(path.join(this.workDir, 'node.lib'))
221
- } else {
222
- libs.push(...this.dist.winLibs)
223
- }
224
- }
225
- return libs.join(';')
226
- }
227
- async getCmakeJsIncludeString() {
228
- let incPaths = []
229
- if (!this.options.isNodeApi) {
230
- // Include and lib:
231
- if (this.dist.headerOnly) {
232
- incPaths = [path.join(this.dist.internalPath, '/include/node')]
233
- } else {
234
- const nodeH = path.join(this.dist.internalPath, '/src')
235
- const v8H = path.join(this.dist.internalPath, '/deps/v8/include')
236
- const uvH = path.join(this.dist.internalPath, '/deps/uv/include')
237
- incPaths = [nodeH, v8H, uvH]
238
- }
239
-
240
- // NAN
241
- const nanH = await locateNAN(this.projectRoot)
242
- if (nanH) {
243
- incPaths.push(nanH)
244
- }
245
- } else {
246
- // Base headers
247
- const apiHeaders = require('node-api-headers')
248
- incPaths.push(apiHeaders.include_dir)
249
-
250
- // Node-api
251
- const napiH = await locateNodeApi(this.projectRoot)
252
- if (napiH) {
253
- incPaths.push(napiH)
254
- }
255
- }
256
-
257
- return incPaths.join(';')
258
- }
259
- getCmakeJsSrcString() {
260
- const srcPaths = []
261
- if (environment.isWin) {
262
- const delayHook = path.normalize(path.join(__dirname, 'cpp', 'win_delay_load_hook.cc'))
263
-
264
- srcPaths.push(delayHook.replace(/\\/gm, '/'))
265
- }
266
-
267
- return srcPaths.join(';')
268
- }
269
- getNodeLibDefPath() {
270
- return environment.isWin && this.options.isNodeApi ? headers.def_paths.node_api_def : undefined
271
- }
272
- async configure() {
273
- this.verifyIfAvailable()
274
-
275
- this.log.info('CMD', 'CONFIGURE')
276
- const listPath = path.join(this.projectRoot, 'CMakeLists.txt')
277
- const command = await this.getConfigureCommand()
278
-
279
- try {
280
- await fs.lstat(listPath)
281
- } catch (e) {
282
- throw new Error("'" + listPath + "' not found.")
283
- }
284
-
285
- try {
286
- await fs.ensureDir(this.workDir)
287
- } catch (e) {
288
- // Ignore
289
- }
290
-
291
- const cwd = process.cwd()
292
- process.chdir(this.workDir)
293
- try {
294
- await this._run(command)
295
- } finally {
296
- process.chdir(cwd)
297
- }
298
- }
299
- async ensureConfigured() {
300
- try {
301
- await fs.lstat(path.join(this.workDir, 'CMakeCache.txt'))
302
- } catch (e) {
303
- await this.configure()
304
- }
305
- }
306
- getBuildCommand() {
307
- const command = [this.path, '--build', this.workDir, '--config', this.config]
308
- if (this.options.target) {
309
- command.push('--target', this.options.target)
310
- }
311
- if (this.options.parallel) {
312
- command.push('--parallel', this.options.parallel)
313
- }
314
- return Promise.resolve(command.concat(this.extraCMakeArgs))
315
- }
316
- async build() {
317
- this.verifyIfAvailable()
318
-
319
- await this.ensureConfigured()
320
- const buildCommand = await this.getBuildCommand()
321
- this.log.info('CMD', 'BUILD')
322
- await this._run(buildCommand)
323
- }
324
- getCleanCommand() {
325
- return [this.path, '-E', 'remove_directory', this.workDir].concat(this.extraCMakeArgs)
326
- }
327
- clean() {
328
- this.verifyIfAvailable()
329
-
330
- this.log.info('CMD', 'CLEAN')
331
- return this._run(this.getCleanCommand())
332
- }
333
- async reconfigure() {
334
- this.extraCMakeArgs = []
335
- await this.clean()
336
- await this.configure()
337
- }
338
- async rebuild() {
339
- this.extraCMakeArgs = []
340
- await this.clean()
341
- await this.build()
342
- }
343
- async compile() {
344
- this.extraCMakeArgs = []
345
- try {
346
- await this.build()
347
- } catch (e) {
348
- this.log.info('REP', 'Build has been failed, trying to do a full rebuild.')
349
- await this.rebuild()
350
- }
351
- }
352
- _run(command) {
353
- this.log.info('RUN', command)
354
- return processHelpers.run(command, { silent: this.silent })
355
- }
356
-
357
- async getGenerators() {
358
- return CMake.getGenerators(this.options, this.log)
359
- }
360
- }
361
-
362
- module.exports = CMake
package/lib/cmLog.js DELETED
@@ -1,61 +0,0 @@
1
- 'use strict'
2
- const log = require('npmlog')
3
-
4
- class CMLog {
5
- get level() {
6
- if (this.options.noLog) {
7
- return 'silly'
8
- } else {
9
- return log.level
10
- }
11
- }
12
-
13
- constructor(options) {
14
- this.options = options || {}
15
- this.debug = require('debug')(this.options.logName || 'cmake-js')
16
- }
17
- silly(cat, msg) {
18
- if (this.options.noLog) {
19
- this.debug(cat + ': ' + msg)
20
- } else {
21
- log.silly(cat, msg)
22
- }
23
- }
24
- verbose(cat, msg) {
25
- if (this.options.noLog) {
26
- this.debug(cat + ': ' + msg)
27
- } else {
28
- log.verbose(cat, msg)
29
- }
30
- }
31
- info(cat, msg) {
32
- if (this.options.noLog) {
33
- this.debug(cat + ': ' + msg)
34
- } else {
35
- log.info(cat, msg)
36
- }
37
- }
38
- warn(cat, msg) {
39
- if (this.options.noLog) {
40
- this.debug(cat + ': ' + msg)
41
- } else {
42
- log.warn(cat, msg)
43
- }
44
- }
45
- http(cat, msg) {
46
- if (this.options.noLog) {
47
- this.debug(cat + ': ' + msg)
48
- } else {
49
- log.http(cat, msg)
50
- }
51
- }
52
- error(cat, msg) {
53
- if (this.options.noLog) {
54
- this.debug(cat + ': ' + msg)
55
- } else {
56
- log.error(cat, msg)
57
- }
58
- }
59
- }
60
-
61
- module.exports = CMLog
package/lib/dist.js DELETED
@@ -1,176 +0,0 @@
1
- 'use strict'
2
- const environment = require('./environment')
3
- const path = require('path')
4
- const urljoin = require('url-join')
5
- const fs = require('fs-extra')
6
- const CMLog = require('./cmLog')
7
- const TargetOptions = require('./targetOptions')
8
- const runtimePaths = require('./runtimePaths')
9
- const Downloader = require('./downloader')
10
- const os = require('os')
11
-
12
- function testSum(sums, sum, fPath) {
13
- const serverSum = sums.find(function (s) {
14
- return s.getPath === fPath
15
- })
16
- if (serverSum && serverSum.sum === sum) {
17
- return
18
- }
19
- throw new Error("SHA sum of file '" + fPath + "' mismatch!")
20
- }
21
-
22
- class Dist {
23
- get internalPath() {
24
- const cacheDirectory = '.cmake-js'
25
- const runtimeArchDirectory = this.targetOptions.runtime + '-' + this.targetOptions.arch
26
- const runtimeVersionDirectory = 'v' + this.targetOptions.runtimeVersion
27
-
28
- return (
29
- this.options.runtimeDirectory ||
30
- path.join(os.homedir(), cacheDirectory, runtimeArchDirectory, runtimeVersionDirectory)
31
- )
32
- }
33
- get externalPath() {
34
- return runtimePaths.get(this.targetOptions).externalPath
35
- }
36
- get downloaded() {
37
- let headers = false
38
- let libs = true
39
- let stat = getStat(this.internalPath)
40
- if (stat.isDirectory()) {
41
- if (this.headerOnly) {
42
- stat = getStat(path.join(this.internalPath, 'include/node/node.h'))
43
- headers = stat.isFile()
44
- } else {
45
- stat = getStat(path.join(this.internalPath, 'src/node.h'))
46
- if (stat.isFile()) {
47
- stat = getStat(path.join(this.internalPath, 'deps/v8/include/v8.h'))
48
- headers = stat.isFile()
49
- }
50
- }
51
- if (environment.isWin) {
52
- for (const libPath of this.winLibs) {
53
- stat = getStat(libPath)
54
- libs = libs && stat.isFile()
55
- }
56
- }
57
- }
58
- return headers && libs
59
-
60
- function getStat(path) {
61
- try {
62
- return fs.statSync(path)
63
- } catch (e) {
64
- return {
65
- isFile: () => false,
66
- isDirectory: () => false,
67
- }
68
- }
69
- }
70
- }
71
- get winLibs() {
72
- const libs = runtimePaths.get(this.targetOptions).winLibs
73
- const result = []
74
- for (const lib of libs) {
75
- result.push(path.join(this.internalPath, lib.dir, lib.name))
76
- }
77
- return result
78
- }
79
- get headerOnly() {
80
- return runtimePaths.get(this.targetOptions).headerOnly
81
- }
82
-
83
- constructor(options) {
84
- this.options = options || {}
85
- this.log = new CMLog(this.options)
86
- this.targetOptions = new TargetOptions(this.options)
87
- this.downloader = new Downloader(this.options)
88
- }
89
-
90
- async ensureDownloaded() {
91
- if (!this.downloaded) {
92
- await this.download()
93
- }
94
- }
95
- async download() {
96
- const log = this.log
97
- log.info('DIST', 'Downloading distribution files to: ' + this.internalPath)
98
- await fs.ensureDir(this.internalPath)
99
- const sums = await this._downloadShaSums()
100
- await Promise.all([this._downloadLibs(sums), this._downloadTar(sums)])
101
- }
102
- async _downloadShaSums() {
103
- if (this.targetOptions.runtime === 'node') {
104
- const sumUrl = urljoin(this.externalPath, 'SHASUMS256.txt')
105
- const log = this.log
106
- log.http('DIST', '\t- ' + sumUrl)
107
- return (await this.downloader.downloadString(sumUrl))
108
- .split('\n')
109
- .map(function (line) {
110
- const parts = line.split(/\s+/)
111
- return {
112
- getPath: parts[1],
113
- sum: parts[0],
114
- }
115
- })
116
- .filter(function (i) {
117
- return i.getPath && i.sum
118
- })
119
- } else {
120
- return null
121
- }
122
- }
123
- async _downloadTar(sums) {
124
- const log = this.log
125
- const self = this
126
- const tarLocalPath = runtimePaths.get(self.targetOptions).tarPath
127
- const tarUrl = urljoin(self.externalPath, tarLocalPath)
128
- log.http('DIST', '\t- ' + tarUrl)
129
-
130
- const sum = await this.downloader.downloadTgz(tarUrl, {
131
- hash: sums ? 'sha256' : null,
132
- cwd: self.internalPath,
133
- strip: 1,
134
- filter: function (entryPath) {
135
- if (entryPath === self.internalPath) {
136
- return true
137
- }
138
- const ext = path.extname(entryPath)
139
- return ext && ext.toLowerCase() === '.h'
140
- },
141
- })
142
-
143
- if (sums) {
144
- testSum(sums, sum, tarLocalPath)
145
- }
146
- }
147
- async _downloadLibs(sums) {
148
- const log = this.log
149
- const self = this
150
- if (!environment.isWin) {
151
- return
152
- }
153
-
154
- const paths = runtimePaths.get(self.targetOptions)
155
- for (const dirs of paths.winLibs) {
156
- const subDir = dirs.dir
157
- const fn = dirs.name
158
- const fPath = subDir ? urljoin(subDir, fn) : fn
159
- const libUrl = urljoin(self.externalPath, fPath)
160
- log.http('DIST', '\t- ' + libUrl)
161
-
162
- await fs.ensureDir(path.join(self.internalPath, subDir))
163
-
164
- const sum = await this.downloader.downloadFile(libUrl, {
165
- path: path.join(self.internalPath, fPath),
166
- hash: sums ? 'sha256' : null,
167
- })
168
-
169
- if (sums) {
170
- testSum(sums, sum, fPath)
171
- }
172
- }
173
- }
174
- }
175
-
176
- module.exports = Dist
package/lib/downloader.js DELETED
@@ -1,92 +0,0 @@
1
- 'use strict'
2
- const crypto = require('crypto')
3
- const axios = require('axios')
4
- const MemoryStream = require('memory-stream')
5
- const zlib = require('zlib')
6
- const tar = require('tar')
7
- const fs = require('fs')
8
- const CMLog = require('./cmLog')
9
-
10
- class Downloader {
11
- constructor(options) {
12
- this.options = options || {}
13
- this.log = new CMLog(this.options)
14
- }
15
- downloadToStream(url, stream, hash) {
16
- const self = this
17
- const shasum = hash ? crypto.createHash(hash) : null
18
- return new Promise(function (resolve, reject) {
19
- let length = 0
20
- let done = 0
21
- let lastPercent = 0
22
- axios
23
- .get(url, { responseType: 'stream' })
24
- .then(function (response) {
25
- length = parseInt(response.headers['content-length'])
26
- if (typeof length !== 'number') {
27
- length = 0
28
- }
29
-
30
- response.data.on('data', function (chunk) {
31
- if (shasum) {
32
- shasum.update(chunk)
33
- }
34
- if (length) {
35
- done += chunk.length
36
- let percent = (done / length) * 100
37
- percent = Math.round(percent / 10) * 10 + 10
38
- if (percent > lastPercent) {
39
- self.log.verbose('DWNL', '\t' + lastPercent + '%')
40
- lastPercent = percent
41
- }
42
- }
43
- })
44
-
45
- response.data.pipe(stream)
46
- })
47
- .catch(function (err) {
48
- reject(err)
49
- })
50
-
51
- stream.once('error', function (err) {
52
- reject(err)
53
- })
54
-
55
- stream.once('finish', function () {
56
- resolve(shasum ? shasum.digest('hex') : undefined)
57
- })
58
- })
59
- }
60
- async downloadString(url) {
61
- const result = new MemoryStream()
62
- await this.downloadToStream(url, result)
63
- return result.toString()
64
- }
65
- async downloadFile(url, options) {
66
- if (typeof options === 'string') {
67
- options.path = options
68
- }
69
- const result = fs.createWriteStream(options.path)
70
- const sum = await this.downloadToStream(url, result, options.hash)
71
- this.testSum(url, sum, options)
72
- return sum
73
- }
74
- async downloadTgz(url, options) {
75
- if (typeof options === 'string') {
76
- options.cwd = options
77
- }
78
- const gunzip = zlib.createGunzip()
79
- const extractor = tar.extract(options)
80
- gunzip.pipe(extractor)
81
- const sum = await this.downloadToStream(url, gunzip, options.hash)
82
- this.testSum(url, sum, options)
83
- return sum
84
- }
85
- testSum(url, sum, options) {
86
- if (options.hash && sum && options.sum && options.sum !== sum) {
87
- throw new Error(options.hash.toUpperCase() + " sum of download '" + url + "' mismatch!")
88
- }
89
- }
90
- }
91
-
92
- module.exports = Downloader