#!/usr/bin/env node var fs = require('fs'); var verifyRequirements = require('./utils/verify-requirements'); var safeExec = require('./utils/child-process-wrapper.js').safeExec; var path = require('path'); // Executes an array of commands one by one. function executeCommands(commands, done, index) { index = (index == undefined ? 0 : index); if (index < commands.length) { var command = commands[index]; if (command.message) console.log(command.message); var options = null; if (typeof command !== 'string') { options = command.options; command = command.command; } safeExec(command, options, executeCommands.bind(this, commands, done, index + 1)); } else done(null); } function printArgs(args) { out = ""; for(key in args) { out += "--"+key+"="+args[key]+" "; } return out; } function makeSqlite3Command() { var npmPath = path.resolve(__dirname, '..', 'build', 'node_modules', '.bin', 'npm'); var nodeGypPath = path.resolve(__dirname, '..', 'build', 'node_modules', 'npm', 'node_modules', '.bin', 'node-gyp'); var appPackageJSON = JSON.parse(fs.readFileSync(path.resolve(__dirname, '..', 'package.json'))); var targetVersion = appPackageJSON['electronVersion']; var targetPlatform = require('os').platform(); var targetArch = require('os').arch(); if ((targetPlatform == 'win32') && (targetArch != 'ia32')) { // Unless electron for windows goes 64bit, this should stay throw new Error("Building for win32 with architecture "+targetArch+". Are you sure you meant to do this?"); } return npmPath+" install https://github.com/bengotow/node-sqlite3/archive/master.tar.gz --ignore-scripts && cd node_modules/sqlite3 && "+npmPath+" run prepublish && "+nodeGypPath+" configure rebuild --target="+targetVersion+" --arch="+targetArch+" --target_platform="+targetPlatform+" --dist-url=https://atom.io/download/atom-shell --module_name=node_sqlite3 --module_path=../lib/binding/node-v44-"+targetPlatform+"-"+targetArch } function bootstrap() { var apmInstallPath = path.resolve(__dirname, '..', 'apm'); if (!fs.existsSync(apmInstallPath)) fs.mkdirSync(apmInstallPath); if (!fs.existsSync(path.join(apmInstallPath, 'node_modules'))) fs.mkdirSync(path.join(apmInstallPath, 'node_modules')); var apmPath = path.resolve(__dirname, '..', 'apm', 'node_modules', 'atom-package-manager', 'bin', 'apm') var apmFlags = process.env.JANKY_SHA1 || process.argv.indexOf('--no-color') !== -1 ? ' --no-color' : ''; var npmPath = path.resolve(__dirname, '..', 'build', 'node_modules', '.bin', 'npm'); var initialNpmCommand = fs.existsSync(npmPath) ? npmPath : 'npm'; var npmFlags = ' --userconfig=' + path.resolve('.npmrc') + ' '; var gruntPath = path.resolve(__dirname, '..', 'build', 'node_modules', '.bin', 'grunt'); var packagesToDedupe = ['fs-plus', 'humanize-plus', 'roaster', 'season', 'grim']; var buildInstallCommand = initialNpmCommand + npmFlags + 'install'; var buildInstallOptions = {cwd: path.resolve(__dirname, '..', 'build')}; var apmInstallCommand = npmPath + npmFlags + '--target=0.10.40 ' + 'install'; var apmInstallOptions = {cwd: apmInstallPath}; var rebuildSqlite3Command = makeSqlite3Command(); var moduleInstallCommand = apmPath + ' install' + apmFlags; var dedupeApmCommand = apmPath + ' dedupe' + apmFlags; var semverOptions = {cwd: path.resolve(__dirname, '..', 'apm', 'node_modules', 'atom-package-manager')}; if (process.argv.indexOf('--no-quiet') === -1) { buildInstallCommand += ' --loglevel error'; apmInstallCommand += ' --loglevel error'; moduleInstallCommand += ' --loglevel error'; dedupeApmCommand += ' --quiet'; buildInstallOptions.ignoreStdout = true; apmInstallOptions.ignoreStdout = true; } // apm ships with 32-bit node so make sure its native modules are compiled // for a 32-bit target architecture if (process.env.JANKY_SHA1 && process.platform === 'win32') apmInstallCommand += ' --arch=ia32'; m1 = "\n---> Installing N1 build tools\n" m1 += " This goes inside the `build` folder and runs `npm install`\n" m1 += " It will use the system `npm` to bootstrap our own N1 npm.\n" m1 += " Our build tools (like Grunt) need to be compiled against Node via `npm`.\n" m1 += " Everything else needs to be compiled against Chromium with `apm`.\n\n" m1 += " $ "+buildInstallCommand+" "+printArgs(buildInstallOptions)+"\n" m2 = "\n\n---> Installing apm\n" m2 += " This installs apm via N1's `npm`\n" m2 += " We use this local apm copy to install all N1 dependencies & packages\n\n" m2 += " $ "+apmInstallCommand+" "+printArgs(apmInstallOptions)+"\n" m3 = "\n\n---> Cleaning apm via `apm clean`\n" m4 = "\n\n---> Installing N1 dependencies & packages via `apm install`\n\n" m4 += " $ "+moduleInstallCommand+"\n" m5 = "\n\n---> De-duping packages `apm clean`\n\n" m5 += " $ apm "+packagesToDedupe.join(' ')+"\n" m6 = "\n\n---> Request version `apm clean`\n\n" m6 += " $ apm request semver "+printArgs(semverOptions)+"\n" m7 = "\n\n---> Getting latest Electron\n\n" var gruntCmd = "" var downloadElectronCmd = gruntPath + " download-electron --gruntfile build/Gruntfile.coffee" m7 += " $ "+downloadElectronCmd var commands = [ { command: buildInstallCommand, message: m1, options: buildInstallOptions }, { command: apmInstallCommand, message: m2, options: apmInstallOptions }, { command: apmPath + ' clean' + apmFlags, message: m3 } ]; // we need this because we don't put our modules in node_modules and npm // install doesn't find them. Run APM install on each package directory manually. internalPackagesDir = path.resolve(__dirname, '..', 'internal_packages'); internalPackages = fs.readdirSync('internal_packages'); internalPackages.forEach(function(dir) { var dirPackageJSONPath = path.join(internalPackagesDir, dir, 'package.json'); // On windows and linux, invoking the apm command is very slow even when there are no // dependencies. Make it faster by not calling unless we find there are deps. if (fs.existsSync(dirPackageJSONPath)) { var dirPackageJSON = JSON.parse(fs.readFileSync(dirPackageJSONPath)); if (dirPackageJSON.dependencies && (Object.keys(dirPackageJSON.dependencies).length > 0)) { commands.push({ command: moduleInstallCommand, message: "Installing dependencies for "+dir, options: {cwd: path.join(internalPackagesDir, dir) } }); } } }); commands = commands.concat([ { command: moduleInstallCommand, message: m4 }, { command: dedupeApmCommand + ' ' + packagesToDedupe.join(' '), message: m5 }, { command: dedupeApmCommand + ' request semver', message: m6, options: semverOptions }, { command: downloadElectronCmd, message: m7 }, { command: rebuildSqlite3Command, message: "Building sqlite3 with command: "+rebuildSqlite3Command } ]); process.chdir(path.dirname(__dirname)); executeCommands(commands, process.exit); } verifyRequirements(function(error, successMessage) { if (error) { console.log(error); process.exit(1); } console.log(successMessage); bootstrap(); });