Add option to install binaries of dependencies

This commit is contained in:
Stéphan Kochen
2022-01-29 19:59:10 +01:00
parent 892ebe3f1a
commit fcc976dcfb
5 changed files with 70 additions and 38 deletions
+5
View File
@@ -133,6 +133,11 @@ Some additional settings are available in `.yarnrc.yml`:
- `isolatedNixBuilds`, see [ISOLATED_BUILDS.md](./ISOLATED_BUILDS.md).
- `installNixBinariesForDependencies` can be set to also install executables
for binaries defined by dependencies. This can be useful if these need to be
in `$PATH` for other tools, or if you're creating a workspace just to collect
command-line tools.
[niv]: https://github.com/nmattia/niv
## Hacking
+57 -36
View File
@@ -1,6 +1,7 @@
import { Command, Option } from "clipanion";
import { Filename, npath, ppath, xfs } from "@yarnpkg/fslib";
import { Filename, PortablePath, npath, ppath, xfs } from "@yarnpkg/fslib";
import { getPnpPath } from "@yarnpkg/plugin-pnp";
import { scriptUtils } from "@yarnpkg/core";
import {
CommandContext,
@@ -34,53 +35,73 @@ export default class InstallBinCommand extends Command<CommandContext> {
const report = await StreamReport.start(
{ configuration, stdout: this.context.stdout },
async (report) => {
if (!workspace || workspace.manifest.bin.size === 0) {
if (!workspace) {
return;
}
let nodeLinker = configuration.get(`nodeLinker`);
if (!supportedLinkers.includes(nodeLinker)) {
nodeLinker = `node-modules`;
report.reportWarning(
0,
`The nodeLinker ${nodeLinker} is not supported - executables may have trouble finding dependencies`
const binDir = npath.toPortablePath(this.binDir);
for (const [name, binaryFile] of workspace.manifest.bin) {
const wrapperPath = ppath.join(binDir, name as Filename);
const binaryPath = ppath.join(
project.cwd,
npath.toPortablePath(binaryFile)
);
await this.writeWrapper(wrapperPath, binaryPath, {
configuration,
project,
});
}
const binDir = npath.toPortablePath(this.binDir);
const pnpPath = getPnpPath(project).cjs;
for (const [name, scriptInput] of workspace.manifest.bin) {
const binPath = ppath.join(binDir, name as Filename);
const scriptPath = ppath.join(
project.cwd,
npath.toPortablePath(scriptInput)
if (configuration.get(`installNixBinariesForDependencies`)) {
await project.resolveEverything({ report, lockfileOnly: true });
const binaries = await scriptUtils.getPackageAccessibleBinaries(
project.topLevelWorkspace.anchoredLocator,
{ project }
);
let script;
switch (nodeLinker) {
case `pnp`:
script = renderTmpl(binWrapperPnpTmpl, {
NODE_PATH: process.execPath,
PNP_PATH: pnpPath,
SCRIPT_PATH: scriptPath,
});
break;
case `node-modules`:
script = renderTmpl(binWrapperNodeModulesTmpl, {
NODE_PATH: process.execPath,
SCRIPT_PATH: scriptPath,
});
break;
default:
throw Error(`Assertion failed: Invalid nodeLinker ${nodeLinker}`);
for (const [name, [_, binaryPath]] of binaries.entries()) {
const wrapperPath = ppath.join(binDir, name as Filename);
await this.writeWrapper(
wrapperPath,
npath.toPortablePath(binaryPath),
{ configuration, project }
);
}
await xfs.writeFilePromise(binPath, script);
await xfs.chmodPromise(binPath, 0o755);
}
}
);
return report.exitCode();
}
private async writeWrapper(
wrapperPath: PortablePath,
binaryPath: PortablePath,
{
configuration,
project,
}: { configuration: Configuration; project: Project }
) {
let wrapper;
switch (configuration.get(`nodeLinker`)) {
case `pnp`:
wrapper = renderTmpl(binWrapperPnpTmpl, {
NODE_PATH: process.execPath,
PNP_PATH: getPnpPath(project).cjs,
BINARY_PATH: binaryPath,
});
break;
case `node-modules`:
wrapper = renderTmpl(binWrapperNodeModulesTmpl, {
NODE_PATH: process.execPath,
BINARY_PATH: binaryPath,
});
break;
default:
throw Error(`Assertion failed: Invalid nodeLinker`);
}
await xfs.writeFilePromise(wrapperPath, wrapper);
await xfs.chmodPromise(wrapperPath, 0o755);
}
}
+6
View File
@@ -13,6 +13,7 @@ declare module "@yarnpkg/core" {
generateDefaultNix: boolean;
enableNixPreload: boolean;
isolatedNixBuilds: string[];
installNixBinariesForDependencies: boolean;
}
}
@@ -55,6 +56,11 @@ const plugin: Plugin<Hooks> = {
default: [],
isArray: true,
},
installNixBinariesForDependencies: {
description: `If true, the Nix output 'bin' directory will also contain executables for binaries defined by dependencies`,
type: SettingsType.BOOLEAN,
default: false,
},
},
};
+1 -1
View File
@@ -1,2 +1,2 @@
#!/bin/sh
exec '@@NODE_PATH@@' '@@SCRIPT_PATH@@' "$@"
exec '@@NODE_PATH@@' '@@BINARY_PATH@@' "$@"
+1 -1
View File
@@ -1,3 +1,3 @@
#!/bin/sh
export NODE_OPTIONS="--require @@PNP_PATH@@"
exec '@@NODE_PATH@@' '@@SCRIPT_PATH@@' "$@"
exec '@@NODE_PATH@@' '@@BINARY_PATH@@' "$@"