source: trip-planner-front/node_modules/node-gyp/lib/configure.js@ 1ad8e64

Last change on this file since 1ad8e64 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 12.1 KB
Line 
1'use strict'
2
3const fs = require('graceful-fs')
4const path = require('path')
5const log = require('npmlog')
6const os = require('os')
7const processRelease = require('./process-release')
8const win = process.platform === 'win32'
9const findNodeDirectory = require('./find-node-directory')
10const msgFormat = require('util').format
11var findPython = require('./find-python')
12if (win) {
13 var findVisualStudio = require('./find-visualstudio')
14}
15
16function configure (gyp, argv, callback) {
17 var python
18 var buildDir = path.resolve('build')
19 var configNames = ['config.gypi', 'common.gypi']
20 var configs = []
21 var nodeDir
22 var release = processRelease(argv, gyp, process.version, process.release)
23
24 findPython(gyp.opts.python, function (err, found) {
25 if (err) {
26 callback(err)
27 } else {
28 python = found
29 getNodeDir()
30 }
31 })
32
33 function getNodeDir () {
34 // 'python' should be set by now
35 process.env.PYTHON = python
36
37 if (gyp.opts.nodedir) {
38 // --nodedir was specified. use that for the dev files
39 nodeDir = gyp.opts.nodedir.replace(/^~/, os.homedir())
40
41 log.verbose('get node dir', 'compiling against specified --nodedir dev files: %s', nodeDir)
42 createBuildDir()
43 } else {
44 // if no --nodedir specified, ensure node dependencies are installed
45 if ('v' + release.version !== process.version) {
46 // if --target was given, then determine a target version to compile for
47 log.verbose('get node dir', 'compiling against --target node version: %s', release.version)
48 } else {
49 // if no --target was specified then use the current host node version
50 log.verbose('get node dir', 'no --target version specified, falling back to host node version: %s', release.version)
51 }
52
53 if (!release.semver) {
54 // could not parse the version string with semver
55 return callback(new Error('Invalid version number: ' + release.version))
56 }
57
58 // If the tarball option is set, always remove and reinstall the headers
59 // into devdir. Otherwise only install if they're not already there.
60 gyp.opts.ensure = !gyp.opts.tarball
61
62 gyp.commands.install([release.version], function (err) {
63 if (err) {
64 return callback(err)
65 }
66 log.verbose('get node dir', 'target node version installed:', release.versionDir)
67 nodeDir = path.resolve(gyp.devDir, release.versionDir)
68 createBuildDir()
69 })
70 }
71 }
72
73 function createBuildDir () {
74 log.verbose('build dir', 'attempting to create "build" dir: %s', buildDir)
75 fs.mkdir(buildDir, { recursive: true }, function (err, isNew) {
76 if (err) {
77 return callback(err)
78 }
79 log.verbose('build dir', '"build" dir needed to be created?', isNew)
80 if (win) {
81 findVisualStudio(release.semver, gyp.opts.msvs_version,
82 createConfigFile)
83 } else {
84 createConfigFile()
85 }
86 })
87 }
88
89 function createConfigFile (err, vsInfo) {
90 if (err) {
91 return callback(err)
92 }
93
94 var configFilename = 'config.gypi'
95 var configPath = path.resolve(buildDir, configFilename)
96
97 log.verbose('build/' + configFilename, 'creating config file')
98
99 var config = process.config || {}
100 var defaults = config.target_defaults
101 var variables = config.variables
102
103 // default "config.variables"
104 if (!variables) {
105 variables = config.variables = {}
106 }
107
108 // default "config.defaults"
109 if (!defaults) {
110 defaults = config.target_defaults = {}
111 }
112
113 // don't inherit the "defaults" from node's `process.config` object.
114 // doing so could cause problems in cases where the `node` executable was
115 // compiled on a different machine (with different lib/include paths) than
116 // the machine where the addon is being built to
117 defaults.cflags = []
118 defaults.defines = []
119 defaults.include_dirs = []
120 defaults.libraries = []
121
122 // set the default_configuration prop
123 if ('debug' in gyp.opts) {
124 defaults.default_configuration = gyp.opts.debug ? 'Debug' : 'Release'
125 }
126
127 if (!defaults.default_configuration) {
128 defaults.default_configuration = 'Release'
129 }
130
131 // set the target_arch variable
132 variables.target_arch = gyp.opts.arch || process.arch || 'ia32'
133 if (variables.target_arch === 'arm64') {
134 defaults.msvs_configuration_platform = 'ARM64'
135 defaults.xcode_configuration_platform = 'arm64'
136 }
137
138 // set the node development directory
139 variables.nodedir = nodeDir
140
141 // disable -T "thin" static archives by default
142 variables.standalone_static_library = gyp.opts.thin ? 0 : 1
143
144 if (win) {
145 process.env.GYP_MSVS_VERSION = Math.min(vsInfo.versionYear, 2015)
146 process.env.GYP_MSVS_OVERRIDE_PATH = vsInfo.path
147 defaults.msbuild_toolset = vsInfo.toolset
148 if (vsInfo.sdk) {
149 defaults.msvs_windows_target_platform_version = vsInfo.sdk
150 }
151 if (variables.target_arch === 'arm64') {
152 if (vsInfo.versionMajor > 15 ||
153 (vsInfo.versionMajor === 15 && vsInfo.versionMajor >= 9)) {
154 defaults.msvs_enable_marmasm = 1
155 } else {
156 log.warn('Compiling ARM64 assembly is only available in\n' +
157 'Visual Studio 2017 version 15.9 and above')
158 }
159 }
160 variables.msbuild_path = vsInfo.msBuild
161 }
162
163 // loop through the rest of the opts and add the unknown ones as variables.
164 // this allows for module-specific configure flags like:
165 //
166 // $ node-gyp configure --shared-libxml2
167 Object.keys(gyp.opts).forEach(function (opt) {
168 if (opt === 'argv') {
169 return
170 }
171 if (opt in gyp.configDefs) {
172 return
173 }
174 variables[opt.replace(/-/g, '_')] = gyp.opts[opt]
175 })
176
177 // ensures that any boolean values from `process.config` get stringified
178 function boolsToString (k, v) {
179 if (typeof v === 'boolean') {
180 return String(v)
181 }
182 return v
183 }
184
185 log.silly('build/' + configFilename, config)
186
187 // now write out the config.gypi file to the build/ dir
188 var prefix = '# Do not edit. File was generated by node-gyp\'s "configure" step'
189
190 var json = JSON.stringify(config, boolsToString, 2)
191 log.verbose('build/' + configFilename, 'writing out config file: %s', configPath)
192 configs.push(configPath)
193 fs.writeFile(configPath, [prefix, json, ''].join('\n'), findConfigs)
194 }
195
196 function findConfigs (err) {
197 if (err) {
198 return callback(err)
199 }
200
201 var name = configNames.shift()
202 if (!name) {
203 return runGyp()
204 }
205 var fullPath = path.resolve(name)
206
207 log.verbose(name, 'checking for gypi file: %s', fullPath)
208 fs.stat(fullPath, function (err) {
209 if (err) {
210 if (err.code === 'ENOENT') {
211 findConfigs() // check next gypi filename
212 } else {
213 callback(err)
214 }
215 } else {
216 log.verbose(name, 'found gypi file')
217 configs.push(fullPath)
218 findConfigs()
219 }
220 })
221 }
222
223 function runGyp (err) {
224 if (err) {
225 return callback(err)
226 }
227
228 if (!~argv.indexOf('-f') && !~argv.indexOf('--format')) {
229 if (win) {
230 log.verbose('gyp', 'gyp format was not specified; forcing "msvs"')
231 // force the 'make' target for non-Windows
232 argv.push('-f', 'msvs')
233 } else {
234 log.verbose('gyp', 'gyp format was not specified; forcing "make"')
235 // force the 'make' target for non-Windows
236 argv.push('-f', 'make')
237 }
238 }
239
240 // include all the ".gypi" files that were found
241 configs.forEach(function (config) {
242 argv.push('-I', config)
243 })
244
245 // For AIX and z/OS we need to set up the path to the exports file
246 // which contains the symbols needed for linking.
247 var nodeExpFile
248 if (process.platform === 'aix' || process.platform === 'os390') {
249 var ext = process.platform === 'aix' ? 'exp' : 'x'
250 var nodeRootDir = findNodeDirectory()
251 var candidates
252
253 if (process.platform === 'aix') {
254 candidates = [
255 'include/node/node',
256 'out/Release/node',
257 'out/Debug/node',
258 'node'
259 ].map(function (file) {
260 return file + '.' + ext
261 })
262 } else {
263 candidates = [
264 'out/Release/obj.target/libnode',
265 'out/Debug/obj.target/libnode',
266 'lib/libnode'
267 ].map(function (file) {
268 return file + '.' + ext
269 })
270 }
271
272 var logprefix = 'find exports file'
273 nodeExpFile = findAccessibleSync(logprefix, nodeRootDir, candidates)
274 if (nodeExpFile !== undefined) {
275 log.verbose(logprefix, 'Found exports file: %s', nodeExpFile)
276 } else {
277 var msg = msgFormat('Could not find node.%s file in %s', ext, nodeRootDir)
278 log.error(logprefix, 'Could not find exports file')
279 return callback(new Error(msg))
280 }
281 }
282
283 // this logic ported from the old `gyp_addon` python file
284 var gypScript = path.resolve(__dirname, '..', 'gyp', 'gyp_main.py')
285 var addonGypi = path.resolve(__dirname, '..', 'addon.gypi')
286 var commonGypi = path.resolve(nodeDir, 'include/node/common.gypi')
287 fs.stat(commonGypi, function (err) {
288 if (err) {
289 commonGypi = path.resolve(nodeDir, 'common.gypi')
290 }
291
292 var outputDir = 'build'
293 if (win) {
294 // Windows expects an absolute path
295 outputDir = buildDir
296 }
297 var nodeGypDir = path.resolve(__dirname, '..')
298
299 var nodeLibFile = path.join(nodeDir,
300 !gyp.opts.nodedir ? '<(target_arch)' : '$(Configuration)',
301 release.name + '.lib')
302
303 argv.push('-I', addonGypi)
304 argv.push('-I', commonGypi)
305 argv.push('-Dlibrary=shared_library')
306 argv.push('-Dvisibility=default')
307 argv.push('-Dnode_root_dir=' + nodeDir)
308 if (process.platform === 'aix' || process.platform === 'os390') {
309 argv.push('-Dnode_exp_file=' + nodeExpFile)
310 }
311 argv.push('-Dnode_gyp_dir=' + nodeGypDir)
312
313 // Do this to keep Cygwin environments happy, else the unescaped '\' gets eaten up,
314 // resulting in bad paths, Ex c:parentFolderfolderanotherFolder instead of c:\parentFolder\folder\anotherFolder
315 if (win) {
316 nodeLibFile = nodeLibFile.replace(/\\/g, '\\\\')
317 }
318 argv.push('-Dnode_lib_file=' + nodeLibFile)
319 argv.push('-Dmodule_root_dir=' + process.cwd())
320 argv.push('-Dnode_engine=' +
321 (gyp.opts.node_engine || process.jsEngine || 'v8'))
322 argv.push('--depth=.')
323 argv.push('--no-parallel')
324
325 // tell gyp to write the Makefile/Solution files into output_dir
326 argv.push('--generator-output', outputDir)
327
328 // tell make to write its output into the same dir
329 argv.push('-Goutput_dir=.')
330
331 // enforce use of the "binding.gyp" file
332 argv.unshift('binding.gyp')
333
334 // execute `gyp` from the current target nodedir
335 argv.unshift(gypScript)
336
337 // make sure python uses files that came with this particular node package
338 var pypath = [path.join(__dirname, '..', 'gyp', 'pylib')]
339 if (process.env.PYTHONPATH) {
340 pypath.push(process.env.PYTHONPATH)
341 }
342 process.env.PYTHONPATH = pypath.join(win ? ';' : ':')
343
344 var cp = gyp.spawn(python, argv)
345 cp.on('exit', onCpExit)
346 })
347 }
348
349 function onCpExit (code) {
350 if (code !== 0) {
351 callback(new Error('`gyp` failed with exit code: ' + code))
352 } else {
353 // we're done
354 callback()
355 }
356 }
357}
358
359/**
360 * Returns the first file or directory from an array of candidates that is
361 * readable by the current user, or undefined if none of the candidates are
362 * readable.
363 */
364function findAccessibleSync (logprefix, dir, candidates) {
365 for (var next = 0; next < candidates.length; next++) {
366 var candidate = path.resolve(dir, candidates[next])
367 try {
368 var fd = fs.openSync(candidate, 'r')
369 } catch (e) {
370 // this candidate was not found or not readable, do nothing
371 log.silly(logprefix, 'Could not open %s: %s', candidate, e.message)
372 continue
373 }
374 fs.closeSync(fd)
375 log.silly(logprefix, 'Found readable %s', candidate)
376 return candidate
377 }
378
379 return undefined
380}
381
382module.exports = configure
383module.exports.test = {
384 findAccessibleSync: findAccessibleSync
385}
386module.exports.usage = 'Generates ' + (win ? 'MSVC project files' : 'a Makefile') + ' for the current module'
Note: See TracBrowser for help on using the repository browser.