Skip to content

Commit

Permalink
Use npm's node-gyp if available, otherwise automatically install node…
Browse files Browse the repository at this point in the history
…-gyp (#3240)

* Attempt to install node-gyp if it's required but missing

* Try to use node-gyp version from npm

* Trailing commas
  • Loading branch information
Daniel15 authored and bestander committed Apr 24, 2017
1 parent 65595e3 commit 50c5bf0
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 46 deletions.
6 changes: 0 additions & 6 deletions bin/node-gyp-bin/node-gyp

This file was deleted.

5 changes: 0 additions & 5 deletions bin/node-gyp-bin/node-gyp.cmd

This file was deleted.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
"minimatch": "^3.0.3",
"mkdirp": "^0.5.1",
"node-emoji": "^1.0.4",
"node-gyp": "^3.2.1",
"object-path": "^0.11.2",
"proper-lockfile": "^2.0.0",
"read": "^1.0.7",
Expand Down
1 change: 0 additions & 1 deletion scripts/build-dist.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ cp LICENSE dist/
cp artifacts/yarn-legacy-*.js dist/lib/yarn-cli.js
cp bin/yarn-bundle-entry.js dist/bin/yarn.js
cp bin/{yarn,yarnpkg,*.cmd} dist/bin/
cp -r bin/node-gyp-bin dist/bin/
# We cannot bundle v8-compile-cache as it must be loaded separately to be effective.
cp node_modules/v8-compile-cache/v8-compile-cache.js dist/lib/v8-compile-cache.js

Expand Down
2 changes: 2 additions & 0 deletions src/reporters/lang/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ const messages = {
possibleCommands: 'Project commands',
commandQuestion: 'Which command would you like to run?',
commandFailed: 'Command failed with exit code $0.',
packageRequiresNodeGyp: 'This package requires node-gyp, which is not currently installed. Yarn will attempt to automatically install it. If this fails, you can run "yarn global add node-gyp" to manually install it.',
nodeGypAutoInstallFailed: 'Failed to auto-install node-gyp. Please run "yarn global add node-gyp" manually. Error: $0',

foundIncompatible: 'Found incompatible module',
incompatibleEngine: 'The engine $0 is incompatible with this module. Expected version $1.',
Expand Down
76 changes: 74 additions & 2 deletions src/util/execute-lifecycle-script.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@ import type Config from '../config.js';
import {MessageError, SpawnError} from '../errors.js';
import * as constants from '../constants.js';
import * as child from './child.js';
import {exists} from './fs.js';
import {registries} from '../resolvers/index.js';
import {fixCmdWinSlashes} from './fix-cmd-win-slashes.js';
import {
run as globalRun,
getBinFolder as getGlobalBinFolder,
} from '../cli/commands/global.js';

const path = require('path');

Expand Down Expand Up @@ -116,8 +121,22 @@ export async function executeLifecycleScript(
// split up the path
const pathParts = (env[constants.ENV_PATH_KEY] || '').split(path.delimiter);

// add node-gyp
pathParts.unshift(path.join(__dirname, '..', '..', 'bin', 'node-gyp-bin'));
// Include node-gyp version that was bundled with the current Node.js version,
// if available.
pathParts.unshift(
path.join(
path.dirname(process.execPath), 'node_modules', 'npm', 'bin', 'node-gyp-bin',
),
);
pathParts.unshift(
path.join(
path.dirname(process.execPath), '..', 'lib', 'node_modules', 'npm', 'bin', 'node-gyp-bin',
),
);

// Add global bin folder, as some packages depend on a globally-installed
// version of node-gyp.
pathParts.unshift(getGlobalBinFolder(config, {}));

// add .bin folders to PATH
for (const registry of Object.keys(registries)) {
Expand All @@ -126,6 +145,8 @@ export async function executeLifecycleScript(
pathParts.unshift(path.join(cwd, binFolder));
}

await checkForGypIfNeeded(config, cmd, pathParts);

// join path back together
env[constants.ENV_PATH_KEY] = pathParts.join(path.delimiter);

Expand Down Expand Up @@ -168,6 +189,57 @@ export async function executeLifecycleScript(

export default executeLifecycleScript;

let checkGypPromise: ?Promise<void> = null;
/**
* Special case: Some packages depend on node-gyp, but don't specify this in
* their package.json dependencies. They assume that node-gyp is available
* globally. We need to detect this case and show an error message.
*/
function checkForGypIfNeeded(
config: Config,
cmd: string,
paths: Array<string>,
): Promise<void> {
if (cmd.substr(0, cmd.indexOf(' ')) !== 'node-gyp') {
return Promise.resolve();
}

// Ensure this only runs once, rather than multiple times in parallel.
if (!checkGypPromise) {
checkGypPromise = _checkForGyp(config, paths);
}
return checkGypPromise;
}

async function _checkForGyp(
config: Config,
paths: Array<string>,
): Promise<void> {
const {reporter} = config;

// Check every directory in the PATH
const allChecks = await Promise.all(
paths.map((dir) => exists(path.join(dir, 'node-gyp'))),
);
if (allChecks.some(Boolean)) {
// node-gyp is available somewhere
return;
}

reporter.info(reporter.lang('packageRequiresNodeGyp'));

try {
await globalRun(
config,
reporter,
{},
['add', 'node-gyp'],
);
} catch (e) {
throw new MessageError(reporter.lang('nodeGypAutoInstallFailed', e.message));
}
}

export async function execFromManifest(config: Config, commandName: string, cwd: string): Promise<void> {
const pkg = await config.maybeReadManifest(cwd);
if (!pkg || !pkg.scripts) {
Expand Down
37 changes: 6 additions & 31 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3295,24 +3295,6 @@ node-emoji@^1.0.4:
dependencies:
string.prototype.codepointat "^0.2.0"

node-gyp@^3.2.1:
version "3.5.0"
resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.5.0.tgz#a8fe5e611d079ec16348a3eb960e78e11c85274a"
dependencies:
fstream "^1.0.0"
glob "^7.0.3"
graceful-fs "^4.1.2"
minimatch "^3.0.2"
mkdirp "^0.5.0"
nopt "2 || 3"
npmlog "0 || 1 || 2 || 3 || 4"
osenv "0"
request "2"
rimraf "2"
semver "2.x || 3.x || 4 || 5"
tar "^2.0.0"
which "1"

node-int64@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
Expand Down Expand Up @@ -3368,7 +3350,7 @@ node-pre-gyp@^0.6.29:
tar "~2.2.1"
tar-pack "~3.3.0"

"nopt@2 || 3", nopt@~3.0.6:
nopt@~3.0.6:
version "3.0.6"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
dependencies:
Expand All @@ -3387,7 +3369,7 @@ normalize-path@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.0.1.tgz#47886ac1662760d4261b7d979d241709d3ce3f7a"

"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.1:
npmlog@^4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.0.2.tgz#d03950e0e78ce1527ba26d2a7592e9348ac3e75f"
dependencies:
Expand Down Expand Up @@ -3501,13 +3483,6 @@ os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"

osenv@0:
version "0.1.4"
resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644"
dependencies:
os-homedir "^1.0.0"
os-tmpdir "^1.0.0"

p-limit@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.1.0.tgz#b07ff2d9a5d88bec806035895a2bab66a27988bc"
Expand Down Expand Up @@ -3903,7 +3878,7 @@ request-capture-har@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/request-capture-har/-/request-capture-har-1.2.2.tgz#cd692cfb2cc744fd84a3358aac6ee51528cf720d"

request@2, request@^2.79.0, request@^2.81.0:
request@^2.79.0, request@^2.81.0:
version "2.81.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0"
dependencies:
Expand Down Expand Up @@ -4054,7 +4029,7 @@ sax@^1.2.1:
version "1.2.2"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.2.tgz#fd8631a23bc7826bef5d871bdb87378c95647828"

"semver@2 || 3 || 4 || 5", "[email protected] || 3.x || 4 || 5", semver@^5.1.0, semver@^5.3.0, semver@~5.3.0:
"semver@2 || 3 || 4 || 5", semver@^5.1.0, semver@^5.3.0, semver@~5.3.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"

Expand Down Expand Up @@ -4352,7 +4327,7 @@ tar-stream@^1.1.2, tar-stream@^1.5.2:
readable-stream "^2.0.0"
xtend "^4.0.0"

tar@^2.0.0, tar@~2.2.1:
tar@~2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1"
dependencies:
Expand Down Expand Up @@ -4705,7 +4680,7 @@ which-module@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f"

which@1, which@^1.1.1, which@^1.2.12:
which@^1.1.1, which@^1.2.12:
version "1.2.12"
resolved "https://registry.yarnpkg.com/which/-/which-1.2.12.tgz#de67b5e450269f194909ef23ece4ebe416fa1192"
dependencies:
Expand Down

0 comments on commit 50c5bf0

Please sign in to comment.