handle_gyp_opts.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. 'use strict';
  2. module.exports = exports = handle_gyp_opts;
  3. const versioning = require('./versioning.js');
  4. const napi = require('./napi.js');
  5. /*
  6. Here we gather node-pre-gyp generated options (from versioning) and pass them along to node-gyp.
  7. We massage the args and options slightly to account for differences in what commands mean between
  8. node-pre-gyp and node-gyp (e.g. see the difference between "build" and "rebuild" below)
  9. Keep in mind: the values inside `argv` and `gyp.opts` below are different depending on whether
  10. node-pre-gyp is called directory, or if it is called in a `run-script` phase of npm.
  11. We also try to preserve any command line options that might have been passed to npm or node-pre-gyp.
  12. But this is fairly difficult without passing way to much through. For example `gyp.opts` contains all
  13. the process.env and npm pushes a lot of variables into process.env which node-pre-gyp inherits. So we have
  14. to be very selective about what we pass through.
  15. For example:
  16. `npm install --build-from-source` will give:
  17. argv == [ 'rebuild' ]
  18. gyp.opts.argv == { remain: [ 'install' ],
  19. cooked: [ 'install', '--fallback-to-build' ],
  20. original: [ 'install', '--fallback-to-build' ] }
  21. `./bin/node-pre-gyp build` will give:
  22. argv == []
  23. gyp.opts.argv == { remain: [ 'build' ],
  24. cooked: [ 'build' ],
  25. original: [ '-C', 'test/app1', 'build' ] }
  26. */
  27. // select set of node-pre-gyp versioning info
  28. // to share with node-gyp
  29. const share_with_node_gyp = [
  30. 'module',
  31. 'module_name',
  32. 'module_path',
  33. 'napi_version',
  34. 'node_abi_napi',
  35. 'napi_build_version',
  36. 'node_napi_label'
  37. ];
  38. function handle_gyp_opts(gyp, argv, callback) {
  39. // Collect node-pre-gyp specific variables to pass to node-gyp
  40. const node_pre_gyp_options = [];
  41. // generate custom node-pre-gyp versioning info
  42. const napi_build_version = napi.get_napi_build_version_from_command_args(argv);
  43. const opts = versioning.evaluate(gyp.package_json, gyp.opts, napi_build_version);
  44. share_with_node_gyp.forEach((key) => {
  45. const val = opts[key];
  46. if (val) {
  47. node_pre_gyp_options.push('--' + key + '=' + val);
  48. } else if (key === 'napi_build_version') {
  49. node_pre_gyp_options.push('--' + key + '=0');
  50. } else {
  51. if (key !== 'napi_version' && key !== 'node_abi_napi')
  52. return callback(new Error('Option ' + key + ' required but not found by node-pre-gyp'));
  53. }
  54. });
  55. // Collect options that follow the special -- which disables nopt parsing
  56. const unparsed_options = [];
  57. let double_hyphen_found = false;
  58. gyp.opts.argv.original.forEach((opt) => {
  59. if (double_hyphen_found) {
  60. unparsed_options.push(opt);
  61. }
  62. if (opt === '--') {
  63. double_hyphen_found = true;
  64. }
  65. });
  66. // We try respect and pass through remaining command
  67. // line options (like --foo=bar) to node-gyp
  68. const cooked = gyp.opts.argv.cooked;
  69. const node_gyp_options = [];
  70. cooked.forEach((value) => {
  71. if (value.length > 2 && value.slice(0, 2) === '--') {
  72. const key = value.slice(2);
  73. const val = cooked[cooked.indexOf(value) + 1];
  74. if (val && val.indexOf('--') === -1) { // handle '--foo=bar' or ['--foo','bar']
  75. node_gyp_options.push('--' + key + '=' + val);
  76. } else { // pass through --foo
  77. node_gyp_options.push(value);
  78. }
  79. }
  80. });
  81. const result = { 'opts': opts, 'gyp': node_gyp_options, 'pre': node_pre_gyp_options, 'unparsed': unparsed_options };
  82. return callback(null, result);
  83. }