build.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. var fs = require('fs'),
  2. path = require('path'),
  3. spawn = require('child_process').spawn,
  4. mkdir = require('mkdirp'),
  5. Mocha = require('mocha');
  6. require('../lib/extensions');
  7. /**
  8. * After build
  9. *
  10. * @param {Object} options
  11. * @api private
  12. */
  13. function afterBuild(options) {
  14. var folder = options.debug ? 'Debug' : 'Release';
  15. var target = path.join(__dirname, '..', 'build', folder, 'binding.node');
  16. var install = path.join(__dirname, '..', 'vendor', process.sassBinaryName, 'binding.node');
  17. mkdir(path.join(__dirname, '..', 'vendor', process.sassBinaryName), function (err) {
  18. if (err && err.code !== 'EEXIST') {
  19. console.error(err.message);
  20. return;
  21. }
  22. fs.stat(target, function (err) {
  23. if (err) {
  24. console.error('Build succeeded but target not found');
  25. return;
  26. }
  27. fs.rename(target, install, function (err) {
  28. if (err) {
  29. console.error(err.message);
  30. return;
  31. }
  32. console.log('Installed in `' + install + '`');
  33. });
  34. });
  35. });
  36. }
  37. /**
  38. * Build
  39. *
  40. * @param {Object} options
  41. * @api private
  42. */
  43. function build(options) {
  44. var proc = spawn(process.execPath, ['node_modules/pangyp/bin/node-gyp', 'rebuild'].concat(options.args), {
  45. stdio: [0, 1, 2]
  46. });
  47. proc.on('exit', function(code) {
  48. if (code) {
  49. if (code === 127) {
  50. console.error([
  51. 'node-gyp not found! Please upgrade your install of npm!',
  52. 'You need at least 1.1.5 (I think) and preferably 1.1.30.'
  53. ].join(' '));
  54. return;
  55. }
  56. console.error('Build failed');
  57. return;
  58. }
  59. afterBuild(options);
  60. });
  61. }
  62. /**
  63. * Parse arguments
  64. *
  65. * @param {Array} args
  66. * @api private
  67. */
  68. function parseArgs(args) {
  69. var options = {
  70. arch: process.arch,
  71. platform: process.platform
  72. };
  73. options.args = args.filter(function(arg) {
  74. if (arg === '-f' || arg === '--force') {
  75. options.force = true;
  76. return false;
  77. } else if (arg.substring(0, 13) === '--target_arch') {
  78. options.arch = arg.substring(14);
  79. } else if (arg === '-d' || arg === '--debug') {
  80. options.debug = true;
  81. }
  82. return true;
  83. });
  84. return options;
  85. }
  86. /**
  87. * Test for pre-built library
  88. *
  89. * @param {Object} options
  90. * @api private
  91. */
  92. function testBinary(options) {
  93. if (options.force || process.env.SASS_FORCE_BUILD) {
  94. return build(options);
  95. }
  96. fs.stat(path.join(__dirname, '..', 'vendor', process.sassBinaryName, 'binding.node'), function (err) {
  97. if (err) {
  98. return build(options);
  99. }
  100. console.log('`' + process.sassBinaryName + '` exists; testing');
  101. var mocha = new Mocha({
  102. ui: 'bdd',
  103. timeout: 999999,
  104. reporter: function() {}
  105. });
  106. mocha.addFile(path.resolve(__dirname, '..', 'test', 'api.js'));
  107. mocha.grep(/should compile sass to css with file/).run(function (done) {
  108. if (done !== 0) {
  109. console.log([
  110. 'Problem with the binary.',
  111. 'Manual build incoming.',
  112. 'Please consider contributing the release binary to https://github.com/sass/node-sass-binaries for npm distribution.'
  113. ].join('\n'));
  114. return build(options);
  115. }
  116. console.log('Binary is fine; exiting');
  117. });
  118. });
  119. }
  120. /**
  121. * Apply arguments and run
  122. */
  123. testBinary(parseArgs(process.argv.slice(2)));