You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					336 lines
				
				14 KiB
			
		
		
			
		
	
	
					336 lines
				
				14 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								'use strict';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports = exports;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const path = require('path');
							 | 
						||
| 
								 | 
							
								const semver = require('semver');
							 | 
						||
| 
								 | 
							
								const url = require('url');
							 | 
						||
| 
								 | 
							
								const detect_libc = require('detect-libc');
							 | 
						||
| 
								 | 
							
								const napi = require('./napi.js');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let abi_crosswalk;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// This is used for unit testing to provide a fake
							 | 
						||
| 
								 | 
							
								// ABI crosswalk that emulates one that is not updated
							 | 
						||
| 
								 | 
							
								// for the current version
							 | 
						||
| 
								 | 
							
								if (process.env.NODE_PRE_GYP_ABI_CROSSWALK) {
							 | 
						||
| 
								 | 
							
								  abi_crosswalk = require(process.env.NODE_PRE_GYP_ABI_CROSSWALK);
							 | 
						||
| 
								 | 
							
								} else {
							 | 
						||
| 
								 | 
							
								  abi_crosswalk = require('./abi_crosswalk.json');
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const major_versions = {};
							 | 
						||
| 
								 | 
							
								Object.keys(abi_crosswalk).forEach((v) => {
							 | 
						||
| 
								 | 
							
								  const major = v.split('.')[0];
							 | 
						||
| 
								 | 
							
								  if (!major_versions[major]) {
							 | 
						||
| 
								 | 
							
								    major_versions[major] = v;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function get_electron_abi(runtime, target_version) {
							 | 
						||
| 
								 | 
							
								  if (!runtime) {
							 | 
						||
| 
								 | 
							
								    throw new Error('get_electron_abi requires valid runtime arg');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if (typeof target_version === 'undefined') {
							 | 
						||
| 
								 | 
							
								    // erroneous CLI call
							 | 
						||
| 
								 | 
							
								    throw new Error('Empty target version is not supported if electron is the target.');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  // Electron guarantees that patch version update won't break native modules.
							 | 
						||
| 
								 | 
							
								  const sem_ver = semver.parse(target_version);
							 | 
						||
| 
								 | 
							
								  return runtime + '-v' + sem_ver.major + '.' + sem_ver.minor;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								module.exports.get_electron_abi = get_electron_abi;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function get_node_webkit_abi(runtime, target_version) {
							 | 
						||
| 
								 | 
							
								  if (!runtime) {
							 | 
						||
| 
								 | 
							
								    throw new Error('get_node_webkit_abi requires valid runtime arg');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if (typeof target_version === 'undefined') {
							 | 
						||
| 
								 | 
							
								    // erroneous CLI call
							 | 
						||
| 
								 | 
							
								    throw new Error('Empty target version is not supported if node-webkit is the target.');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return runtime + '-v' + target_version;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								module.exports.get_node_webkit_abi = get_node_webkit_abi;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function get_node_abi(runtime, versions) {
							 | 
						||
| 
								 | 
							
								  if (!runtime) {
							 | 
						||
| 
								 | 
							
								    throw new Error('get_node_abi requires valid runtime arg');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if (!versions) {
							 | 
						||
| 
								 | 
							
								    throw new Error('get_node_abi requires valid process.versions object');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  const sem_ver = semver.parse(versions.node);
							 | 
						||
| 
								 | 
							
								  if (sem_ver.major === 0 && sem_ver.minor % 2) { // odd series
							 | 
						||
| 
								 | 
							
								    // https://github.com/mapbox/node-pre-gyp/issues/124
							 | 
						||
| 
								 | 
							
								    return runtime + '-v' + versions.node;
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    // process.versions.modules added in >= v0.10.4 and v0.11.7
							 | 
						||
| 
								 | 
							
								    // https://github.com/joyent/node/commit/ccabd4a6fa8a6eb79d29bc3bbe9fe2b6531c2d8e
							 | 
						||
| 
								 | 
							
								    return versions.modules ? runtime + '-v' + (+versions.modules) :
							 | 
						||
| 
								 | 
							
								      'v8-' + versions.v8.split('.').slice(0, 2).join('.');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								module.exports.get_node_abi = get_node_abi;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function get_runtime_abi(runtime, target_version) {
							 | 
						||
| 
								 | 
							
								  if (!runtime) {
							 | 
						||
| 
								 | 
							
								    throw new Error('get_runtime_abi requires valid runtime arg');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if (runtime === 'node-webkit') {
							 | 
						||
| 
								 | 
							
								    return get_node_webkit_abi(runtime, target_version || process.versions['node-webkit']);
							 | 
						||
| 
								 | 
							
								  } else if (runtime === 'electron') {
							 | 
						||
| 
								 | 
							
								    return get_electron_abi(runtime, target_version || process.versions.electron);
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    if (runtime !== 'node') {
							 | 
						||
| 
								 | 
							
								      throw new Error("Unknown Runtime: '" + runtime + "'");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    if (!target_version) {
							 | 
						||
| 
								 | 
							
								      return get_node_abi(runtime, process.versions);
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      let cross_obj;
							 | 
						||
| 
								 | 
							
								      // abi_crosswalk generated with ./scripts/abi_crosswalk.js
							 | 
						||
| 
								 | 
							
								      if (abi_crosswalk[target_version]) {
							 | 
						||
| 
								 | 
							
								        cross_obj = abi_crosswalk[target_version];
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        const target_parts = target_version.split('.').map((i) => { return +i; });
							 | 
						||
| 
								 | 
							
								        if (target_parts.length !== 3) { // parse failed
							 | 
						||
| 
								 | 
							
								          throw new Error('Unknown target version: ' + target_version);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        /*
							 | 
						||
| 
								 | 
							
								                    The below code tries to infer the last known ABI compatible version
							 | 
						||
| 
								 | 
							
								                    that we have recorded in the abi_crosswalk.json when an exact match
							 | 
						||
| 
								 | 
							
								                    is not possible. The reasons for this to exist are complicated:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                       - We support passing --target to be able to allow developers to package binaries for versions of node
							 | 
						||
| 
								 | 
							
								                         that are not the same one as they are running. This might also be used in combination with the
							 | 
						||
| 
								 | 
							
								                         --target_arch or --target_platform flags to also package binaries for alternative platforms
							 | 
						||
| 
								 | 
							
								                       - When --target is passed we can't therefore determine the ABI (process.versions.modules) from the node
							 | 
						||
| 
								 | 
							
								                         version that is running in memory
							 | 
						||
| 
								 | 
							
								                       - So, therefore node-pre-gyp keeps an "ABI crosswalk" (lib/util/abi_crosswalk.json) to be able to look
							 | 
						||
| 
								 | 
							
								                         this info up for all versions
							 | 
						||
| 
								 | 
							
								                       - But we cannot easily predict what the future ABI will be for released versions
							 | 
						||
| 
								 | 
							
								                       - And node-pre-gyp needs to be a `bundledDependency` in apps that depend on it in order to work correctly
							 | 
						||
| 
								 | 
							
								                         by being fully available at install time.
							 | 
						||
| 
								 | 
							
								                       - So, the speed of node releases and the bundled nature of node-pre-gyp mean that a new node-pre-gyp release
							 | 
						||
| 
								 | 
							
								                         need to happen for every node.js/io.js/node-webkit/nw.js/atom-shell/etc release that might come online if
							 | 
						||
| 
								 | 
							
								                         you want the `--target` flag to keep working for the latest version
							 | 
						||
| 
								 | 
							
								                       - Which is impractical ^^
							 | 
						||
| 
								 | 
							
								                       - Hence the below code guesses about future ABI to make the need to update node-pre-gyp less demanding.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                    In practice then you can have a dependency of your app like `node-sqlite3` that bundles a `node-pre-gyp` that
							 | 
						||
| 
								 | 
							
								                    only knows about node v0.10.33 in the `abi_crosswalk.json` but target node v0.10.34 (which is assumed to be
							 | 
						||
| 
								 | 
							
								                    ABI compatible with v0.10.33).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                    TODO: use semver module instead of custom version parsing
							 | 
						||
| 
								 | 
							
								                */
							 | 
						||
| 
								 | 
							
								        const major = target_parts[0];
							 | 
						||
| 
								 | 
							
								        let minor = target_parts[1];
							 | 
						||
| 
								 | 
							
								        let patch = target_parts[2];
							 | 
						||
| 
								 | 
							
								        // io.js: yeah if node.js ever releases 1.x this will break
							 | 
						||
| 
								 | 
							
								        // but that is unlikely to happen: https://github.com/iojs/io.js/pull/253#issuecomment-69432616
							 | 
						||
| 
								 | 
							
								        if (major === 1) {
							 | 
						||
| 
								 | 
							
								          // look for last release that is the same major version
							 | 
						||
| 
								 | 
							
								          // e.g. we assume io.js 1.x is ABI compatible with >= 1.0.0
							 | 
						||
| 
								 | 
							
								          while (true) {
							 | 
						||
| 
								 | 
							
								            if (minor > 0) --minor;
							 | 
						||
| 
								 | 
							
								            if (patch > 0) --patch;
							 | 
						||
| 
								 | 
							
								            const new_iojs_target = '' + major + '.' + minor + '.' + patch;
							 | 
						||
| 
								 | 
							
								            if (abi_crosswalk[new_iojs_target]) {
							 | 
						||
| 
								 | 
							
								              cross_obj = abi_crosswalk[new_iojs_target];
							 | 
						||
| 
								 | 
							
								              console.log('Warning: node-pre-gyp could not find exact match for ' + target_version);
							 | 
						||
| 
								 | 
							
								              console.log('Warning: but node-pre-gyp successfully choose ' + new_iojs_target + ' as ABI compatible target');
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            if (minor === 0 && patch === 0) {
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        } else if (major >= 2) {
							 | 
						||
| 
								 | 
							
								          // look for last release that is the same major version
							 | 
						||
| 
								 | 
							
								          if (major_versions[major]) {
							 | 
						||
| 
								 | 
							
								            cross_obj = abi_crosswalk[major_versions[major]];
							 | 
						||
| 
								 | 
							
								            console.log('Warning: node-pre-gyp could not find exact match for ' + target_version);
							 | 
						||
| 
								 | 
							
								            console.log('Warning: but node-pre-gyp successfully choose ' + major_versions[major] + ' as ABI compatible target');
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        } else if (major === 0) { // node.js
							 | 
						||
| 
								 | 
							
								          if (target_parts[1] % 2 === 0) { // for stable/even node.js series
							 | 
						||
| 
								 | 
							
								            // look for the last release that is the same minor release
							 | 
						||
| 
								 | 
							
								            // e.g. we assume node 0.10.x is ABI compatible with >= 0.10.0
							 | 
						||
| 
								 | 
							
								            while (--patch > 0) {
							 | 
						||
| 
								 | 
							
								              const new_node_target = '' + major + '.' + minor + '.' + patch;
							 | 
						||
| 
								 | 
							
								              if (abi_crosswalk[new_node_target]) {
							 | 
						||
| 
								 | 
							
								                cross_obj = abi_crosswalk[new_node_target];
							 | 
						||
| 
								 | 
							
								                console.log('Warning: node-pre-gyp could not find exact match for ' + target_version);
							 | 
						||
| 
								 | 
							
								                console.log('Warning: but node-pre-gyp successfully choose ' + new_node_target + ' as ABI compatible target');
							 | 
						||
| 
								 | 
							
								                break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      if (!cross_obj) {
							 | 
						||
| 
								 | 
							
								        throw new Error('Unsupported target version: ' + target_version);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      // emulate process.versions
							 | 
						||
| 
								 | 
							
								      const versions_obj = {
							 | 
						||
| 
								 | 
							
								        node: target_version,
							 | 
						||
| 
								 | 
							
								        v8: cross_obj.v8 + '.0',
							 | 
						||
| 
								 | 
							
								        // abi_crosswalk uses 1 for node versions lacking process.versions.modules
							 | 
						||
| 
								 | 
							
								        // process.versions.modules added in >= v0.10.4 and v0.11.7
							 | 
						||
| 
								 | 
							
								        modules: cross_obj.node_abi > 1 ? cross_obj.node_abi : undefined
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								      return get_node_abi(runtime, versions_obj);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								module.exports.get_runtime_abi = get_runtime_abi;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const required_parameters = [
							 | 
						||
| 
								 | 
							
								  'module_name',
							 | 
						||
| 
								 | 
							
								  'module_path',
							 | 
						||
| 
								 | 
							
								  'host'
							 | 
						||
| 
								 | 
							
								];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function validate_config(package_json, opts) {
							 | 
						||
| 
								 | 
							
								  const msg = package_json.name + ' package.json is not node-pre-gyp ready:\n';
							 | 
						||
| 
								 | 
							
								  const missing = [];
							 | 
						||
| 
								 | 
							
								  if (!package_json.main) {
							 | 
						||
| 
								 | 
							
								    missing.push('main');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if (!package_json.version) {
							 | 
						||
| 
								 | 
							
								    missing.push('version');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if (!package_json.name) {
							 | 
						||
| 
								 | 
							
								    missing.push('name');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if (!package_json.binary) {
							 | 
						||
| 
								 | 
							
								    missing.push('binary');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  const o = package_json.binary;
							 | 
						||
| 
								 | 
							
								  if (o) {
							 | 
						||
| 
								 | 
							
								    required_parameters.forEach((p) => {
							 | 
						||
| 
								 | 
							
								      if (!o[p] || typeof o[p] !== 'string') {
							 | 
						||
| 
								 | 
							
								        missing.push('binary.' + p);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (missing.length >= 1) {
							 | 
						||
| 
								 | 
							
								    throw new Error(msg + 'package.json must declare these properties: \n' + missing.join('\n'));
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if (o) {
							 | 
						||
| 
								 | 
							
								    // enforce https over http
							 | 
						||
| 
								 | 
							
								    const protocol = url.parse(o.host).protocol;
							 | 
						||
| 
								 | 
							
								    if (protocol === 'http:') {
							 | 
						||
| 
								 | 
							
								      throw new Error("'host' protocol (" + protocol + ") is invalid - only 'https:' is accepted");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  napi.validate_package_json(package_json, opts);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports.validate_config = validate_config;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function eval_template(template, opts) {
							 | 
						||
| 
								 | 
							
								  Object.keys(opts).forEach((key) => {
							 | 
						||
| 
								 | 
							
								    const pattern = '{' + key + '}';
							 | 
						||
| 
								 | 
							
								    while (template.indexOf(pattern) > -1) {
							 | 
						||
| 
								 | 
							
								      template = template.replace(pattern, opts[key]);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								  return template;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// url.resolve needs single trailing slash
							 | 
						||
| 
								 | 
							
								// to behave correctly, otherwise a double slash
							 | 
						||
| 
								 | 
							
								// may end up in the url which breaks requests
							 | 
						||
| 
								 | 
							
								// and a lacking slash may not lead to proper joining
							 | 
						||
| 
								 | 
							
								function fix_slashes(pathname) {
							 | 
						||
| 
								 | 
							
								  if (pathname.slice(-1) !== '/') {
							 | 
						||
| 
								 | 
							
								    return pathname + '/';
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return pathname;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// remove double slashes
							 | 
						||
| 
								 | 
							
								// note: path.normalize will not work because
							 | 
						||
| 
								 | 
							
								// it will convert forward to back slashes
							 | 
						||
| 
								 | 
							
								function drop_double_slashes(pathname) {
							 | 
						||
| 
								 | 
							
								  return pathname.replace(/\/\//g, '/');
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function get_process_runtime(versions) {
							 | 
						||
| 
								 | 
							
								  let runtime = 'node';
							 | 
						||
| 
								 | 
							
								  if (versions['node-webkit']) {
							 | 
						||
| 
								 | 
							
								    runtime = 'node-webkit';
							 | 
						||
| 
								 | 
							
								  } else if (versions.electron) {
							 | 
						||
| 
								 | 
							
								    runtime = 'electron';
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return runtime;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports.get_process_runtime = get_process_runtime;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const default_package_name = '{module_name}-v{version}-{node_abi}-{platform}-{arch}.tar.gz';
							 | 
						||
| 
								 | 
							
								const default_remote_path = '';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports.evaluate = function(package_json, options, napi_build_version) {
							 | 
						||
| 
								 | 
							
								  options = options || {};
							 | 
						||
| 
								 | 
							
								  validate_config(package_json, options); // options is a suitable substitute for opts in this case
							 | 
						||
| 
								 | 
							
								  const v = package_json.version;
							 | 
						||
| 
								 | 
							
								  const module_version = semver.parse(v);
							 | 
						||
| 
								 | 
							
								  const runtime = options.runtime || get_process_runtime(process.versions);
							 | 
						||
| 
								 | 
							
								  const opts = {
							 | 
						||
| 
								 | 
							
								    name: package_json.name,
							 | 
						||
| 
								 | 
							
								    configuration: options.debug ? 'Debug' : 'Release',
							 | 
						||
| 
								 | 
							
								    debug: options.debug,
							 | 
						||
| 
								 | 
							
								    module_name: package_json.binary.module_name,
							 | 
						||
| 
								 | 
							
								    version: module_version.version,
							 | 
						||
| 
								 | 
							
								    prerelease: module_version.prerelease.length ? module_version.prerelease.join('.') : '',
							 | 
						||
| 
								 | 
							
								    build: module_version.build.length ? module_version.build.join('.') : '',
							 | 
						||
| 
								 | 
							
								    major: module_version.major,
							 | 
						||
| 
								 | 
							
								    minor: module_version.minor,
							 | 
						||
| 
								 | 
							
								    patch: module_version.patch,
							 | 
						||
| 
								 | 
							
								    runtime: runtime,
							 | 
						||
| 
								 | 
							
								    node_abi: get_runtime_abi(runtime, options.target),
							 | 
						||
| 
								 | 
							
								    node_abi_napi: napi.get_napi_version(options.target) ? 'napi' : get_runtime_abi(runtime, options.target),
							 | 
						||
| 
								 | 
							
								    napi_version: napi.get_napi_version(options.target), // non-zero numeric, undefined if unsupported
							 | 
						||
| 
								 | 
							
								    napi_build_version: napi_build_version || '',
							 | 
						||
| 
								 | 
							
								    node_napi_label: napi_build_version ? 'napi-v' + napi_build_version : get_runtime_abi(runtime, options.target),
							 | 
						||
| 
								 | 
							
								    target: options.target || '',
							 | 
						||
| 
								 | 
							
								    platform: options.target_platform || process.platform,
							 | 
						||
| 
								 | 
							
								    target_platform: options.target_platform || process.platform,
							 | 
						||
| 
								 | 
							
								    arch: options.target_arch || process.arch,
							 | 
						||
| 
								 | 
							
								    target_arch: options.target_arch || process.arch,
							 | 
						||
| 
								 | 
							
								    libc: options.target_libc || detect_libc.familySync() || 'unknown',
							 | 
						||
| 
								 | 
							
								    module_main: package_json.main,
							 | 
						||
| 
								 | 
							
								    toolset: options.toolset || '', // address https://github.com/mapbox/node-pre-gyp/issues/119
							 | 
						||
| 
								 | 
							
								    bucket: package_json.binary.bucket,
							 | 
						||
| 
								 | 
							
								    region: package_json.binary.region,
							 | 
						||
| 
								 | 
							
								    s3ForcePathStyle: package_json.binary.s3ForcePathStyle || false
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								    // support host mirror with npm config `--{module_name}_binary_host_mirror`
							 | 
						||
| 
								 | 
							
								    // e.g.: https://github.com/node-inspector/v8-profiler/blob/master/package.json#L25
							 | 
						||
| 
								 | 
							
								    // > npm install v8-profiler --profiler_binary_host_mirror=https://npm.taobao.org/mirrors/node-inspector/
							 | 
						||
| 
								 | 
							
								  const validModuleName = opts.module_name.replace('-', '_');
							 | 
						||
| 
								 | 
							
								  const host = process.env['npm_config_' + validModuleName + '_binary_host_mirror'] || package_json.binary.host;
							 | 
						||
| 
								 | 
							
								  opts.host = fix_slashes(eval_template(host, opts));
							 | 
						||
| 
								 | 
							
								  opts.module_path = eval_template(package_json.binary.module_path, opts);
							 | 
						||
| 
								 | 
							
								  // now we resolve the module_path to ensure it is absolute so that binding.gyp variables work predictably
							 | 
						||
| 
								 | 
							
								  if (options.module_root) {
							 | 
						||
| 
								 | 
							
								    // resolve relative to known module root: works for pre-binding require
							 | 
						||
| 
								 | 
							
								    opts.module_path = path.join(options.module_root, opts.module_path);
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    // resolve relative to current working directory: works for node-pre-gyp commands
							 | 
						||
| 
								 | 
							
								    opts.module_path = path.resolve(opts.module_path);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  opts.module = path.join(opts.module_path, opts.module_name + '.node');
							 | 
						||
| 
								 | 
							
								  opts.remote_path = package_json.binary.remote_path ? drop_double_slashes(fix_slashes(eval_template(package_json.binary.remote_path, opts))) : default_remote_path;
							 | 
						||
| 
								 | 
							
								  const package_name = package_json.binary.package_name ? package_json.binary.package_name : default_package_name;
							 | 
						||
| 
								 | 
							
								  opts.package_name = eval_template(package_name, opts);
							 | 
						||
| 
								 | 
							
								  opts.staged_tarball = path.join('build/stage', opts.remote_path, opts.package_name);
							 | 
						||
| 
								 | 
							
								  opts.hosted_path = url.resolve(opts.host, opts.remote_path);
							 | 
						||
| 
								 | 
							
								  opts.hosted_tarball = url.resolve(opts.hosted_path, opts.package_name);
							 | 
						||
| 
								 | 
							
								  return opts;
							 | 
						||
| 
								 | 
							
								};
							 |