first commit
continuous-integration/drone/push Build is failing
Details
continuous-integration/drone/push Build is failing
Details
This commit is contained in:
commit
6dd15521ad
|
|
@ -0,0 +1,52 @@
|
||||||
|
kind: pipeline
|
||||||
|
name: Build Image
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Lint Check
|
||||||
|
image: node:21-alpine
|
||||||
|
commands:
|
||||||
|
- npm install
|
||||||
|
# - npm run lint
|
||||||
|
|
||||||
|
- name: Build Docker Image
|
||||||
|
image: plugins/docker
|
||||||
|
settings:
|
||||||
|
build_args: ''
|
||||||
|
username:
|
||||||
|
from_secret: docker_username
|
||||||
|
password:
|
||||||
|
from_secret: docker_password
|
||||||
|
repo: git.midastix.com/ci-docker-repo-user/gemtrack-backend
|
||||||
|
registry: git.midastix.com
|
||||||
|
when:
|
||||||
|
branch:
|
||||||
|
- main
|
||||||
|
event:
|
||||||
|
- push
|
||||||
|
|
||||||
|
- name: Deploy image
|
||||||
|
image: appleboy/drone-ssh
|
||||||
|
settings:
|
||||||
|
host: gemtrack-backend.midastix.com
|
||||||
|
username: mfs-api
|
||||||
|
key:
|
||||||
|
from_secret: server_ssh_pkey
|
||||||
|
port: 22
|
||||||
|
command_timeout: 3m
|
||||||
|
script:
|
||||||
|
- echo "Deploying image"
|
||||||
|
- sudo /opt/deployable/gemtrack-backend/docker/deploy.sh
|
||||||
|
- echo "Completed Deployment"
|
||||||
|
when:
|
||||||
|
branch:
|
||||||
|
- main
|
||||||
|
event:
|
||||||
|
- push
|
||||||
|
# trigger:
|
||||||
|
# branch:
|
||||||
|
# - main
|
||||||
|
# - feature/api_dev
|
||||||
|
# - feature/openapi
|
||||||
|
# - feature/oem_apis
|
||||||
|
# event:
|
||||||
|
# - push
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"arcanis.vscode-zipfs"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"search.exclude": {
|
||||||
|
"**/.yarn": true,
|
||||||
|
"**/.pnp.*": true
|
||||||
|
},
|
||||||
|
"typescript.tsdk": ".yarn/sdks/typescript/lib",
|
||||||
|
"typescript.enablePromptUseWorkspaceTsdk": true
|
||||||
|
}
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,5 @@
|
||||||
|
# This file is automatically generated by @yarnpkg/sdks.
|
||||||
|
# Manual changes might be lost!
|
||||||
|
|
||||||
|
integrations:
|
||||||
|
- vscode
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
const {existsSync} = require(`fs`);
|
||||||
|
const {createRequire, register} = require(`module`);
|
||||||
|
const {resolve} = require(`path`);
|
||||||
|
const {pathToFileURL} = require(`url`);
|
||||||
|
|
||||||
|
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||||
|
|
||||||
|
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||||
|
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||||
|
const absRequire = createRequire(absPnpApiPath);
|
||||||
|
|
||||||
|
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||||
|
const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
|
||||||
|
|
||||||
|
if (existsSync(absPnpApiPath)) {
|
||||||
|
if (!process.versions.pnp) {
|
||||||
|
// Setup the environment to be able to require typescript/bin/tsc
|
||||||
|
require(absPnpApiPath).setup();
|
||||||
|
if (isPnpLoaderEnabled && register) {
|
||||||
|
register(pathToFileURL(absPnpLoaderPath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||||
|
? exports => absRequire(absUserWrapperPath)(exports)
|
||||||
|
: exports => exports;
|
||||||
|
|
||||||
|
// Defer to the real typescript/bin/tsc your application uses
|
||||||
|
module.exports = wrapWithUserWrapper(absRequire(`typescript/bin/tsc`));
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
const {existsSync} = require(`fs`);
|
||||||
|
const {createRequire, register} = require(`module`);
|
||||||
|
const {resolve} = require(`path`);
|
||||||
|
const {pathToFileURL} = require(`url`);
|
||||||
|
|
||||||
|
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||||
|
|
||||||
|
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||||
|
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||||
|
const absRequire = createRequire(absPnpApiPath);
|
||||||
|
|
||||||
|
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||||
|
const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
|
||||||
|
|
||||||
|
if (existsSync(absPnpApiPath)) {
|
||||||
|
if (!process.versions.pnp) {
|
||||||
|
// Setup the environment to be able to require typescript/bin/tsserver
|
||||||
|
require(absPnpApiPath).setup();
|
||||||
|
if (isPnpLoaderEnabled && register) {
|
||||||
|
register(pathToFileURL(absPnpLoaderPath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||||
|
? exports => absRequire(absUserWrapperPath)(exports)
|
||||||
|
: exports => exports;
|
||||||
|
|
||||||
|
// Defer to the real typescript/bin/tsserver your application uses
|
||||||
|
module.exports = wrapWithUserWrapper(absRequire(`typescript/bin/tsserver`));
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
const {existsSync} = require(`fs`);
|
||||||
|
const {createRequire, register} = require(`module`);
|
||||||
|
const {resolve} = require(`path`);
|
||||||
|
const {pathToFileURL} = require(`url`);
|
||||||
|
|
||||||
|
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||||
|
|
||||||
|
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||||
|
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||||
|
const absRequire = createRequire(absPnpApiPath);
|
||||||
|
|
||||||
|
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||||
|
const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
|
||||||
|
|
||||||
|
if (existsSync(absPnpApiPath)) {
|
||||||
|
if (!process.versions.pnp) {
|
||||||
|
// Setup the environment to be able to require typescript/lib/tsc.js
|
||||||
|
require(absPnpApiPath).setup();
|
||||||
|
if (isPnpLoaderEnabled && register) {
|
||||||
|
register(pathToFileURL(absPnpLoaderPath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||||
|
? exports => absRequire(absUserWrapperPath)(exports)
|
||||||
|
: exports => exports;
|
||||||
|
|
||||||
|
// Defer to the real typescript/lib/tsc.js your application uses
|
||||||
|
module.exports = wrapWithUserWrapper(absRequire(`typescript/lib/tsc.js`));
|
||||||
|
|
@ -0,0 +1,248 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
const {existsSync} = require(`fs`);
|
||||||
|
const {createRequire, register} = require(`module`);
|
||||||
|
const {resolve} = require(`path`);
|
||||||
|
const {pathToFileURL} = require(`url`);
|
||||||
|
|
||||||
|
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||||
|
|
||||||
|
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||||
|
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||||
|
const absRequire = createRequire(absPnpApiPath);
|
||||||
|
|
||||||
|
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||||
|
const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
|
||||||
|
|
||||||
|
if (existsSync(absPnpApiPath)) {
|
||||||
|
if (!process.versions.pnp) {
|
||||||
|
// Setup the environment to be able to require typescript/lib/tsserver.js
|
||||||
|
require(absPnpApiPath).setup();
|
||||||
|
if (isPnpLoaderEnabled && register) {
|
||||||
|
register(pathToFileURL(absPnpLoaderPath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||||
|
? exports => absRequire(absUserWrapperPath)(exports)
|
||||||
|
: exports => exports;
|
||||||
|
|
||||||
|
const moduleWrapper = exports => {
|
||||||
|
return wrapWithUserWrapper(moduleWrapperFn(exports));
|
||||||
|
};
|
||||||
|
|
||||||
|
const moduleWrapperFn = tsserver => {
|
||||||
|
if (!process.versions.pnp) {
|
||||||
|
return tsserver;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {isAbsolute} = require(`path`);
|
||||||
|
const pnpApi = require(`pnpapi`);
|
||||||
|
|
||||||
|
const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//);
|
||||||
|
const isPortal = str => str.startsWith("portal:/");
|
||||||
|
const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`);
|
||||||
|
|
||||||
|
const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => {
|
||||||
|
return `${locator.name}@${locator.reference}`;
|
||||||
|
}));
|
||||||
|
|
||||||
|
// VSCode sends the zip paths to TS using the "zip://" prefix, that TS
|
||||||
|
// doesn't understand. This layer makes sure to remove the protocol
|
||||||
|
// before forwarding it to TS, and to add it back on all returned paths.
|
||||||
|
|
||||||
|
function toEditorPath(str) {
|
||||||
|
// We add the `zip:` prefix to both `.zip/` paths and virtual paths
|
||||||
|
if (isAbsolute(str) && !str.match(/^\^?(zip:|\/zip\/)/) && (str.match(/\.zip\//) || isVirtual(str))) {
|
||||||
|
// We also take the opportunity to turn virtual paths into physical ones;
|
||||||
|
// this makes it much easier to work with workspaces that list peer
|
||||||
|
// dependencies, since otherwise Ctrl+Click would bring us to the virtual
|
||||||
|
// file instances instead of the real ones.
|
||||||
|
//
|
||||||
|
// We only do this to modules owned by the the dependency tree roots.
|
||||||
|
// This avoids breaking the resolution when jumping inside a vendor
|
||||||
|
// with peer dep (otherwise jumping into react-dom would show resolution
|
||||||
|
// errors on react).
|
||||||
|
//
|
||||||
|
const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str;
|
||||||
|
if (resolved) {
|
||||||
|
const locator = pnpApi.findPackageLocator(resolved);
|
||||||
|
if (locator && (dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || isPortal(locator.reference))) {
|
||||||
|
str = resolved;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
str = normalize(str);
|
||||||
|
|
||||||
|
if (str.match(/\.zip\//)) {
|
||||||
|
switch (hostInfo) {
|
||||||
|
// Absolute VSCode `Uri.fsPath`s need to start with a slash.
|
||||||
|
// VSCode only adds it automatically for supported schemes,
|
||||||
|
// so we have to do it manually for the `zip` scheme.
|
||||||
|
// The path needs to start with a caret otherwise VSCode doesn't handle the protocol
|
||||||
|
//
|
||||||
|
// Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910
|
||||||
|
//
|
||||||
|
// 2021-10-08: VSCode changed the format in 1.61.
|
||||||
|
// Before | ^zip:/c:/foo/bar.zip/package.json
|
||||||
|
// After | ^/zip//c:/foo/bar.zip/package.json
|
||||||
|
//
|
||||||
|
// 2022-04-06: VSCode changed the format in 1.66.
|
||||||
|
// Before | ^/zip//c:/foo/bar.zip/package.json
|
||||||
|
// After | ^/zip/c:/foo/bar.zip/package.json
|
||||||
|
//
|
||||||
|
// 2022-05-06: VSCode changed the format in 1.68
|
||||||
|
// Before | ^/zip/c:/foo/bar.zip/package.json
|
||||||
|
// After | ^/zip//c:/foo/bar.zip/package.json
|
||||||
|
//
|
||||||
|
case `vscode <1.61`: {
|
||||||
|
str = `^zip:${str}`;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case `vscode <1.66`: {
|
||||||
|
str = `^/zip/${str}`;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case `vscode <1.68`: {
|
||||||
|
str = `^/zip${str}`;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case `vscode`: {
|
||||||
|
str = `^/zip/${str}`;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
// To make "go to definition" work,
|
||||||
|
// We have to resolve the actual file system path from virtual path
|
||||||
|
// and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip)
|
||||||
|
case `coc-nvim`: {
|
||||||
|
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
|
||||||
|
str = resolve(`zipfile:${str}`);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
// Support neovim native LSP and [typescript-language-server](https://github.com/theia-ide/typescript-language-server)
|
||||||
|
// We have to resolve the actual file system path from virtual path,
|
||||||
|
// everything else is up to neovim
|
||||||
|
case `neovim`: {
|
||||||
|
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
|
||||||
|
str = `zipfile://${str}`;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default: {
|
||||||
|
str = `zip:${str}`;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
str = str.replace(/^\/?/, process.platform === `win32` ? `` : `/`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
function fromEditorPath(str) {
|
||||||
|
switch (hostInfo) {
|
||||||
|
case `coc-nvim`: {
|
||||||
|
str = str.replace(/\.zip::/, `.zip/`);
|
||||||
|
// The path for coc-nvim is in format of /<pwd>/zipfile:/<pwd>/.yarn/...
|
||||||
|
// So in order to convert it back, we use .* to match all the thing
|
||||||
|
// before `zipfile:`
|
||||||
|
return process.platform === `win32`
|
||||||
|
? str.replace(/^.*zipfile:\//, ``)
|
||||||
|
: str.replace(/^.*zipfile:/, ``);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case `neovim`: {
|
||||||
|
str = str.replace(/\.zip::/, `.zip/`);
|
||||||
|
// The path for neovim is in format of zipfile:///<pwd>/.yarn/...
|
||||||
|
return str.replace(/^zipfile:\/\//, ``);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case `vscode`:
|
||||||
|
default: {
|
||||||
|
return str.replace(/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, process.platform === `win32` ? `` : `/`)
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force enable 'allowLocalPluginLoads'
|
||||||
|
// TypeScript tries to resolve plugins using a path relative to itself
|
||||||
|
// which doesn't work when using the global cache
|
||||||
|
// https://github.com/microsoft/TypeScript/blob/1b57a0395e0bff191581c9606aab92832001de62/src/server/project.ts#L2238
|
||||||
|
// VSCode doesn't want to enable 'allowLocalPluginLoads' due to security concerns but
|
||||||
|
// TypeScript already does local loads and if this code is running the user trusts the workspace
|
||||||
|
// https://github.com/microsoft/vscode/issues/45856
|
||||||
|
const ConfiguredProject = tsserver.server.ConfiguredProject;
|
||||||
|
const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype;
|
||||||
|
ConfiguredProject.prototype.enablePluginsWithOptions = function() {
|
||||||
|
this.projectService.allowLocalPluginLoads = true;
|
||||||
|
return originalEnablePluginsWithOptions.apply(this, arguments);
|
||||||
|
};
|
||||||
|
|
||||||
|
// And here is the point where we hijack the VSCode <-> TS communications
|
||||||
|
// by adding ourselves in the middle. We locate everything that looks
|
||||||
|
// like an absolute path of ours and normalize it.
|
||||||
|
|
||||||
|
const Session = tsserver.server.Session;
|
||||||
|
const {onMessage: originalOnMessage, send: originalSend} = Session.prototype;
|
||||||
|
let hostInfo = `unknown`;
|
||||||
|
|
||||||
|
Object.assign(Session.prototype, {
|
||||||
|
onMessage(/** @type {string | object} */ message) {
|
||||||
|
const isStringMessage = typeof message === 'string';
|
||||||
|
const parsedMessage = isStringMessage ? JSON.parse(message) : message;
|
||||||
|
|
||||||
|
if (
|
||||||
|
parsedMessage != null &&
|
||||||
|
typeof parsedMessage === `object` &&
|
||||||
|
parsedMessage.arguments &&
|
||||||
|
typeof parsedMessage.arguments.hostInfo === `string`
|
||||||
|
) {
|
||||||
|
hostInfo = parsedMessage.arguments.hostInfo;
|
||||||
|
if (hostInfo === `vscode` && process.env.VSCODE_IPC_HOOK) {
|
||||||
|
const [, major, minor] = (process.env.VSCODE_IPC_HOOK.match(
|
||||||
|
// The RegExp from https://semver.org/ but without the caret at the start
|
||||||
|
/(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
|
||||||
|
) ?? []).map(Number)
|
||||||
|
|
||||||
|
if (major === 1) {
|
||||||
|
if (minor < 61) {
|
||||||
|
hostInfo += ` <1.61`;
|
||||||
|
} else if (minor < 66) {
|
||||||
|
hostInfo += ` <1.66`;
|
||||||
|
} else if (minor < 68) {
|
||||||
|
hostInfo += ` <1.68`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const processedMessageJSON = JSON.stringify(parsedMessage, (key, value) => {
|
||||||
|
return typeof value === 'string' ? fromEditorPath(value) : value;
|
||||||
|
});
|
||||||
|
|
||||||
|
return originalOnMessage.call(
|
||||||
|
this,
|
||||||
|
isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
send(/** @type {any} */ msg) {
|
||||||
|
return originalSend.call(this, JSON.parse(JSON.stringify(msg, (key, value) => {
|
||||||
|
return typeof value === `string` ? toEditorPath(value) : value;
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return tsserver;
|
||||||
|
};
|
||||||
|
|
||||||
|
const [major, minor] = absRequire(`typescript/package.json`).version.split(`.`, 2).map(value => parseInt(value, 10));
|
||||||
|
// In TypeScript@>=5.5 the tsserver uses the public TypeScript API so that needs to be patched as well.
|
||||||
|
// Ref https://github.com/microsoft/TypeScript/pull/55326
|
||||||
|
if (major > 5 || (major === 5 && minor >= 5)) {
|
||||||
|
moduleWrapper(absRequire(`typescript`));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defer to the real typescript/lib/tsserver.js your application uses
|
||||||
|
module.exports = moduleWrapper(absRequire(`typescript/lib/tsserver.js`));
|
||||||
|
|
@ -0,0 +1,248 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
const {existsSync} = require(`fs`);
|
||||||
|
const {createRequire, register} = require(`module`);
|
||||||
|
const {resolve} = require(`path`);
|
||||||
|
const {pathToFileURL} = require(`url`);
|
||||||
|
|
||||||
|
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||||
|
|
||||||
|
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||||
|
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||||
|
const absRequire = createRequire(absPnpApiPath);
|
||||||
|
|
||||||
|
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||||
|
const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
|
||||||
|
|
||||||
|
if (existsSync(absPnpApiPath)) {
|
||||||
|
if (!process.versions.pnp) {
|
||||||
|
// Setup the environment to be able to require typescript/lib/tsserverlibrary.js
|
||||||
|
require(absPnpApiPath).setup();
|
||||||
|
if (isPnpLoaderEnabled && register) {
|
||||||
|
register(pathToFileURL(absPnpLoaderPath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||||
|
? exports => absRequire(absUserWrapperPath)(exports)
|
||||||
|
: exports => exports;
|
||||||
|
|
||||||
|
const moduleWrapper = exports => {
|
||||||
|
return wrapWithUserWrapper(moduleWrapperFn(exports));
|
||||||
|
};
|
||||||
|
|
||||||
|
const moduleWrapperFn = tsserver => {
|
||||||
|
if (!process.versions.pnp) {
|
||||||
|
return tsserver;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {isAbsolute} = require(`path`);
|
||||||
|
const pnpApi = require(`pnpapi`);
|
||||||
|
|
||||||
|
const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//);
|
||||||
|
const isPortal = str => str.startsWith("portal:/");
|
||||||
|
const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`);
|
||||||
|
|
||||||
|
const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => {
|
||||||
|
return `${locator.name}@${locator.reference}`;
|
||||||
|
}));
|
||||||
|
|
||||||
|
// VSCode sends the zip paths to TS using the "zip://" prefix, that TS
|
||||||
|
// doesn't understand. This layer makes sure to remove the protocol
|
||||||
|
// before forwarding it to TS, and to add it back on all returned paths.
|
||||||
|
|
||||||
|
function toEditorPath(str) {
|
||||||
|
// We add the `zip:` prefix to both `.zip/` paths and virtual paths
|
||||||
|
if (isAbsolute(str) && !str.match(/^\^?(zip:|\/zip\/)/) && (str.match(/\.zip\//) || isVirtual(str))) {
|
||||||
|
// We also take the opportunity to turn virtual paths into physical ones;
|
||||||
|
// this makes it much easier to work with workspaces that list peer
|
||||||
|
// dependencies, since otherwise Ctrl+Click would bring us to the virtual
|
||||||
|
// file instances instead of the real ones.
|
||||||
|
//
|
||||||
|
// We only do this to modules owned by the the dependency tree roots.
|
||||||
|
// This avoids breaking the resolution when jumping inside a vendor
|
||||||
|
// with peer dep (otherwise jumping into react-dom would show resolution
|
||||||
|
// errors on react).
|
||||||
|
//
|
||||||
|
const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str;
|
||||||
|
if (resolved) {
|
||||||
|
const locator = pnpApi.findPackageLocator(resolved);
|
||||||
|
if (locator && (dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || isPortal(locator.reference))) {
|
||||||
|
str = resolved;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
str = normalize(str);
|
||||||
|
|
||||||
|
if (str.match(/\.zip\//)) {
|
||||||
|
switch (hostInfo) {
|
||||||
|
// Absolute VSCode `Uri.fsPath`s need to start with a slash.
|
||||||
|
// VSCode only adds it automatically for supported schemes,
|
||||||
|
// so we have to do it manually for the `zip` scheme.
|
||||||
|
// The path needs to start with a caret otherwise VSCode doesn't handle the protocol
|
||||||
|
//
|
||||||
|
// Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910
|
||||||
|
//
|
||||||
|
// 2021-10-08: VSCode changed the format in 1.61.
|
||||||
|
// Before | ^zip:/c:/foo/bar.zip/package.json
|
||||||
|
// After | ^/zip//c:/foo/bar.zip/package.json
|
||||||
|
//
|
||||||
|
// 2022-04-06: VSCode changed the format in 1.66.
|
||||||
|
// Before | ^/zip//c:/foo/bar.zip/package.json
|
||||||
|
// After | ^/zip/c:/foo/bar.zip/package.json
|
||||||
|
//
|
||||||
|
// 2022-05-06: VSCode changed the format in 1.68
|
||||||
|
// Before | ^/zip/c:/foo/bar.zip/package.json
|
||||||
|
// After | ^/zip//c:/foo/bar.zip/package.json
|
||||||
|
//
|
||||||
|
case `vscode <1.61`: {
|
||||||
|
str = `^zip:${str}`;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case `vscode <1.66`: {
|
||||||
|
str = `^/zip/${str}`;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case `vscode <1.68`: {
|
||||||
|
str = `^/zip${str}`;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case `vscode`: {
|
||||||
|
str = `^/zip/${str}`;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
// To make "go to definition" work,
|
||||||
|
// We have to resolve the actual file system path from virtual path
|
||||||
|
// and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip)
|
||||||
|
case `coc-nvim`: {
|
||||||
|
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
|
||||||
|
str = resolve(`zipfile:${str}`);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
// Support neovim native LSP and [typescript-language-server](https://github.com/theia-ide/typescript-language-server)
|
||||||
|
// We have to resolve the actual file system path from virtual path,
|
||||||
|
// everything else is up to neovim
|
||||||
|
case `neovim`: {
|
||||||
|
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
|
||||||
|
str = `zipfile://${str}`;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default: {
|
||||||
|
str = `zip:${str}`;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
str = str.replace(/^\/?/, process.platform === `win32` ? `` : `/`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
function fromEditorPath(str) {
|
||||||
|
switch (hostInfo) {
|
||||||
|
case `coc-nvim`: {
|
||||||
|
str = str.replace(/\.zip::/, `.zip/`);
|
||||||
|
// The path for coc-nvim is in format of /<pwd>/zipfile:/<pwd>/.yarn/...
|
||||||
|
// So in order to convert it back, we use .* to match all the thing
|
||||||
|
// before `zipfile:`
|
||||||
|
return process.platform === `win32`
|
||||||
|
? str.replace(/^.*zipfile:\//, ``)
|
||||||
|
: str.replace(/^.*zipfile:/, ``);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case `neovim`: {
|
||||||
|
str = str.replace(/\.zip::/, `.zip/`);
|
||||||
|
// The path for neovim is in format of zipfile:///<pwd>/.yarn/...
|
||||||
|
return str.replace(/^zipfile:\/\//, ``);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case `vscode`:
|
||||||
|
default: {
|
||||||
|
return str.replace(/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, process.platform === `win32` ? `` : `/`)
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force enable 'allowLocalPluginLoads'
|
||||||
|
// TypeScript tries to resolve plugins using a path relative to itself
|
||||||
|
// which doesn't work when using the global cache
|
||||||
|
// https://github.com/microsoft/TypeScript/blob/1b57a0395e0bff191581c9606aab92832001de62/src/server/project.ts#L2238
|
||||||
|
// VSCode doesn't want to enable 'allowLocalPluginLoads' due to security concerns but
|
||||||
|
// TypeScript already does local loads and if this code is running the user trusts the workspace
|
||||||
|
// https://github.com/microsoft/vscode/issues/45856
|
||||||
|
const ConfiguredProject = tsserver.server.ConfiguredProject;
|
||||||
|
const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype;
|
||||||
|
ConfiguredProject.prototype.enablePluginsWithOptions = function() {
|
||||||
|
this.projectService.allowLocalPluginLoads = true;
|
||||||
|
return originalEnablePluginsWithOptions.apply(this, arguments);
|
||||||
|
};
|
||||||
|
|
||||||
|
// And here is the point where we hijack the VSCode <-> TS communications
|
||||||
|
// by adding ourselves in the middle. We locate everything that looks
|
||||||
|
// like an absolute path of ours and normalize it.
|
||||||
|
|
||||||
|
const Session = tsserver.server.Session;
|
||||||
|
const {onMessage: originalOnMessage, send: originalSend} = Session.prototype;
|
||||||
|
let hostInfo = `unknown`;
|
||||||
|
|
||||||
|
Object.assign(Session.prototype, {
|
||||||
|
onMessage(/** @type {string | object} */ message) {
|
||||||
|
const isStringMessage = typeof message === 'string';
|
||||||
|
const parsedMessage = isStringMessage ? JSON.parse(message) : message;
|
||||||
|
|
||||||
|
if (
|
||||||
|
parsedMessage != null &&
|
||||||
|
typeof parsedMessage === `object` &&
|
||||||
|
parsedMessage.arguments &&
|
||||||
|
typeof parsedMessage.arguments.hostInfo === `string`
|
||||||
|
) {
|
||||||
|
hostInfo = parsedMessage.arguments.hostInfo;
|
||||||
|
if (hostInfo === `vscode` && process.env.VSCODE_IPC_HOOK) {
|
||||||
|
const [, major, minor] = (process.env.VSCODE_IPC_HOOK.match(
|
||||||
|
// The RegExp from https://semver.org/ but without the caret at the start
|
||||||
|
/(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
|
||||||
|
) ?? []).map(Number)
|
||||||
|
|
||||||
|
if (major === 1) {
|
||||||
|
if (minor < 61) {
|
||||||
|
hostInfo += ` <1.61`;
|
||||||
|
} else if (minor < 66) {
|
||||||
|
hostInfo += ` <1.66`;
|
||||||
|
} else if (minor < 68) {
|
||||||
|
hostInfo += ` <1.68`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const processedMessageJSON = JSON.stringify(parsedMessage, (key, value) => {
|
||||||
|
return typeof value === 'string' ? fromEditorPath(value) : value;
|
||||||
|
});
|
||||||
|
|
||||||
|
return originalOnMessage.call(
|
||||||
|
this,
|
||||||
|
isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
send(/** @type {any} */ msg) {
|
||||||
|
return originalSend.call(this, JSON.parse(JSON.stringify(msg, (key, value) => {
|
||||||
|
return typeof value === `string` ? toEditorPath(value) : value;
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return tsserver;
|
||||||
|
};
|
||||||
|
|
||||||
|
const [major, minor] = absRequire(`typescript/package.json`).version.split(`.`, 2).map(value => parseInt(value, 10));
|
||||||
|
// In TypeScript@>=5.5 the tsserver uses the public TypeScript API so that needs to be patched as well.
|
||||||
|
// Ref https://github.com/microsoft/TypeScript/pull/55326
|
||||||
|
if (major > 5 || (major === 5 && minor >= 5)) {
|
||||||
|
moduleWrapper(absRequire(`typescript`));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defer to the real typescript/lib/tsserverlibrary.js your application uses
|
||||||
|
module.exports = moduleWrapper(absRequire(`typescript/lib/tsserverlibrary.js`));
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
const {existsSync} = require(`fs`);
|
||||||
|
const {createRequire, register} = require(`module`);
|
||||||
|
const {resolve} = require(`path`);
|
||||||
|
const {pathToFileURL} = require(`url`);
|
||||||
|
|
||||||
|
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||||
|
|
||||||
|
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||||
|
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||||
|
const absRequire = createRequire(absPnpApiPath);
|
||||||
|
|
||||||
|
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||||
|
const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
|
||||||
|
|
||||||
|
if (existsSync(absPnpApiPath)) {
|
||||||
|
if (!process.versions.pnp) {
|
||||||
|
// Setup the environment to be able to require typescript
|
||||||
|
require(absPnpApiPath).setup();
|
||||||
|
if (isPnpLoaderEnabled && register) {
|
||||||
|
register(pathToFileURL(absPnpLoaderPath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||||
|
? exports => absRequire(absUserWrapperPath)(exports)
|
||||||
|
: exports => exports;
|
||||||
|
|
||||||
|
// Defer to the real typescript your application uses
|
||||||
|
module.exports = wrapWithUserWrapper(absRequire(`typescript`));
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"name": "typescript",
|
||||||
|
"version": "6.0.2-sdk",
|
||||||
|
"main": "./lib/typescript.js",
|
||||||
|
"type": "commonjs",
|
||||||
|
"bin": {
|
||||||
|
"tsc": "./bin/tsc",
|
||||||
|
"tsserver": "./bin/tsserver"
|
||||||
|
}
|
||||||
|
}
|
||||||
0
.yarn/unplugged/@rolldown-binding-win32-x64-msvc-npm-1.0.0-rc.15-534011b6d3/node_modules/@rolldown/binding-win32-x64-msvc/.ready
generated
vendored
Normal file
0
.yarn/unplugged/@rolldown-binding-win32-x64-msvc-npm-1.0.0-rc.15-534011b6d3/node_modules/@rolldown/binding-win32-x64-msvc/.ready
generated
vendored
Normal file
3
.yarn/unplugged/@rolldown-binding-win32-x64-msvc-npm-1.0.0-rc.15-534011b6d3/node_modules/@rolldown/binding-win32-x64-msvc/README.md
generated
vendored
Normal file
3
.yarn/unplugged/@rolldown-binding-win32-x64-msvc-npm-1.0.0-rc.15-534011b6d3/node_modules/@rolldown/binding-win32-x64-msvc/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
# `@rolldown/binding-win32-x64-msvc`
|
||||||
|
|
||||||
|
This is the **x86_64-pc-windows-msvc** binary for `@rolldown/binding`
|
||||||
37
.yarn/unplugged/@rolldown-binding-win32-x64-msvc-npm-1.0.0-rc.15-534011b6d3/node_modules/@rolldown/binding-win32-x64-msvc/package.json
generated
vendored
Normal file
37
.yarn/unplugged/@rolldown-binding-win32-x64-msvc-npm-1.0.0-rc.15-534011b6d3/node_modules/@rolldown/binding-win32-x64-msvc/package.json
generated
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
{
|
||||||
|
"name": "@rolldown/binding-win32-x64-msvc",
|
||||||
|
"version": "1.0.0-rc.15",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"main": "rolldown-binding.win32-x64-msvc.node",
|
||||||
|
"files": [
|
||||||
|
"rolldown-binding.win32-x64-msvc.node"
|
||||||
|
],
|
||||||
|
"description": "Fast JavaScript/TypeScript bundler in Rust with Rollup-compatible API.",
|
||||||
|
"keywords": [
|
||||||
|
"bundler",
|
||||||
|
"esbuild",
|
||||||
|
"parcel",
|
||||||
|
"rolldown",
|
||||||
|
"rollup",
|
||||||
|
"webpack"
|
||||||
|
],
|
||||||
|
"homepage": "https://rolldown.rs/",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": "^20.19.0 || >=22.12.0"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/rolldown/rolldown.git",
|
||||||
|
"directory": "packages/rolldown"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"registry": "https://registry.npmjs.org/",
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
]
|
||||||
|
}
|
||||||
Binary file not shown.
0
.yarn/unplugged/@tailwindcss-oxide-win32-x64-msvc-npm-4.2.2-5fae6fe118/node_modules/@tailwindcss/oxide-win32-x64-msvc/.ready
generated
vendored
Normal file
0
.yarn/unplugged/@tailwindcss-oxide-win32-x64-msvc-npm-4.2.2-5fae6fe118/node_modules/@tailwindcss/oxide-win32-x64-msvc/.ready
generated
vendored
Normal file
21
.yarn/unplugged/@tailwindcss-oxide-win32-x64-msvc-npm-4.2.2-5fae6fe118/node_modules/@tailwindcss/oxide-win32-x64-msvc/LICENSE
generated
vendored
Normal file
21
.yarn/unplugged/@tailwindcss-oxide-win32-x64-msvc-npm-4.2.2-5fae6fe118/node_modules/@tailwindcss/oxide-win32-x64-msvc/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) Tailwind Labs, Inc.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
3
.yarn/unplugged/@tailwindcss-oxide-win32-x64-msvc-npm-4.2.2-5fae6fe118/node_modules/@tailwindcss/oxide-win32-x64-msvc/README.md
generated
vendored
Normal file
3
.yarn/unplugged/@tailwindcss-oxide-win32-x64-msvc-npm-4.2.2-5fae6fe118/node_modules/@tailwindcss/oxide-win32-x64-msvc/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
# `@tailwindcss/oxide-win32-x64-msvc`
|
||||||
|
|
||||||
|
This is the **x86_64-pc-windows-msvc** binary for `@tailwindcss/oxide`
|
||||||
27
.yarn/unplugged/@tailwindcss-oxide-win32-x64-msvc-npm-4.2.2-5fae6fe118/node_modules/@tailwindcss/oxide-win32-x64-msvc/package.json
generated
vendored
Normal file
27
.yarn/unplugged/@tailwindcss-oxide-win32-x64-msvc-npm-4.2.2-5fae6fe118/node_modules/@tailwindcss/oxide-win32-x64-msvc/package.json
generated
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"name": "@tailwindcss/oxide-win32-x64-msvc",
|
||||||
|
"version": "4.2.2",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/tailwindlabs/tailwindcss.git",
|
||||||
|
"directory": "crates/node/npm/win32-x64-msvc"
|
||||||
|
},
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"main": "tailwindcss-oxide.win32-x64-msvc.node",
|
||||||
|
"files": [
|
||||||
|
"tailwindcss-oxide.win32-x64-msvc.node"
|
||||||
|
],
|
||||||
|
"publishConfig": {
|
||||||
|
"provenance": true,
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 20"
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
0
.yarn/unplugged/lightningcss-win32-x64-msvc-npm-1.32.0-3c26fdaa38/node_modules/lightningcss-win32-x64-msvc/.ready
generated
vendored
Normal file
0
.yarn/unplugged/lightningcss-win32-x64-msvc-npm-1.32.0-3c26fdaa38/node_modules/lightningcss-win32-x64-msvc/.ready
generated
vendored
Normal file
373
.yarn/unplugged/lightningcss-win32-x64-msvc-npm-1.32.0-3c26fdaa38/node_modules/lightningcss-win32-x64-msvc/LICENSE
generated
vendored
Normal file
373
.yarn/unplugged/lightningcss-win32-x64-msvc-npm-1.32.0-3c26fdaa38/node_modules/lightningcss-win32-x64-msvc/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,373 @@
|
||||||
|
Mozilla Public License Version 2.0
|
||||||
|
==================================
|
||||||
|
|
||||||
|
1. Definitions
|
||||||
|
--------------
|
||||||
|
|
||||||
|
1.1. "Contributor"
|
||||||
|
means each individual or legal entity that creates, contributes to
|
||||||
|
the creation of, or owns Covered Software.
|
||||||
|
|
||||||
|
1.2. "Contributor Version"
|
||||||
|
means the combination of the Contributions of others (if any) used
|
||||||
|
by a Contributor and that particular Contributor's Contribution.
|
||||||
|
|
||||||
|
1.3. "Contribution"
|
||||||
|
means Covered Software of a particular Contributor.
|
||||||
|
|
||||||
|
1.4. "Covered Software"
|
||||||
|
means Source Code Form to which the initial Contributor has attached
|
||||||
|
the notice in Exhibit A, the Executable Form of such Source Code
|
||||||
|
Form, and Modifications of such Source Code Form, in each case
|
||||||
|
including portions thereof.
|
||||||
|
|
||||||
|
1.5. "Incompatible With Secondary Licenses"
|
||||||
|
means
|
||||||
|
|
||||||
|
(a) that the initial Contributor has attached the notice described
|
||||||
|
in Exhibit B to the Covered Software; or
|
||||||
|
|
||||||
|
(b) that the Covered Software was made available under the terms of
|
||||||
|
version 1.1 or earlier of the License, but not also under the
|
||||||
|
terms of a Secondary License.
|
||||||
|
|
||||||
|
1.6. "Executable Form"
|
||||||
|
means any form of the work other than Source Code Form.
|
||||||
|
|
||||||
|
1.7. "Larger Work"
|
||||||
|
means a work that combines Covered Software with other material, in
|
||||||
|
a separate file or files, that is not Covered Software.
|
||||||
|
|
||||||
|
1.8. "License"
|
||||||
|
means this document.
|
||||||
|
|
||||||
|
1.9. "Licensable"
|
||||||
|
means having the right to grant, to the maximum extent possible,
|
||||||
|
whether at the time of the initial grant or subsequently, any and
|
||||||
|
all of the rights conveyed by this License.
|
||||||
|
|
||||||
|
1.10. "Modifications"
|
||||||
|
means any of the following:
|
||||||
|
|
||||||
|
(a) any file in Source Code Form that results from an addition to,
|
||||||
|
deletion from, or modification of the contents of Covered
|
||||||
|
Software; or
|
||||||
|
|
||||||
|
(b) any new file in Source Code Form that contains any Covered
|
||||||
|
Software.
|
||||||
|
|
||||||
|
1.11. "Patent Claims" of a Contributor
|
||||||
|
means any patent claim(s), including without limitation, method,
|
||||||
|
process, and apparatus claims, in any patent Licensable by such
|
||||||
|
Contributor that would be infringed, but for the grant of the
|
||||||
|
License, by the making, using, selling, offering for sale, having
|
||||||
|
made, import, or transfer of either its Contributions or its
|
||||||
|
Contributor Version.
|
||||||
|
|
||||||
|
1.12. "Secondary License"
|
||||||
|
means either the GNU General Public License, Version 2.0, the GNU
|
||||||
|
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||||
|
Public License, Version 3.0, or any later versions of those
|
||||||
|
licenses.
|
||||||
|
|
||||||
|
1.13. "Source Code Form"
|
||||||
|
means the form of the work preferred for making modifications.
|
||||||
|
|
||||||
|
1.14. "You" (or "Your")
|
||||||
|
means an individual or a legal entity exercising rights under this
|
||||||
|
License. For legal entities, "You" includes any entity that
|
||||||
|
controls, is controlled by, or is under common control with You. For
|
||||||
|
purposes of this definition, "control" means (a) the power, direct
|
||||||
|
or indirect, to cause the direction or management of such entity,
|
||||||
|
whether by contract or otherwise, or (b) ownership of more than
|
||||||
|
fifty percent (50%) of the outstanding shares or beneficial
|
||||||
|
ownership of such entity.
|
||||||
|
|
||||||
|
2. License Grants and Conditions
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
2.1. Grants
|
||||||
|
|
||||||
|
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||||
|
non-exclusive license:
|
||||||
|
|
||||||
|
(a) under intellectual property rights (other than patent or trademark)
|
||||||
|
Licensable by such Contributor to use, reproduce, make available,
|
||||||
|
modify, display, perform, distribute, and otherwise exploit its
|
||||||
|
Contributions, either on an unmodified basis, with Modifications, or
|
||||||
|
as part of a Larger Work; and
|
||||||
|
|
||||||
|
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||||
|
for sale, have made, import, and otherwise transfer either its
|
||||||
|
Contributions or its Contributor Version.
|
||||||
|
|
||||||
|
2.2. Effective Date
|
||||||
|
|
||||||
|
The licenses granted in Section 2.1 with respect to any Contribution
|
||||||
|
become effective for each Contribution on the date the Contributor first
|
||||||
|
distributes such Contribution.
|
||||||
|
|
||||||
|
2.3. Limitations on Grant Scope
|
||||||
|
|
||||||
|
The licenses granted in this Section 2 are the only rights granted under
|
||||||
|
this License. No additional rights or licenses will be implied from the
|
||||||
|
distribution or licensing of Covered Software under this License.
|
||||||
|
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||||
|
Contributor:
|
||||||
|
|
||||||
|
(a) for any code that a Contributor has removed from Covered Software;
|
||||||
|
or
|
||||||
|
|
||||||
|
(b) for infringements caused by: (i) Your and any other third party's
|
||||||
|
modifications of Covered Software, or (ii) the combination of its
|
||||||
|
Contributions with other software (except as part of its Contributor
|
||||||
|
Version); or
|
||||||
|
|
||||||
|
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||||
|
its Contributions.
|
||||||
|
|
||||||
|
This License does not grant any rights in the trademarks, service marks,
|
||||||
|
or logos of any Contributor (except as may be necessary to comply with
|
||||||
|
the notice requirements in Section 3.4).
|
||||||
|
|
||||||
|
2.4. Subsequent Licenses
|
||||||
|
|
||||||
|
No Contributor makes additional grants as a result of Your choice to
|
||||||
|
distribute the Covered Software under a subsequent version of this
|
||||||
|
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||||
|
permitted under the terms of Section 3.3).
|
||||||
|
|
||||||
|
2.5. Representation
|
||||||
|
|
||||||
|
Each Contributor represents that the Contributor believes its
|
||||||
|
Contributions are its original creation(s) or it has sufficient rights
|
||||||
|
to grant the rights to its Contributions conveyed by this License.
|
||||||
|
|
||||||
|
2.6. Fair Use
|
||||||
|
|
||||||
|
This License is not intended to limit any rights You have under
|
||||||
|
applicable copyright doctrines of fair use, fair dealing, or other
|
||||||
|
equivalents.
|
||||||
|
|
||||||
|
2.7. Conditions
|
||||||
|
|
||||||
|
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||||
|
in Section 2.1.
|
||||||
|
|
||||||
|
3. Responsibilities
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
3.1. Distribution of Source Form
|
||||||
|
|
||||||
|
All distribution of Covered Software in Source Code Form, including any
|
||||||
|
Modifications that You create or to which You contribute, must be under
|
||||||
|
the terms of this License. You must inform recipients that the Source
|
||||||
|
Code Form of the Covered Software is governed by the terms of this
|
||||||
|
License, and how they can obtain a copy of this License. You may not
|
||||||
|
attempt to alter or restrict the recipients' rights in the Source Code
|
||||||
|
Form.
|
||||||
|
|
||||||
|
3.2. Distribution of Executable Form
|
||||||
|
|
||||||
|
If You distribute Covered Software in Executable Form then:
|
||||||
|
|
||||||
|
(a) such Covered Software must also be made available in Source Code
|
||||||
|
Form, as described in Section 3.1, and You must inform recipients of
|
||||||
|
the Executable Form how they can obtain a copy of such Source Code
|
||||||
|
Form by reasonable means in a timely manner, at a charge no more
|
||||||
|
than the cost of distribution to the recipient; and
|
||||||
|
|
||||||
|
(b) You may distribute such Executable Form under the terms of this
|
||||||
|
License, or sublicense it under different terms, provided that the
|
||||||
|
license for the Executable Form does not attempt to limit or alter
|
||||||
|
the recipients' rights in the Source Code Form under this License.
|
||||||
|
|
||||||
|
3.3. Distribution of a Larger Work
|
||||||
|
|
||||||
|
You may create and distribute a Larger Work under terms of Your choice,
|
||||||
|
provided that You also comply with the requirements of this License for
|
||||||
|
the Covered Software. If the Larger Work is a combination of Covered
|
||||||
|
Software with a work governed by one or more Secondary Licenses, and the
|
||||||
|
Covered Software is not Incompatible With Secondary Licenses, this
|
||||||
|
License permits You to additionally distribute such Covered Software
|
||||||
|
under the terms of such Secondary License(s), so that the recipient of
|
||||||
|
the Larger Work may, at their option, further distribute the Covered
|
||||||
|
Software under the terms of either this License or such Secondary
|
||||||
|
License(s).
|
||||||
|
|
||||||
|
3.4. Notices
|
||||||
|
|
||||||
|
You may not remove or alter the substance of any license notices
|
||||||
|
(including copyright notices, patent notices, disclaimers of warranty,
|
||||||
|
or limitations of liability) contained within the Source Code Form of
|
||||||
|
the Covered Software, except that You may alter any license notices to
|
||||||
|
the extent required to remedy known factual inaccuracies.
|
||||||
|
|
||||||
|
3.5. Application of Additional Terms
|
||||||
|
|
||||||
|
You may choose to offer, and to charge a fee for, warranty, support,
|
||||||
|
indemnity or liability obligations to one or more recipients of Covered
|
||||||
|
Software. However, You may do so only on Your own behalf, and not on
|
||||||
|
behalf of any Contributor. You must make it absolutely clear that any
|
||||||
|
such warranty, support, indemnity, or liability obligation is offered by
|
||||||
|
You alone, and You hereby agree to indemnify every Contributor for any
|
||||||
|
liability incurred by such Contributor as a result of warranty, support,
|
||||||
|
indemnity or liability terms You offer. You may include additional
|
||||||
|
disclaimers of warranty and limitations of liability specific to any
|
||||||
|
jurisdiction.
|
||||||
|
|
||||||
|
4. Inability to Comply Due to Statute or Regulation
|
||||||
|
---------------------------------------------------
|
||||||
|
|
||||||
|
If it is impossible for You to comply with any of the terms of this
|
||||||
|
License with respect to some or all of the Covered Software due to
|
||||||
|
statute, judicial order, or regulation then You must: (a) comply with
|
||||||
|
the terms of this License to the maximum extent possible; and (b)
|
||||||
|
describe the limitations and the code they affect. Such description must
|
||||||
|
be placed in a text file included with all distributions of the Covered
|
||||||
|
Software under this License. Except to the extent prohibited by statute
|
||||||
|
or regulation, such description must be sufficiently detailed for a
|
||||||
|
recipient of ordinary skill to be able to understand it.
|
||||||
|
|
||||||
|
5. Termination
|
||||||
|
--------------
|
||||||
|
|
||||||
|
5.1. The rights granted under this License will terminate automatically
|
||||||
|
if You fail to comply with any of its terms. However, if You become
|
||||||
|
compliant, then the rights granted under this License from a particular
|
||||||
|
Contributor are reinstated (a) provisionally, unless and until such
|
||||||
|
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||||
|
ongoing basis, if such Contributor fails to notify You of the
|
||||||
|
non-compliance by some reasonable means prior to 60 days after You have
|
||||||
|
come back into compliance. Moreover, Your grants from a particular
|
||||||
|
Contributor are reinstated on an ongoing basis if such Contributor
|
||||||
|
notifies You of the non-compliance by some reasonable means, this is the
|
||||||
|
first time You have received notice of non-compliance with this License
|
||||||
|
from such Contributor, and You become compliant prior to 30 days after
|
||||||
|
Your receipt of the notice.
|
||||||
|
|
||||||
|
5.2. If You initiate litigation against any entity by asserting a patent
|
||||||
|
infringement claim (excluding declaratory judgment actions,
|
||||||
|
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||||
|
directly or indirectly infringes any patent, then the rights granted to
|
||||||
|
You by any and all Contributors for the Covered Software under Section
|
||||||
|
2.1 of this License shall terminate.
|
||||||
|
|
||||||
|
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||||
|
end user license agreements (excluding distributors and resellers) which
|
||||||
|
have been validly granted by You or Your distributors under this License
|
||||||
|
prior to termination shall survive termination.
|
||||||
|
|
||||||
|
************************************************************************
|
||||||
|
* *
|
||||||
|
* 6. Disclaimer of Warranty *
|
||||||
|
* ------------------------- *
|
||||||
|
* *
|
||||||
|
* Covered Software is provided under this License on an "as is" *
|
||||||
|
* basis, without warranty of any kind, either expressed, implied, or *
|
||||||
|
* statutory, including, without limitation, warranties that the *
|
||||||
|
* Covered Software is free of defects, merchantable, fit for a *
|
||||||
|
* particular purpose or non-infringing. The entire risk as to the *
|
||||||
|
* quality and performance of the Covered Software is with You. *
|
||||||
|
* Should any Covered Software prove defective in any respect, You *
|
||||||
|
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||||
|
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||||
|
* essential part of this License. No use of any Covered Software is *
|
||||||
|
* authorized under this License except under this disclaimer. *
|
||||||
|
* *
|
||||||
|
************************************************************************
|
||||||
|
|
||||||
|
************************************************************************
|
||||||
|
* *
|
||||||
|
* 7. Limitation of Liability *
|
||||||
|
* -------------------------- *
|
||||||
|
* *
|
||||||
|
* Under no circumstances and under no legal theory, whether tort *
|
||||||
|
* (including negligence), contract, or otherwise, shall any *
|
||||||
|
* Contributor, or anyone who distributes Covered Software as *
|
||||||
|
* permitted above, be liable to You for any direct, indirect, *
|
||||||
|
* special, incidental, or consequential damages of any character *
|
||||||
|
* including, without limitation, damages for lost profits, loss of *
|
||||||
|
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||||
|
* and all other commercial damages or losses, even if such party *
|
||||||
|
* shall have been informed of the possibility of such damages. This *
|
||||||
|
* limitation of liability shall not apply to liability for death or *
|
||||||
|
* personal injury resulting from such party's negligence to the *
|
||||||
|
* extent applicable law prohibits such limitation. Some *
|
||||||
|
* jurisdictions do not allow the exclusion or limitation of *
|
||||||
|
* incidental or consequential damages, so this exclusion and *
|
||||||
|
* limitation may not apply to You. *
|
||||||
|
* *
|
||||||
|
************************************************************************
|
||||||
|
|
||||||
|
8. Litigation
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Any litigation relating to this License may be brought only in the
|
||||||
|
courts of a jurisdiction where the defendant maintains its principal
|
||||||
|
place of business and such litigation shall be governed by laws of that
|
||||||
|
jurisdiction, without reference to its conflict-of-law provisions.
|
||||||
|
Nothing in this Section shall prevent a party's ability to bring
|
||||||
|
cross-claims or counter-claims.
|
||||||
|
|
||||||
|
9. Miscellaneous
|
||||||
|
----------------
|
||||||
|
|
||||||
|
This License represents the complete agreement concerning the subject
|
||||||
|
matter hereof. If any provision of this License is held to be
|
||||||
|
unenforceable, such provision shall be reformed only to the extent
|
||||||
|
necessary to make it enforceable. Any law or regulation which provides
|
||||||
|
that the language of a contract shall be construed against the drafter
|
||||||
|
shall not be used to construe this License against a Contributor.
|
||||||
|
|
||||||
|
10. Versions of the License
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
10.1. New Versions
|
||||||
|
|
||||||
|
Mozilla Foundation is the license steward. Except as provided in Section
|
||||||
|
10.3, no one other than the license steward has the right to modify or
|
||||||
|
publish new versions of this License. Each version will be given a
|
||||||
|
distinguishing version number.
|
||||||
|
|
||||||
|
10.2. Effect of New Versions
|
||||||
|
|
||||||
|
You may distribute the Covered Software under the terms of the version
|
||||||
|
of the License under which You originally received the Covered Software,
|
||||||
|
or under the terms of any subsequent version published by the license
|
||||||
|
steward.
|
||||||
|
|
||||||
|
10.3. Modified Versions
|
||||||
|
|
||||||
|
If you create software not governed by this License, and you want to
|
||||||
|
create a new license for such software, you may create and use a
|
||||||
|
modified version of this License if you rename the license and remove
|
||||||
|
any references to the name of the license steward (except to note that
|
||||||
|
such modified license differs from this License).
|
||||||
|
|
||||||
|
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||||
|
Licenses
|
||||||
|
|
||||||
|
If You choose to distribute Source Code Form that is Incompatible With
|
||||||
|
Secondary Licenses under the terms of this version of the License, the
|
||||||
|
notice described in Exhibit B of this License must be attached.
|
||||||
|
|
||||||
|
Exhibit A - Source Code Form License Notice
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
If it is not possible or desirable to put the notice in a particular
|
||||||
|
file, then You may include the notice in a location (such as a LICENSE
|
||||||
|
file in a relevant directory) where a recipient would be likely to look
|
||||||
|
for such a notice.
|
||||||
|
|
||||||
|
You may add additional accurate notices of copyright ownership.
|
||||||
|
|
||||||
|
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||||
|
defined by the Mozilla Public License, v. 2.0.
|
||||||
1
.yarn/unplugged/lightningcss-win32-x64-msvc-npm-1.32.0-3c26fdaa38/node_modules/lightningcss-win32-x64-msvc/README.md
generated
vendored
Normal file
1
.yarn/unplugged/lightningcss-win32-x64-msvc-npm-1.32.0-3c26fdaa38/node_modules/lightningcss-win32-x64-msvc/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
This is the x86_64-pc-windows-msvc build of lightningcss. See https://github.com/parcel-bundler/lightningcss for details.
|
||||||
BIN
.yarn/unplugged/lightningcss-win32-x64-msvc-npm-1.32.0-3c26fdaa38/node_modules/lightningcss-win32-x64-msvc/lightningcss.win32-x64-msvc.node
generated
vendored
Normal file
BIN
.yarn/unplugged/lightningcss-win32-x64-msvc-npm-1.32.0-3c26fdaa38/node_modules/lightningcss-win32-x64-msvc/lightningcss.win32-x64-msvc.node
generated
vendored
Normal file
Binary file not shown.
34
.yarn/unplugged/lightningcss-win32-x64-msvc-npm-1.32.0-3c26fdaa38/node_modules/lightningcss-win32-x64-msvc/package.json
generated
vendored
Normal file
34
.yarn/unplugged/lightningcss-win32-x64-msvc-npm-1.32.0-3c26fdaa38/node_modules/lightningcss-win32-x64-msvc/package.json
generated
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"name": "lightningcss-win32-x64-msvc",
|
||||||
|
"version": "1.32.0",
|
||||||
|
"license": "MPL-2.0",
|
||||||
|
"description": "A CSS parser, transformer, and minifier written in Rust",
|
||||||
|
"main": "lightningcss.win32-x64-msvc.node",
|
||||||
|
"browserslist": "last 2 versions, not dead",
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/parcel"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/parcel-bundler/lightningcss.git"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12.0.0"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"lightningcss.win32-x64-msvc.node"
|
||||||
|
],
|
||||||
|
"resolutions": {
|
||||||
|
"lightningcss": "link:."
|
||||||
|
},
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
]
|
||||||
|
}
|
||||||
0
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/.ready
generated
vendored
Normal file
0
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/.ready
generated
vendored
Normal file
3
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/.release-please-manifest.json
generated
vendored
Normal file
3
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/.release-please-manifest.json
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
".": "12.2.0"
|
||||||
|
}
|
||||||
1202
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/CHANGELOG.md
generated
vendored
Normal file
1202
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/CHANGELOG.md
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/CODE_OF_CONDUCT.md
generated
vendored
Normal file
4
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/CODE_OF_CONDUCT.md
generated
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
# Code of Conduct
|
||||||
|
|
||||||
|
* [Node.js Code of Conduct](https://github.com/nodejs/admin/blob/master/CODE_OF_CONDUCT.md)
|
||||||
|
* [Node.js Moderation Policy](https://github.com/nodejs/admin/blob/master/Moderation-Policy.md)
|
||||||
44
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/CONTRIBUTING.md
generated
vendored
Normal file
44
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/CONTRIBUTING.md
generated
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
# Contributing to node-gyp
|
||||||
|
|
||||||
|
## Making changes to gyp-next
|
||||||
|
|
||||||
|
Changes in the subfolder `gyp/` should be submitted to the
|
||||||
|
[`gyp-next`][] repository first. The `gyp/` folder is regularly
|
||||||
|
synced from [`gyp-next`][] with GitHub Actions workflow
|
||||||
|
[`update-gyp-next.yml`](.github/workflows/update-gyp-next.yml),
|
||||||
|
and any changes in this folder would be overridden by the workflow.
|
||||||
|
|
||||||
|
## Code of Conduct
|
||||||
|
|
||||||
|
Please read the
|
||||||
|
[Code of Conduct](https://github.com/nodejs/admin/blob/main/CODE_OF_CONDUCT.md)
|
||||||
|
which explains the minimum behavior expectations for node-gyp contributors.
|
||||||
|
|
||||||
|
<a id="developers-certificate-of-origin"></a>
|
||||||
|
## Developer's Certificate of Origin 1.1
|
||||||
|
|
||||||
|
By making a contribution to this project, I certify that:
|
||||||
|
|
||||||
|
* (a) The contribution was created in whole or in part by me and I
|
||||||
|
have the right to submit it under the open source license
|
||||||
|
indicated in the file; or
|
||||||
|
|
||||||
|
* (b) The contribution is based upon previous work that, to the best
|
||||||
|
of my knowledge, is covered under an appropriate open source
|
||||||
|
license and I have the right under that license to submit that
|
||||||
|
work with modifications, whether created in whole or in part
|
||||||
|
by me, under the same open source license (unless I am
|
||||||
|
permitted to submit under a different license), as indicated
|
||||||
|
in the file; or
|
||||||
|
|
||||||
|
* (c) The contribution was provided directly to me by some other
|
||||||
|
person who certified (a), (b) or (c) and I have not modified
|
||||||
|
it.
|
||||||
|
|
||||||
|
* (d) I understand and agree that this project and the contribution
|
||||||
|
are public and that a record of the contribution (including all
|
||||||
|
personal information I submit with it, including my sign-off) is
|
||||||
|
maintained indefinitely and may be redistributed consistent with
|
||||||
|
this project or the open source license(s) involved.
|
||||||
|
|
||||||
|
[`gyp-next`]: https://github.com/nodejs/gyp-next
|
||||||
24
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/LICENSE
generated
vendored
Normal file
24
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
(The MIT License)
|
||||||
|
|
||||||
|
Copyright (c) 2012 Nathan Rajlich <nathan@tootallnate.net>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person
|
||||||
|
obtaining a copy of this software and associated documentation
|
||||||
|
files (the "Software"), to deal in the Software without
|
||||||
|
restriction, including without limitation the rights to use,
|
||||||
|
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following
|
||||||
|
conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
OTHER DEALINGS IN THE SOFTWARE.
|
||||||
290
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/README.md
generated
vendored
Normal file
290
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,290 @@
|
||||||
|
# `node-gyp` - Node.js native addon build tool
|
||||||
|
|
||||||
|
[](https://github.com/nodejs/node-gyp/actions?query=workflow%3ATests+branch%3Amain)
|
||||||
|

|
||||||
|
|
||||||
|
`node-gyp` is a cross-platform command-line tool written in Node.js for
|
||||||
|
compiling native addon modules for Node.js. It contains a vendored copy of the
|
||||||
|
[gyp-next](https://github.com/nodejs/gyp-next) project that was previously used
|
||||||
|
by the Chromium team and extended to support the development of Node.js native
|
||||||
|
addons.
|
||||||
|
|
||||||
|
Note that `node-gyp` is _not_ used to build Node.js itself.
|
||||||
|
|
||||||
|
All current and LTS target versions of Node.js are supported. Depending on what version of Node.js is actually installed on your system
|
||||||
|
`node-gyp` downloads the necessary development files or headers for the target version. List of stable Node.js versions can be found on [Node.js website](https://nodejs.org/en/about/previous-releases).
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
* The same build commands work on any of the supported platforms
|
||||||
|
* Supports the targeting of different versions of Node.js
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
> [!Important]
|
||||||
|
> Python >= v3.12 requires `node-gyp` >= v10
|
||||||
|
|
||||||
|
You can install `node-gyp` using `npm`:
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
npm install -g node-gyp
|
||||||
|
```
|
||||||
|
|
||||||
|
Depending on your operating system, you will need to install:
|
||||||
|
|
||||||
|
### On Unix
|
||||||
|
|
||||||
|
* [A supported version of Python](https://devguide.python.org/versions/)
|
||||||
|
* `make`
|
||||||
|
* A proper C/C++ compiler toolchain, like [GCC](https://gcc.gnu.org)
|
||||||
|
|
||||||
|
### On macOS
|
||||||
|
|
||||||
|
* [A supported version of Python](https://devguide.python.org/versions/)
|
||||||
|
* `Xcode Command Line Tools` which will install `clang`, `clang++`, and `make`.
|
||||||
|
* Install the `Xcode Command Line Tools` standalone by running `xcode-select --install`. -- OR --
|
||||||
|
* Alternatively, if you already have the [full Xcode installed](https://developer.apple.com/xcode/download/), you can install the Command Line Tools under the menu `Xcode -> Open Developer Tool -> More Developer Tools...`.
|
||||||
|
|
||||||
|
|
||||||
|
### On Windows
|
||||||
|
|
||||||
|
Install tools with [Chocolatey](https://chocolatey.org):
|
||||||
|
``` bash
|
||||||
|
choco install python visualstudio2022-workload-vctools -y
|
||||||
|
```
|
||||||
|
|
||||||
|
Or install and configure Python and Visual Studio tools manually:
|
||||||
|
|
||||||
|
* Follow the instructions in [Using Python on Windows](https://docs.python.org/3/using/windows.html) to install
|
||||||
|
the current [version of Python](https://www.python.org/downloads/).
|
||||||
|
|
||||||
|
* Install Visual C++ Build Environment: For Visual Studio 2019 or later, use the `Desktop development with C++` workload from [Visual Studio Community](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community). For a version older than Visual Studio 2019, install [Visual Studio Build Tools](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=BuildTools) with the `Visual C++ build tools` option.
|
||||||
|
|
||||||
|
To target native ARM64 Node.js on Windows on ARM, add the components "Visual C++ compilers and libraries for ARM64" and "Visual C++ ATL for ARM64".
|
||||||
|
|
||||||
|
To use the native ARM64 C++ compiler on Windows on ARM, ensure that you have Visual Studio 2022 [17.4 or later](https://devblogs.microsoft.com/visualstudio/arm64-visual-studio-is-officially-here/) installed.
|
||||||
|
|
||||||
|
It's advised to install the following PowerShell module: [VSSetup](https://github.com/microsoft/vssetup.powershell) using `Install-Module VSSetup -Scope CurrentUser`.
|
||||||
|
This will make Visual Studio detection logic use a more flexible and accessible method, avoiding PowerShell's `ConstrainedLanguage` mode.
|
||||||
|
|
||||||
|
### Configuring Python Dependency
|
||||||
|
|
||||||
|
`node-gyp` requires that you have installed a [supported version of Python](https://devguide.python.org/versions/).
|
||||||
|
If you have multiple versions of Python installed, you can identify which version
|
||||||
|
`node-gyp` should use in one of the following ways:
|
||||||
|
|
||||||
|
1. by setting the `--python` command-line option, e.g.:
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
node-gyp <command> --python /path/to/executable/python
|
||||||
|
```
|
||||||
|
|
||||||
|
2. If `node-gyp` is called by way of `npm`, *and* you have multiple versions of
|
||||||
|
Python installed, then you can set the `npm_config_python` environment variable
|
||||||
|
to the appropriate path:
|
||||||
|
``` bash
|
||||||
|
export npm_config_python=/path/to/executable/python
|
||||||
|
```
|
||||||
|
Or on Windows:
|
||||||
|
```console
|
||||||
|
py --list-paths # To see the installed Python versions
|
||||||
|
set npm_config_python=C:\path\to\python.exe # CMD
|
||||||
|
$Env:npm_config_python="C:\path\to\python.exe" # PowerShell
|
||||||
|
```
|
||||||
|
|
||||||
|
3. If the `PYTHON` environment variable is set to the path of a Python executable,
|
||||||
|
then that version will be used if it is a supported version.
|
||||||
|
|
||||||
|
4. If the `NODE_GYP_FORCE_PYTHON` environment variable is set to the path of a
|
||||||
|
Python executable, it will be used instead of any of the other configured or
|
||||||
|
built-in Python search paths. If it's not a compatible version, no further
|
||||||
|
searching will be done.
|
||||||
|
|
||||||
|
### Build for Third Party Node.js Runtimes
|
||||||
|
|
||||||
|
When building modules for third-party Node.js runtimes like Electron, which have
|
||||||
|
different build configurations from the official Node.js distribution, you
|
||||||
|
should use `--dist-url` or `--nodedir` flags to specify the headers of the
|
||||||
|
runtime to build for.
|
||||||
|
|
||||||
|
Also when `--dist-url` or `--nodedir` flags are passed, node-gyp will use the
|
||||||
|
`config.gypi` shipped in the headers distribution to generate build
|
||||||
|
configurations, which is different from the default mode that would use the
|
||||||
|
`process.config` object of the running Node.js instance.
|
||||||
|
|
||||||
|
Some old versions of Electron shipped malformed `config.gypi` in their headers
|
||||||
|
distributions, and you might need to pass `--force-process-config` to node-gyp
|
||||||
|
to work around configuration errors.
|
||||||
|
|
||||||
|
## How to Use
|
||||||
|
|
||||||
|
To compile your native addon first go to its root directory:
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
cd my_node_addon
|
||||||
|
```
|
||||||
|
|
||||||
|
The next step is to generate the appropriate project build files for the current
|
||||||
|
platform. Use `configure` for that:
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
node-gyp configure
|
||||||
|
```
|
||||||
|
|
||||||
|
Auto-detection fails for Visual C++ Build Tools 2015, so `--msvs_version=2015`
|
||||||
|
needs to be added (not needed when run by npm as configured above):
|
||||||
|
``` bash
|
||||||
|
node-gyp configure --msvs_version=2015
|
||||||
|
```
|
||||||
|
|
||||||
|
__Note__: The `configure` step looks for a `binding.gyp` file in the current
|
||||||
|
directory to process. See below for instructions on creating a `binding.gyp` file.
|
||||||
|
|
||||||
|
Now you will have either a `Makefile` (on Unix platforms) or a `vcxproj` file
|
||||||
|
(on Windows) in the `build/` directory. Next, invoke the `build` command:
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
node-gyp build
|
||||||
|
```
|
||||||
|
|
||||||
|
Now you have your compiled `.node` bindings file! The compiled bindings end up
|
||||||
|
in `build/Debug/` or `build/Release/`, depending on the build mode. At this point,
|
||||||
|
you can require the `.node` file with Node.js and run your tests!
|
||||||
|
|
||||||
|
__Note:__ To create a _Debug_ build of the bindings file, pass the `--debug` (or
|
||||||
|
`-d`) switch when running either the `configure`, `build` or `rebuild` commands.
|
||||||
|
|
||||||
|
## The `binding.gyp` file
|
||||||
|
|
||||||
|
A `binding.gyp` file describes the configuration to build your module, in a
|
||||||
|
JSON-like format. This file gets placed in the root of your package, alongside
|
||||||
|
`package.json`.
|
||||||
|
|
||||||
|
A barebones `gyp` file appropriate for building a Node.js addon could look like:
|
||||||
|
|
||||||
|
```python
|
||||||
|
{
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"target_name": "binding",
|
||||||
|
"sources": [ "src/binding.cc" ]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Further reading
|
||||||
|
|
||||||
|
The **[docs](./docs/)** directory contains additional documentation on specific node-gyp topics that may be useful if you are experiencing problems installing or building addons using node-gyp.
|
||||||
|
|
||||||
|
Some additional resources for Node.js native addons and writing `gyp` configuration files:
|
||||||
|
|
||||||
|
* ["Going Native" a nodeschool.io tutorial](http://nodeschool.io/#goingnative)
|
||||||
|
* ["Hello World" node addon example](https://github.com/nodejs/node/tree/main/test/addons/hello-world)
|
||||||
|
* [gyp user documentation](https://gyp.gsrc.io/docs/UserDocumentation.md)
|
||||||
|
* [gyp input format reference](https://gyp.gsrc.io/docs/InputFormatReference.md)
|
||||||
|
* [*"binding.gyp" files out in the wild* wiki page](./docs/binding.gyp-files-in-the-wild.md)
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
`node-gyp` responds to the following commands:
|
||||||
|
|
||||||
|
| **Command** | **Description**
|
||||||
|
|:--------------|:---------------------------------------------------------------
|
||||||
|
| `help` | Shows the help dialog
|
||||||
|
| `build` | Invokes `make`/`msbuild.exe` and builds the native addon
|
||||||
|
| `clean` | Removes the `build` directory if it exists
|
||||||
|
| `configure` | Generates project build files for the current platform
|
||||||
|
| `rebuild` | Runs `clean`, `configure` and `build` all in a row
|
||||||
|
| `install` | Installs Node.js header files for the given version
|
||||||
|
| `list` | Lists the currently installed Node.js header versions
|
||||||
|
| `remove` | Removes the Node.js header files for the given version
|
||||||
|
|
||||||
|
|
||||||
|
## Command Options
|
||||||
|
|
||||||
|
`node-gyp` accepts the following command options:
|
||||||
|
|
||||||
|
| **Command** | **Description**
|
||||||
|
|:----------------------------------|:------------------------------------------
|
||||||
|
| `-j n`, `--jobs n` | Run `make` in parallel. The value `max` will use all available CPU cores
|
||||||
|
| `--target=v6.2.1` | Node.js version to build for (default is `process.version`)
|
||||||
|
| `--silly`, `--loglevel=silly` | Log all progress to console
|
||||||
|
| `--verbose`, `--loglevel=verbose` | Log most progress to console
|
||||||
|
| `--silent`, `--loglevel=silent` | Don't log anything to console
|
||||||
|
| `debug`, `--debug` | Make Debug build (default is `Release`)
|
||||||
|
| `--release`, `--no-debug` | Make Release build
|
||||||
|
| `-C $dir`, `--directory=$dir` | Run command in different directory
|
||||||
|
| `--make=$make` | Override `make` command (e.g. `gmake`)
|
||||||
|
| `--thin=yes` | Enable thin static libraries
|
||||||
|
| `--arch=$arch` | Set target architecture (e.g. ia32)
|
||||||
|
| `--tarball=$path` | Get headers from a local tarball
|
||||||
|
| `--devdir=$path` | SDK download directory (default is OS cache directory)
|
||||||
|
| `--ensure` | Don't reinstall headers if already present
|
||||||
|
| `--dist-url=$url` | Download header tarball from custom URL
|
||||||
|
| `--proxy=$url` | Set HTTP(S) proxy for downloading header tarball
|
||||||
|
| `--noproxy=$urls` | Set urls to ignore proxies when downloading header tarball
|
||||||
|
| `--cafile=$cafile` | Override default CA chain (to download tarball)
|
||||||
|
| `--nodedir=$path` | Set the path to the node source code
|
||||||
|
| `--python=$path` | Set path to the Python binary
|
||||||
|
| `--msvs_version=$version` | Set Visual Studio version (Windows only)
|
||||||
|
| `--solution=$solution` | Set Visual Studio Solution version (Windows only)
|
||||||
|
| `--force-process-config` | Force using runtime's `process.config` object to generate `config.gypi` file
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### package.json
|
||||||
|
|
||||||
|
Use the `config` object in your package.json with each key in the form `node_gyp_OPTION_NAME`. Any of the command
|
||||||
|
options listed above can be set (dashes in option names should be replaced by underscores).
|
||||||
|
|
||||||
|
For example, to set `devdir` equal to `/tmp/.gyp`, your package.json would contain this:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"node_gyp_devdir": "/tmp/.gyp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Environment variables
|
||||||
|
|
||||||
|
Use the form `npm_package_config_node_gyp_OPTION_NAME` for any of the command options listed
|
||||||
|
above (dashes in option names should be replaced by underscores).
|
||||||
|
|
||||||
|
For example, to set `devdir` equal to `/tmp/.gyp`, you would:
|
||||||
|
|
||||||
|
Run this on Unix:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export npm_package_config_node_gyp_devdir=/tmp/.gyp
|
||||||
|
```
|
||||||
|
|
||||||
|
Or this on Windows:
|
||||||
|
|
||||||
|
```console
|
||||||
|
set npm_package_config_node_gyp_devdir=c:\temp\.gyp
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that in versions of npm before v11 it was possible to use the prefix `npm_config_` for
|
||||||
|
environment variables. This was deprecated in npm@11 and will be removed in npm@12 so it
|
||||||
|
is recommended to convert your environment variables to the above format.
|
||||||
|
|
||||||
|
### `npm` configuration for npm versions before v9
|
||||||
|
|
||||||
|
Use the form `OPTION_NAME` for any of the command options listed above.
|
||||||
|
|
||||||
|
For example, to set `devdir` equal to `/tmp/.gyp`, you would run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm config set [--global] devdir /tmp/.gyp
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:** Configuration set via `npm` will only be used when `node-gyp`
|
||||||
|
is run via `npm`, not when `node-gyp` is run directly.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
`node-gyp` is available under the MIT license. See the [LICENSE
|
||||||
|
file](LICENSE) for details.
|
||||||
2
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/SECURITY.md
generated
vendored
Normal file
2
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/SECURITY.md
generated
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
If you believe you have found a security issue in the software in this
|
||||||
|
repository, please consult https://github.com/nodejs/node/blob/HEAD/SECURITY.md.
|
||||||
204
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/addon.gypi
generated
vendored
Normal file
204
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/addon.gypi
generated
vendored
Normal file
|
|
@ -0,0 +1,204 @@
|
||||||
|
{
|
||||||
|
'variables' : {
|
||||||
|
'node_engine_include_dir%': 'deps/v8/include',
|
||||||
|
'node_host_binary%': 'node',
|
||||||
|
'node_with_ltcg%': 'true',
|
||||||
|
},
|
||||||
|
'target_defaults': {
|
||||||
|
'type': 'loadable_module',
|
||||||
|
'win_delay_load_hook': 'true',
|
||||||
|
'product_prefix': '',
|
||||||
|
|
||||||
|
'conditions': [
|
||||||
|
[ 'node_engine=="chakracore"', {
|
||||||
|
'variables': {
|
||||||
|
'node_engine_include_dir%': 'deps/chakrashim/include'
|
||||||
|
},
|
||||||
|
}]
|
||||||
|
],
|
||||||
|
|
||||||
|
'include_dirs': [
|
||||||
|
'<(node_root_dir)/include/node',
|
||||||
|
'<(node_root_dir)/src',
|
||||||
|
'<(node_root_dir)/deps/openssl/config',
|
||||||
|
'<(node_root_dir)/deps/openssl/openssl/include',
|
||||||
|
'<(node_root_dir)/deps/uv/include',
|
||||||
|
'<(node_root_dir)/deps/zlib',
|
||||||
|
'<(node_root_dir)/<(node_engine_include_dir)'
|
||||||
|
],
|
||||||
|
'defines!': [
|
||||||
|
'BUILDING_UV_SHARED=1', # Inherited from common.gypi.
|
||||||
|
'BUILDING_V8_SHARED=1', # Inherited from common.gypi.
|
||||||
|
],
|
||||||
|
'defines': [
|
||||||
|
'NODE_GYP_MODULE_NAME=>(_target_name)',
|
||||||
|
'USING_UV_SHARED=1',
|
||||||
|
'USING_V8_SHARED=1',
|
||||||
|
# Warn when using deprecated V8 APIs.
|
||||||
|
'V8_DEPRECATION_WARNINGS=1'
|
||||||
|
],
|
||||||
|
|
||||||
|
'target_conditions': [
|
||||||
|
['_type=="loadable_module"', {
|
||||||
|
'product_extension': 'node',
|
||||||
|
'defines': [
|
||||||
|
'BUILDING_NODE_EXTENSION'
|
||||||
|
],
|
||||||
|
'xcode_settings': {
|
||||||
|
'OTHER_LDFLAGS': [
|
||||||
|
'-undefined dynamic_lookup'
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}],
|
||||||
|
|
||||||
|
['_type=="static_library"', {
|
||||||
|
# set to `1` to *disable* the -T thin archive 'ld' flag.
|
||||||
|
# older linkers don't support this flag.
|
||||||
|
'standalone_static_library': '<(standalone_static_library)'
|
||||||
|
}],
|
||||||
|
|
||||||
|
['_type!="executable"', {
|
||||||
|
'conditions': [
|
||||||
|
[ 'OS=="android"', {
|
||||||
|
'cflags!': [ '-fPIE' ],
|
||||||
|
}]
|
||||||
|
]
|
||||||
|
}],
|
||||||
|
|
||||||
|
['_win_delay_load_hook=="true"', {
|
||||||
|
# If the addon specifies `'win_delay_load_hook': 'true'` in its
|
||||||
|
# binding.gyp, link a delay-load hook into the DLL. This hook ensures
|
||||||
|
# that the addon will work regardless of whether the node/iojs binary
|
||||||
|
# is named node.exe, iojs.exe, or something else.
|
||||||
|
'conditions': [
|
||||||
|
[ 'OS=="win"', {
|
||||||
|
'defines': [ 'HOST_BINARY=\"<(node_host_binary)<(EXECUTABLE_SUFFIX)\"', ],
|
||||||
|
'sources': [
|
||||||
|
'<(node_gyp_dir)/src/win_delay_load_hook.cc',
|
||||||
|
],
|
||||||
|
'msvs_settings': {
|
||||||
|
'VCLinkerTool': {
|
||||||
|
'DelayLoadDLLs': [ '<(node_host_binary)<(EXECUTABLE_SUFFIX)' ],
|
||||||
|
# Don't print a linker warning when no imports from either .exe
|
||||||
|
# are used.
|
||||||
|
'AdditionalOptions': [ '/ignore:4199' ],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}],
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
],
|
||||||
|
|
||||||
|
'conditions': [
|
||||||
|
[ 'OS=="mac"', {
|
||||||
|
'defines': [
|
||||||
|
'_DARWIN_USE_64_BIT_INODE=1'
|
||||||
|
],
|
||||||
|
'xcode_settings': {
|
||||||
|
'DYLIB_INSTALL_NAME_BASE': '@rpath'
|
||||||
|
},
|
||||||
|
}],
|
||||||
|
[ 'OS=="aix"', {
|
||||||
|
'ldflags': [
|
||||||
|
'-Wl,-bimport:<(node_exp_file)'
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
[ 'OS=="os400"', {
|
||||||
|
'ldflags': [
|
||||||
|
'-Wl,-bimport:<(node_exp_file)'
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
[ 'OS=="zos"', {
|
||||||
|
'conditions': [
|
||||||
|
[ '"<!(echo $CC)" != "clang" and \
|
||||||
|
"<!(echo $CC)" != "ibm-clang64" and \
|
||||||
|
"<!(echo $CC)" != "ibm-clang"', {
|
||||||
|
'cflags': [
|
||||||
|
'-q64',
|
||||||
|
'-Wc,DLL',
|
||||||
|
'-qlonglong',
|
||||||
|
'-qenum=int',
|
||||||
|
'-qxclang=-fexec-charset=ISO8859-1'
|
||||||
|
],
|
||||||
|
'ldflags': [
|
||||||
|
'-q64',
|
||||||
|
'<(node_exp_file)',
|
||||||
|
],
|
||||||
|
}, {
|
||||||
|
'cflags': [
|
||||||
|
'-m64',
|
||||||
|
],
|
||||||
|
'ldflags': [
|
||||||
|
'-m64',
|
||||||
|
'<(node_exp_file)',
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
],
|
||||||
|
'defines': [
|
||||||
|
'_ALL_SOURCE',
|
||||||
|
'MAP_FAILED=-1',
|
||||||
|
'_UNIX03_SOURCE',
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
[ 'OS=="win"', {
|
||||||
|
'conditions': [
|
||||||
|
['node_engine=="chakracore"', {
|
||||||
|
'library_dirs': [ '<(node_root_dir)/$(ConfigurationName)' ],
|
||||||
|
'libraries': [ '<@(node_engine_libs)' ],
|
||||||
|
}],
|
||||||
|
['node_with_ltcg=="true"', {
|
||||||
|
'msvs_settings': {
|
||||||
|
'VCCLCompilerTool': {
|
||||||
|
'WholeProgramOptimization': 'true' # /GL, whole program optimization, needed for LTCG
|
||||||
|
},
|
||||||
|
'VCLibrarianTool': {
|
||||||
|
'AdditionalOptions': [
|
||||||
|
'/LTCG:INCREMENTAL', # incremental link-time code generation
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'VCLinkerTool': {
|
||||||
|
'OptimizeReferences': 2, # /OPT:REF
|
||||||
|
'EnableCOMDATFolding': 2, # /OPT:ICF
|
||||||
|
'LinkIncremental': 1, # disable incremental linking
|
||||||
|
'AdditionalOptions': [
|
||||||
|
'/LTCG:INCREMENTAL', # incremental link-time code generation
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
],
|
||||||
|
'libraries': [
|
||||||
|
'-lkernel32.lib',
|
||||||
|
'-luser32.lib',
|
||||||
|
'-lgdi32.lib',
|
||||||
|
'-lwinspool.lib',
|
||||||
|
'-lcomdlg32.lib',
|
||||||
|
'-ladvapi32.lib',
|
||||||
|
'-lshell32.lib',
|
||||||
|
'-lole32.lib',
|
||||||
|
'-loleaut32.lib',
|
||||||
|
'-luuid.lib',
|
||||||
|
'-lodbc32.lib',
|
||||||
|
'-ldelayimp.lib',
|
||||||
|
'-l"<(node_lib_file)"'
|
||||||
|
],
|
||||||
|
'msvs_disabled_warnings': [
|
||||||
|
# warning C4251: 'node::ObjectWrap::handle_' : class 'v8::Persistent<T>'
|
||||||
|
# needs to have dll-interface to be used by
|
||||||
|
# clients of class 'node::ObjectWrap'
|
||||||
|
4251
|
||||||
|
],
|
||||||
|
}, {
|
||||||
|
# OS!="win"
|
||||||
|
'defines': [
|
||||||
|
'_LARGEFILE_SOURCE',
|
||||||
|
'_FILE_OFFSET_BITS=64'
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
[ 'OS in "freebsd openbsd netbsd solaris android openharmony" or \
|
||||||
|
(OS=="linux" and target_arch!="ia32")', {
|
||||||
|
'cflags': [ '-fPIC' ],
|
||||||
|
}],
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
145
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/bin/node-gyp.js
generated
vendored
Normal file
145
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/bin/node-gyp.js
generated
vendored
Normal file
|
|
@ -0,0 +1,145 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
process.title = 'node-gyp'
|
||||||
|
|
||||||
|
const envPaths = require('env-paths')
|
||||||
|
const gyp = require('../')
|
||||||
|
const log = require('../lib/log')
|
||||||
|
const os = require('os')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process and execute the selected commands.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const prog = gyp()
|
||||||
|
let completed = false
|
||||||
|
prog.parseArgv(process.argv)
|
||||||
|
prog.devDir = prog.opts.devdir
|
||||||
|
|
||||||
|
const homeDir = os.homedir()
|
||||||
|
if (prog.devDir) {
|
||||||
|
prog.devDir = prog.devDir.replace(/^~/, homeDir)
|
||||||
|
} else if (homeDir) {
|
||||||
|
prog.devDir = envPaths('node-gyp', { suffix: '' }).cache
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
"node-gyp requires that the user's home directory is specified " +
|
||||||
|
'in either of the environmental variables HOME or USERPROFILE. ' +
|
||||||
|
'Overide with: --devdir /path/to/.node-gyp')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prog.todo.length === 0) {
|
||||||
|
if (~process.argv.indexOf('-v') || ~process.argv.indexOf('--version')) {
|
||||||
|
log.stdout('v%s', prog.version)
|
||||||
|
} else {
|
||||||
|
log.stdout('%s', prog.usage())
|
||||||
|
}
|
||||||
|
process.exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info('it worked if it ends with', 'ok')
|
||||||
|
log.verbose('cli', process.argv)
|
||||||
|
log.info('using', 'node-gyp@%s', prog.version)
|
||||||
|
log.info('using', 'node@%s | %s | %s', process.versions.node, process.platform, process.arch)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change dir if -C/--directory was passed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const dir = prog.opts.directory
|
||||||
|
if (dir) {
|
||||||
|
const fs = require('fs')
|
||||||
|
try {
|
||||||
|
const stat = fs.statSync(dir)
|
||||||
|
if (stat.isDirectory()) {
|
||||||
|
log.info('chdir', dir)
|
||||||
|
process.chdir(dir)
|
||||||
|
} else {
|
||||||
|
log.warn('chdir', dir + ' is not a directory')
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (e.code === 'ENOENT') {
|
||||||
|
log.warn('chdir', dir + ' is not a directory')
|
||||||
|
} else {
|
||||||
|
log.warn('chdir', 'error during chdir() "%s"', e.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function run () {
|
||||||
|
const command = prog.todo.shift()
|
||||||
|
if (!command) {
|
||||||
|
// done!
|
||||||
|
completed = true
|
||||||
|
log.info('ok')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const args = await prog.commands[command.name](command.args) ?? []
|
||||||
|
|
||||||
|
if (command.name === 'list') {
|
||||||
|
if (args.length) {
|
||||||
|
args.forEach((version) => log.stdout(version))
|
||||||
|
} else {
|
||||||
|
log.stdout('No node development files installed. Use `node-gyp install` to install a version.')
|
||||||
|
}
|
||||||
|
} else if (args.length >= 1) {
|
||||||
|
log.stdout(...args.slice(1))
|
||||||
|
}
|
||||||
|
|
||||||
|
// now run the next command in the queue
|
||||||
|
return run()
|
||||||
|
} catch (err) {
|
||||||
|
log.error(command.name + ' error')
|
||||||
|
log.error('stack', err.stack)
|
||||||
|
errorMessage()
|
||||||
|
log.error('not ok')
|
||||||
|
return process.exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
process.on('exit', function (code) {
|
||||||
|
if (!completed && !code) {
|
||||||
|
log.error('Completion callback never invoked!')
|
||||||
|
issueMessage()
|
||||||
|
process.exit(6)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
process.on('uncaughtException', function (err) {
|
||||||
|
log.error('UNCAUGHT EXCEPTION')
|
||||||
|
log.error('stack', err.stack)
|
||||||
|
issueMessage()
|
||||||
|
process.exit(7)
|
||||||
|
})
|
||||||
|
|
||||||
|
function errorMessage () {
|
||||||
|
// copied from npm's lib/utils/error-handler.js
|
||||||
|
const os = require('os')
|
||||||
|
log.error('System', os.type() + ' ' + os.release())
|
||||||
|
log.error('command', process.argv
|
||||||
|
.map(JSON.stringify).join(' '))
|
||||||
|
log.error('cwd', process.cwd())
|
||||||
|
log.error('node -v', process.version)
|
||||||
|
log.error('node-gyp -v', 'v' + prog.package.version)
|
||||||
|
// print the npm package version
|
||||||
|
for (const env of ['npm_package_name', 'npm_package_version']) {
|
||||||
|
const value = process.env[env]
|
||||||
|
if (value != null) {
|
||||||
|
log.error(`$${env}`, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function issueMessage () {
|
||||||
|
errorMessage()
|
||||||
|
log.error('', ['Node-gyp failed to build your package.',
|
||||||
|
'Try to update npm and/or node-gyp and if it does not help file an issue with the package author.'
|
||||||
|
].join('\n'))
|
||||||
|
}
|
||||||
|
|
||||||
|
// start running the given commands!
|
||||||
|
run()
|
||||||
3
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/eslint.config.js
generated
vendored
Normal file
3
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/eslint.config.js
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
module.exports = require('neostandard')({})
|
||||||
3
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/.release-please-manifest.json
generated
vendored
Normal file
3
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/.release-please-manifest.json
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
".": "0.21.1"
|
||||||
|
}
|
||||||
28
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/LICENSE
generated
vendored
Normal file
28
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
Copyright (c) 2020 Node.js contributors. All rights reserved.
|
||||||
|
Copyright (c) 2009 Google Inc. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
4
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/data/ninja/build.ninja
generated
vendored
Normal file
4
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/data/ninja/build.ninja
generated
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
rule cc
|
||||||
|
command = cc $in $out
|
||||||
|
|
||||||
|
build my.out: cc my.in
|
||||||
12
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/data/win/large-pdb-shim.cc
generated
vendored
Normal file
12
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/data/win/large-pdb-shim.cc
generated
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
// Copyright (c) 2013 Google Inc. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
// This file is used to generate an empty .pdb -- with a 4KB pagesize -- that is
|
||||||
|
// then used during the final link for modules that have large PDBs. Otherwise,
|
||||||
|
// the linker will generate a pdb with a page size of 1KB, which imposes a limit
|
||||||
|
// of 1GB on the .pdb. By generating an initial empty .pdb with the compiler
|
||||||
|
// (rather than the linker), this limit is avoided. With this in place PDBs may
|
||||||
|
// grow to 2GB.
|
||||||
|
//
|
||||||
|
// This file is referenced by the msvs_large_pdb mechanism in MSVSUtil.py.
|
||||||
116
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/docs/GypVsCMake.md
generated
vendored
Normal file
116
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/docs/GypVsCMake.md
generated
vendored
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
# vs. CMake
|
||||||
|
|
||||||
|
GYP was originally created to generate native IDE project files (Visual Studio, Xcode) for building [Chromium](http://www.chromim.org).
|
||||||
|
|
||||||
|
The functionality of GYP is very similar to the [CMake](http://www.cmake.org)
|
||||||
|
build tool. Bradley Nelson wrote up the following description of why the team
|
||||||
|
created GYP instead of using CMake. The text below is copied from
|
||||||
|
http://www.mail-archive.com/webkit-dev@lists.webkit.org/msg11029.html
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Re: [webkit-dev] CMake as a build system?
|
||||||
|
Bradley Nelson
|
||||||
|
Mon, 19 Apr 2010 22:38:30 -0700
|
||||||
|
|
||||||
|
Here's the innards of an email with a laundry list of stuff I came up with a
|
||||||
|
while back on the gyp-developers list in response to Mike Craddick regarding
|
||||||
|
what motivated gyp's development, since we were aware of cmake at the time
|
||||||
|
(we'd even started a speculative port):
|
||||||
|
|
||||||
|
|
||||||
|
I did an exploratory port of portions of Chromium to cmake (I think I got as
|
||||||
|
far as net, base, sandbox, and part of webkit).
|
||||||
|
There were a number of motivations, not all of which would apply to other
|
||||||
|
projects. Also, some of the design of gyp was informed by experience at
|
||||||
|
Google with large projects built wholly from source, leading to features
|
||||||
|
absent from cmake, but not strictly required for Chromium.
|
||||||
|
|
||||||
|
1. Ability to incrementally transition on Windows. It took us about 6 months
|
||||||
|
to switch fully to gyp. Previous attempts to move to scons had taken a long
|
||||||
|
time and failed, due to the requirement to transition while in flight. For a
|
||||||
|
substantial period of time, we had a hybrid of checked in vcproj and gyp generated
|
||||||
|
vcproj. To this day we still have a good number of GUIDs pinned in the gyp files,
|
||||||
|
because different parts of our release pipeline have leftover assumptions
|
||||||
|
regarding manipulating the raw sln/vcprojs. This transition occurred from
|
||||||
|
the bottom up, largely because modules like base were easier to convert, and
|
||||||
|
had a lower churn rate. During early stages of the transition, the majority
|
||||||
|
of the team wasn't even aware they were using gyp, as it integrated into
|
||||||
|
their existing workflow, and only affected modules that had been converted.
|
||||||
|
|
||||||
|
2. Generation of a more 'normal' vcproj file. Gyp attempts, particularly on
|
||||||
|
Windows, to generate vcprojs which resemble hand generated projects. It
|
||||||
|
doesn't generate any Makefile type projects, but instead produces msvs
|
||||||
|
Custom Build Steps and Custom Build Rules. This makes the resulting projects
|
||||||
|
easier to understand from the IDE and avoids parts of the IDE that simply
|
||||||
|
don't function correctly if you use Makefile projects. Our early hope with
|
||||||
|
gyp was to support the least common denominator of features present in each
|
||||||
|
of the platform specific project file formats, rather than falling back on
|
||||||
|
generated Makefiles/shell scripts to emulate some common abstraction. CMake by
|
||||||
|
comparison makes a good faith attempt to use native project features, but
|
||||||
|
falls back on generated scripts in order to preserve the same semantics on
|
||||||
|
each platforms.
|
||||||
|
|
||||||
|
3. Abstraction on the level of project settings, rather than command line
|
||||||
|
flags. In gyp's syntax you can add nearly any option present in a hand
|
||||||
|
generated xcode/vcproj file. This allows you to use abstractions built into
|
||||||
|
the IDEs rather than reverse engineering them possibly incorrectly for
|
||||||
|
things like: manifest generation, precompiled headers, bundle generation.
|
||||||
|
When somebody wants to use a particular menu option from msvs, I'm able to
|
||||||
|
do a web search on the name of the setting from the IDE and provide them
|
||||||
|
with a gyp stanza that does the equivalent. In many cases, not all project
|
||||||
|
file constructs correspond to command line flags.
|
||||||
|
|
||||||
|
4. Strong notion of module public/private interface. Gyp allows targets to
|
||||||
|
publish a set of direct_dependent_settings, specifying things like
|
||||||
|
include_dirs, defines, platforms specific settings, etc. This means that
|
||||||
|
when module A depends on module B, it automatically acquires the right build
|
||||||
|
settings without module A being filled with assumptions/knowledge of exactly
|
||||||
|
how module B is built. Additionally, all of the transitive dependencies of
|
||||||
|
module B are pulled in. This avoids their being a single top level view of
|
||||||
|
the project, rather each gyp file expresses knowledge about its immediate
|
||||||
|
neighbors. This keep local knowledge local. CMake effectively has a large
|
||||||
|
shared global namespace.
|
||||||
|
|
||||||
|
5. Cross platform generation. CMake is not able to generate all project
|
||||||
|
files on all platforms. For example xcode projects cannot be generated from
|
||||||
|
windows (cmake uses mac specific libraries to do project generation). This
|
||||||
|
means that for instance generating a tarball containing pregenerated
|
||||||
|
projects for all platforms is hard with Cmake (requires distribution to
|
||||||
|
several machine types).
|
||||||
|
|
||||||
|
6. Gyp has rudimentary cross compile support. Currently we've added enough
|
||||||
|
functionality to gyp to support x86 -> arm cross compiles. Last I checked
|
||||||
|
this functionality wasn't present in cmake. (This occurred later).
|
||||||
|
|
||||||
|
|
||||||
|
That being said there are a number of drawbacks currently to gyp:
|
||||||
|
|
||||||
|
1. Because platform specific settings are expressed at the project file
|
||||||
|
level (rather than the command line level). Settings which might otherwise
|
||||||
|
be shared in common between platforms (flags to gcc on mac/linux), end up
|
||||||
|
being repeated twice. Though in fairness there is actually less sharing here
|
||||||
|
than you'd think. include_dirs and defines actually represent 90% of what
|
||||||
|
can be typically shared.
|
||||||
|
|
||||||
|
2. CMake may be more mature, having been applied to a broader range of
|
||||||
|
projects. There a number of 'tool modules' for cmake, which are shared in a
|
||||||
|
common community.
|
||||||
|
|
||||||
|
3. gyp currently makes some nasty assumptions about the availability of
|
||||||
|
chromium's hermetic copy of cygwin on windows. This causes you to either
|
||||||
|
have to special case a number of rules, or swallow this copy of cygwin as a
|
||||||
|
build time dependency.
|
||||||
|
|
||||||
|
4. CMake includes a fairly readable imperative language. Currently Gyp has a
|
||||||
|
somewhat poorly specified declarative language (variable expansion happens
|
||||||
|
in sometimes weird and counter-intuitive ways). In fairness though, gyp assumes
|
||||||
|
that external python scripts can be used as an escape hatch. Also gyp avoids
|
||||||
|
a lot of the things you'd need imperative code for, by having a nice target
|
||||||
|
settings publication mechanism.
|
||||||
|
|
||||||
|
5. (Feature/drawback depending on personal preference). Gyp's syntax is
|
||||||
|
DEEPLY nested. It suffers from all of Lisp's advantages and drawbacks.
|
||||||
|
|
||||||
|
-BradN
|
||||||
|
```
|
||||||
46
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/docs/Hacking.md
generated
vendored
Normal file
46
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/docs/Hacking.md
generated
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
# Hacking
|
||||||
|
|
||||||
|
## Getting the sources
|
||||||
|
|
||||||
|
Git is required to hack on anything, you can set up a git clone of GYP
|
||||||
|
as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir foo
|
||||||
|
cd foo
|
||||||
|
git clone git@github.com:nodejs/gyp-next.git
|
||||||
|
cd gyp
|
||||||
|
```
|
||||||
|
|
||||||
|
(this will clone gyp underneath it into `foo/gyp`.
|
||||||
|
`foo` can be any directory name you want. Once you've done that,
|
||||||
|
you can use the repo like anything other Git repo.
|
||||||
|
|
||||||
|
## Testing your change
|
||||||
|
|
||||||
|
GYP has a suite of tests which you can run with the provided test driver
|
||||||
|
to make sure your changes aren't breaking anything important.
|
||||||
|
|
||||||
|
You run the test driver with e.g.
|
||||||
|
|
||||||
|
``` sh
|
||||||
|
$ python -m pip install --upgrade pip
|
||||||
|
$ pip install --editable ".[dev]"
|
||||||
|
$ python -m pytest
|
||||||
|
```
|
||||||
|
|
||||||
|
See [Testing](Testing.md) for more details on the test framework.
|
||||||
|
|
||||||
|
Note that it can be handy to look at the project files output by the tests
|
||||||
|
to diagnose problems. The easiest way to do that is by kindly asking the
|
||||||
|
test driver to leave the temporary directories it creates in-place.
|
||||||
|
This is done by setting the environment variable "PRESERVE", e.g.
|
||||||
|
|
||||||
|
```
|
||||||
|
set PRESERVE=all # On Windows
|
||||||
|
export PRESERVE=all # On saner platforms.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Reviewing your change
|
||||||
|
|
||||||
|
All changes to GYP must be code reviewed before submission.
|
||||||
1083
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/docs/InputFormatReference.md
generated
vendored
Normal file
1083
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/docs/InputFormatReference.md
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
430
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/docs/LanguageSpecification.md
generated
vendored
Normal file
430
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/docs/LanguageSpecification.md
generated
vendored
Normal file
|
|
@ -0,0 +1,430 @@
|
||||||
|
# Language Specification
|
||||||
|
|
||||||
|
## Objective
|
||||||
|
|
||||||
|
Create a tool for the Chromium project that generates native Visual Studio,
|
||||||
|
Xcode and SCons and/or make build files from a platform-independent input
|
||||||
|
format. Make the input format as reasonably general as possible without
|
||||||
|
spending extra time trying to "get everything right," except where not doing so
|
||||||
|
would likely lead Chromium to an eventual dead end. When in doubt, do what
|
||||||
|
Chromium needs and don't worry about generalizing the solution.
|
||||||
|
|
||||||
|
## Background
|
||||||
|
|
||||||
|
Numerous other projects, both inside and outside Google, have tried to
|
||||||
|
create a simple, universal cross-platform build representation that
|
||||||
|
still allows sufficient per-platform flexibility to accommodate
|
||||||
|
irreconcilable differences. The fact that no obvious working candidate
|
||||||
|
exists that meets Chromium's requirements indicates this is probably a
|
||||||
|
tougher problem than it appears at first glance. We aim to succeed by
|
||||||
|
creating a tool that is highly specific to Chromium's specific use case,
|
||||||
|
not to the general case of design a completely platform-independent tool
|
||||||
|
for expressing any possible build.
|
||||||
|
|
||||||
|
The Mac has the most sophisticated model for application development
|
||||||
|
through an IDE. Consequently, we will use the Xcode model as the
|
||||||
|
starting point (the input file format must handle Chromium's use of
|
||||||
|
Xcode seamlessly) and adapt the design as necessary for the other
|
||||||
|
platforms.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The overall design has the following characteristics:
|
||||||
|
|
||||||
|
* Input configurations are specified in files with the suffix `.gyp`.
|
||||||
|
* Each `.gyp` file specifies how to build the targets for the
|
||||||
|
"component" defined by that file.
|
||||||
|
* Each `.gyp` file generates one or more output files appropriate to
|
||||||
|
the platform:
|
||||||
|
* On Mac, a `.gyp` file generates one Xcode .xcodeproj bundle with
|
||||||
|
information about how its targets are built.
|
||||||
|
* On Windows, a `.gyp` file generates one Visual Studio .sln file,
|
||||||
|
and one Visual Studio .vcproj file per target.
|
||||||
|
* On Linux, a `.gyp` file generates one SCons file and/or one
|
||||||
|
Makefile per target
|
||||||
|
* The `.gyp` file syntax is a Python data structure.
|
||||||
|
* Use of arbitrary Python in `.gyp` files is forbidden.
|
||||||
|
* Use of eval() with restricted globals and locals on `.gyp` file
|
||||||
|
contents restricts the input to an evaluated expression, not
|
||||||
|
arbitrary Python statements.
|
||||||
|
* All input is expected to comply with JSON, with two exceptions:
|
||||||
|
the # character (not inside strings) begins a comment that lasts
|
||||||
|
until the end of the line, and trailing commas are permitted at
|
||||||
|
the end of list and dict contents.
|
||||||
|
* Input data is a dictionary of keywords and values.
|
||||||
|
* "Invalid" keywords on any given data structure are not illegal,
|
||||||
|
they're just ignored.
|
||||||
|
* TODO: providing warnings on use of illegal keywords would help
|
||||||
|
users catch typos. Figure out something nice to do with this.
|
||||||
|
|
||||||
|
## Detailed Design
|
||||||
|
|
||||||
|
Some up-front design principles/thoughts/TODOs:
|
||||||
|
|
||||||
|
* Re-use keywords consistently.
|
||||||
|
* Keywords that allow configuration of a platform-specific concept get
|
||||||
|
prefixed appropriately:
|
||||||
|
* Examples: `msvs_disabled_warnings`, `xcode_framework_dirs`
|
||||||
|
* The input syntax is declarative and data-driven.
|
||||||
|
* This gets enforced by using Python `eval()` (which only evaluates
|
||||||
|
an expression) instead of `exec` (which executes arbitrary python)
|
||||||
|
* Semantic meanings of specific keyword values get deferred until all
|
||||||
|
are read and the configuration is being evaluated to spit out the
|
||||||
|
appropriate file(s)
|
||||||
|
* Source file lists:
|
||||||
|
* Are flat lists. Any imposed ordering within the `.gyp` file (e.g.
|
||||||
|
alphabetically) is purely by convention and for developer
|
||||||
|
convenience. When source files are linked or archived together,
|
||||||
|
it is expected that this will occur in the order that files are
|
||||||
|
listed in the `.gyp` file.
|
||||||
|
* Source file lists contain no mechanism for by-hand folder
|
||||||
|
configuration (`Filter` tags in Visual Studio, `Groups` in Xcode)
|
||||||
|
* A folder hierarchy is created automatically that mirrors the file
|
||||||
|
system
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
'target_defaults': {
|
||||||
|
'defines': [
|
||||||
|
'U_STATIC_IMPLEMENTATION',
|
||||||
|
['LOGFILE', 'foo.log',],
|
||||||
|
],
|
||||||
|
'include_dirs': [
|
||||||
|
'..',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'foo',
|
||||||
|
'type': 'static_library',
|
||||||
|
'sources': [
|
||||||
|
'foo/src/foo.cc',
|
||||||
|
'foo/src/foo_main.cc',
|
||||||
|
],
|
||||||
|
'include_dirs': [
|
||||||
|
'foo',
|
||||||
|
'foo/include',
|
||||||
|
],
|
||||||
|
'conditions': [
|
||||||
|
[ 'OS==mac', { 'sources': [ 'platform_test_mac.mm' ] } ]
|
||||||
|
],
|
||||||
|
'direct_dependent_settings': {
|
||||||
|
'defines': [
|
||||||
|
'UNIT_TEST',
|
||||||
|
],
|
||||||
|
'include_dirs': [
|
||||||
|
'foo',
|
||||||
|
'foo/include',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Structural Elements
|
||||||
|
|
||||||
|
### Top-level Dictionary
|
||||||
|
|
||||||
|
This is the single dictionary in the `.gyp` file that defines the
|
||||||
|
targets and how they're to be built.
|
||||||
|
|
||||||
|
The following keywords are meaningful within the top-level dictionary
|
||||||
|
definition:
|
||||||
|
|
||||||
|
| *Keyword* | *Description* |
|
||||||
|
|:------------------|:------------------|
|
||||||
|
| `conditions` | A conditional section that may contain other items that can be present in a top-level dictionary, on a conditional basis. See the "Conditionals" section below. |
|
||||||
|
| `includes` | A list of `.gypi` files to be included in the top-level dictionary. |
|
||||||
|
| `target_defaults` | A dictionary of default settings to be inherited by all targets in the top-level dictionary. See the "Settings keywords" section below. |
|
||||||
|
| `targets` | A list of target specifications. See the "targets" below. |
|
||||||
|
| `variables` | A dictionary containing variable definitions. Each key in this dictionary is the name of a variable, and each value must be a string value that the variable is to be set to. |
|
||||||
|
|
||||||
|
### targets
|
||||||
|
|
||||||
|
A list of dictionaries defining targets to be built by the files
|
||||||
|
generated from this `.gyp` file.
|
||||||
|
|
||||||
|
Targets may contain `includes`, `conditions`, and `variables` sections
|
||||||
|
as permitted in the root dictionary. The following additional keywords
|
||||||
|
have structural meaning for target definitions:
|
||||||
|
|
||||||
|
| *Keyword* | *Description* |
|
||||||
|
|:---------------------------- |:------------------------------------------|
|
||||||
|
| `actions` | A list of special custom actions to perform on a specific input file, or files, to produce output files. See the "Actions" section below. |
|
||||||
|
| `all_dependent_settings` | A dictionary of settings to be applied to all dependents of the target, transitively. This includes direct dependents and the entire set of their dependents, and so on. This section may contain anything found within a `target` dictionary, except `configurations`, `target_name`, and `type` sections. Compare `direct_dependent_settings` and `link_settings`. |
|
||||||
|
| `configurations` | A list of dictionaries defining build configurations for the target. See the "Configurations" section below. |
|
||||||
|
| `copies` | A list of copy actions to perform. See the "Copies" section below. |
|
||||||
|
| `defines` | A list of preprocessor definitions to be passed on the command line to the C/C++ compiler (via `-D` or `/D` options). |
|
||||||
|
| `dependencies` | A list of targets on which this target depends. Targets in other `.gyp` files are specified as `../path/to/other.gyp:target_we_want`. |
|
||||||
|
| `direct_dependent_settings` | A dictionary of settings to be applied to other targets that depend on this target. These settings will only be applied to direct dependents. This section may contain anything found within a `target` dictionary, except `configurations`, `target_name`, and `type` sections. Compare with `all_dependent_settings` and `link_settings`. |
|
||||||
|
| `include_dirs` | A list of include directories to be passed on the command line to the C/C++ compiler (via `-I` or `/I` options). |
|
||||||
|
| `libraries` | A list of list of libraries (and/or frameworks) on which this target depends. |
|
||||||
|
| `link_settings` | A dictionary of settings to be applied to targets in which this target's contents are linked. `executable` and `shared_library` targets are linkable, so if they depend on a non-linkable target such as a `static_library`, they will adopt its `link_settings`. This section can contain anything found within a `target` dictionary, except `configurations`, `target_name`, and `type` sections. Compare `all_dependent_settings` and `direct_dependent_settings`. |
|
||||||
|
| `rules` | A special custom action to perform on a list of input files, to produce output files. See the "Rules" section below. |
|
||||||
|
| `sources` | A list of source files that are used to build this target or which should otherwise show up in the IDE for this target. In practice, we expect this list to be a union of all files necessary to build the target on all platforms, as well as other related files that aren't actually used for building, like README files. |
|
||||||
|
| `target_conditions` | Like `conditions`, but evaluation is delayed until the settings have been merged into an actual target. `target_conditions` may be used to place conditionals into a `target_defaults` section but have them still depend on specific target settings. |
|
||||||
|
| `target_name` | The name of a target being defined. |
|
||||||
|
| `type` | The type of target being defined. This field currently supports `executable`, `static_library`, `shared_library`, and `none`. The `none` target type is useful when producing output which is not linked. For example, converting raw translation files into resources or documentation into platform specific help files. |
|
||||||
|
| `msvs_props` | A list of Visual Studio property sheets (`.vsprops` files) to be used to build the target. |
|
||||||
|
| `xcode_config_file` | An Xcode configuration (`.xcconfig` file) to be used to build the target. |
|
||||||
|
| `xcode_framework_dirs` | A list of framework directories be used to build the target. |
|
||||||
|
|
||||||
|
You can affect the way that lists/dictionaries are merged together (for
|
||||||
|
example the way a list in target\_defaults interacts with the same named
|
||||||
|
list in the target itself) with a couple of special characters, which
|
||||||
|
are covered in [Merge
|
||||||
|
Basics](InputFormatReference#Merge_Basics_(=,_?,_+).md) and [List
|
||||||
|
Filters](InputFormatReference#List_Filters.md) on the
|
||||||
|
InputFormatReference page.
|
||||||
|
|
||||||
|
### configurations
|
||||||
|
|
||||||
|
`configurations` sections may be found within `targets` or
|
||||||
|
`target_defaults` sections. The `configurations` section is a list of
|
||||||
|
dictionaries specifying different build configurations. Because
|
||||||
|
configurations are implemented as lists, it is not currently possible to
|
||||||
|
override aspects of configurations that are imported into a target from
|
||||||
|
a `target_defaults` section.
|
||||||
|
|
||||||
|
NOTE: It is extremely important that each target within a project define
|
||||||
|
the same set of configurations. This continues to apply even when a
|
||||||
|
project spans across multiple `.gyp` files.
|
||||||
|
|
||||||
|
A configuration dictionary may contain anything that can be found within
|
||||||
|
a target dictionary, except for `actions`, `all_dependent_settings`,
|
||||||
|
`configurations`, `dependencies`, `direct_dependent_settings`,
|
||||||
|
`libraries`, `link_settings`, `sources`, `target_name`, and `type`.
|
||||||
|
|
||||||
|
Configuration dictionaries may also contain these elements:
|
||||||
|
|
||||||
|
| *Keyword* | *Description* |
|
||||||
|
|:---------------------|:----------------------------------------------------|
|
||||||
|
| `configuration_name` | Required attribute. The name of the configuration. |
|
||||||
|
|
||||||
|
### Conditionals
|
||||||
|
|
||||||
|
Conditionals may appear within any dictionary in a `.gyp` file. There
|
||||||
|
are two tpes of conditionals, which differ only in the timing of their
|
||||||
|
processing. `conditions` sections are processed shortly after loading
|
||||||
|
`.gyp` files, and `target_conditions` sections are processed after all
|
||||||
|
dependencies have been computed.
|
||||||
|
|
||||||
|
A conditional section is introduced with a `conditions` or
|
||||||
|
`target_conditions` dictionary keyword, and is composed of a list. Each
|
||||||
|
list contains two or three elements. The first two elements, which are
|
||||||
|
always required, are the conditional expression to evaluate and a
|
||||||
|
dictionary containing settings to merge into the dictionary containing
|
||||||
|
the `conditions` or `target_conditions` section if the expression
|
||||||
|
evaluates to true. The third, optional, list element is a dictionary to
|
||||||
|
merge if the expression evaluates to false.
|
||||||
|
|
||||||
|
The `eval()` of the expression string takes place in the context of
|
||||||
|
global and/or local dictionaries that constructed from the `.gyp` input
|
||||||
|
data, and overrides the `__builtin__` dictionary, to prevent the
|
||||||
|
execution of arbitrary Python code.
|
||||||
|
|
||||||
|
### Actions
|
||||||
|
|
||||||
|
An `actions` section provides a list of custom build actions to perform
|
||||||
|
on inputs, producing outputs. The `actions` section is organized as a
|
||||||
|
list. Each item in the list is a dictionary having the following form:
|
||||||
|
|
||||||
|
| *Keyword* | *Type* | *Description* |
|
||||||
|
|:--------------|:-------|:-----------------------------|
|
||||||
|
| `action_name` | string | The name of the action. Depending on how actions are implemented in the various generators, some may desire or require this property to be set to a unique name; others may ignore this property entirely. |
|
||||||
|
| `inputs` | list | A list of pathnames treated as inputs to the custom action. |
|
||||||
|
| `outputs` | list | A list of pathnames that the custom action produces. |
|
||||||
|
| `action` | list | A command line invocation used to produce `outputs` from `inputs`. For maximum cross-platform compatibility, invocations that require a Python interpreter should be specified with a first element `"python"`. This will enable generators for environments with specialized Python installations to be able to perform the action in an appropriate Python environment. |
|
||||||
|
| `message` | string | A message to be displayed to the user by the build system when the action is run. |
|
||||||
|
|
||||||
|
Build environments will compare `inputs` and `outputs`. If any `output`
|
||||||
|
is missing or is outdated relative to any `input`, the custom action
|
||||||
|
will be invoked. If all `outputs` are present and newer than all
|
||||||
|
`inputs`, the `outputs` are considered up-to-date and the action need
|
||||||
|
not be invoked.
|
||||||
|
|
||||||
|
Actions are implemented in Xcode as shell script build phases performed
|
||||||
|
prior to the compilation phase. In the Visual Studio generator, actions
|
||||||
|
appear files with a `FileConfiguration` containing a custom
|
||||||
|
`VCCustomBuildTool` specifying the remainder of the inputs, the outputs,
|
||||||
|
and the action.
|
||||||
|
|
||||||
|
Combined with variable expansions, actions can be quite powerful. Here
|
||||||
|
is an example action that leverages variable expansions to minimize
|
||||||
|
duplication of pathnames:
|
||||||
|
|
||||||
|
```
|
||||||
|
'sources': [
|
||||||
|
# libraries.cc is generated by the js2c action below.
|
||||||
|
'<(INTERMEDIATE_DIR)/libraries.cc',
|
||||||
|
],
|
||||||
|
'actions': [
|
||||||
|
{
|
||||||
|
'variables': {
|
||||||
|
'core_library_files': [
|
||||||
|
'src/runtime.js',
|
||||||
|
'src/v8natives.js',
|
||||||
|
'src/macros.py',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'action_name': 'js2c',
|
||||||
|
'inputs': [
|
||||||
|
'tools/js2c.py',
|
||||||
|
'<@(core_library_files)',
|
||||||
|
],
|
||||||
|
'outputs': [
|
||||||
|
'<(INTERMEDIATE_DIR)/libraries.cc',
|
||||||
|
'<(INTERMEDIATE_DIR)/libraries-empty.cc',
|
||||||
|
],
|
||||||
|
'action': ['python', 'tools/js2c.py', '<@(_outputs)', 'CORE', '<@(core_library_files)'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rules
|
||||||
|
|
||||||
|
A `rules` section provides custom build action to perform on inputs, producing
|
||||||
|
outputs. The `rules` section is organized as a list. Each item in the list is
|
||||||
|
a dictionary having the following form:
|
||||||
|
|
||||||
|
| *Keyword* | *Type* | *Description* |
|
||||||
|
|:------------|:-------|:-----------------------------------------|
|
||||||
|
| `rule_name` | string | The name of the rule. Depending on how Rules are implemented in the various generators, some may desire or require this property to be set to a unique name; others may ignore this property entirely. |
|
||||||
|
| `extension` | string | All source files of the current target with the given extension will be treated successively as inputs to the rule. |
|
||||||
|
| `inputs` | list | Additional dependencies of the rule. |
|
||||||
|
| `outputs` | list | A list of pathnames that the rule produces. Has access to `RULE_INPUT_` variables (see below). |
|
||||||
|
| `action` | list | A command line invocation used to produce `outputs` from `inputs`. For maximum cross-platform compatibility, invocations that require a Python interpreter should be specified with a first element `"python"`. This will enable generators for environments with specialized Python installations to be able to perform the action in an appropriate Python environment. Has access to `RULE_INPUT_` variables (see below). |
|
||||||
|
| `message` | string | A message to be displayed to the user by the build system when the action is run. Has access to `RULE_INPUT_` variables (see below). |
|
||||||
|
|
||||||
|
There are several variables available to `outputs`, `action`, and `message`.
|
||||||
|
|
||||||
|
| *Variable* | *Description* |
|
||||||
|
|:---------------------|:------------------------------------|
|
||||||
|
| `RULE_INPUT_PATH` | The full path to the current input. |
|
||||||
|
| `RULE_INPUT_DIRNAME` | The directory of the current input. |
|
||||||
|
| `RULE_INPUT_NAME` | The file name of the current input. |
|
||||||
|
| `RULE_INPUT_ROOT` | The file name of the current input without extension. |
|
||||||
|
| `RULE_INPUT_EXT` | The file name extension of the current input. |
|
||||||
|
|
||||||
|
Rules can be thought of as Action generators. For each source selected
|
||||||
|
by `extension` an special action is created. This action starts out with
|
||||||
|
the same `inputs`, `outputs`, `action`, and `message` as the rule. The
|
||||||
|
source is added to the action's `inputs`. The `outputs`, `action`, and
|
||||||
|
`message` are then handled the same but with the additional variables.
|
||||||
|
If the `_output` variable is used in the `action` or `message` the
|
||||||
|
`RULE_INPUT_` variables in `output` will be expanded for the current
|
||||||
|
source.
|
||||||
|
|
||||||
|
### Copies
|
||||||
|
|
||||||
|
A `copies` section provides a simple means of copying files. The
|
||||||
|
`copies` section is organized as a list. Each item in the list is a
|
||||||
|
dictionary having the following form:
|
||||||
|
|
||||||
|
| *Keyword* | *Type* | *Description* |
|
||||||
|
|:--------------|:-------|:------------------------------|
|
||||||
|
| `destination` | string | The directory into which the `files` will be copied. |
|
||||||
|
| `files` | list | A list of files to be copied. |
|
||||||
|
|
||||||
|
The copies will be created in `destination` and have the same file name
|
||||||
|
as the file they are copied from. Even if the `files` are from multiple
|
||||||
|
directories they will all be copied into the `destination` directory.
|
||||||
|
Each `destination` file has an implicit build dependency on the file it
|
||||||
|
is copied from.
|
||||||
|
|
||||||
|
### Generated Xcode .pbxproj Files
|
||||||
|
|
||||||
|
We derive the following things in a `project.pbxproj` plist file within
|
||||||
|
an `.xcodeproj` bundle from the above input file formats as follows:
|
||||||
|
|
||||||
|
* `Group hierarchy`: This is generated in a fixed format with contents
|
||||||
|
derived from the input files. There is no provision for the user to
|
||||||
|
specify additional groups or create a custom hierarchy.
|
||||||
|
* `Configuration group`: This will be used with the
|
||||||
|
`xcode_config_file` property above, if needed.
|
||||||
|
* `Source group`: The union of the `sources` lists of all `targets`
|
||||||
|
after applying appropriate `conditions`. The resulting list is
|
||||||
|
sorted and put into a group hierarchy that matches the layout of
|
||||||
|
the directory tree on disk, with a root of // (the top of the
|
||||||
|
hierarchy).
|
||||||
|
* `Frameworks group`: Taken directly from `libraries` value for the
|
||||||
|
target, after applying appropriate conditions.
|
||||||
|
* `Projects group`: References to other `.xcodeproj` bundles that
|
||||||
|
are needed by the `.xcodeproj` in which the group is contained.
|
||||||
|
* `Products group`: Output from the various targets.
|
||||||
|
* `Project References`:
|
||||||
|
* `Project Configurations`:
|
||||||
|
* Per-`.xcodeproj` file settings are not supported, all settings are
|
||||||
|
applied at the target level.
|
||||||
|
* `Targets`:
|
||||||
|
* `Phases`: Copy sources, link with libraries/frameworks, ...
|
||||||
|
* `Target Configurations`: Specified by input.
|
||||||
|
* `Dependencies`: (local and remote)
|
||||||
|
|
||||||
|
### Generated Visual Studio .vcproj Files
|
||||||
|
|
||||||
|
We derive the following sections in a `.vcproj` file from the above
|
||||||
|
input file formats as follows:
|
||||||
|
|
||||||
|
* `VisualStudioProject`:
|
||||||
|
* `Platforms`:
|
||||||
|
* `ToolFiles`:
|
||||||
|
* `Configurations`:
|
||||||
|
* `Configuration`:
|
||||||
|
* `References`:
|
||||||
|
* `Files`:
|
||||||
|
* `Filter`:
|
||||||
|
* `File`:
|
||||||
|
* `FileConfiguration`:
|
||||||
|
* `Tool`:
|
||||||
|
* `Globals`:
|
||||||
|
|
||||||
|
### Generated Visual Studio .sln Files
|
||||||
|
|
||||||
|
We derive the following sections in a `.sln` file from the above input
|
||||||
|
file formats as follows:
|
||||||
|
|
||||||
|
* `Projects`:
|
||||||
|
* `WebsiteProperties`:
|
||||||
|
* `ProjectDependencies`:
|
||||||
|
* `Global`:
|
||||||
|
* `SolutionConfigurationPlatforms`:
|
||||||
|
* `ProjectConfigurationPlatforms`:
|
||||||
|
* `SolutionProperties`:
|
||||||
|
* `NestedProjects`:
|
||||||
|
|
||||||
|
## Caveats
|
||||||
|
|
||||||
|
Notes/Question from very first prototype draft of the language.
|
||||||
|
Make sure these issues are addressed somewhere before deleting.
|
||||||
|
|
||||||
|
* Libraries are easy, application abstraction is harder
|
||||||
|
* Applications involves resource compilation
|
||||||
|
* Applications involve many inputs
|
||||||
|
* Applications include transitive closure of dependencies
|
||||||
|
* Specific use cases like cc\_library
|
||||||
|
* Mac compiles more than just .c/.cpp files (specifically, .m and .mm
|
||||||
|
files)
|
||||||
|
* Compiler options vary by:
|
||||||
|
* File type
|
||||||
|
* Target type
|
||||||
|
* Individual file
|
||||||
|
* Files may have custom settings per file per platform, but we probably
|
||||||
|
don't care or need to support this in gyp.
|
||||||
|
* Will all linked non-Chromium projects always use the same versions of every
|
||||||
|
subsystem?
|
||||||
|
* Variants are difficult. We've identified the following variants (some
|
||||||
|
specific to Chromium, some typical of other projects in the same ballpark):
|
||||||
|
* Target platform
|
||||||
|
* V8 vs. JSC
|
||||||
|
* Debug vs. Release
|
||||||
|
* Toolchain (VS version, gcc, version)
|
||||||
|
* Host platform
|
||||||
|
* L10N
|
||||||
|
* Vendor
|
||||||
|
* Purify / Valgrind
|
||||||
|
* Will everyone upgrade VS at once?
|
||||||
|
* What does a dylib dependency mean?
|
||||||
27
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/docs/README.md
generated
vendored
Normal file
27
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/docs/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
# Generate Your Projects (gyp-next)
|
||||||
|
|
||||||
|
GYP is a Meta-Build system: a build system that generates other build systems.
|
||||||
|
|
||||||
|
* [User documentation](./UserDocumentation.md)
|
||||||
|
* [Input Format Reference](./InputFormatReference.md)
|
||||||
|
* [Language specification](./LanguageSpecification.md)
|
||||||
|
* [Hacking](./Hacking.md)
|
||||||
|
* [Testing](./Testing.md)
|
||||||
|
* [GYP vs. CMake](./GypVsCMake.md)
|
||||||
|
|
||||||
|
GYP is intended to support large projects that need to be built on multiple
|
||||||
|
platforms (e.g., Mac, Windows, Linux), and where it is important that
|
||||||
|
the project can be built using the IDEs that are popular on each platform
|
||||||
|
as if the project is a "native" one.
|
||||||
|
|
||||||
|
It can be used to generate XCode projects, Visual Studio projects, Ninja
|
||||||
|
build files, and Makefiles. In each case GYP's goal is to replicate as
|
||||||
|
closely as possible the way one would set up a native build of the project
|
||||||
|
using the IDE.
|
||||||
|
|
||||||
|
GYP can also be used to generate "hybrid" projects that provide the IDE
|
||||||
|
scaffolding for a nice user experience but call out to Ninja to do the actual
|
||||||
|
building (which is usually much faster than the native build systems of the
|
||||||
|
IDEs).
|
||||||
|
|
||||||
|
For more information on GYP, click on the links above.
|
||||||
450
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/docs/Testing.md
generated
vendored
Normal file
450
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/docs/Testing.md
generated
vendored
Normal file
|
|
@ -0,0 +1,450 @@
|
||||||
|
# Testing
|
||||||
|
|
||||||
|
NOTE: this document is outdated and needs to be updated. Read with your own discretion.
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
This document describes the GYP testing infrastructure,
|
||||||
|
as provided by the `TestGyp.py` module.
|
||||||
|
|
||||||
|
These tests emphasize testing the _behavior_ of the
|
||||||
|
various GYP-generated build configurations:
|
||||||
|
Visual Studio, Xcode, SCons, Make, etc.
|
||||||
|
The goal is _not_ to test the output of the GYP generators by,
|
||||||
|
for example, comparing a GYP-generated Makefile
|
||||||
|
against a set of known "golden" Makefiles
|
||||||
|
(although the testing infrastructure could
|
||||||
|
be used to write those kinds of tests).
|
||||||
|
The idea is that the generated build configuration files
|
||||||
|
could be completely written to add a feature or fix a bug
|
||||||
|
so long as they continue to support the functional behaviors
|
||||||
|
defined by the tests: building programs, shared libraries, etc.
|
||||||
|
|
||||||
|
## "Hello, world!" GYP test configuration
|
||||||
|
|
||||||
|
Here is an actual test configuration,
|
||||||
|
a simple build of a C program to print `"Hello, world!"`.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ls -l test/hello
|
||||||
|
total 20
|
||||||
|
-rw-r--r-- 1 knight knight 312 Jul 30 20:22 gyptest-all.py
|
||||||
|
-rw-r--r-- 1 knight knight 307 Jul 30 20:22 gyptest-default.py
|
||||||
|
-rwxr-xr-x 1 knight knight 326 Jul 30 20:22 gyptest-target.py
|
||||||
|
-rw-r--r-- 1 knight knight 98 Jul 30 20:22 hello.c
|
||||||
|
-rw-r--r-- 1 knight knight 142 Jul 30 20:22 hello.gyp
|
||||||
|
$
|
||||||
|
```
|
||||||
|
|
||||||
|
The `gyptest-*.py` files are three separate tests (test scripts)
|
||||||
|
that use this configuration. The first one, `gyptest-all.py`,
|
||||||
|
looks like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Verifies simplest-possible build of a "Hello, world!" program
|
||||||
|
using an explicit build target of 'all'.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import TestGyp
|
||||||
|
|
||||||
|
test = TestGyp.TestGyp()
|
||||||
|
|
||||||
|
test.run_gyp('hello.gyp')
|
||||||
|
|
||||||
|
test.build_all('hello.gyp')
|
||||||
|
|
||||||
|
test.run_built_executable('hello', stdout="Hello, world!\n")
|
||||||
|
|
||||||
|
test.pass_test()
|
||||||
|
```
|
||||||
|
|
||||||
|
The test script above runs GYP against the specified input file
|
||||||
|
(`hello.gyp`) to generate a build configuration.
|
||||||
|
It then tries to build the `'all'` target
|
||||||
|
(or its equivalent) using the generated build configuration.
|
||||||
|
Last, it verifies that the build worked as expected
|
||||||
|
by running the executable program (`hello`)
|
||||||
|
that was just presumably built by the generated configuration,
|
||||||
|
and verifies that the output from the program
|
||||||
|
matches the expected `stdout` string (`"Hello, world!\n"`).
|
||||||
|
|
||||||
|
Which configuration is generated
|
||||||
|
(i.e., which build tool to test)
|
||||||
|
is specified when the test is run;
|
||||||
|
see the next section.
|
||||||
|
|
||||||
|
Surrounding the functional parts of the test
|
||||||
|
described above are the header,
|
||||||
|
which should be basically the same for each test
|
||||||
|
(modulo a different description in the docstring):
|
||||||
|
|
||||||
|
```
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Verifies simplest-possible build of a "Hello, world!" program
|
||||||
|
using an explicit build target of 'all'.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import TestGyp
|
||||||
|
|
||||||
|
test = TestGyp.TestGyp()
|
||||||
|
```
|
||||||
|
|
||||||
|
Similarly, the footer should be the same in every test:
|
||||||
|
|
||||||
|
```
|
||||||
|
test.pass_test()
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
Test scripts are run by the `gyptest.py` script.
|
||||||
|
You can specify (an) explicit test script(s) to run:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ python gyptest.py test/hello/gyptest-all.py
|
||||||
|
PYTHONPATH=/home/knight/src/gyp/trunk/test/lib
|
||||||
|
TESTGYP_FORMAT=scons
|
||||||
|
/usr/bin/python test/hello/gyptest-all.py
|
||||||
|
PASSED
|
||||||
|
$
|
||||||
|
```
|
||||||
|
|
||||||
|
If you specify a directory, all test scripts
|
||||||
|
(scripts prefixed with `gyptest-`) underneath
|
||||||
|
the directory will be run:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ python gyptest.py test/hello
|
||||||
|
PYTHONPATH=/home/knight/src/gyp/trunk/test/lib
|
||||||
|
TESTGYP_FORMAT=scons
|
||||||
|
/usr/bin/python test/hello/gyptest-all.py
|
||||||
|
PASSED
|
||||||
|
/usr/bin/python test/hello/gyptest-default.py
|
||||||
|
PASSED
|
||||||
|
/usr/bin/python test/hello/gyptest-target.py
|
||||||
|
PASSED
|
||||||
|
$
|
||||||
|
```
|
||||||
|
|
||||||
|
Or you can specify the `-a` option to run all scripts
|
||||||
|
in the tree:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ python gyptest.py -a
|
||||||
|
PYTHONPATH=/home/knight/src/gyp/trunk/test/lib
|
||||||
|
TESTGYP_FORMAT=scons
|
||||||
|
/usr/bin/python test/configurations/gyptest-configurations.py
|
||||||
|
PASSED
|
||||||
|
/usr/bin/python test/defines/gyptest-defines.py
|
||||||
|
PASSED
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
/usr/bin/python test/variables/gyptest-commands.py
|
||||||
|
PASSED
|
||||||
|
$
|
||||||
|
```
|
||||||
|
|
||||||
|
If any tests fail during the run,
|
||||||
|
the `gyptest.py` script will report them in a
|
||||||
|
summary at the end.
|
||||||
|
|
||||||
|
## Debugging tests
|
||||||
|
|
||||||
|
Tests that create intermediate output do so under the gyp/out/testworkarea
|
||||||
|
directory. On test completion, intermediate output is cleaned up. To preserve
|
||||||
|
this output, set the environment variable PRESERVE=1. This can be handy to
|
||||||
|
inspect intermediate data when debugging a test.
|
||||||
|
|
||||||
|
You can also set PRESERVE\_PASS=1, PRESERVE\_FAIL=1 or PRESERVE\_NO\_RESULT=1
|
||||||
|
to preserve output for tests that fall into one of those categories.
|
||||||
|
|
||||||
|
# Specifying the format (build tool) to use
|
||||||
|
|
||||||
|
By default, the `gyptest.py` script will generate configurations for
|
||||||
|
the "primary" supported build tool for the platform you're on:
|
||||||
|
Visual Studio on Windows,
|
||||||
|
Xcode on Mac,
|
||||||
|
and (currently) SCons on Linux.
|
||||||
|
An alternate format (build tool) may be specified
|
||||||
|
using the `-f` option:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ python gyptest.py -f make test/hello/gyptest-all.py
|
||||||
|
PYTHONPATH=/home/knight/src/gyp/trunk/test/lib
|
||||||
|
TESTGYP_FORMAT=make
|
||||||
|
/usr/bin/python test/hello/gyptest-all.py
|
||||||
|
PASSED
|
||||||
|
$
|
||||||
|
```
|
||||||
|
|
||||||
|
Multiple tools may be specified in a single pass as
|
||||||
|
a comma-separated list:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ python gyptest.py -f make,scons test/hello/gyptest-all.py
|
||||||
|
PYTHONPATH=/home/knight/src/gyp/trunk/test/lib
|
||||||
|
TESTGYP_FORMAT=make
|
||||||
|
/usr/bin/python test/hello/gyptest-all.py
|
||||||
|
PASSED
|
||||||
|
TESTGYP_FORMAT=scons
|
||||||
|
/usr/bin/python test/hello/gyptest-all.py
|
||||||
|
PASSED
|
||||||
|
$
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test script functions and methods
|
||||||
|
|
||||||
|
The `TestGyp` class contains a lot of functionality
|
||||||
|
intended to make it easy to write tests.
|
||||||
|
This section describes the most useful pieces for GYP testing.
|
||||||
|
|
||||||
|
(The `TestGyp` class is actually a subclass of more generic
|
||||||
|
`TestCommon` and `TestCmd` base classes
|
||||||
|
that contain even more functionality than is
|
||||||
|
described here.)
|
||||||
|
|
||||||
|
### Initialization
|
||||||
|
|
||||||
|
The standard initialization formula is:
|
||||||
|
|
||||||
|
```
|
||||||
|
import TestGyp
|
||||||
|
test = TestGyp.TestGyp()
|
||||||
|
```
|
||||||
|
|
||||||
|
This copies the contents of the directory tree in which
|
||||||
|
the test script lives to a temporary directory for execution,
|
||||||
|
and arranges for the temporary directory's removal on exit.
|
||||||
|
|
||||||
|
By default, any comparisons of output or file contents
|
||||||
|
must be exact matches for the test to pass.
|
||||||
|
If you need to use regular expressions for matches,
|
||||||
|
a useful alternative initialization is:
|
||||||
|
|
||||||
|
```
|
||||||
|
import TestGyp
|
||||||
|
test = TestGyp.TestGyp(match = TestGyp.match_re,
|
||||||
|
diff = TestGyp.diff_re)`
|
||||||
|
```
|
||||||
|
|
||||||
|
### Running GYP
|
||||||
|
|
||||||
|
The canonical invocation is to simply specify the `.gyp` file to be executed:
|
||||||
|
|
||||||
|
```
|
||||||
|
test.run_gyp('file.gyp')
|
||||||
|
```
|
||||||
|
|
||||||
|
Additional GYP arguments may be specified:
|
||||||
|
|
||||||
|
```
|
||||||
|
test.run_gyp('file.gyp', arguments=['arg1', 'arg2', ...])
|
||||||
|
```
|
||||||
|
|
||||||
|
To execute GYP from a subdirectory (where, presumably, the specified file
|
||||||
|
lives):
|
||||||
|
|
||||||
|
```
|
||||||
|
test.run_gyp('file.gyp', chdir='subdir')
|
||||||
|
```
|
||||||
|
|
||||||
|
### Running the build tool
|
||||||
|
|
||||||
|
Running the build tool requires passing in a `.gyp` file, which may be used to
|
||||||
|
calculate the name of a specific build configuration file (such as a MSVS
|
||||||
|
solution file corresponding to the `.gyp` file).
|
||||||
|
|
||||||
|
There are several different `.build_*()` methods for invoking different types
|
||||||
|
of builds.
|
||||||
|
|
||||||
|
To invoke a build tool with an explicit `all` target (or equivalent):
|
||||||
|
|
||||||
|
```
|
||||||
|
test.build_all('file.gyp')
|
||||||
|
```
|
||||||
|
|
||||||
|
To invoke a build tool with its default behavior (for example, executing `make`
|
||||||
|
with no targets specified):
|
||||||
|
|
||||||
|
```
|
||||||
|
test.build_default('file.gyp')
|
||||||
|
```
|
||||||
|
|
||||||
|
To invoke a build tool with an explicit specified target:
|
||||||
|
|
||||||
|
```
|
||||||
|
test.build_target('file.gyp', 'target')
|
||||||
|
```
|
||||||
|
|
||||||
|
### Running executables
|
||||||
|
|
||||||
|
The most useful method executes a program built by the GYP-generated
|
||||||
|
configuration:
|
||||||
|
|
||||||
|
```
|
||||||
|
test.run_built_executable('program')
|
||||||
|
```
|
||||||
|
|
||||||
|
The `.run_built_executable()` method will account for the actual built target
|
||||||
|
output location for the build tool being tested, as well as tack on any
|
||||||
|
necessary executable file suffix for the platform (for example `.exe` on
|
||||||
|
Windows).
|
||||||
|
|
||||||
|
`stdout=` and `stderr=` keyword arguments specify expected standard output and
|
||||||
|
error output, respectively. Failure to match these (if specified) will cause
|
||||||
|
the test to fail. An explicit `None` value will suppress that verification:
|
||||||
|
|
||||||
|
```
|
||||||
|
test.run_built_executable('program',
|
||||||
|
stdout="expect this output\n",
|
||||||
|
stderr=None)
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that the default values are `stdout=None` and `stderr=''` (that is, no
|
||||||
|
check for standard output, and error output must be empty).
|
||||||
|
|
||||||
|
Arbitrary executables (not necessarily those built by GYP) can be executed with
|
||||||
|
the lower-level `.run()` method:
|
||||||
|
|
||||||
|
```
|
||||||
|
test.run('program')
|
||||||
|
```
|
||||||
|
|
||||||
|
The program must be in the local directory (that is, the temporary directory
|
||||||
|
for test execution) or be an absolute path name.
|
||||||
|
|
||||||
|
### Fetching command output
|
||||||
|
|
||||||
|
```
|
||||||
|
test.stdout()
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the standard output from the most recent executed command (including
|
||||||
|
`.run_gyp()`, `.build_*()`, or `.run*()` methods).
|
||||||
|
|
||||||
|
```
|
||||||
|
test.stderr()
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the error output from the most recent executed command (including
|
||||||
|
`.run_gyp()`, `.build_*()`, or `.run*()` methods).
|
||||||
|
|
||||||
|
### Verifying existence or non-existence of files or directories
|
||||||
|
|
||||||
|
```
|
||||||
|
test.must_exist('file_or_dir')
|
||||||
|
```
|
||||||
|
|
||||||
|
Verifies that the specified file or directory exists, and fails the test if it
|
||||||
|
doesn't.
|
||||||
|
|
||||||
|
```
|
||||||
|
test.must_not_exist('file_or_dir')
|
||||||
|
```
|
||||||
|
|
||||||
|
Verifies that the specified file or directory does not exist, and fails the
|
||||||
|
test if it does.
|
||||||
|
|
||||||
|
### Verifying file contents
|
||||||
|
|
||||||
|
```
|
||||||
|
test.must_match('file', 'expected content\n')
|
||||||
|
```
|
||||||
|
|
||||||
|
Verifies that the content of the specified file match the expected string, and
|
||||||
|
fails the test if it does not. By default, the match must be exact, but
|
||||||
|
line-by-line regular expressions may be used if the `TestGyp` object was
|
||||||
|
initialized with `TestGyp.match_re`.
|
||||||
|
|
||||||
|
```
|
||||||
|
test.must_not_match('file', 'expected content\n')
|
||||||
|
```
|
||||||
|
|
||||||
|
Verifies that the content of the specified file does _not_ match the expected
|
||||||
|
string, and fails the test if it does. By default, the match must be exact,
|
||||||
|
but line-by-line regular expressions may be used if the `TestGyp` object was
|
||||||
|
initialized with `TestGyp.match_re`.
|
||||||
|
|
||||||
|
```
|
||||||
|
test.must_contain('file', 'substring')
|
||||||
|
```
|
||||||
|
|
||||||
|
Verifies that the specified file contains the specified substring, and fails
|
||||||
|
the test if it does not.
|
||||||
|
|
||||||
|
```
|
||||||
|
test.must_not_contain('file', 'substring')
|
||||||
|
```
|
||||||
|
|
||||||
|
Verifies that the specified file does not contain the specified substring, and
|
||||||
|
fails the test if it does.
|
||||||
|
|
||||||
|
```
|
||||||
|
test.must_contain_all_lines(output, lines)
|
||||||
|
```
|
||||||
|
|
||||||
|
Verifies that the output string contains all of the "lines" in the specified
|
||||||
|
list of lines. In practice, the lines can be any substring and need not be
|
||||||
|
`\n`-terminated lines per se. If any line is missing, the test fails.
|
||||||
|
|
||||||
|
```
|
||||||
|
test.must_not_contain_any_lines(output, lines)
|
||||||
|
```
|
||||||
|
|
||||||
|
Verifies that the output string does _not_ contain any of the "lines" in the
|
||||||
|
specified list of lines. In practice, the lines can be any substring and need
|
||||||
|
not be `\n`-terminated lines per se. If any line exists in the output string,
|
||||||
|
the test fails.
|
||||||
|
|
||||||
|
```
|
||||||
|
test.must_contain_any_line(output, lines)
|
||||||
|
```
|
||||||
|
|
||||||
|
Verifies that the output string contains at least one of the "lines" in the
|
||||||
|
specified list of lines. In practice, the lines can be any substring and need
|
||||||
|
not be `\n`-terminated lines per se. If none of the specified lines is present,
|
||||||
|
the test fails.
|
||||||
|
|
||||||
|
### Reading file contents
|
||||||
|
|
||||||
|
```
|
||||||
|
test.read('file')
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the contents of the specified file. Directory elements contained in a
|
||||||
|
list will be joined:
|
||||||
|
|
||||||
|
```
|
||||||
|
test.read(['subdir', 'file'])
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test success or failure
|
||||||
|
|
||||||
|
```
|
||||||
|
test.fail_test()
|
||||||
|
```
|
||||||
|
|
||||||
|
Fails the test, reporting `FAILED` on standard output and exiting with an exit
|
||||||
|
status of `1`.
|
||||||
|
|
||||||
|
```
|
||||||
|
test.pass_test()
|
||||||
|
```
|
||||||
|
|
||||||
|
Passes the test, reporting `PASSED` on standard output and exiting with an exit
|
||||||
|
status of `0`.
|
||||||
|
|
||||||
|
```
|
||||||
|
test.no_result()
|
||||||
|
```
|
||||||
|
|
||||||
|
Indicates the test had no valid result (i.e., the conditions could not be
|
||||||
|
tested because of an external factor like a full file system). Reports `NO
|
||||||
|
RESULT` on standard output and exits with a status of `2`.
|
||||||
965
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/docs/UserDocumentation.md
generated
vendored
Normal file
965
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/docs/UserDocumentation.md
generated
vendored
Normal file
|
|
@ -0,0 +1,965 @@
|
||||||
|
# User Documentation
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
This document is intended to provide a user-level guide to GYP. The
|
||||||
|
emphasis here is on how to use GYP to accomplish specific tasks, not on
|
||||||
|
the complete technical language specification. (For that, see the
|
||||||
|
[LanguageSpecification](LanguageSpecification.md).)
|
||||||
|
|
||||||
|
The document below starts with some overviews to provide context: an
|
||||||
|
overview of the structure of a `.gyp` file itself, an overview of a
|
||||||
|
typical executable-program target in a `.gyp` file, an an overview of a
|
||||||
|
typical library target in a `.gyp` file.
|
||||||
|
|
||||||
|
After the overviews, there are examples of `gyp` patterns for different
|
||||||
|
common use cases.
|
||||||
|
|
||||||
|
## Skeleton of a typical Chromium .gyp file
|
||||||
|
|
||||||
|
Here is the skeleton of a typical `.gyp` file in the Chromium tree:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
'variables': {
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
},
|
||||||
|
'includes': [
|
||||||
|
'../build/common.gypi',
|
||||||
|
],
|
||||||
|
'target_defaults': {
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
},
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'target_1',
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'target_name': 'target_2',
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'conditions': [
|
||||||
|
['OS=="linux"', {
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'linux_target_3',
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
['OS=="win"', {
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'windows_target_4',
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}, { # OS != "win"
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'non_windows_target_5',
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
},
|
||||||
|
}],
|
||||||
|
],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The entire file just contains a Python dictionary. (It's actually JSON,
|
||||||
|
with two small Pythonic deviations: comments are introduced with `#`,
|
||||||
|
and a `,` (comma)) is legal after the last element in a list or
|
||||||
|
dictionary.)
|
||||||
|
|
||||||
|
The top-level pieces in the `.gyp` file are as follows:
|
||||||
|
|
||||||
|
`'variables'`: Definitions of variables that can be interpolated and
|
||||||
|
used in various other parts of the file.
|
||||||
|
|
||||||
|
`'includes'`: A list of of other files that will be included in this
|
||||||
|
file. By convention, included files have the suffix `.gypi` (gyp
|
||||||
|
include).
|
||||||
|
|
||||||
|
`'target_defaults'`: Settings that will apply to _all_ of the targets
|
||||||
|
defined in this `.gyp` file.
|
||||||
|
|
||||||
|
`'targets'`: The list of targets for which this `.gyp` file can
|
||||||
|
generate builds. Each target is a dictionary that contains settings
|
||||||
|
describing all the information necessary to build the target.
|
||||||
|
|
||||||
|
`'conditions'`: A list of condition specifications that can modify the
|
||||||
|
contents of the items in the global dictionary defined by this `.gyp`
|
||||||
|
file based on the values of different variables. As implied by the
|
||||||
|
above example, the most common use of a `conditions` section in the
|
||||||
|
top-level dictionary is to add platform-specific targets to the
|
||||||
|
`targets` list.
|
||||||
|
|
||||||
|
## Skeleton of a typical executable target in a .gyp file
|
||||||
|
|
||||||
|
The most straightforward target is probably a simple executable program.
|
||||||
|
Here is an example `executable` target that demonstrates the features
|
||||||
|
that should cover most simple uses of gyp:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'foo',
|
||||||
|
'type': 'executable',
|
||||||
|
'msvs_guid': '5ECEC9E5-8F23-47B6-93E0-C3B328B3BE65',
|
||||||
|
'dependencies': [
|
||||||
|
'xyzzy',
|
||||||
|
'../bar/bar.gyp:bar',
|
||||||
|
],
|
||||||
|
'defines': [
|
||||||
|
'DEFINE_FOO',
|
||||||
|
'DEFINE_A_VALUE=value',
|
||||||
|
],
|
||||||
|
'include_dirs': [
|
||||||
|
'..',
|
||||||
|
],
|
||||||
|
'sources': [
|
||||||
|
'file1.cc',
|
||||||
|
'file2.cc',
|
||||||
|
],
|
||||||
|
'conditions': [
|
||||||
|
['OS=="linux"', {
|
||||||
|
'defines': [
|
||||||
|
'LINUX_DEFINE',
|
||||||
|
],
|
||||||
|
'include_dirs': [
|
||||||
|
'include/linux',
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
['OS=="win"', {
|
||||||
|
'defines': [
|
||||||
|
'WINDOWS_SPECIFIC_DEFINE',
|
||||||
|
],
|
||||||
|
}, { # OS != "win",
|
||||||
|
'defines': [
|
||||||
|
'NON_WINDOWS_DEFINE',
|
||||||
|
],
|
||||||
|
}]
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The top-level settings in the target include:
|
||||||
|
|
||||||
|
`'target_name'`: The name by which the target should be known, which
|
||||||
|
should be unique across all `.gyp` files. This name will be used as the
|
||||||
|
project name in the generated Visual Studio solution, as the target name
|
||||||
|
in the generated XCode configuration, and as the alias for building this
|
||||||
|
target from the command line of the generated SCons configuration.
|
||||||
|
|
||||||
|
`'type'`: Set to `executable`, logically enough.
|
||||||
|
|
||||||
|
`'msvs_guid'`: THIS IS ONLY TRANSITIONAL. This is a hard-coded GUID
|
||||||
|
values that will be used in the generated Visual Studio solution
|
||||||
|
file(s). This allows us to check in a `chrome.sln` file that
|
||||||
|
interoperates with gyp-generated project files. Once everything in
|
||||||
|
Chromium is being generated by gyp, it will no longer be important that
|
||||||
|
the GUIDs stay constant across invocations, and we'll likely get rid of
|
||||||
|
these settings,
|
||||||
|
|
||||||
|
`'dependencies'`: This lists other targets that this target depends on.
|
||||||
|
The gyp-generated files will guarantee that the other targets are built
|
||||||
|
before this target. Any library targets in the `dependencies` list will
|
||||||
|
be linked with this target. The various settings (`defines`,
|
||||||
|
`include_dirs`, etc.) listed in the `direct_dependent_settings` sections
|
||||||
|
of the targets in this list will be applied to how _this_ target is
|
||||||
|
built and linked. See the more complete discussion of
|
||||||
|
`direct_dependent_settings`, below.
|
||||||
|
|
||||||
|
`'defines'`: The C preprocessor definitions that will be passed in on
|
||||||
|
compilation command lines (using `-D` or `/D` options).
|
||||||
|
|
||||||
|
`'include_dirs'`: The directories in which included header files live.
|
||||||
|
These will be passed in on compilation command lines (using `-I` or `/I`
|
||||||
|
options).
|
||||||
|
|
||||||
|
`'sources'`: The source files for this target.
|
||||||
|
|
||||||
|
`'conditions'`: A block of conditions that will be evaluated to update
|
||||||
|
the different settings in the target dictionary.
|
||||||
|
|
||||||
|
## Skeleton of a typical library target in a .gyp file
|
||||||
|
|
||||||
|
The vast majority of targets are libraries. Here is an example of a
|
||||||
|
library target including the additional features that should cover most
|
||||||
|
needs of libraries:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'foo',
|
||||||
|
'type': '<(library)'
|
||||||
|
'msvs_guid': '5ECEC9E5-8F23-47B6-93E0-C3B328B3BE65',
|
||||||
|
'dependencies': [
|
||||||
|
'xyzzy',
|
||||||
|
'../bar/bar.gyp:bar',
|
||||||
|
],
|
||||||
|
'defines': [
|
||||||
|
'DEFINE_FOO',
|
||||||
|
'DEFINE_A_VALUE=value',
|
||||||
|
],
|
||||||
|
'include_dirs': [
|
||||||
|
'..',
|
||||||
|
],
|
||||||
|
'direct_dependent_settings': {
|
||||||
|
'defines': [
|
||||||
|
'DEFINE_FOO',
|
||||||
|
'DEFINE_ADDITIONAL',
|
||||||
|
],
|
||||||
|
'linkflags': [
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'export_dependent_settings': [
|
||||||
|
'../bar/bar.gyp:bar',
|
||||||
|
],
|
||||||
|
'sources': [
|
||||||
|
'file1.cc',
|
||||||
|
'file2.cc',
|
||||||
|
],
|
||||||
|
'conditions': [
|
||||||
|
['OS=="linux"', {
|
||||||
|
'defines': [
|
||||||
|
'LINUX_DEFINE',
|
||||||
|
],
|
||||||
|
'include_dirs': [
|
||||||
|
'include/linux',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
['OS=="win"', {
|
||||||
|
'defines': [
|
||||||
|
'WINDOWS_SPECIFIC_DEFINE',
|
||||||
|
],
|
||||||
|
}, { # OS != "win",
|
||||||
|
'defines': [
|
||||||
|
'NON_WINDOWS_DEFINE',
|
||||||
|
],
|
||||||
|
}]
|
||||||
|
],
|
||||||
|
],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The possible entries in a library target are largely the same as those
|
||||||
|
that can be specified for an executable target (`defines`,
|
||||||
|
`include_dirs`, etc.). The differences include:
|
||||||
|
|
||||||
|
`'type'`: This should almost always be set to '<(library)', which allows
|
||||||
|
the user to define at gyp time whether libraries are to be built static
|
||||||
|
or shared. (On Linux, at least, linking with shared libraries saves
|
||||||
|
significant link time.) If it's necessary to pin down the type of
|
||||||
|
library to be built, the `type` can be set explicitly to
|
||||||
|
`static_library` or `shared_library`.
|
||||||
|
|
||||||
|
`'direct_dependent_settings'`: This defines the settings that will be
|
||||||
|
applied to other targets that _directly depend_ on this target--that is,
|
||||||
|
that list _this_ target in their `'dependencies'` setting. This is
|
||||||
|
where you list the `defines`, `include_dirs`, `cflags` and `linkflags`
|
||||||
|
that other targets that compile or link against this target need to
|
||||||
|
build consistently.
|
||||||
|
|
||||||
|
`'export_dependent_settings'`: This lists the targets whose
|
||||||
|
`direct_dependent_settings` should be "passed on" to other targets that
|
||||||
|
use (depend on) this target. `TODO: expand on this description.`
|
||||||
|
|
||||||
|
## Use Cases
|
||||||
|
|
||||||
|
These use cases are intended to cover the most common actions performed
|
||||||
|
by developers using GYP.
|
||||||
|
|
||||||
|
Note that these examples are _not_ fully-functioning, self-contained
|
||||||
|
examples (or else they'd be way too long). Each example mostly contains
|
||||||
|
just the keywords and settings relevant to the example, with perhaps a
|
||||||
|
few extra keywords for context. The intent is to try to show the
|
||||||
|
specific pieces you need to pay attention to when doing something.
|
||||||
|
[NOTE: if practical use shows that these examples are confusing without
|
||||||
|
additional context, please add what's necessary to clarify things.]
|
||||||
|
|
||||||
|
### Add new source files
|
||||||
|
|
||||||
|
There are similar but slightly different patterns for adding a
|
||||||
|
platform-independent source file vs. adding a source file that only
|
||||||
|
builds on some of the supported platforms.
|
||||||
|
|
||||||
|
#### Add a source file that builds on all platforms
|
||||||
|
|
||||||
|
**Simplest possible case**: You are adding a file(s) that builds on all
|
||||||
|
platforms.
|
||||||
|
|
||||||
|
Just add the file(s) to the `sources` list of the appropriate dictionary
|
||||||
|
in the `targets` list:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'my_target',
|
||||||
|
'type': 'executable',
|
||||||
|
'sources': [
|
||||||
|
'../other/file_1.cc',
|
||||||
|
'new_file.cc',
|
||||||
|
'subdir/file3.cc',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
File path names are relative to the directory in which the `.gyp` file lives.
|
||||||
|
|
||||||
|
Keep the list sorted alphabetically (unless there's a really, really,
|
||||||
|
_really_ good reason not to).
|
||||||
|
|
||||||
|
#### Add a platform-specific source file
|
||||||
|
|
||||||
|
##### Your platform-specific file is named `*_linux.{ext}`, `*_mac.{ext}`, `*_posix.{ext}` or `*_win.{ext}`
|
||||||
|
|
||||||
|
The simplest way to add a platform-specific source file, assuming you're
|
||||||
|
adding a completely new file and get to name it, is to use one of the
|
||||||
|
following standard suffixes:
|
||||||
|
|
||||||
|
* `_linux` (e.g. `foo_linux.cc`)
|
||||||
|
* `_mac` (e.g. `foo_mac.cc`)
|
||||||
|
* `_posix` (e.g. `foo_posix.cc`)
|
||||||
|
* `_win` (e.g. `foo_win.cc`)
|
||||||
|
|
||||||
|
Simply add the file to the `sources` list of the appropriate dict within
|
||||||
|
the `targets` list, like you would any other source file.
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'foo',
|
||||||
|
'type': 'executable',
|
||||||
|
'sources': [
|
||||||
|
'independent.cc',
|
||||||
|
'specific_win.cc',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
The Chromium `.gyp` files all have appropriate `conditions` entries to
|
||||||
|
filter out the files that aren't appropriate for the current platform.
|
||||||
|
In the above example, the `specific_win.cc` file will be removed
|
||||||
|
automatically from the source-list on non-Windows builds.
|
||||||
|
|
||||||
|
##### Your platform-specific file does not use an already-defined pattern
|
||||||
|
|
||||||
|
If your platform-specific file does not contain a
|
||||||
|
`*_{linux,mac,posix,win}` substring (or some other pattern that's
|
||||||
|
already in the `conditions` for the target), and you can't change the
|
||||||
|
file name, there are two patterns that can be used.
|
||||||
|
|
||||||
|
**Preferred**: Add the file to the `sources` list of the appropriate
|
||||||
|
dictionary within the `targets` list. Add an appropriate `conditions`
|
||||||
|
section to exclude the specific files name:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'foo',
|
||||||
|
'type': 'executable',
|
||||||
|
'sources': [
|
||||||
|
'linux_specific.cc',
|
||||||
|
],
|
||||||
|
'conditions': [
|
||||||
|
['OS != "linux"', {
|
||||||
|
'sources!': [
|
||||||
|
# Linux-only; exclude on other platforms.
|
||||||
|
'linux_specific.cc',
|
||||||
|
]
|
||||||
|
}[,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
Despite the duplicate listing, the above is generally preferred because
|
||||||
|
the `sources` list contains a useful global list of all sources on all
|
||||||
|
platforms with consistent sorting on all platforms.
|
||||||
|
|
||||||
|
**Non-preferred**: In some situations, however, it might make sense to
|
||||||
|
list a platform-specific file only in a `conditions` section that
|
||||||
|
specifically _includes_ it in the `sources` list:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'foo',
|
||||||
|
'type': 'executable',
|
||||||
|
'sources': [],
|
||||||
|
['OS == "linux"', {
|
||||||
|
'sources': [
|
||||||
|
# Only add to sources list on Linux.
|
||||||
|
'linux_specific.cc',
|
||||||
|
]
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
The above two examples end up generating equivalent builds, with the
|
||||||
|
small exception that the `sources` lists will list the files in
|
||||||
|
different orders. (The first example defines explicitly where
|
||||||
|
`linux_specific.cc` appears in the list--perhaps in in the
|
||||||
|
middle--whereas the second example will always tack it on to the end of
|
||||||
|
the list.)
|
||||||
|
|
||||||
|
**Including or excluding files using patterns**: There are more
|
||||||
|
complicated ways to construct a `sources` list based on patterns. See
|
||||||
|
`TODO` below.
|
||||||
|
|
||||||
|
### Add a new executable
|
||||||
|
|
||||||
|
An executable program is probably the most straightforward type of
|
||||||
|
target, since all it typically needs is a list of source files, some
|
||||||
|
compiler/linker settings (probably varied by platform), and some library
|
||||||
|
targets on which it depends and which must be used in the final link.
|
||||||
|
|
||||||
|
#### Add an executable that builds on all platforms
|
||||||
|
|
||||||
|
Add a dictionary defining the new executable target to the `targets`
|
||||||
|
list in the appropriate `.gyp` file. Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'new_unit_tests',
|
||||||
|
'type': 'executable',
|
||||||
|
'defines': [
|
||||||
|
'FOO',
|
||||||
|
],
|
||||||
|
'include_dirs': [
|
||||||
|
'..',
|
||||||
|
],
|
||||||
|
'dependencies': [
|
||||||
|
'other_target_in_this_file',
|
||||||
|
'other_gyp2:target_in_other_gyp2',
|
||||||
|
],
|
||||||
|
'sources': [
|
||||||
|
'new_additional_source.cc',
|
||||||
|
'new_unit_tests.cc',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Add a platform-specific executable
|
||||||
|
|
||||||
|
Add a dictionary defining the new executable target to the `targets`
|
||||||
|
list within an appropriate `conditions` block for the platform. The
|
||||||
|
`conditions` block should be a sibling to the top-level `targets` list:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
'targets': [
|
||||||
|
],
|
||||||
|
'conditions': [
|
||||||
|
['OS=="win"', {
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'new_unit_tests',
|
||||||
|
'type': 'executable',
|
||||||
|
'defines': [
|
||||||
|
'FOO',
|
||||||
|
],
|
||||||
|
'include_dirs': [
|
||||||
|
'..',
|
||||||
|
],
|
||||||
|
'dependencies': [
|
||||||
|
'other_target_in_this_file',
|
||||||
|
'other_gyp2:target_in_other_gyp2',
|
||||||
|
],
|
||||||
|
'sources': [
|
||||||
|
'new_additional_source.cc',
|
||||||
|
'new_unit_tests.cc',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Add settings to a target
|
||||||
|
|
||||||
|
There are several different types of settings that can be defined for
|
||||||
|
any given target.
|
||||||
|
|
||||||
|
#### Add new preprocessor definitions (`-D` or `/D` flags)
|
||||||
|
|
||||||
|
New preprocessor definitions are added by the `defines` setting:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'existing_target',
|
||||||
|
'defines': [
|
||||||
|
'FOO',
|
||||||
|
'BAR=some_value',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
These may be specified directly in a target's settings, as in the above
|
||||||
|
example, or in a `conditions` section.
|
||||||
|
|
||||||
|
#### Add a new include directory (`-I` or `/I` flags)
|
||||||
|
|
||||||
|
New include directories are added by the `include_dirs` setting:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'existing_target',
|
||||||
|
'include_dirs': [
|
||||||
|
'..',
|
||||||
|
'include',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
These may be specified directly in a target's settings, as in the above
|
||||||
|
example, or in a `conditions` section.
|
||||||
|
|
||||||
|
#### Add new compiler flags
|
||||||
|
|
||||||
|
Specific compiler flags can be added with the `cflags` setting:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'existing_target',
|
||||||
|
'conditions': [
|
||||||
|
['OS=="win"', {
|
||||||
|
'cflags': [
|
||||||
|
'/WX',
|
||||||
|
],
|
||||||
|
}, { # OS != "win"
|
||||||
|
'cflags': [
|
||||||
|
'-Werror',
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
Because these flags will be specific to the actual compiler involved,
|
||||||
|
they will almost always be only set within a `conditions` section.
|
||||||
|
|
||||||
|
#### Add new linker flags
|
||||||
|
|
||||||
|
Setting linker flags is OS-specific. On linux and most non-mac posix
|
||||||
|
systems, they can be added with the `ldflags` setting:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'existing_target',
|
||||||
|
'conditions': [
|
||||||
|
['OS=="linux"', {
|
||||||
|
'ldflags': [
|
||||||
|
'-pthread',
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
Because these flags will be specific to the actual linker involved,
|
||||||
|
they will almost always be only set within a `conditions` section.
|
||||||
|
|
||||||
|
On OS X, linker settings are set via `xcode_settings`, on Windows via
|
||||||
|
`msvs_settings`.
|
||||||
|
|
||||||
|
#### Exclude settings on a platform
|
||||||
|
|
||||||
|
Any given settings keyword (`defines`, `include_dirs`, etc.) has a
|
||||||
|
corresponding form with a trailing `!` (exclamation point) to remove
|
||||||
|
values from a setting. One useful example of this is to remove the
|
||||||
|
Linux `-Werror` flag from the global settings defined in
|
||||||
|
`build/common.gypi`:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'third_party_target',
|
||||||
|
'conditions': [
|
||||||
|
['OS=="linux"', {
|
||||||
|
'cflags!': [
|
||||||
|
'-Werror',
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cross-compiling
|
||||||
|
|
||||||
|
GYP has some (relatively limited) support for cross-compiling.
|
||||||
|
|
||||||
|
If the variable `GYP_CROSSCOMPILE` or one of the toolchain-related
|
||||||
|
variables (like `CC_host` or `CC_target`) is set, GYP will think that
|
||||||
|
you wish to do a cross-compile.
|
||||||
|
|
||||||
|
When cross-compiling, each target can be part of a "host" build, a
|
||||||
|
"target" build, or both. By default, the target is assumed to be (only)
|
||||||
|
part of the "target" build. The 'toolsets' property can be set on a
|
||||||
|
target to change the default.
|
||||||
|
|
||||||
|
A target's dependencies are assumed to match the build type (so, if A
|
||||||
|
depends on B, by default that means that a target build of A depends on
|
||||||
|
a target build of B). You can explicitly depend on targets across
|
||||||
|
toolchains by specifying "#host" or "#target" in the dependencies list.
|
||||||
|
If GYP is not doing a cross-compile, the "#host" and "#target" will be
|
||||||
|
stripped as needed, so nothing breaks.
|
||||||
|
|
||||||
|
### Add a new library
|
||||||
|
|
||||||
|
TODO: write intro
|
||||||
|
|
||||||
|
#### Add a library that builds on all platforms
|
||||||
|
|
||||||
|
Add the a dictionary defining the new library target to the `targets`
|
||||||
|
list in the appropriate `.gyp` file. Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'new_library',
|
||||||
|
'type': '<(library)',
|
||||||
|
'defines': [
|
||||||
|
'FOO',
|
||||||
|
'BAR=some_value',
|
||||||
|
],
|
||||||
|
'include_dirs': [
|
||||||
|
'..',
|
||||||
|
],
|
||||||
|
'dependencies': [
|
||||||
|
'other_target_in_this_file',
|
||||||
|
'other_gyp2:target_in_other_gyp2',
|
||||||
|
],
|
||||||
|
'direct_dependent_settings': {
|
||||||
|
'include_dirs': '.',
|
||||||
|
},
|
||||||
|
'export_dependent_settings': [
|
||||||
|
'other_target_in_this_file',
|
||||||
|
],
|
||||||
|
'sources': [
|
||||||
|
'new_additional_source.cc',
|
||||||
|
'new_library.cc',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The use of the `<(library)` variable above should be the default `type`
|
||||||
|
setting for most library targets, as it allows the developer to choose,
|
||||||
|
at `gyp` time, whether to build with static or shared libraries.
|
||||||
|
(Building with shared libraries saves a _lot_ of link time on Linux.)
|
||||||
|
|
||||||
|
It may be necessary to build a specific library as a fixed type. Is so,
|
||||||
|
the `type` field can be hard-wired appropriately. For a static library:
|
||||||
|
|
||||||
|
```
|
||||||
|
'type': 'static_library',
|
||||||
|
```
|
||||||
|
|
||||||
|
For a shared library:
|
||||||
|
|
||||||
|
```
|
||||||
|
'type': 'shared_library',
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Add a platform-specific library
|
||||||
|
|
||||||
|
Add a dictionary defining the new library target to the `targets` list
|
||||||
|
within a `conditions` block that's a sibling to the top-level `targets`
|
||||||
|
list:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
'targets': [
|
||||||
|
],
|
||||||
|
'conditions': [
|
||||||
|
['OS=="win"', {
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'new_library',
|
||||||
|
'type': '<(library)',
|
||||||
|
'defines': [
|
||||||
|
'FOO',
|
||||||
|
'BAR=some_value',
|
||||||
|
],
|
||||||
|
'include_dirs': [
|
||||||
|
'..',
|
||||||
|
],
|
||||||
|
'dependencies': [
|
||||||
|
'other_target_in_this_file',
|
||||||
|
'other_gyp2:target_in_other_gyp2',
|
||||||
|
],
|
||||||
|
'direct_dependent_settings': {
|
||||||
|
'include_dirs': '.',
|
||||||
|
},
|
||||||
|
'export_dependent_settings': [
|
||||||
|
'other_target_in_this_file',
|
||||||
|
],
|
||||||
|
'sources': [
|
||||||
|
'new_additional_source.cc',
|
||||||
|
'new_library.cc',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dependencies between targets
|
||||||
|
|
||||||
|
GYP provides useful primitives for establishing dependencies between
|
||||||
|
targets, which need to be configured in the following situations.
|
||||||
|
|
||||||
|
#### Linking with another library target
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'foo',
|
||||||
|
'dependencies': [
|
||||||
|
'libbar',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'target_name': 'libbar',
|
||||||
|
'type': '<(library)',
|
||||||
|
'sources': [
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that if the library target is in a different `.gyp` file, you have
|
||||||
|
to specify the path to other `.gyp` file, relative to this `.gyp` file's
|
||||||
|
directory:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'foo',
|
||||||
|
'dependencies': [
|
||||||
|
'../bar/bar.gyp:libbar',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Adding a library often involves updating multiple `.gyp` files, adding
|
||||||
|
the target to the appropriate `.gyp` file (possibly a newly-added `.gyp`
|
||||||
|
file), and updating targets in the other `.gyp` files that depend on
|
||||||
|
(link with) the new library.
|
||||||
|
|
||||||
|
#### Compiling with necessary flags for a library target dependency
|
||||||
|
|
||||||
|
We need to build a library (often a third-party library) with specific
|
||||||
|
preprocessor definitions or command-line flags, and need to ensure that
|
||||||
|
targets that depend on the library build with the same settings. This
|
||||||
|
situation is handled by a `direct_dependent_settings` block:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'foo',
|
||||||
|
'type': 'executable',
|
||||||
|
'dependencies': [
|
||||||
|
'libbar',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'target_name': 'libbar',
|
||||||
|
'type': '<(library)',
|
||||||
|
'defines': [
|
||||||
|
'LOCAL_DEFINE_FOR_LIBBAR',
|
||||||
|
'DEFINE_TO_USE_LIBBAR',
|
||||||
|
],
|
||||||
|
'include_dirs': [
|
||||||
|
'..',
|
||||||
|
'include/libbar',
|
||||||
|
],
|
||||||
|
'direct_dependent_settings': {
|
||||||
|
'defines': [
|
||||||
|
'DEFINE_TO_USE_LIBBAR',
|
||||||
|
],
|
||||||
|
'include_dirs': [
|
||||||
|
'include/libbar',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In the above example, the sources of the `foo` executable will be
|
||||||
|
compiled with the options `-DDEFINE_TO_USE_LIBBAR -Iinclude/libbar`,
|
||||||
|
because of those settings' being listed in the
|
||||||
|
`direct_dependent_settings` block.
|
||||||
|
|
||||||
|
Note that these settings will likely need to be replicated in the
|
||||||
|
settings for the library target itself, so that the library will build
|
||||||
|
with the same options. This does not prevent the target from defining
|
||||||
|
additional options for its "internal" use when compiling its own source
|
||||||
|
files. (In the above example, these are the `LOCAL_DEFINE_FOR_LIBBAR`
|
||||||
|
define, and the `..` entry in the `include_dirs` list.)
|
||||||
|
|
||||||
|
#### When a library depends on an additional library at final link time
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'foo',
|
||||||
|
'type': 'executable',
|
||||||
|
'dependencies': [
|
||||||
|
'libbar',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'target_name': 'libbar',
|
||||||
|
'type': '<(library)',
|
||||||
|
'dependencies': [
|
||||||
|
'libother'
|
||||||
|
],
|
||||||
|
'export_dependent_settings': [
|
||||||
|
'libother'
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'target_name': 'libother',
|
||||||
|
'type': '<(library)',
|
||||||
|
'direct_dependent_settings': {
|
||||||
|
'defines': [
|
||||||
|
'DEFINE_FOR_LIBOTHER',
|
||||||
|
],
|
||||||
|
'include_dirs': [
|
||||||
|
'include/libother',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Support for Mac OS X bundles
|
||||||
|
|
||||||
|
gyp supports building bundles on OS X (.app, .framework, .bundle, etc).
|
||||||
|
Here is an example of this:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
'target_name': 'test_app',
|
||||||
|
'product_name': 'Test App Gyp',
|
||||||
|
'type': 'executable',
|
||||||
|
'mac_bundle': 1,
|
||||||
|
'sources': [
|
||||||
|
'main.m',
|
||||||
|
'TestAppAppDelegate.h',
|
||||||
|
'TestAppAppDelegate.m',
|
||||||
|
],
|
||||||
|
'mac_bundle_resources': [
|
||||||
|
'TestApp/English.lproj/InfoPlist.strings',
|
||||||
|
'TestApp/English.lproj/MainMenu.xib',
|
||||||
|
],
|
||||||
|
'link_settings': {
|
||||||
|
'libraries': [
|
||||||
|
'$(SDKROOT)/System/Library/Frameworks/Cocoa.framework',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'xcode_settings': {
|
||||||
|
'INFOPLIST_FILE': 'TestApp/TestApp-Info.plist',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
The `mac_bundle` key tells gyp that this target should be a bundle.
|
||||||
|
`executable` targets get extension `.app` by default, `shared_library`
|
||||||
|
targets get `.framework` – but you can change the bundle extensions by
|
||||||
|
setting `product_extension` if you want. Files listed in
|
||||||
|
`mac_bundle_resources` will be copied to the bundle's `Resource` folder
|
||||||
|
of the bundle. You can also set
|
||||||
|
`process_outputs_as_mac_bundle_resources` to 1 in actions and rules to
|
||||||
|
let the output of actions and rules be added to that folder (similar to
|
||||||
|
`process_outputs_as_sources`). If `product_name` is not set, the bundle
|
||||||
|
will be named after `target_name`as usual.
|
||||||
|
|
||||||
|
### Move files (refactoring)
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
### Custom build steps
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
#### Adding an explicit build step to generate specific files
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
#### Adding a rule to handle files with a new suffix
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
### Build flavors
|
||||||
|
|
||||||
|
TODO
|
||||||
8
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/gyp
generated
vendored
Normal file
8
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/gyp
generated
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# Copyright 2013 The Chromium Authors. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
base=$(dirname "$0")
|
||||||
|
exec python "${base}/gyp_main.py" "$@"
|
||||||
5
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/gyp.bat
generated
vendored
Normal file
5
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/gyp.bat
generated
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
@rem Copyright (c) 2009 Google Inc. All rights reserved.
|
||||||
|
@rem Use of this source code is governed by a BSD-style license that can be
|
||||||
|
@rem found in the LICENSE file.
|
||||||
|
|
||||||
|
@python "%~dp0gyp_main.py" %*
|
||||||
45
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/gyp_main.py
generated
vendored
Normal file
45
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/gyp_main.py
generated
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Copyright (c) 2009 Google Inc. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def IsCygwin():
|
||||||
|
# Function copied from pylib/gyp/common.py
|
||||||
|
try:
|
||||||
|
out = subprocess.Popen(
|
||||||
|
"uname", stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
||||||
|
)
|
||||||
|
stdout, _ = out.communicate()
|
||||||
|
return "CYGWIN" in stdout.decode("utf-8")
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def UnixifyPath(path):
|
||||||
|
try:
|
||||||
|
if not IsCygwin():
|
||||||
|
return path
|
||||||
|
out = subprocess.Popen(
|
||||||
|
["cygpath", "-u", path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
||||||
|
)
|
||||||
|
stdout, _ = out.communicate()
|
||||||
|
return stdout.decode("utf-8")
|
||||||
|
except Exception:
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
# Make sure we're using the version of pylib in this repo, not one installed
|
||||||
|
# elsewhere on the system. Also convert to Unix style path on Cygwin systems,
|
||||||
|
# else the 'gyp' library will not be found
|
||||||
|
path = UnixifyPath(sys.argv[0])
|
||||||
|
sys.path.insert(0, os.path.join(os.path.dirname(path), "pylib"))
|
||||||
|
import gyp # noqa: E402
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(gyp.script_main())
|
||||||
365
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/MSVSNew.py
generated
vendored
Normal file
365
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/MSVSNew.py
generated
vendored
Normal file
|
|
@ -0,0 +1,365 @@
|
||||||
|
# Copyright (c) 2012 Google Inc. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
"""New implementation of Visual Studio project generation."""
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
import os
|
||||||
|
import random
|
||||||
|
from operator import attrgetter
|
||||||
|
|
||||||
|
import gyp.common
|
||||||
|
|
||||||
|
|
||||||
|
def cmp(x, y):
|
||||||
|
return (x > y) - (x < y)
|
||||||
|
|
||||||
|
|
||||||
|
# Initialize random number generator
|
||||||
|
random.seed()
|
||||||
|
|
||||||
|
# GUIDs for project types
|
||||||
|
ENTRY_TYPE_GUIDS = {
|
||||||
|
"project": "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}",
|
||||||
|
"folder": "{2150E333-8FDC-42A3-9474-1A3956D46DE8}",
|
||||||
|
}
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Helper functions
|
||||||
|
|
||||||
|
|
||||||
|
def MakeGuid(name, seed="msvs_new"):
|
||||||
|
"""Returns a GUID for the specified target name.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: Target name.
|
||||||
|
seed: Seed for SHA-256 hash.
|
||||||
|
Returns:
|
||||||
|
A GUID-line string calculated from the name and seed.
|
||||||
|
|
||||||
|
This generates something which looks like a GUID, but depends only on the
|
||||||
|
name and seed. This means the same name/seed will always generate the same
|
||||||
|
GUID, so that projects and solutions which refer to each other can explicitly
|
||||||
|
determine the GUID to refer to explicitly. It also means that the GUID will
|
||||||
|
not change when the project for a target is rebuilt.
|
||||||
|
"""
|
||||||
|
# Calculate a SHA-256 signature for the seed and name.
|
||||||
|
d = hashlib.sha256((str(seed) + str(name)).encode("utf-8")).hexdigest().upper()
|
||||||
|
# Convert most of the signature to GUID form (discard the rest)
|
||||||
|
guid = (
|
||||||
|
"{"
|
||||||
|
+ d[:8]
|
||||||
|
+ "-"
|
||||||
|
+ d[8:12]
|
||||||
|
+ "-"
|
||||||
|
+ d[12:16]
|
||||||
|
+ "-"
|
||||||
|
+ d[16:20]
|
||||||
|
+ "-"
|
||||||
|
+ d[20:32]
|
||||||
|
+ "}"
|
||||||
|
)
|
||||||
|
return guid
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
class MSVSSolutionEntry:
|
||||||
|
def __cmp__(self, other):
|
||||||
|
# Sort by name then guid (so things are in order on vs2008).
|
||||||
|
return cmp((self.name, self.get_guid()), (other.name, other.get_guid()))
|
||||||
|
|
||||||
|
|
||||||
|
class MSVSFolder(MSVSSolutionEntry):
|
||||||
|
"""Folder in a Visual Studio project or solution."""
|
||||||
|
|
||||||
|
def __init__(self, path, name=None, entries=None, guid=None, items=None):
|
||||||
|
"""Initializes the folder.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
path: Full path to the folder.
|
||||||
|
name: Name of the folder.
|
||||||
|
entries: List of folder entries to nest inside this folder. May contain
|
||||||
|
Folder or Project objects. May be None, if the folder is empty.
|
||||||
|
guid: GUID to use for folder, if not None.
|
||||||
|
items: List of solution items to include in the folder project. May be
|
||||||
|
None, if the folder does not directly contain items.
|
||||||
|
"""
|
||||||
|
if name:
|
||||||
|
self.name = name
|
||||||
|
else:
|
||||||
|
# Use last layer.
|
||||||
|
self.name = os.path.basename(path)
|
||||||
|
|
||||||
|
self.path = path
|
||||||
|
self.guid = guid
|
||||||
|
|
||||||
|
# Copy passed lists (or set to empty lists)
|
||||||
|
self.entries = sorted(entries or [], key=attrgetter("path"))
|
||||||
|
self.items = list(items or [])
|
||||||
|
|
||||||
|
self.entry_type_guid = ENTRY_TYPE_GUIDS["folder"]
|
||||||
|
|
||||||
|
def get_guid(self):
|
||||||
|
if self.guid is None:
|
||||||
|
# Use consistent guids for folders (so things don't regenerate).
|
||||||
|
self.guid = MakeGuid(self.path, seed="msvs_folder")
|
||||||
|
return self.guid
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
class MSVSProject(MSVSSolutionEntry):
|
||||||
|
"""Visual Studio project."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
path,
|
||||||
|
name=None,
|
||||||
|
dependencies=None,
|
||||||
|
guid=None,
|
||||||
|
spec=None,
|
||||||
|
build_file=None,
|
||||||
|
config_platform_overrides=None,
|
||||||
|
fixpath_prefix=None,
|
||||||
|
):
|
||||||
|
"""Initializes the project.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
path: Absolute path to the project file.
|
||||||
|
name: Name of project. If None, the name will be the same as the base
|
||||||
|
name of the project file.
|
||||||
|
dependencies: List of other Project objects this project is dependent
|
||||||
|
upon, if not None.
|
||||||
|
guid: GUID to use for project, if not None.
|
||||||
|
spec: Dictionary specifying how to build this project.
|
||||||
|
build_file: Filename of the .gyp file that the vcproj file comes from.
|
||||||
|
config_platform_overrides: optional dict of configuration platforms to
|
||||||
|
used in place of the default for this target.
|
||||||
|
fixpath_prefix: the path used to adjust the behavior of _fixpath
|
||||||
|
"""
|
||||||
|
self.path = path
|
||||||
|
self.guid = guid
|
||||||
|
self.spec = spec
|
||||||
|
self.build_file = build_file
|
||||||
|
# Use project filename if name not specified
|
||||||
|
self.name = name or os.path.splitext(os.path.basename(path))[0]
|
||||||
|
|
||||||
|
# Copy passed lists (or set to empty lists)
|
||||||
|
self.dependencies = list(dependencies or [])
|
||||||
|
|
||||||
|
self.entry_type_guid = ENTRY_TYPE_GUIDS["project"]
|
||||||
|
|
||||||
|
if config_platform_overrides:
|
||||||
|
self.config_platform_overrides = config_platform_overrides
|
||||||
|
else:
|
||||||
|
self.config_platform_overrides = {}
|
||||||
|
self.fixpath_prefix = fixpath_prefix
|
||||||
|
self.msbuild_toolset = None
|
||||||
|
|
||||||
|
def set_dependencies(self, dependencies):
|
||||||
|
self.dependencies = list(dependencies or [])
|
||||||
|
|
||||||
|
def get_guid(self):
|
||||||
|
if self.guid is None:
|
||||||
|
# Set GUID from path
|
||||||
|
# TODO(rspangler): This is fragile.
|
||||||
|
# 1. We can't just use the project filename sans path, since there could
|
||||||
|
# be multiple projects with the same base name (for example,
|
||||||
|
# foo/unittest.vcproj and bar/unittest.vcproj).
|
||||||
|
# 2. The path needs to be relative to $SOURCE_ROOT, so that the project
|
||||||
|
# GUID is the same whether it's included from base/base.sln or
|
||||||
|
# foo/bar/baz/baz.sln.
|
||||||
|
# 3. The GUID needs to be the same each time this builder is invoked, so
|
||||||
|
# that we don't need to rebuild the solution when the project changes.
|
||||||
|
# 4. We should be able to handle pre-built project files by reading the
|
||||||
|
# GUID from the files.
|
||||||
|
self.guid = MakeGuid(self.name)
|
||||||
|
return self.guid
|
||||||
|
|
||||||
|
def set_msbuild_toolset(self, msbuild_toolset):
|
||||||
|
self.msbuild_toolset = msbuild_toolset
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
class MSVSSolution:
|
||||||
|
"""Visual Studio solution."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self, path, version, entries=None, variants=None, websiteProperties=True
|
||||||
|
):
|
||||||
|
"""Initializes the solution.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
path: Path to solution file.
|
||||||
|
version: Format version to emit.
|
||||||
|
entries: List of entries in solution. May contain Folder or Project
|
||||||
|
objects. May be None, if the folder is empty.
|
||||||
|
variants: List of build variant strings. If none, a default list will
|
||||||
|
be used.
|
||||||
|
websiteProperties: Flag to decide if the website properties section
|
||||||
|
is generated.
|
||||||
|
"""
|
||||||
|
self.path = path
|
||||||
|
self.websiteProperties = websiteProperties
|
||||||
|
self.version = version
|
||||||
|
|
||||||
|
# Copy passed lists (or set to empty lists)
|
||||||
|
self.entries = list(entries or [])
|
||||||
|
|
||||||
|
if variants:
|
||||||
|
# Copy passed list
|
||||||
|
self.variants = variants[:]
|
||||||
|
else:
|
||||||
|
# Use default
|
||||||
|
self.variants = ["Debug|Win32", "Release|Win32"]
|
||||||
|
# TODO(rspangler): Need to be able to handle a mapping of solution config
|
||||||
|
# to project config. Should we be able to handle variants being a dict,
|
||||||
|
# or add a separate variant_map variable? If it's a dict, we can't
|
||||||
|
# guarantee the order of variants since dict keys aren't ordered.
|
||||||
|
|
||||||
|
# TODO(rspangler): Automatically write to disk for now; should delay until
|
||||||
|
# node-evaluation time.
|
||||||
|
self.Write()
|
||||||
|
|
||||||
|
def Write(self, writer=gyp.common.WriteOnDiff):
|
||||||
|
"""Writes the solution file to disk.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
IndexError: An entry appears multiple times.
|
||||||
|
"""
|
||||||
|
# Walk the entry tree and collect all the folders and projects.
|
||||||
|
all_entries = set()
|
||||||
|
entries_to_check = self.entries[:]
|
||||||
|
while entries_to_check:
|
||||||
|
e = entries_to_check.pop(0)
|
||||||
|
|
||||||
|
# If this entry has been visited, nothing to do.
|
||||||
|
if e in all_entries:
|
||||||
|
continue
|
||||||
|
|
||||||
|
all_entries.add(e)
|
||||||
|
|
||||||
|
# If this is a folder, check its entries too.
|
||||||
|
if isinstance(e, MSVSFolder):
|
||||||
|
entries_to_check += e.entries
|
||||||
|
|
||||||
|
all_entries = sorted(all_entries, key=attrgetter("path"))
|
||||||
|
|
||||||
|
# Open file and print header
|
||||||
|
f = writer(self.path)
|
||||||
|
f.write(
|
||||||
|
"Microsoft Visual Studio Solution File, "
|
||||||
|
"Format Version %s\r\n" % self.version.SolutionVersion()
|
||||||
|
)
|
||||||
|
f.write("# %s\r\n" % self.version.Description())
|
||||||
|
|
||||||
|
# Project entries
|
||||||
|
sln_root = os.path.split(self.path)[0]
|
||||||
|
for e in all_entries:
|
||||||
|
relative_path = gyp.common.RelativePath(e.path, sln_root)
|
||||||
|
# msbuild does not accept an empty folder_name.
|
||||||
|
# use '.' in case relative_path is empty.
|
||||||
|
folder_name = relative_path.replace("/", "\\") or "."
|
||||||
|
f.write(
|
||||||
|
'Project("%s") = "%s", "%s", "%s"\r\n'
|
||||||
|
% (
|
||||||
|
e.entry_type_guid, # Entry type GUID
|
||||||
|
e.name, # Folder name
|
||||||
|
folder_name, # Folder name (again)
|
||||||
|
e.get_guid(), # Entry GUID
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# TODO(rspangler): Need a way to configure this stuff
|
||||||
|
if self.websiteProperties:
|
||||||
|
f.write(
|
||||||
|
"\tProjectSection(WebsiteProperties) = preProject\r\n"
|
||||||
|
'\t\tDebug.AspNetCompiler.Debug = "True"\r\n'
|
||||||
|
'\t\tRelease.AspNetCompiler.Debug = "False"\r\n'
|
||||||
|
"\tEndProjectSection\r\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
if isinstance(e, MSVSFolder) and e.items:
|
||||||
|
f.write("\tProjectSection(SolutionItems) = preProject\r\n")
|
||||||
|
for i in e.items:
|
||||||
|
f.write(f"\t\t{i} = {i}\r\n")
|
||||||
|
f.write("\tEndProjectSection\r\n")
|
||||||
|
|
||||||
|
if isinstance(e, MSVSProject) and e.dependencies:
|
||||||
|
f.write("\tProjectSection(ProjectDependencies) = postProject\r\n")
|
||||||
|
for d in e.dependencies:
|
||||||
|
f.write(f"\t\t{d.get_guid()} = {d.get_guid()}\r\n")
|
||||||
|
f.write("\tEndProjectSection\r\n")
|
||||||
|
|
||||||
|
f.write("EndProject\r\n")
|
||||||
|
|
||||||
|
# Global section
|
||||||
|
f.write("Global\r\n")
|
||||||
|
|
||||||
|
# Configurations (variants)
|
||||||
|
f.write("\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\r\n")
|
||||||
|
for v in self.variants:
|
||||||
|
f.write(f"\t\t{v} = {v}\r\n")
|
||||||
|
f.write("\tEndGlobalSection\r\n")
|
||||||
|
|
||||||
|
# Sort config guids for easier diffing of solution changes.
|
||||||
|
config_guids = []
|
||||||
|
config_guids_overrides = {}
|
||||||
|
for e in all_entries:
|
||||||
|
if isinstance(e, MSVSProject):
|
||||||
|
config_guids.append(e.get_guid())
|
||||||
|
config_guids_overrides[e.get_guid()] = e.config_platform_overrides
|
||||||
|
config_guids.sort()
|
||||||
|
|
||||||
|
f.write("\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n")
|
||||||
|
for g in config_guids:
|
||||||
|
for v in self.variants:
|
||||||
|
nv = config_guids_overrides[g].get(v, v)
|
||||||
|
# Pick which project configuration to build for this solution
|
||||||
|
# configuration.
|
||||||
|
f.write(
|
||||||
|
"\t\t%s.%s.ActiveCfg = %s\r\n"
|
||||||
|
% (
|
||||||
|
g, # Project GUID
|
||||||
|
v, # Solution build configuration
|
||||||
|
nv, # Project build config for that solution config
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Enable project in this solution configuration.
|
||||||
|
f.write(
|
||||||
|
"\t\t%s.%s.Build.0 = %s\r\n"
|
||||||
|
% (
|
||||||
|
g, # Project GUID
|
||||||
|
v, # Solution build configuration
|
||||||
|
nv, # Project build config for that solution config
|
||||||
|
)
|
||||||
|
)
|
||||||
|
f.write("\tEndGlobalSection\r\n")
|
||||||
|
|
||||||
|
# TODO(rspangler): Should be able to configure this stuff too (though I've
|
||||||
|
# never seen this be any different)
|
||||||
|
f.write("\tGlobalSection(SolutionProperties) = preSolution\r\n")
|
||||||
|
f.write("\t\tHideSolutionNode = FALSE\r\n")
|
||||||
|
f.write("\tEndGlobalSection\r\n")
|
||||||
|
|
||||||
|
# Folder mappings
|
||||||
|
# Omit this section if there are no folders
|
||||||
|
if any(e.entries for e in all_entries if isinstance(e, MSVSFolder)):
|
||||||
|
f.write("\tGlobalSection(NestedProjects) = preSolution\r\n")
|
||||||
|
for e in all_entries:
|
||||||
|
if not isinstance(e, MSVSFolder):
|
||||||
|
continue # Does not apply to projects, only folders
|
||||||
|
for subentry in e.entries:
|
||||||
|
f.write(f"\t\t{subentry.get_guid()} = {e.get_guid()}\r\n")
|
||||||
|
f.write("\tEndGlobalSection\r\n")
|
||||||
|
|
||||||
|
f.write("EndGlobal\r\n")
|
||||||
|
|
||||||
|
f.close()
|
||||||
206
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/MSVSProject.py
generated
vendored
Normal file
206
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/MSVSProject.py
generated
vendored
Normal file
|
|
@ -0,0 +1,206 @@
|
||||||
|
# Copyright (c) 2012 Google Inc. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
"""Visual Studio project reader/writer."""
|
||||||
|
|
||||||
|
from gyp import easy_xml
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
class Tool:
|
||||||
|
"""Visual Studio tool."""
|
||||||
|
|
||||||
|
def __init__(self, name, attrs=None):
|
||||||
|
"""Initializes the tool.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: Tool name.
|
||||||
|
attrs: Dict of tool attributes; may be None.
|
||||||
|
"""
|
||||||
|
self._attrs = attrs or {}
|
||||||
|
self._attrs["Name"] = name
|
||||||
|
|
||||||
|
def _GetSpecification(self):
|
||||||
|
"""Creates an element for the tool.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A new xml.dom.Element for the tool.
|
||||||
|
"""
|
||||||
|
return ["Tool", self._attrs]
|
||||||
|
|
||||||
|
|
||||||
|
class Filter:
|
||||||
|
"""Visual Studio filter - that is, a virtual folder."""
|
||||||
|
|
||||||
|
def __init__(self, name, contents=None):
|
||||||
|
"""Initializes the folder.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: Filter (folder) name.
|
||||||
|
contents: List of filenames and/or Filter objects contained.
|
||||||
|
"""
|
||||||
|
self.name = name
|
||||||
|
self.contents = list(contents or [])
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
class Writer:
|
||||||
|
"""Visual Studio XML project writer."""
|
||||||
|
|
||||||
|
def __init__(self, project_path, version, name, guid=None, platforms=None):
|
||||||
|
"""Initializes the project.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
project_path: Path to the project file.
|
||||||
|
version: Format version to emit.
|
||||||
|
name: Name of the project.
|
||||||
|
guid: GUID to use for project, if not None.
|
||||||
|
platforms: Array of string, the supported platforms. If null, ['Win32']
|
||||||
|
"""
|
||||||
|
self.project_path = project_path
|
||||||
|
self.version = version
|
||||||
|
self.name = name
|
||||||
|
self.guid = guid
|
||||||
|
|
||||||
|
# Default to Win32 for platforms.
|
||||||
|
if not platforms:
|
||||||
|
platforms = ["Win32"]
|
||||||
|
|
||||||
|
# Initialize the specifications of the various sections.
|
||||||
|
self.platform_section = ["Platforms"]
|
||||||
|
for platform in platforms:
|
||||||
|
self.platform_section.append(["Platform", {"Name": platform}])
|
||||||
|
self.tool_files_section = ["ToolFiles"]
|
||||||
|
self.configurations_section = ["Configurations"]
|
||||||
|
self.files_section = ["Files"]
|
||||||
|
|
||||||
|
# Keep a dict keyed on filename to speed up access.
|
||||||
|
self.files_dict = {}
|
||||||
|
|
||||||
|
def AddToolFile(self, path):
|
||||||
|
"""Adds a tool file to the project.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
path: Relative path from project to tool file.
|
||||||
|
"""
|
||||||
|
self.tool_files_section.append(["ToolFile", {"RelativePath": path}])
|
||||||
|
|
||||||
|
def _GetSpecForConfiguration(self, config_type, config_name, attrs, tools):
|
||||||
|
"""Returns the specification for a configuration.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
config_type: Type of configuration node.
|
||||||
|
config_name: Configuration name.
|
||||||
|
attrs: Dict of configuration attributes; may be None.
|
||||||
|
tools: List of tools (strings or Tool objects); may be None.
|
||||||
|
Returns:
|
||||||
|
"""
|
||||||
|
# Handle defaults
|
||||||
|
if not attrs:
|
||||||
|
attrs = {}
|
||||||
|
if not tools:
|
||||||
|
tools = []
|
||||||
|
|
||||||
|
# Add configuration node and its attributes
|
||||||
|
node_attrs = attrs.copy()
|
||||||
|
node_attrs["Name"] = config_name
|
||||||
|
specification = [config_type, node_attrs]
|
||||||
|
|
||||||
|
# Add tool nodes and their attributes
|
||||||
|
if tools:
|
||||||
|
for t in tools:
|
||||||
|
if isinstance(t, Tool):
|
||||||
|
specification.append(t._GetSpecification())
|
||||||
|
else:
|
||||||
|
specification.append(Tool(t)._GetSpecification())
|
||||||
|
return specification
|
||||||
|
|
||||||
|
def AddConfig(self, name, attrs=None, tools=None):
|
||||||
|
"""Adds a configuration to the project.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: Configuration name.
|
||||||
|
attrs: Dict of configuration attributes; may be None.
|
||||||
|
tools: List of tools (strings or Tool objects); may be None.
|
||||||
|
"""
|
||||||
|
spec = self._GetSpecForConfiguration("Configuration", name, attrs, tools)
|
||||||
|
self.configurations_section.append(spec)
|
||||||
|
|
||||||
|
def _AddFilesToNode(self, parent, files):
|
||||||
|
"""Adds files and/or filters to the parent node.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
parent: Destination node
|
||||||
|
files: A list of Filter objects and/or relative paths to files.
|
||||||
|
|
||||||
|
Will call itself recursively, if the files list contains Filter objects.
|
||||||
|
"""
|
||||||
|
for f in files:
|
||||||
|
if isinstance(f, Filter):
|
||||||
|
node = ["Filter", {"Name": f.name}]
|
||||||
|
self._AddFilesToNode(node, f.contents)
|
||||||
|
else:
|
||||||
|
node = ["File", {"RelativePath": f}]
|
||||||
|
self.files_dict[f] = node
|
||||||
|
parent.append(node)
|
||||||
|
|
||||||
|
def AddFiles(self, files):
|
||||||
|
"""Adds files to the project.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
files: A list of Filter objects and/or relative paths to files.
|
||||||
|
|
||||||
|
This makes a copy of the file/filter tree at the time of this call. If you
|
||||||
|
later add files to a Filter object which was passed into a previous call
|
||||||
|
to AddFiles(), it will not be reflected in this project.
|
||||||
|
"""
|
||||||
|
self._AddFilesToNode(self.files_section, files)
|
||||||
|
# TODO(rspangler) This also doesn't handle adding files to an existing
|
||||||
|
# filter. That is, it doesn't merge the trees.
|
||||||
|
|
||||||
|
def AddFileConfig(self, path, config, attrs=None, tools=None):
|
||||||
|
"""Adds a configuration to a file.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
path: Relative path to the file.
|
||||||
|
config: Name of configuration to add.
|
||||||
|
attrs: Dict of configuration attributes; may be None.
|
||||||
|
tools: List of tools (strings or Tool objects); may be None.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: Relative path does not match any file added via AddFiles().
|
||||||
|
"""
|
||||||
|
# Find the file node with the right relative path
|
||||||
|
parent = self.files_dict.get(path)
|
||||||
|
if not parent:
|
||||||
|
raise ValueError('AddFileConfig: file "%s" not in project.' % path)
|
||||||
|
|
||||||
|
# Add the config to the file node
|
||||||
|
spec = self._GetSpecForConfiguration("FileConfiguration", config, attrs, tools)
|
||||||
|
parent.append(spec)
|
||||||
|
|
||||||
|
def WriteIfChanged(self):
|
||||||
|
"""Writes the project file."""
|
||||||
|
# First create XML content definition
|
||||||
|
content = [
|
||||||
|
"VisualStudioProject",
|
||||||
|
{
|
||||||
|
"ProjectType": "Visual C++",
|
||||||
|
"Version": self.version.ProjectVersion(),
|
||||||
|
"Name": self.name,
|
||||||
|
"ProjectGUID": self.guid,
|
||||||
|
"RootNamespace": self.name,
|
||||||
|
"Keyword": "Win32Proj",
|
||||||
|
},
|
||||||
|
self.platform_section,
|
||||||
|
self.tool_files_section,
|
||||||
|
self.configurations_section,
|
||||||
|
["References"], # empty section
|
||||||
|
self.files_section,
|
||||||
|
["Globals"], # empty section
|
||||||
|
]
|
||||||
|
easy_xml.WriteXmlIfChanged(content, self.project_path, encoding="Windows-1252")
|
||||||
1283
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py
generated
vendored
Normal file
1283
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1545
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings_test.py
generated
vendored
Normal file
1545
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings_test.py
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
59
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/MSVSToolFile.py
generated
vendored
Normal file
59
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/MSVSToolFile.py
generated
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
# Copyright (c) 2012 Google Inc. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
"""Visual Studio project reader/writer."""
|
||||||
|
|
||||||
|
from gyp import easy_xml
|
||||||
|
|
||||||
|
|
||||||
|
class Writer:
|
||||||
|
"""Visual Studio XML tool file writer."""
|
||||||
|
|
||||||
|
def __init__(self, tool_file_path, name):
|
||||||
|
"""Initializes the tool file.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
tool_file_path: Path to the tool file.
|
||||||
|
name: Name of the tool file.
|
||||||
|
"""
|
||||||
|
self.tool_file_path = tool_file_path
|
||||||
|
self.name = name
|
||||||
|
self.rules_section = ["Rules"]
|
||||||
|
|
||||||
|
def AddCustomBuildRule(
|
||||||
|
self, name, cmd, description, additional_dependencies, outputs, extensions
|
||||||
|
):
|
||||||
|
"""Adds a rule to the tool file.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: Name of the rule.
|
||||||
|
description: Description of the rule.
|
||||||
|
cmd: Command line of the rule.
|
||||||
|
additional_dependencies: other files which may trigger the rule.
|
||||||
|
outputs: outputs of the rule.
|
||||||
|
extensions: extensions handled by the rule.
|
||||||
|
"""
|
||||||
|
rule = [
|
||||||
|
"CustomBuildRule",
|
||||||
|
{
|
||||||
|
"Name": name,
|
||||||
|
"ExecutionDescription": description,
|
||||||
|
"CommandLine": cmd,
|
||||||
|
"Outputs": ";".join(outputs),
|
||||||
|
"FileExtensions": ";".join(extensions),
|
||||||
|
"AdditionalDependencies": ";".join(additional_dependencies),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
self.rules_section.append(rule)
|
||||||
|
|
||||||
|
def WriteIfChanged(self):
|
||||||
|
"""Writes the tool file."""
|
||||||
|
content = [
|
||||||
|
"VisualStudioToolFile",
|
||||||
|
{"Version": "8.00", "Name": self.name},
|
||||||
|
self.rules_section,
|
||||||
|
]
|
||||||
|
easy_xml.WriteXmlIfChanged(
|
||||||
|
content, self.tool_file_path, encoding="Windows-1252"
|
||||||
|
)
|
||||||
152
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/MSVSUserFile.py
generated
vendored
Normal file
152
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/MSVSUserFile.py
generated
vendored
Normal file
|
|
@ -0,0 +1,152 @@
|
||||||
|
# Copyright (c) 2012 Google Inc. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
"""Visual Studio user preferences file writer."""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import socket # for gethostname
|
||||||
|
|
||||||
|
from gyp import easy_xml
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
def _FindCommandInPath(command):
|
||||||
|
"""If there are no slashes in the command given, this function
|
||||||
|
searches the PATH env to find the given command, and converts it
|
||||||
|
to an absolute path. We have to do this because MSVS is looking
|
||||||
|
for an actual file to launch a debugger on, not just a command
|
||||||
|
line. Note that this happens at GYP time, so anything needing to
|
||||||
|
be built needs to have a full path."""
|
||||||
|
if "/" in command or "\\" in command:
|
||||||
|
# If the command already has path elements (either relative or
|
||||||
|
# absolute), then assume it is constructed properly.
|
||||||
|
return command
|
||||||
|
else:
|
||||||
|
# Search through the path list and find an existing file that
|
||||||
|
# we can access.
|
||||||
|
paths = os.environ.get("PATH", "").split(os.pathsep)
|
||||||
|
for path in paths:
|
||||||
|
item = os.path.join(path, command)
|
||||||
|
if os.path.isfile(item) and os.access(item, os.X_OK):
|
||||||
|
return item
|
||||||
|
return command
|
||||||
|
|
||||||
|
|
||||||
|
def _QuoteWin32CommandLineArgs(args):
|
||||||
|
new_args = []
|
||||||
|
for arg in args:
|
||||||
|
# Replace all double-quotes with double-double-quotes to escape
|
||||||
|
# them for cmd shell, and then quote the whole thing if there
|
||||||
|
# are any.
|
||||||
|
if arg.find('"') != -1:
|
||||||
|
arg = '""'.join(arg.split('"'))
|
||||||
|
arg = '"%s"' % arg
|
||||||
|
|
||||||
|
# Otherwise, if there are any spaces, quote the whole arg.
|
||||||
|
elif re.search(r"[ \t\n]", arg):
|
||||||
|
arg = '"%s"' % arg
|
||||||
|
new_args.append(arg)
|
||||||
|
return new_args
|
||||||
|
|
||||||
|
|
||||||
|
class Writer:
|
||||||
|
"""Visual Studio XML user user file writer."""
|
||||||
|
|
||||||
|
def __init__(self, user_file_path, version, name):
|
||||||
|
"""Initializes the user file.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user_file_path: Path to the user file.
|
||||||
|
version: Version info.
|
||||||
|
name: Name of the user file.
|
||||||
|
"""
|
||||||
|
self.user_file_path = user_file_path
|
||||||
|
self.version = version
|
||||||
|
self.name = name
|
||||||
|
self.configurations = {}
|
||||||
|
|
||||||
|
def AddConfig(self, name):
|
||||||
|
"""Adds a configuration to the project.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: Configuration name.
|
||||||
|
"""
|
||||||
|
self.configurations[name] = ["Configuration", {"Name": name}]
|
||||||
|
|
||||||
|
def AddDebugSettings(
|
||||||
|
self, config_name, command, environment={}, working_directory=""
|
||||||
|
):
|
||||||
|
"""Adds a DebugSettings node to the user file for a particular config.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
command: command line to run. First element in the list is the
|
||||||
|
executable. All elements of the command will be quoted if
|
||||||
|
necessary.
|
||||||
|
working_directory: other files which may trigger the rule. (optional)
|
||||||
|
"""
|
||||||
|
command = _QuoteWin32CommandLineArgs(command)
|
||||||
|
|
||||||
|
abs_command = _FindCommandInPath(command[0])
|
||||||
|
|
||||||
|
if environment and isinstance(environment, dict):
|
||||||
|
env_list = [f'{key}="{val}"' for (key, val) in environment.items()]
|
||||||
|
environment = " ".join(env_list)
|
||||||
|
else:
|
||||||
|
environment = ""
|
||||||
|
|
||||||
|
n_cmd = [
|
||||||
|
"DebugSettings",
|
||||||
|
{
|
||||||
|
"Command": abs_command,
|
||||||
|
"WorkingDirectory": working_directory,
|
||||||
|
"CommandArguments": " ".join(command[1:]),
|
||||||
|
"RemoteMachine": socket.gethostname(),
|
||||||
|
"Environment": environment,
|
||||||
|
"EnvironmentMerge": "true",
|
||||||
|
# Currently these are all "dummy" values that we're just setting
|
||||||
|
# in the default manner that MSVS does it. We could use some of
|
||||||
|
# these to add additional capabilities, I suppose, but they might
|
||||||
|
# not have parity with other platforms then.
|
||||||
|
"Attach": "false",
|
||||||
|
"DebuggerType": "3", # 'auto' debugger
|
||||||
|
"Remote": "1",
|
||||||
|
"RemoteCommand": "",
|
||||||
|
"HttpUrl": "",
|
||||||
|
"PDBPath": "",
|
||||||
|
"SQLDebugging": "",
|
||||||
|
"DebuggerFlavor": "0",
|
||||||
|
"MPIRunCommand": "",
|
||||||
|
"MPIRunArguments": "",
|
||||||
|
"MPIRunWorkingDirectory": "",
|
||||||
|
"ApplicationCommand": "",
|
||||||
|
"ApplicationArguments": "",
|
||||||
|
"ShimCommand": "",
|
||||||
|
"MPIAcceptMode": "",
|
||||||
|
"MPIAcceptFilter": "",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
# Find the config, and add it if it doesn't exist.
|
||||||
|
if config_name not in self.configurations:
|
||||||
|
self.AddConfig(config_name)
|
||||||
|
|
||||||
|
# Add the DebugSettings onto the appropriate config.
|
||||||
|
self.configurations[config_name].append(n_cmd)
|
||||||
|
|
||||||
|
def WriteIfChanged(self):
|
||||||
|
"""Writes the user file."""
|
||||||
|
configs = ["Configurations"]
|
||||||
|
for config, spec in sorted(self.configurations.items()):
|
||||||
|
configs.append(spec)
|
||||||
|
|
||||||
|
content = [
|
||||||
|
"VisualStudioUserFile",
|
||||||
|
{"Version": self.version.ProjectVersion(), "Name": self.name},
|
||||||
|
configs,
|
||||||
|
]
|
||||||
|
easy_xml.WriteXmlIfChanged(
|
||||||
|
content, self.user_file_path, encoding="Windows-1252"
|
||||||
|
)
|
||||||
270
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/MSVSUtil.py
generated
vendored
Normal file
270
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/MSVSUtil.py
generated
vendored
Normal file
|
|
@ -0,0 +1,270 @@
|
||||||
|
# Copyright (c) 2013 Google Inc. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
"""Utility functions shared amongst the Windows generators."""
|
||||||
|
|
||||||
|
import copy
|
||||||
|
import os
|
||||||
|
|
||||||
|
# A dictionary mapping supported target types to extensions.
|
||||||
|
TARGET_TYPE_EXT = {
|
||||||
|
"executable": "exe",
|
||||||
|
"loadable_module": "dll",
|
||||||
|
"shared_library": "dll",
|
||||||
|
"static_library": "lib",
|
||||||
|
"windows_driver": "sys",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _GetLargePdbShimCcPath():
|
||||||
|
"""Returns the path of the large_pdb_shim.cc file."""
|
||||||
|
this_dir = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
src_dir = os.path.abspath(os.path.join(this_dir, "..", ".."))
|
||||||
|
win_data_dir = os.path.join(src_dir, "data", "win")
|
||||||
|
large_pdb_shim_cc = os.path.join(win_data_dir, "large-pdb-shim.cc")
|
||||||
|
return large_pdb_shim_cc
|
||||||
|
|
||||||
|
|
||||||
|
def _DeepCopySomeKeys(in_dict, keys):
|
||||||
|
"""Performs a partial deep-copy on |in_dict|, only copying the keys in |keys|.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
in_dict: The dictionary to copy.
|
||||||
|
keys: The keys to be copied. If a key is in this list and doesn't exist in
|
||||||
|
|in_dict| this is not an error.
|
||||||
|
Returns:
|
||||||
|
The partially deep-copied dictionary.
|
||||||
|
"""
|
||||||
|
d = {}
|
||||||
|
for key in keys:
|
||||||
|
if key not in in_dict:
|
||||||
|
continue
|
||||||
|
d[key] = copy.deepcopy(in_dict[key])
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
|
def _SuffixName(name, suffix):
|
||||||
|
"""Add a suffix to the end of a target.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
name: name of the target (foo#target)
|
||||||
|
suffix: the suffix to be added
|
||||||
|
Returns:
|
||||||
|
Target name with suffix added (foo_suffix#target)
|
||||||
|
"""
|
||||||
|
parts = name.rsplit("#", 1)
|
||||||
|
parts[0] = f"{parts[0]}_{suffix}"
|
||||||
|
return "#".join(parts)
|
||||||
|
|
||||||
|
|
||||||
|
def _ShardName(name, number):
|
||||||
|
"""Add a shard number to the end of a target.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
name: name of the target (foo#target)
|
||||||
|
number: shard number
|
||||||
|
Returns:
|
||||||
|
Target name with shard added (foo_1#target)
|
||||||
|
"""
|
||||||
|
return _SuffixName(name, str(number))
|
||||||
|
|
||||||
|
|
||||||
|
def ShardTargets(target_list, target_dicts):
|
||||||
|
"""Shard some targets apart to work around the linkers limits.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
target_list: List of target pairs: 'base/base.gyp:base'.
|
||||||
|
target_dicts: Dict of target properties keyed on target pair.
|
||||||
|
Returns:
|
||||||
|
Tuple of the new sharded versions of the inputs.
|
||||||
|
"""
|
||||||
|
# Gather the targets to shard, and how many pieces.
|
||||||
|
targets_to_shard = {}
|
||||||
|
for t in target_dicts:
|
||||||
|
shards = int(target_dicts[t].get("msvs_shard", 0))
|
||||||
|
if shards:
|
||||||
|
targets_to_shard[t] = shards
|
||||||
|
# Shard target_list.
|
||||||
|
new_target_list = []
|
||||||
|
for t in target_list:
|
||||||
|
if t in targets_to_shard:
|
||||||
|
for i in range(targets_to_shard[t]):
|
||||||
|
new_target_list.append(_ShardName(t, i))
|
||||||
|
else:
|
||||||
|
new_target_list.append(t)
|
||||||
|
# Shard target_dict.
|
||||||
|
new_target_dicts = {}
|
||||||
|
for t in target_dicts:
|
||||||
|
if t in targets_to_shard:
|
||||||
|
for i in range(targets_to_shard[t]):
|
||||||
|
name = _ShardName(t, i)
|
||||||
|
new_target_dicts[name] = copy.copy(target_dicts[t])
|
||||||
|
new_target_dicts[name]["target_name"] = _ShardName(
|
||||||
|
new_target_dicts[name]["target_name"], i
|
||||||
|
)
|
||||||
|
sources = new_target_dicts[name].get("sources", [])
|
||||||
|
new_sources = []
|
||||||
|
for pos in range(i, len(sources), targets_to_shard[t]):
|
||||||
|
new_sources.append(sources[pos])
|
||||||
|
new_target_dicts[name]["sources"] = new_sources
|
||||||
|
else:
|
||||||
|
new_target_dicts[t] = target_dicts[t]
|
||||||
|
# Shard dependencies.
|
||||||
|
for t in sorted(new_target_dicts):
|
||||||
|
for deptype in ("dependencies", "dependencies_original"):
|
||||||
|
dependencies = copy.copy(new_target_dicts[t].get(deptype, []))
|
||||||
|
new_dependencies = []
|
||||||
|
for d in dependencies:
|
||||||
|
if d in targets_to_shard:
|
||||||
|
for i in range(targets_to_shard[d]):
|
||||||
|
new_dependencies.append(_ShardName(d, i))
|
||||||
|
else:
|
||||||
|
new_dependencies.append(d)
|
||||||
|
new_target_dicts[t][deptype] = new_dependencies
|
||||||
|
|
||||||
|
return (new_target_list, new_target_dicts)
|
||||||
|
|
||||||
|
|
||||||
|
def _GetPdbPath(target_dict, config_name, vars):
|
||||||
|
"""Returns the path to the PDB file that will be generated by a given
|
||||||
|
configuration.
|
||||||
|
|
||||||
|
The lookup proceeds as follows:
|
||||||
|
- Look for an explicit path in the VCLinkerTool configuration block.
|
||||||
|
- Look for an 'msvs_large_pdb_path' variable.
|
||||||
|
- Use '<(PRODUCT_DIR)/<(product_name).(exe|dll).pdb' if 'product_name' is
|
||||||
|
specified.
|
||||||
|
- Use '<(PRODUCT_DIR)/<(target_name).(exe|dll).pdb'.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
target_dict: The target dictionary to be searched.
|
||||||
|
config_name: The name of the configuration of interest.
|
||||||
|
vars: A dictionary of common GYP variables with generator-specific values.
|
||||||
|
Returns:
|
||||||
|
The path of the corresponding PDB file.
|
||||||
|
"""
|
||||||
|
config = target_dict["configurations"][config_name]
|
||||||
|
msvs = config.setdefault("msvs_settings", {})
|
||||||
|
|
||||||
|
linker = msvs.get("VCLinkerTool", {})
|
||||||
|
|
||||||
|
pdb_path = linker.get("ProgramDatabaseFile")
|
||||||
|
if pdb_path:
|
||||||
|
return pdb_path
|
||||||
|
|
||||||
|
variables = target_dict.get("variables", {})
|
||||||
|
pdb_path = variables.get("msvs_large_pdb_path", None)
|
||||||
|
if pdb_path:
|
||||||
|
return pdb_path
|
||||||
|
|
||||||
|
pdb_base = target_dict.get("product_name", target_dict["target_name"])
|
||||||
|
pdb_base = "{}.{}.pdb".format(pdb_base, TARGET_TYPE_EXT[target_dict["type"]])
|
||||||
|
pdb_path = vars["PRODUCT_DIR"] + "/" + pdb_base
|
||||||
|
|
||||||
|
return pdb_path
|
||||||
|
|
||||||
|
|
||||||
|
def InsertLargePdbShims(target_list, target_dicts, vars):
|
||||||
|
"""Insert a shim target that forces the linker to use 4KB pagesize PDBs.
|
||||||
|
|
||||||
|
This is a workaround for targets with PDBs greater than 1GB in size, the
|
||||||
|
limit for the 1KB pagesize PDBs created by the linker by default.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
target_list: List of target pairs: 'base/base.gyp:base'.
|
||||||
|
target_dicts: Dict of target properties keyed on target pair.
|
||||||
|
vars: A dictionary of common GYP variables with generator-specific values.
|
||||||
|
Returns:
|
||||||
|
Tuple of the shimmed version of the inputs.
|
||||||
|
"""
|
||||||
|
# Determine which targets need shimming.
|
||||||
|
targets_to_shim = []
|
||||||
|
for t in target_dicts:
|
||||||
|
target_dict = target_dicts[t]
|
||||||
|
|
||||||
|
# We only want to shim targets that have msvs_large_pdb enabled.
|
||||||
|
if not int(target_dict.get("msvs_large_pdb", 0)):
|
||||||
|
continue
|
||||||
|
# This is intended for executable, shared_library and loadable_module
|
||||||
|
# targets where every configuration is set up to produce a PDB output.
|
||||||
|
# If any of these conditions is not true then the shim logic will fail
|
||||||
|
# below.
|
||||||
|
targets_to_shim.append(t)
|
||||||
|
|
||||||
|
large_pdb_shim_cc = _GetLargePdbShimCcPath()
|
||||||
|
|
||||||
|
for t in targets_to_shim:
|
||||||
|
target_dict = target_dicts[t]
|
||||||
|
target_name = target_dict.get("target_name")
|
||||||
|
|
||||||
|
base_dict = _DeepCopySomeKeys(
|
||||||
|
target_dict, ["configurations", "default_configuration", "toolset"]
|
||||||
|
)
|
||||||
|
|
||||||
|
# This is the dict for copying the source file (part of the GYP tree)
|
||||||
|
# to the intermediate directory of the project. This is necessary because
|
||||||
|
# we can't always build a relative path to the shim source file (on Windows
|
||||||
|
# GYP and the project may be on different drives), and Ninja hates absolute
|
||||||
|
# paths (it ends up generating the .obj and .obj.d alongside the source
|
||||||
|
# file, polluting GYPs tree).
|
||||||
|
copy_suffix = "large_pdb_copy"
|
||||||
|
copy_target_name = target_name + "_" + copy_suffix
|
||||||
|
full_copy_target_name = _SuffixName(t, copy_suffix)
|
||||||
|
shim_cc_basename = os.path.basename(large_pdb_shim_cc)
|
||||||
|
shim_cc_dir = vars["SHARED_INTERMEDIATE_DIR"] + "/" + copy_target_name
|
||||||
|
shim_cc_path = shim_cc_dir + "/" + shim_cc_basename
|
||||||
|
copy_dict = copy.deepcopy(base_dict)
|
||||||
|
copy_dict["target_name"] = copy_target_name
|
||||||
|
copy_dict["type"] = "none"
|
||||||
|
copy_dict["sources"] = [large_pdb_shim_cc]
|
||||||
|
copy_dict["copies"] = [
|
||||||
|
{"destination": shim_cc_dir, "files": [large_pdb_shim_cc]}
|
||||||
|
]
|
||||||
|
|
||||||
|
# This is the dict for the PDB generating shim target. It depends on the
|
||||||
|
# copy target.
|
||||||
|
shim_suffix = "large_pdb_shim"
|
||||||
|
shim_target_name = target_name + "_" + shim_suffix
|
||||||
|
full_shim_target_name = _SuffixName(t, shim_suffix)
|
||||||
|
shim_dict = copy.deepcopy(base_dict)
|
||||||
|
shim_dict["target_name"] = shim_target_name
|
||||||
|
shim_dict["type"] = "static_library"
|
||||||
|
shim_dict["sources"] = [shim_cc_path]
|
||||||
|
shim_dict["dependencies"] = [full_copy_target_name]
|
||||||
|
|
||||||
|
# Set up the shim to output its PDB to the same location as the final linker
|
||||||
|
# target.
|
||||||
|
for config_name, config in shim_dict.get("configurations").items():
|
||||||
|
pdb_path = _GetPdbPath(target_dict, config_name, vars)
|
||||||
|
|
||||||
|
# A few keys that we don't want to propagate.
|
||||||
|
for key in ["msvs_precompiled_header", "msvs_precompiled_source", "test"]:
|
||||||
|
config.pop(key, None)
|
||||||
|
|
||||||
|
msvs = config.setdefault("msvs_settings", {})
|
||||||
|
|
||||||
|
# Update the compiler directives in the shim target.
|
||||||
|
compiler = msvs.setdefault("VCCLCompilerTool", {})
|
||||||
|
compiler["DebugInformationFormat"] = "3"
|
||||||
|
compiler["ProgramDataBaseFileName"] = pdb_path
|
||||||
|
|
||||||
|
# Set the explicit PDB path in the appropriate configuration of the
|
||||||
|
# original target.
|
||||||
|
config = target_dict["configurations"][config_name]
|
||||||
|
msvs = config.setdefault("msvs_settings", {})
|
||||||
|
linker = msvs.setdefault("VCLinkerTool", {})
|
||||||
|
linker["GenerateDebugInformation"] = "true"
|
||||||
|
linker["ProgramDatabaseFile"] = pdb_path
|
||||||
|
|
||||||
|
# Add the new targets. They must go to the beginning of the list so that
|
||||||
|
# the dependency generation works as expected in ninja.
|
||||||
|
target_list.insert(0, full_copy_target_name)
|
||||||
|
target_list.insert(0, full_shim_target_name)
|
||||||
|
target_dicts[full_copy_target_name] = copy_dict
|
||||||
|
target_dicts[full_shim_target_name] = shim_dict
|
||||||
|
|
||||||
|
# Update the original target to depend on the shim target.
|
||||||
|
target_dict.setdefault("dependencies", []).append(full_shim_target_name)
|
||||||
|
|
||||||
|
return (target_list, target_dicts)
|
||||||
599
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/MSVSVersion.py
generated
vendored
Normal file
599
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/MSVSVersion.py
generated
vendored
Normal file
|
|
@ -0,0 +1,599 @@
|
||||||
|
# Copyright (c) 2013 Google Inc. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
"""Handle version information related to Visual Stuio."""
|
||||||
|
|
||||||
|
import errno
|
||||||
|
import glob
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def JoinPath(*args):
|
||||||
|
return os.path.normpath(os.path.join(*args))
|
||||||
|
|
||||||
|
|
||||||
|
class VisualStudioVersion:
|
||||||
|
"""Information regarding a version of Visual Studio."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
short_name,
|
||||||
|
description,
|
||||||
|
solution_version,
|
||||||
|
project_version,
|
||||||
|
flat_sln,
|
||||||
|
uses_vcxproj,
|
||||||
|
path,
|
||||||
|
sdk_based,
|
||||||
|
default_toolset=None,
|
||||||
|
compatible_sdks=None,
|
||||||
|
):
|
||||||
|
self.short_name = short_name
|
||||||
|
self.description = description
|
||||||
|
self.solution_version = solution_version
|
||||||
|
self.project_version = project_version
|
||||||
|
self.flat_sln = flat_sln
|
||||||
|
self.uses_vcxproj = uses_vcxproj
|
||||||
|
self.path = path
|
||||||
|
self.sdk_based = sdk_based
|
||||||
|
self.default_toolset = default_toolset
|
||||||
|
compatible_sdks = compatible_sdks or []
|
||||||
|
compatible_sdks.sort(key=lambda v: float(v.replace("v", "")), reverse=True)
|
||||||
|
self.compatible_sdks = compatible_sdks
|
||||||
|
|
||||||
|
def ShortName(self):
|
||||||
|
return self.short_name
|
||||||
|
|
||||||
|
def Description(self):
|
||||||
|
"""Get the full description of the version."""
|
||||||
|
return self.description
|
||||||
|
|
||||||
|
def SolutionVersion(self):
|
||||||
|
"""Get the version number of the sln files."""
|
||||||
|
return self.solution_version
|
||||||
|
|
||||||
|
def ProjectVersion(self):
|
||||||
|
"""Get the version number of the vcproj or vcxproj files."""
|
||||||
|
return self.project_version
|
||||||
|
|
||||||
|
def FlatSolution(self):
|
||||||
|
return self.flat_sln
|
||||||
|
|
||||||
|
def UsesVcxproj(self):
|
||||||
|
"""Returns true if this version uses a vcxproj file."""
|
||||||
|
return self.uses_vcxproj
|
||||||
|
|
||||||
|
def ProjectExtension(self):
|
||||||
|
"""Returns the file extension for the project."""
|
||||||
|
return (self.uses_vcxproj and ".vcxproj") or ".vcproj"
|
||||||
|
|
||||||
|
def Path(self):
|
||||||
|
"""Returns the path to Visual Studio installation."""
|
||||||
|
return self.path
|
||||||
|
|
||||||
|
def ToolPath(self, tool):
|
||||||
|
"""Returns the path to a given compiler tool."""
|
||||||
|
return os.path.normpath(os.path.join(self.path, "VC/bin", tool))
|
||||||
|
|
||||||
|
def DefaultToolset(self):
|
||||||
|
"""Returns the msbuild toolset version that will be used in the absence
|
||||||
|
of a user override."""
|
||||||
|
return self.default_toolset
|
||||||
|
|
||||||
|
def _SetupScriptInternal(self, target_arch):
|
||||||
|
"""Returns a command (with arguments) to be used to set up the
|
||||||
|
environment."""
|
||||||
|
assert target_arch in ("x86", "x64"), "target_arch not supported"
|
||||||
|
# If WindowsSDKDir is set and SetEnv.Cmd exists then we are using the
|
||||||
|
# depot_tools build tools and should run SetEnv.Cmd to set up the
|
||||||
|
# environment. The check for WindowsSDKDir alone is not sufficient because
|
||||||
|
# this is set by running vcvarsall.bat.
|
||||||
|
sdk_dir = os.environ.get("WindowsSDKDir", "")
|
||||||
|
setup_path = JoinPath(sdk_dir, "Bin", "SetEnv.Cmd")
|
||||||
|
if self.sdk_based and sdk_dir and os.path.exists(setup_path):
|
||||||
|
return [setup_path, "/" + target_arch]
|
||||||
|
|
||||||
|
is_host_arch_x64 = (
|
||||||
|
os.environ.get("PROCESSOR_ARCHITECTURE") == "AMD64"
|
||||||
|
or os.environ.get("PROCESSOR_ARCHITEW6432") == "AMD64"
|
||||||
|
)
|
||||||
|
|
||||||
|
# For VS2017 (and newer) it's fairly easy
|
||||||
|
if self.short_name >= "2017":
|
||||||
|
script_path = JoinPath(
|
||||||
|
self.path, "VC", "Auxiliary", "Build", "vcvarsall.bat"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Always use a native executable, cross-compiling if necessary.
|
||||||
|
host_arch = "amd64" if is_host_arch_x64 else "x86"
|
||||||
|
msvc_target_arch = "amd64" if target_arch == "x64" else "x86"
|
||||||
|
arg = host_arch
|
||||||
|
if host_arch != msvc_target_arch:
|
||||||
|
arg += "_" + msvc_target_arch
|
||||||
|
|
||||||
|
return [script_path, arg]
|
||||||
|
|
||||||
|
# We try to find the best version of the env setup batch.
|
||||||
|
vcvarsall = JoinPath(self.path, "VC", "vcvarsall.bat")
|
||||||
|
if target_arch == "x86":
|
||||||
|
if (
|
||||||
|
self.short_name >= "2013"
|
||||||
|
and self.short_name[-1] != "e"
|
||||||
|
and is_host_arch_x64
|
||||||
|
):
|
||||||
|
# VS2013 and later, non-Express have a x64-x86 cross that we want
|
||||||
|
# to prefer.
|
||||||
|
return [vcvarsall, "amd64_x86"]
|
||||||
|
else:
|
||||||
|
# Otherwise, the standard x86 compiler. We don't use VC/vcvarsall.bat
|
||||||
|
# for x86 because vcvarsall calls vcvars32, which it can only find if
|
||||||
|
# VS??COMNTOOLS is set, which isn't guaranteed.
|
||||||
|
return [JoinPath(self.path, "Common7", "Tools", "vsvars32.bat")]
|
||||||
|
elif target_arch == "x64":
|
||||||
|
arg = "x86_amd64"
|
||||||
|
# Use the 64-on-64 compiler if we're not using an express edition and
|
||||||
|
# we're running on a 64bit OS.
|
||||||
|
if self.short_name[-1] != "e" and is_host_arch_x64:
|
||||||
|
arg = "amd64"
|
||||||
|
return [vcvarsall, arg]
|
||||||
|
|
||||||
|
def SetupScript(self, target_arch):
|
||||||
|
script_data = self._SetupScriptInternal(target_arch)
|
||||||
|
script_path = script_data[0]
|
||||||
|
if not os.path.exists(script_path):
|
||||||
|
raise Exception(
|
||||||
|
"%s is missing - make sure VC++ tools are installed." % script_path
|
||||||
|
)
|
||||||
|
return script_data
|
||||||
|
|
||||||
|
|
||||||
|
def _RegistryQueryBase(sysdir, key, value):
|
||||||
|
"""Use reg.exe to read a particular key.
|
||||||
|
|
||||||
|
While ideally we might use the win32 module, we would like gyp to be
|
||||||
|
python neutral, so for instance cygwin python lacks this module.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
sysdir: The system subdirectory to attempt to launch reg.exe from.
|
||||||
|
key: The registry key to read from.
|
||||||
|
value: The particular value to read.
|
||||||
|
Return:
|
||||||
|
stdout from reg.exe, or None for failure.
|
||||||
|
"""
|
||||||
|
# Skip if not on Windows or Python Win32 setup issue
|
||||||
|
if sys.platform not in ("win32", "cygwin"):
|
||||||
|
return None
|
||||||
|
# Setup params to pass to and attempt to launch reg.exe
|
||||||
|
cmd = [os.path.join(os.environ.get("WINDIR", ""), sysdir, "reg.exe"), "query", key]
|
||||||
|
if value:
|
||||||
|
cmd.extend(["/v", value])
|
||||||
|
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
# Obtain the stdout from reg.exe, reading to the end so p.returncode is valid
|
||||||
|
# Note that the error text may be in [1] in some cases
|
||||||
|
text = p.communicate()[0].decode("utf-8")
|
||||||
|
# Check return code from reg.exe; officially 0==success and 1==error
|
||||||
|
if p.returncode:
|
||||||
|
return None
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
def _RegistryQuery(key, value=None):
|
||||||
|
r"""Use reg.exe to read a particular key through _RegistryQueryBase.
|
||||||
|
|
||||||
|
First tries to launch from %WinDir%\Sysnative to avoid WoW64 redirection. If
|
||||||
|
that fails, it falls back to System32. Sysnative is available on Vista and
|
||||||
|
up and available on Windows Server 2003 and XP through KB patch 942589. Note
|
||||||
|
that Sysnative will always fail if using 64-bit python due to it being a
|
||||||
|
virtual directory and System32 will work correctly in the first place.
|
||||||
|
|
||||||
|
KB 942589 - http://support.microsoft.com/kb/942589/en-us.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
key: The registry key.
|
||||||
|
value: The particular registry value to read (optional).
|
||||||
|
Return:
|
||||||
|
stdout from reg.exe, or None for failure.
|
||||||
|
"""
|
||||||
|
text = None
|
||||||
|
try:
|
||||||
|
text = _RegistryQueryBase("Sysnative", key, value)
|
||||||
|
except OSError as e:
|
||||||
|
if e.errno == errno.ENOENT:
|
||||||
|
text = _RegistryQueryBase("System32", key, value)
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
def _RegistryGetValueUsingWinReg(key, value):
|
||||||
|
"""Use the _winreg module to obtain the value of a registry key.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
key: The registry key.
|
||||||
|
value: The particular registry value to read.
|
||||||
|
Return:
|
||||||
|
contents of the registry key's value, or None on failure. Throws
|
||||||
|
ImportError if winreg is unavailable.
|
||||||
|
"""
|
||||||
|
from winreg import HKEY_LOCAL_MACHINE, OpenKey, QueryValueEx # noqa: PLC0415
|
||||||
|
|
||||||
|
try:
|
||||||
|
root, subkey = key.split("\\", 1)
|
||||||
|
assert root == "HKLM" # Only need HKLM for now.
|
||||||
|
with OpenKey(HKEY_LOCAL_MACHINE, subkey) as hkey:
|
||||||
|
return QueryValueEx(hkey, value)[0]
|
||||||
|
except OSError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _RegistryGetValue(key, value):
|
||||||
|
"""Use _winreg or reg.exe to obtain the value of a registry key.
|
||||||
|
|
||||||
|
Using _winreg is preferable because it solves an issue on some corporate
|
||||||
|
environments where access to reg.exe is locked down. However, we still need
|
||||||
|
to fallback to reg.exe for the case where the _winreg module is not available
|
||||||
|
(for example in cygwin python).
|
||||||
|
|
||||||
|
Args:
|
||||||
|
key: The registry key.
|
||||||
|
value: The particular registry value to read.
|
||||||
|
Return:
|
||||||
|
contents of the registry key's value, or None on failure.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return _RegistryGetValueUsingWinReg(key, value)
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Fallback to reg.exe if we fail to import _winreg.
|
||||||
|
text = _RegistryQuery(key, value)
|
||||||
|
if not text:
|
||||||
|
return None
|
||||||
|
# Extract value.
|
||||||
|
match = re.search(r"REG_\w+\s+([^\r]+)\r\n", text)
|
||||||
|
if not match:
|
||||||
|
return None
|
||||||
|
return match.group(1)
|
||||||
|
|
||||||
|
|
||||||
|
def _CreateVersion(name, path, sdk_based=False):
|
||||||
|
"""Sets up MSVS project generation.
|
||||||
|
|
||||||
|
Setup is based off the GYP_MSVS_VERSION environment variable or whatever is
|
||||||
|
autodetected if GYP_MSVS_VERSION is not explicitly specified. If a version is
|
||||||
|
passed in that doesn't match a value in versions python will throw a error.
|
||||||
|
"""
|
||||||
|
if path:
|
||||||
|
path = os.path.normpath(path)
|
||||||
|
versions = {
|
||||||
|
"2026": VisualStudioVersion(
|
||||||
|
"2026",
|
||||||
|
"Visual Studio 2026",
|
||||||
|
solution_version="12.00",
|
||||||
|
project_version="18.0",
|
||||||
|
flat_sln=False,
|
||||||
|
uses_vcxproj=True,
|
||||||
|
path=path,
|
||||||
|
sdk_based=sdk_based,
|
||||||
|
default_toolset="v145",
|
||||||
|
compatible_sdks=["v8.1", "v10.0"],
|
||||||
|
),
|
||||||
|
"2022": VisualStudioVersion(
|
||||||
|
"2022",
|
||||||
|
"Visual Studio 2022",
|
||||||
|
solution_version="12.00",
|
||||||
|
project_version="17.0",
|
||||||
|
flat_sln=False,
|
||||||
|
uses_vcxproj=True,
|
||||||
|
path=path,
|
||||||
|
sdk_based=sdk_based,
|
||||||
|
default_toolset="v143",
|
||||||
|
compatible_sdks=["v8.1", "v10.0"],
|
||||||
|
),
|
||||||
|
"2019": VisualStudioVersion(
|
||||||
|
"2019",
|
||||||
|
"Visual Studio 2019",
|
||||||
|
solution_version="12.00",
|
||||||
|
project_version="16.0",
|
||||||
|
flat_sln=False,
|
||||||
|
uses_vcxproj=True,
|
||||||
|
path=path,
|
||||||
|
sdk_based=sdk_based,
|
||||||
|
default_toolset="v142",
|
||||||
|
compatible_sdks=["v8.1", "v10.0"],
|
||||||
|
),
|
||||||
|
"2017": VisualStudioVersion(
|
||||||
|
"2017",
|
||||||
|
"Visual Studio 2017",
|
||||||
|
solution_version="12.00",
|
||||||
|
project_version="15.0",
|
||||||
|
flat_sln=False,
|
||||||
|
uses_vcxproj=True,
|
||||||
|
path=path,
|
||||||
|
sdk_based=sdk_based,
|
||||||
|
default_toolset="v141",
|
||||||
|
compatible_sdks=["v8.1", "v10.0"],
|
||||||
|
),
|
||||||
|
"2015": VisualStudioVersion(
|
||||||
|
"2015",
|
||||||
|
"Visual Studio 2015",
|
||||||
|
solution_version="12.00",
|
||||||
|
project_version="14.0",
|
||||||
|
flat_sln=False,
|
||||||
|
uses_vcxproj=True,
|
||||||
|
path=path,
|
||||||
|
sdk_based=sdk_based,
|
||||||
|
default_toolset="v140",
|
||||||
|
),
|
||||||
|
"2013": VisualStudioVersion(
|
||||||
|
"2013",
|
||||||
|
"Visual Studio 2013",
|
||||||
|
solution_version="13.00",
|
||||||
|
project_version="12.0",
|
||||||
|
flat_sln=False,
|
||||||
|
uses_vcxproj=True,
|
||||||
|
path=path,
|
||||||
|
sdk_based=sdk_based,
|
||||||
|
default_toolset="v120",
|
||||||
|
),
|
||||||
|
"2013e": VisualStudioVersion(
|
||||||
|
"2013e",
|
||||||
|
"Visual Studio 2013",
|
||||||
|
solution_version="13.00",
|
||||||
|
project_version="12.0",
|
||||||
|
flat_sln=True,
|
||||||
|
uses_vcxproj=True,
|
||||||
|
path=path,
|
||||||
|
sdk_based=sdk_based,
|
||||||
|
default_toolset="v120",
|
||||||
|
),
|
||||||
|
"2012": VisualStudioVersion(
|
||||||
|
"2012",
|
||||||
|
"Visual Studio 2012",
|
||||||
|
solution_version="12.00",
|
||||||
|
project_version="4.0",
|
||||||
|
flat_sln=False,
|
||||||
|
uses_vcxproj=True,
|
||||||
|
path=path,
|
||||||
|
sdk_based=sdk_based,
|
||||||
|
default_toolset="v110",
|
||||||
|
),
|
||||||
|
"2012e": VisualStudioVersion(
|
||||||
|
"2012e",
|
||||||
|
"Visual Studio 2012",
|
||||||
|
solution_version="12.00",
|
||||||
|
project_version="4.0",
|
||||||
|
flat_sln=True,
|
||||||
|
uses_vcxproj=True,
|
||||||
|
path=path,
|
||||||
|
sdk_based=sdk_based,
|
||||||
|
default_toolset="v110",
|
||||||
|
),
|
||||||
|
"2010": VisualStudioVersion(
|
||||||
|
"2010",
|
||||||
|
"Visual Studio 2010",
|
||||||
|
solution_version="11.00",
|
||||||
|
project_version="4.0",
|
||||||
|
flat_sln=False,
|
||||||
|
uses_vcxproj=True,
|
||||||
|
path=path,
|
||||||
|
sdk_based=sdk_based,
|
||||||
|
),
|
||||||
|
"2010e": VisualStudioVersion(
|
||||||
|
"2010e",
|
||||||
|
"Visual C++ Express 2010",
|
||||||
|
solution_version="11.00",
|
||||||
|
project_version="4.0",
|
||||||
|
flat_sln=True,
|
||||||
|
uses_vcxproj=True,
|
||||||
|
path=path,
|
||||||
|
sdk_based=sdk_based,
|
||||||
|
),
|
||||||
|
"2008": VisualStudioVersion(
|
||||||
|
"2008",
|
||||||
|
"Visual Studio 2008",
|
||||||
|
solution_version="10.00",
|
||||||
|
project_version="9.00",
|
||||||
|
flat_sln=False,
|
||||||
|
uses_vcxproj=False,
|
||||||
|
path=path,
|
||||||
|
sdk_based=sdk_based,
|
||||||
|
),
|
||||||
|
"2008e": VisualStudioVersion(
|
||||||
|
"2008e",
|
||||||
|
"Visual Studio 2008",
|
||||||
|
solution_version="10.00",
|
||||||
|
project_version="9.00",
|
||||||
|
flat_sln=True,
|
||||||
|
uses_vcxproj=False,
|
||||||
|
path=path,
|
||||||
|
sdk_based=sdk_based,
|
||||||
|
),
|
||||||
|
"2005": VisualStudioVersion(
|
||||||
|
"2005",
|
||||||
|
"Visual Studio 2005",
|
||||||
|
solution_version="9.00",
|
||||||
|
project_version="8.00",
|
||||||
|
flat_sln=False,
|
||||||
|
uses_vcxproj=False,
|
||||||
|
path=path,
|
||||||
|
sdk_based=sdk_based,
|
||||||
|
),
|
||||||
|
"2005e": VisualStudioVersion(
|
||||||
|
"2005e",
|
||||||
|
"Visual Studio 2005",
|
||||||
|
solution_version="9.00",
|
||||||
|
project_version="8.00",
|
||||||
|
flat_sln=True,
|
||||||
|
uses_vcxproj=False,
|
||||||
|
path=path,
|
||||||
|
sdk_based=sdk_based,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
return versions[str(name)]
|
||||||
|
|
||||||
|
|
||||||
|
def _ConvertToCygpath(path):
|
||||||
|
"""Convert to cygwin path if we are using cygwin."""
|
||||||
|
if sys.platform == "cygwin":
|
||||||
|
p = subprocess.Popen(["cygpath", path], stdout=subprocess.PIPE)
|
||||||
|
path = p.communicate()[0].decode("utf-8").strip()
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def _DetectVisualStudioVersions(versions_to_check, force_express):
|
||||||
|
"""Collect the list of installed visual studio versions.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A list of visual studio versions installed in descending order of
|
||||||
|
usage preference.
|
||||||
|
Base this on the registry and a quick check if devenv.exe exists.
|
||||||
|
Possibilities are:
|
||||||
|
2005(e) - Visual Studio 2005 (8)
|
||||||
|
2008(e) - Visual Studio 2008 (9)
|
||||||
|
2010(e) - Visual Studio 2010 (10)
|
||||||
|
2012(e) - Visual Studio 2012 (11)
|
||||||
|
2013(e) - Visual Studio 2013 (12)
|
||||||
|
2015 - Visual Studio 2015 (14)
|
||||||
|
2017 - Visual Studio 2017 (15)
|
||||||
|
2019 - Visual Studio 2019 (16)
|
||||||
|
2022 - Visual Studio 2022 (17)
|
||||||
|
Where (e) is e for express editions of MSVS and blank otherwise.
|
||||||
|
"""
|
||||||
|
version_to_year = {
|
||||||
|
"8.0": "2005",
|
||||||
|
"9.0": "2008",
|
||||||
|
"10.0": "2010",
|
||||||
|
"11.0": "2012",
|
||||||
|
"12.0": "2013",
|
||||||
|
"14.0": "2015",
|
||||||
|
"15.0": "2017",
|
||||||
|
"16.0": "2019",
|
||||||
|
"17.0": "2022",
|
||||||
|
"18.0": "2026",
|
||||||
|
}
|
||||||
|
versions = []
|
||||||
|
for version in versions_to_check:
|
||||||
|
# Old method of searching for which VS version is installed
|
||||||
|
# We don't use the 2010-encouraged-way because we also want to get the
|
||||||
|
# path to the binaries, which it doesn't offer.
|
||||||
|
keys = [
|
||||||
|
r"HKLM\Software\Microsoft\VisualStudio\%s" % version,
|
||||||
|
r"HKLM\Software\Wow6432Node\Microsoft\VisualStudio\%s" % version,
|
||||||
|
r"HKLM\Software\Microsoft\VCExpress\%s" % version,
|
||||||
|
r"HKLM\Software\Wow6432Node\Microsoft\VCExpress\%s" % version,
|
||||||
|
]
|
||||||
|
for index in range(len(keys)):
|
||||||
|
path = _RegistryGetValue(keys[index], "InstallDir")
|
||||||
|
if not path:
|
||||||
|
continue
|
||||||
|
path = _ConvertToCygpath(path)
|
||||||
|
# Check for full.
|
||||||
|
full_path = os.path.join(path, "devenv.exe")
|
||||||
|
express_path = os.path.join(path, "*express.exe")
|
||||||
|
if not force_express and os.path.exists(full_path):
|
||||||
|
# Add this one.
|
||||||
|
versions.append(
|
||||||
|
_CreateVersion(
|
||||||
|
version_to_year[version], os.path.join(path, "..", "..")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
# Check for express.
|
||||||
|
elif glob.glob(express_path):
|
||||||
|
# Add this one.
|
||||||
|
versions.append(
|
||||||
|
_CreateVersion(
|
||||||
|
version_to_year[version] + "e", os.path.join(path, "..", "..")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# The old method above does not work when only SDK is installed.
|
||||||
|
keys = [
|
||||||
|
r"HKLM\Software\Microsoft\VisualStudio\SxS\VC7",
|
||||||
|
r"HKLM\Software\Wow6432Node\Microsoft\VisualStudio\SxS\VC7",
|
||||||
|
r"HKLM\Software\Microsoft\VisualStudio\SxS\VS7",
|
||||||
|
r"HKLM\Software\Wow6432Node\Microsoft\VisualStudio\SxS\VS7",
|
||||||
|
]
|
||||||
|
for index in range(len(keys)):
|
||||||
|
path = _RegistryGetValue(keys[index], version)
|
||||||
|
if not path:
|
||||||
|
continue
|
||||||
|
path = _ConvertToCygpath(path)
|
||||||
|
if version == "15.0":
|
||||||
|
if os.path.exists(path):
|
||||||
|
versions.append(_CreateVersion("2017", path))
|
||||||
|
elif version != "14.0": # There is no Express edition for 2015.
|
||||||
|
versions.append(
|
||||||
|
_CreateVersion(
|
||||||
|
version_to_year[version] + "e",
|
||||||
|
os.path.join(path, ".."),
|
||||||
|
sdk_based=True,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return versions
|
||||||
|
|
||||||
|
|
||||||
|
def SelectVisualStudioVersion(version="auto", allow_fallback=True):
|
||||||
|
"""Select which version of Visual Studio projects to generate.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
version: Hook to allow caller to force a particular version (vs auto).
|
||||||
|
Returns:
|
||||||
|
An object representing a visual studio project format version.
|
||||||
|
"""
|
||||||
|
# In auto mode, check environment variable for override.
|
||||||
|
if version == "auto":
|
||||||
|
version = os.environ.get("GYP_MSVS_VERSION", "auto")
|
||||||
|
version_map = {
|
||||||
|
"auto": (
|
||||||
|
"18.0",
|
||||||
|
"17.0",
|
||||||
|
"16.0",
|
||||||
|
"15.0",
|
||||||
|
"14.0",
|
||||||
|
"12.0",
|
||||||
|
"10.0",
|
||||||
|
"9.0",
|
||||||
|
"8.0",
|
||||||
|
"11.0",
|
||||||
|
),
|
||||||
|
"2005": ("8.0",),
|
||||||
|
"2005e": ("8.0",),
|
||||||
|
"2008": ("9.0",),
|
||||||
|
"2008e": ("9.0",),
|
||||||
|
"2010": ("10.0",),
|
||||||
|
"2010e": ("10.0",),
|
||||||
|
"2012": ("11.0",),
|
||||||
|
"2012e": ("11.0",),
|
||||||
|
"2013": ("12.0",),
|
||||||
|
"2013e": ("12.0",),
|
||||||
|
"2015": ("14.0",),
|
||||||
|
"2017": ("15.0",),
|
||||||
|
"2019": ("16.0",),
|
||||||
|
"2022": ("17.0",),
|
||||||
|
"2026": ("18.0",),
|
||||||
|
}
|
||||||
|
if override_path := os.environ.get("GYP_MSVS_OVERRIDE_PATH"):
|
||||||
|
msvs_version = os.environ.get("GYP_MSVS_VERSION")
|
||||||
|
if not msvs_version:
|
||||||
|
raise ValueError(
|
||||||
|
"GYP_MSVS_OVERRIDE_PATH requires GYP_MSVS_VERSION to be "
|
||||||
|
"set to a particular version (e.g. 2010e)."
|
||||||
|
)
|
||||||
|
return _CreateVersion(msvs_version, override_path, sdk_based=True)
|
||||||
|
version = str(version)
|
||||||
|
versions = _DetectVisualStudioVersions(version_map[version], "e" in version)
|
||||||
|
if not versions:
|
||||||
|
if not allow_fallback:
|
||||||
|
raise ValueError("Could not locate Visual Studio installation.")
|
||||||
|
if version == "auto":
|
||||||
|
# Default to 2005 if we couldn't find anything
|
||||||
|
return _CreateVersion("2005", None)
|
||||||
|
else:
|
||||||
|
return _CreateVersion(version, None)
|
||||||
|
return versions[0]
|
||||||
707
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/__init__.py
generated
vendored
Normal file
707
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/__init__.py
generated
vendored
Normal file
|
|
@ -0,0 +1,707 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Copyright (c) 2012 Google Inc. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import copy
|
||||||
|
import os.path
|
||||||
|
import re
|
||||||
|
import shlex
|
||||||
|
import sys
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
import gyp.input
|
||||||
|
from gyp.common import GypError
|
||||||
|
|
||||||
|
# Default debug modes for GYP
|
||||||
|
debug = {}
|
||||||
|
|
||||||
|
# List of "official" debug modes, but you can use anything you like.
|
||||||
|
DEBUG_GENERAL = "general"
|
||||||
|
DEBUG_VARIABLES = "variables"
|
||||||
|
DEBUG_INCLUDES = "includes"
|
||||||
|
|
||||||
|
|
||||||
|
def EscapeForCString(string: bytes | str) -> str:
|
||||||
|
if isinstance(string, str):
|
||||||
|
string = string.encode(encoding="utf8")
|
||||||
|
|
||||||
|
backslash_or_double_quote = {ord("\\"), ord('"')}
|
||||||
|
result = ""
|
||||||
|
for char in string:
|
||||||
|
if char in backslash_or_double_quote or not 32 <= char < 127:
|
||||||
|
result += "\\%03o" % char
|
||||||
|
else:
|
||||||
|
result += chr(char)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def DebugOutput(mode, message, *args):
|
||||||
|
if "all" in gyp.debug or mode in gyp.debug:
|
||||||
|
ctx = ("unknown", 0, "unknown")
|
||||||
|
try:
|
||||||
|
f = traceback.extract_stack(limit=2)
|
||||||
|
if f:
|
||||||
|
ctx = f[0][:3]
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
if args:
|
||||||
|
message %= args
|
||||||
|
print(
|
||||||
|
"%s:%s:%d:%s %s"
|
||||||
|
% (mode.upper(), os.path.basename(ctx[0]), ctx[1], ctx[2], message)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def FindBuildFiles():
|
||||||
|
extension = ".gyp"
|
||||||
|
files = os.listdir(os.getcwd())
|
||||||
|
build_files = []
|
||||||
|
for file in files:
|
||||||
|
if file.endswith(extension):
|
||||||
|
build_files.append(file)
|
||||||
|
return build_files
|
||||||
|
|
||||||
|
|
||||||
|
def Load(
|
||||||
|
build_files,
|
||||||
|
format,
|
||||||
|
default_variables={},
|
||||||
|
includes=[],
|
||||||
|
depth=".",
|
||||||
|
params=None,
|
||||||
|
check=False,
|
||||||
|
circular_check=True,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Loads one or more specified build files.
|
||||||
|
default_variables and includes will be copied before use.
|
||||||
|
Returns the generator for the specified format and the
|
||||||
|
data returned by loading the specified build files.
|
||||||
|
"""
|
||||||
|
if params is None:
|
||||||
|
params = {}
|
||||||
|
|
||||||
|
if "-" in format:
|
||||||
|
format, params["flavor"] = format.split("-", 1)
|
||||||
|
|
||||||
|
default_variables = copy.copy(default_variables)
|
||||||
|
|
||||||
|
# Default variables provided by this program and its modules should be
|
||||||
|
# named WITH_CAPITAL_LETTERS to provide a distinct "best practice" namespace,
|
||||||
|
# avoiding collisions with user and automatic variables.
|
||||||
|
default_variables["GENERATOR"] = format
|
||||||
|
default_variables["GENERATOR_FLAVOR"] = params.get("flavor", "")
|
||||||
|
|
||||||
|
# Format can be a custom python file, or by default the name of a module
|
||||||
|
# within gyp.generator.
|
||||||
|
if format.endswith(".py"):
|
||||||
|
generator_name = os.path.splitext(format)[0]
|
||||||
|
path, generator_name = os.path.split(generator_name)
|
||||||
|
|
||||||
|
# Make sure the path to the custom generator is in sys.path
|
||||||
|
# Don't worry about removing it once we are done. Keeping the path
|
||||||
|
# to each generator that is used in sys.path is likely harmless and
|
||||||
|
# arguably a good idea.
|
||||||
|
path = os.path.abspath(path)
|
||||||
|
if path not in sys.path:
|
||||||
|
sys.path.insert(0, path)
|
||||||
|
else:
|
||||||
|
generator_name = "gyp.generator." + format
|
||||||
|
|
||||||
|
# These parameters are passed in order (as opposed to by key)
|
||||||
|
# because ActivePython cannot handle key parameters to __import__.
|
||||||
|
generator = __import__(generator_name, globals(), locals(), generator_name)
|
||||||
|
for key, val in generator.generator_default_variables.items():
|
||||||
|
default_variables.setdefault(key, val)
|
||||||
|
|
||||||
|
output_dir = params["options"].generator_output or params["options"].toplevel_dir
|
||||||
|
if default_variables["GENERATOR"] == "ninja":
|
||||||
|
product_dir_abs = os.path.join(
|
||||||
|
output_dir, "out", default_variables.get("build_type", "default")
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
product_dir_abs = os.path.join(
|
||||||
|
output_dir, default_variables["CONFIGURATION_NAME"]
|
||||||
|
)
|
||||||
|
|
||||||
|
default_variables.setdefault("PRODUCT_DIR_ABS", product_dir_abs)
|
||||||
|
default_variables.setdefault(
|
||||||
|
"PRODUCT_DIR_ABS_CSTR", EscapeForCString(product_dir_abs)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Give the generator the opportunity to set additional variables based on
|
||||||
|
# the params it will receive in the output phase.
|
||||||
|
if getattr(generator, "CalculateVariables", None):
|
||||||
|
generator.CalculateVariables(default_variables, params)
|
||||||
|
|
||||||
|
# Give the generator the opportunity to set generator_input_info based on
|
||||||
|
# the params it will receive in the output phase.
|
||||||
|
if getattr(generator, "CalculateGeneratorInputInfo", None):
|
||||||
|
generator.CalculateGeneratorInputInfo(params)
|
||||||
|
|
||||||
|
# Fetch the generator specific info that gets fed to input, we use getattr
|
||||||
|
# so we can default things and the generators only have to provide what
|
||||||
|
# they need.
|
||||||
|
generator_input_info = {
|
||||||
|
"non_configuration_keys": getattr(
|
||||||
|
generator, "generator_additional_non_configuration_keys", []
|
||||||
|
),
|
||||||
|
"path_sections": getattr(generator, "generator_additional_path_sections", []),
|
||||||
|
"extra_sources_for_rules": getattr(
|
||||||
|
generator, "generator_extra_sources_for_rules", []
|
||||||
|
),
|
||||||
|
"generator_supports_multiple_toolsets": getattr(
|
||||||
|
generator, "generator_supports_multiple_toolsets", False
|
||||||
|
),
|
||||||
|
"generator_wants_static_library_dependencies_adjusted": getattr(
|
||||||
|
generator, "generator_wants_static_library_dependencies_adjusted", True
|
||||||
|
),
|
||||||
|
"generator_wants_sorted_dependencies": getattr(
|
||||||
|
generator, "generator_wants_sorted_dependencies", False
|
||||||
|
),
|
||||||
|
"generator_filelist_paths": getattr(
|
||||||
|
generator, "generator_filelist_paths", None
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
# Process the input specific to this generator.
|
||||||
|
result = gyp.input.Load(
|
||||||
|
build_files,
|
||||||
|
default_variables,
|
||||||
|
includes[:],
|
||||||
|
depth,
|
||||||
|
generator_input_info,
|
||||||
|
check,
|
||||||
|
circular_check,
|
||||||
|
params["parallel"],
|
||||||
|
params["root_targets"],
|
||||||
|
)
|
||||||
|
return [generator] + result
|
||||||
|
|
||||||
|
|
||||||
|
def NameValueListToDict(name_value_list):
|
||||||
|
"""
|
||||||
|
Takes an array of strings of the form 'NAME=VALUE' and creates a dictionary
|
||||||
|
of the pairs. If a string is simply NAME, then the value in the dictionary
|
||||||
|
is set to True. If VALUE can be converted to an integer, it is.
|
||||||
|
"""
|
||||||
|
result = {}
|
||||||
|
for item in name_value_list:
|
||||||
|
tokens = item.split("=", 1)
|
||||||
|
if len(tokens) == 2:
|
||||||
|
# If we can make it an int, use that, otherwise, use the string.
|
||||||
|
try:
|
||||||
|
token_value = int(tokens[1])
|
||||||
|
except ValueError:
|
||||||
|
token_value = tokens[1]
|
||||||
|
# Set the variable to the supplied value.
|
||||||
|
result[tokens[0]] = token_value
|
||||||
|
else:
|
||||||
|
# No value supplied, treat it as a boolean and set it.
|
||||||
|
result[tokens[0]] = True
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def ShlexEnv(env_name):
|
||||||
|
if flags := os.environ.get(env_name) or []:
|
||||||
|
flags = shlex.split(flags)
|
||||||
|
return flags
|
||||||
|
|
||||||
|
|
||||||
|
def FormatOpt(opt, value):
|
||||||
|
if opt.startswith("--"):
|
||||||
|
return f"{opt}={value}"
|
||||||
|
return opt + value
|
||||||
|
|
||||||
|
|
||||||
|
def RegenerateAppendFlag(flag, values, predicate, env_name, options):
|
||||||
|
"""Regenerate a list of command line flags, for an option of action='append'.
|
||||||
|
|
||||||
|
The |env_name|, if given, is checked in the environment and used to generate
|
||||||
|
an initial list of options, then the options that were specified on the
|
||||||
|
command line (given in |values|) are appended. This matches the handling of
|
||||||
|
environment variables and command line flags where command line flags override
|
||||||
|
the environment, while not requiring the environment to be set when the flags
|
||||||
|
are used again.
|
||||||
|
"""
|
||||||
|
flags = []
|
||||||
|
if options.use_environment and env_name:
|
||||||
|
for flag_value in ShlexEnv(env_name):
|
||||||
|
value = FormatOpt(flag, predicate(flag_value))
|
||||||
|
if value in flags:
|
||||||
|
flags.remove(value)
|
||||||
|
flags.append(value)
|
||||||
|
if values:
|
||||||
|
for flag_value in values:
|
||||||
|
flags.append(FormatOpt(flag, predicate(flag_value)))
|
||||||
|
return flags
|
||||||
|
|
||||||
|
|
||||||
|
def RegenerateFlags(options):
|
||||||
|
"""Given a parsed options object, and taking the environment variables into
|
||||||
|
account, returns a list of flags that should regenerate an equivalent options
|
||||||
|
object (even in the absence of the environment variables.)
|
||||||
|
|
||||||
|
Any path options will be normalized relative to depth.
|
||||||
|
|
||||||
|
The format flag is not included, as it is assumed the calling generator will
|
||||||
|
set that as appropriate.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def FixPath(path):
|
||||||
|
path = gyp.common.FixIfRelativePath(path, options.depth)
|
||||||
|
if not path:
|
||||||
|
return os.path.curdir
|
||||||
|
return path
|
||||||
|
|
||||||
|
def Noop(value):
|
||||||
|
return value
|
||||||
|
|
||||||
|
# We always want to ignore the environment when regenerating, to avoid
|
||||||
|
# duplicate or changed flags in the environment at the time of regeneration.
|
||||||
|
flags = ["--ignore-environment"]
|
||||||
|
for name, metadata in options._regeneration_metadata.items():
|
||||||
|
opt = metadata["opt"]
|
||||||
|
value = getattr(options, name)
|
||||||
|
value_predicate = (metadata["type"] == "path" and FixPath) or Noop
|
||||||
|
action = metadata["action"]
|
||||||
|
env_name = metadata["env_name"]
|
||||||
|
if action == "append":
|
||||||
|
flags.extend(
|
||||||
|
RegenerateAppendFlag(opt, value, value_predicate, env_name, options)
|
||||||
|
)
|
||||||
|
elif action in ("store", None): # None is a synonym for 'store'.
|
||||||
|
if value:
|
||||||
|
flags.append(FormatOpt(opt, value_predicate(value)))
|
||||||
|
elif options.use_environment and env_name and os.environ.get(env_name):
|
||||||
|
flags.append(FormatOpt(opt, value_predicate(os.environ.get(env_name))))
|
||||||
|
elif action in ("store_true", "store_false"):
|
||||||
|
if (action == "store_true" and value) or (
|
||||||
|
action == "store_false" and not value
|
||||||
|
):
|
||||||
|
flags.append(opt)
|
||||||
|
elif options.use_environment and env_name:
|
||||||
|
print(
|
||||||
|
"Warning: environment regeneration unimplemented "
|
||||||
|
"for %s flag %r env_name %r" % (action, opt, env_name),
|
||||||
|
file=sys.stderr,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
print(
|
||||||
|
"Warning: regeneration unimplemented for action %r "
|
||||||
|
"flag %r" % (action, opt),
|
||||||
|
file=sys.stderr,
|
||||||
|
)
|
||||||
|
|
||||||
|
return flags
|
||||||
|
|
||||||
|
|
||||||
|
class RegeneratableOptionParser(argparse.ArgumentParser):
|
||||||
|
def __init__(self, usage):
|
||||||
|
self.__regeneratable_options = {}
|
||||||
|
argparse.ArgumentParser.__init__(self, usage=usage)
|
||||||
|
|
||||||
|
def add_argument(self, *args, **kw):
|
||||||
|
"""Add an option to the parser.
|
||||||
|
|
||||||
|
This accepts the same arguments as ArgumentParser.add_argument, plus the
|
||||||
|
following:
|
||||||
|
regenerate: can be set to False to prevent this option from being included
|
||||||
|
in regeneration.
|
||||||
|
env_name: name of environment variable that additional values for this
|
||||||
|
option come from.
|
||||||
|
type: adds type='path', to tell the regenerator that the values of
|
||||||
|
this option need to be made relative to options.depth
|
||||||
|
"""
|
||||||
|
env_name = kw.pop("env_name", None)
|
||||||
|
if "dest" in kw and kw.pop("regenerate", True):
|
||||||
|
dest = kw["dest"]
|
||||||
|
|
||||||
|
# The path type is needed for regenerating, for optparse we can just treat
|
||||||
|
# it as a string.
|
||||||
|
type = kw.get("type")
|
||||||
|
if type == "path":
|
||||||
|
kw["type"] = str
|
||||||
|
|
||||||
|
self.__regeneratable_options[dest] = {
|
||||||
|
"action": kw.get("action"),
|
||||||
|
"type": type,
|
||||||
|
"env_name": env_name,
|
||||||
|
"opt": args[0],
|
||||||
|
}
|
||||||
|
|
||||||
|
argparse.ArgumentParser.add_argument(self, *args, **kw)
|
||||||
|
|
||||||
|
def parse_args(self, *args):
|
||||||
|
values, args = argparse.ArgumentParser.parse_known_args(self, *args)
|
||||||
|
values._regeneration_metadata = self.__regeneratable_options
|
||||||
|
return values, args
|
||||||
|
|
||||||
|
|
||||||
|
def gyp_main(args):
|
||||||
|
my_name = os.path.basename(sys.argv[0])
|
||||||
|
usage = "%(prog)s [options ...] [build_file ...]"
|
||||||
|
|
||||||
|
parser = RegeneratableOptionParser(usage=usage.replace("%s", "%(prog)s"))
|
||||||
|
parser.add_argument(
|
||||||
|
"--build",
|
||||||
|
dest="configs",
|
||||||
|
action="append",
|
||||||
|
help="configuration for build after project generation",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--check", dest="check", action="store_true", help="check format of gyp files"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--config-dir",
|
||||||
|
dest="config_dir",
|
||||||
|
action="store",
|
||||||
|
env_name="GYP_CONFIG_DIR",
|
||||||
|
default=None,
|
||||||
|
help="The location for configuration files like include.gypi.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-d",
|
||||||
|
"--debug",
|
||||||
|
dest="debug",
|
||||||
|
metavar="DEBUGMODE",
|
||||||
|
action="append",
|
||||||
|
default=[],
|
||||||
|
help="turn on a debugging "
|
||||||
|
'mode for debugging GYP. Supported modes are "variables", '
|
||||||
|
'"includes" and "general" or "all" for all of them.',
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-D",
|
||||||
|
dest="defines",
|
||||||
|
action="append",
|
||||||
|
metavar="VAR=VAL",
|
||||||
|
env_name="GYP_DEFINES",
|
||||||
|
help="sets variable VAR to value VAL",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--depth",
|
||||||
|
dest="depth",
|
||||||
|
metavar="PATH",
|
||||||
|
type="path",
|
||||||
|
help="set DEPTH gyp variable to a relative path to PATH",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-f",
|
||||||
|
"--format",
|
||||||
|
dest="formats",
|
||||||
|
action="append",
|
||||||
|
env_name="GYP_GENERATORS",
|
||||||
|
regenerate=False,
|
||||||
|
help="output formats to generate",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-G",
|
||||||
|
dest="generator_flags",
|
||||||
|
action="append",
|
||||||
|
default=[],
|
||||||
|
metavar="FLAG=VAL",
|
||||||
|
env_name="GYP_GENERATOR_FLAGS",
|
||||||
|
help="sets generator flag FLAG to VAL",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--generator-output",
|
||||||
|
dest="generator_output",
|
||||||
|
action="store",
|
||||||
|
default=None,
|
||||||
|
metavar="DIR",
|
||||||
|
type="path",
|
||||||
|
env_name="GYP_GENERATOR_OUTPUT",
|
||||||
|
help="puts generated build files under DIR",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--ignore-environment",
|
||||||
|
dest="use_environment",
|
||||||
|
action="store_false",
|
||||||
|
default=True,
|
||||||
|
regenerate=False,
|
||||||
|
help="do not read options from environment variables",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-I",
|
||||||
|
"--include",
|
||||||
|
dest="includes",
|
||||||
|
action="append",
|
||||||
|
metavar="INCLUDE",
|
||||||
|
type="path",
|
||||||
|
help="files to include in all loaded .gyp files",
|
||||||
|
)
|
||||||
|
# --no-circular-check disables the check for circular relationships between
|
||||||
|
# .gyp files. These relationships should not exist, but they've only been
|
||||||
|
# observed to be harmful with the Xcode generator. Chromium's .gyp files
|
||||||
|
# currently have some circular relationships on non-Mac platforms, so this
|
||||||
|
# option allows the strict behavior to be used on Macs and the lenient
|
||||||
|
# behavior to be used elsewhere.
|
||||||
|
# TODO(mark): Remove this option when http://crbug.com/35878 is fixed.
|
||||||
|
parser.add_argument(
|
||||||
|
"--no-circular-check",
|
||||||
|
dest="circular_check",
|
||||||
|
action="store_false",
|
||||||
|
default=True,
|
||||||
|
regenerate=False,
|
||||||
|
help="don't check for circular relationships between files",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--no-parallel",
|
||||||
|
action="store_true",
|
||||||
|
default=False,
|
||||||
|
help="Disable multiprocessing",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-S",
|
||||||
|
"--suffix",
|
||||||
|
dest="suffix",
|
||||||
|
default="",
|
||||||
|
help="suffix to add to generated files",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--toplevel-dir",
|
||||||
|
dest="toplevel_dir",
|
||||||
|
action="store",
|
||||||
|
default=None,
|
||||||
|
metavar="DIR",
|
||||||
|
type="path",
|
||||||
|
help="directory to use as the root of the source tree",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-R",
|
||||||
|
"--root-target",
|
||||||
|
dest="root_targets",
|
||||||
|
action="append",
|
||||||
|
metavar="TARGET",
|
||||||
|
help="include only TARGET and its deep dependencies",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-V",
|
||||||
|
"--version",
|
||||||
|
dest="version",
|
||||||
|
action="store_true",
|
||||||
|
help="Show the version and exit.",
|
||||||
|
)
|
||||||
|
|
||||||
|
options, build_files_arg = parser.parse_args(args)
|
||||||
|
if options.version:
|
||||||
|
import pkg_resources # noqa: PLC0415
|
||||||
|
|
||||||
|
print(f"v{pkg_resources.get_distribution('gyp-next').version}")
|
||||||
|
return 0
|
||||||
|
build_files = build_files_arg
|
||||||
|
|
||||||
|
# Set up the configuration directory (defaults to ~/.gyp)
|
||||||
|
if not options.config_dir:
|
||||||
|
home = None
|
||||||
|
home_dot_gyp = None
|
||||||
|
if options.use_environment:
|
||||||
|
home_dot_gyp = os.environ.get("GYP_CONFIG_DIR", None)
|
||||||
|
if home_dot_gyp:
|
||||||
|
home_dot_gyp = os.path.expanduser(home_dot_gyp)
|
||||||
|
|
||||||
|
if not home_dot_gyp:
|
||||||
|
home_vars = ["HOME"]
|
||||||
|
if sys.platform in ("cygwin", "win32"):
|
||||||
|
home_vars.append("USERPROFILE")
|
||||||
|
for home_var in home_vars:
|
||||||
|
home = os.getenv(home_var)
|
||||||
|
if home:
|
||||||
|
home_dot_gyp = os.path.join(home, ".gyp")
|
||||||
|
if not os.path.exists(home_dot_gyp):
|
||||||
|
home_dot_gyp = None
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
home_dot_gyp = os.path.expanduser(options.config_dir)
|
||||||
|
|
||||||
|
if home_dot_gyp and not os.path.exists(home_dot_gyp):
|
||||||
|
home_dot_gyp = None
|
||||||
|
|
||||||
|
if not options.formats:
|
||||||
|
# If no format was given on the command line, then check the env variable.
|
||||||
|
generate_formats = []
|
||||||
|
if options.use_environment:
|
||||||
|
generate_formats = os.environ.get("GYP_GENERATORS") or []
|
||||||
|
if generate_formats:
|
||||||
|
generate_formats = re.split(r"[\s,]", generate_formats)
|
||||||
|
if generate_formats:
|
||||||
|
options.formats = generate_formats
|
||||||
|
# Nothing in the variable, default based on platform.
|
||||||
|
elif sys.platform == "darwin":
|
||||||
|
options.formats = ["xcode"]
|
||||||
|
elif sys.platform in ("win32", "cygwin"):
|
||||||
|
options.formats = ["msvs"]
|
||||||
|
else:
|
||||||
|
options.formats = ["make"]
|
||||||
|
|
||||||
|
if not options.generator_output and options.use_environment:
|
||||||
|
g_o = os.environ.get("GYP_GENERATOR_OUTPUT")
|
||||||
|
if g_o:
|
||||||
|
options.generator_output = g_o
|
||||||
|
|
||||||
|
options.parallel = not options.no_parallel
|
||||||
|
|
||||||
|
for mode in options.debug:
|
||||||
|
gyp.debug[mode] = 1
|
||||||
|
|
||||||
|
# Do an extra check to avoid work when we're not debugging.
|
||||||
|
if DEBUG_GENERAL in gyp.debug:
|
||||||
|
DebugOutput(DEBUG_GENERAL, "running with these options:")
|
||||||
|
for option, value in sorted(options.__dict__.items()):
|
||||||
|
if option[0] == "_":
|
||||||
|
continue
|
||||||
|
if isinstance(value, str):
|
||||||
|
DebugOutput(DEBUG_GENERAL, " %s: '%s'", option, value)
|
||||||
|
else:
|
||||||
|
DebugOutput(DEBUG_GENERAL, " %s: %s", option, value)
|
||||||
|
|
||||||
|
if not build_files:
|
||||||
|
build_files = FindBuildFiles()
|
||||||
|
if not build_files:
|
||||||
|
raise GypError((usage + "\n\n%s: error: no build_file") % (my_name, my_name))
|
||||||
|
|
||||||
|
# TODO(mark): Chromium-specific hack!
|
||||||
|
# For Chromium, the gyp "depth" variable should always be a relative path
|
||||||
|
# to Chromium's top-level "src" directory. If no depth variable was set
|
||||||
|
# on the command line, try to find a "src" directory by looking at the
|
||||||
|
# absolute path to each build file's directory. The first "src" component
|
||||||
|
# found will be treated as though it were the path used for --depth.
|
||||||
|
if not options.depth:
|
||||||
|
for build_file in build_files:
|
||||||
|
build_file_dir = os.path.abspath(os.path.dirname(build_file))
|
||||||
|
build_file_dir_components = build_file_dir.split(os.path.sep)
|
||||||
|
components_len = len(build_file_dir_components)
|
||||||
|
for index in range(components_len - 1, -1, -1):
|
||||||
|
if build_file_dir_components[index] == "src":
|
||||||
|
options.depth = os.path.sep.join(build_file_dir_components)
|
||||||
|
break
|
||||||
|
del build_file_dir_components[index]
|
||||||
|
|
||||||
|
# If the inner loop found something, break without advancing to another
|
||||||
|
# build file.
|
||||||
|
if options.depth:
|
||||||
|
break
|
||||||
|
|
||||||
|
if not options.depth:
|
||||||
|
raise GypError(
|
||||||
|
"Could not automatically locate src directory. This is"
|
||||||
|
"a temporary Chromium feature that will be removed. Use"
|
||||||
|
"--depth as a workaround."
|
||||||
|
)
|
||||||
|
|
||||||
|
# If toplevel-dir is not set, we assume that depth is the root of our source
|
||||||
|
# tree.
|
||||||
|
if not options.toplevel_dir:
|
||||||
|
options.toplevel_dir = options.depth
|
||||||
|
|
||||||
|
# -D on the command line sets variable defaults - D isn't just for define,
|
||||||
|
# it's for default. Perhaps there should be a way to force (-F?) a
|
||||||
|
# variable's value so that it can't be overridden by anything else.
|
||||||
|
cmdline_default_variables = {}
|
||||||
|
defines = []
|
||||||
|
if options.use_environment:
|
||||||
|
defines += ShlexEnv("GYP_DEFINES")
|
||||||
|
if options.defines:
|
||||||
|
defines += options.defines
|
||||||
|
cmdline_default_variables = NameValueListToDict(defines)
|
||||||
|
if DEBUG_GENERAL in gyp.debug:
|
||||||
|
DebugOutput(
|
||||||
|
DEBUG_GENERAL, "cmdline_default_variables: %s", cmdline_default_variables
|
||||||
|
)
|
||||||
|
|
||||||
|
# Set up includes.
|
||||||
|
includes = []
|
||||||
|
|
||||||
|
# If ~/.gyp/include.gypi exists, it'll be forcibly included into every
|
||||||
|
# .gyp file that's loaded, before anything else is included.
|
||||||
|
if home_dot_gyp:
|
||||||
|
default_include = os.path.join(home_dot_gyp, "include.gypi")
|
||||||
|
if os.path.exists(default_include):
|
||||||
|
print("Using overrides found in " + default_include)
|
||||||
|
includes.append(default_include)
|
||||||
|
|
||||||
|
# Command-line --include files come after the default include.
|
||||||
|
if options.includes:
|
||||||
|
includes.extend(options.includes)
|
||||||
|
|
||||||
|
# Generator flags should be prefixed with the target generator since they
|
||||||
|
# are global across all generator runs.
|
||||||
|
gen_flags = []
|
||||||
|
if options.use_environment:
|
||||||
|
gen_flags += ShlexEnv("GYP_GENERATOR_FLAGS")
|
||||||
|
if options.generator_flags:
|
||||||
|
gen_flags += options.generator_flags
|
||||||
|
generator_flags = NameValueListToDict(gen_flags)
|
||||||
|
if DEBUG_GENERAL in gyp.debug:
|
||||||
|
DebugOutput(DEBUG_GENERAL, "generator_flags: %s", generator_flags)
|
||||||
|
|
||||||
|
# Generate all requested formats (use a set in case we got one format request
|
||||||
|
# twice)
|
||||||
|
for format in set(options.formats):
|
||||||
|
params = {
|
||||||
|
"options": options,
|
||||||
|
"build_files": build_files,
|
||||||
|
"generator_flags": generator_flags,
|
||||||
|
"cwd": os.getcwd(),
|
||||||
|
"build_files_arg": build_files_arg,
|
||||||
|
"gyp_binary": sys.argv[0],
|
||||||
|
"home_dot_gyp": home_dot_gyp,
|
||||||
|
"parallel": options.parallel,
|
||||||
|
"root_targets": options.root_targets,
|
||||||
|
"target_arch": cmdline_default_variables.get("target_arch", ""),
|
||||||
|
}
|
||||||
|
|
||||||
|
# Start with the default variables from the command line.
|
||||||
|
[generator, flat_list, targets, data] = Load(
|
||||||
|
build_files,
|
||||||
|
format,
|
||||||
|
cmdline_default_variables,
|
||||||
|
includes,
|
||||||
|
options.depth,
|
||||||
|
params,
|
||||||
|
options.check,
|
||||||
|
options.circular_check,
|
||||||
|
)
|
||||||
|
|
||||||
|
# TODO(mark): Pass |data| for now because the generator needs a list of
|
||||||
|
# build files that came in. In the future, maybe it should just accept
|
||||||
|
# a list, and not the whole data dict.
|
||||||
|
# NOTE: flat_list is the flattened dependency graph specifying the order
|
||||||
|
# that targets may be built. Build systems that operate serially or that
|
||||||
|
# need to have dependencies defined before dependents reference them should
|
||||||
|
# generate targets in the order specified in flat_list.
|
||||||
|
generator.GenerateOutput(flat_list, targets, data, params)
|
||||||
|
|
||||||
|
if options.configs:
|
||||||
|
valid_configs = targets[flat_list[0]]["configurations"]
|
||||||
|
for conf in options.configs:
|
||||||
|
if conf not in valid_configs:
|
||||||
|
raise GypError("Invalid config specified via --build: %s" % conf)
|
||||||
|
generator.PerformBuild(data, options.configs, params)
|
||||||
|
|
||||||
|
# Done
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def main(args):
|
||||||
|
try:
|
||||||
|
return gyp_main(args)
|
||||||
|
except GypError as e:
|
||||||
|
sys.stderr.write("gyp: %s\n" % e)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
# NOTE: console_scripts calls this function with no arguments
|
||||||
|
def script_main():
|
||||||
|
return main(sys.argv[1:])
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(script_main())
|
||||||
725
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/common.py
generated
vendored
Normal file
725
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/common.py
generated
vendored
Normal file
|
|
@ -0,0 +1,725 @@
|
||||||
|
# Copyright (c) 2012 Google Inc. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
import errno
|
||||||
|
import filecmp
|
||||||
|
import os.path
|
||||||
|
import re
|
||||||
|
import shlex
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
from collections.abc import MutableSet
|
||||||
|
|
||||||
|
|
||||||
|
# A minimal memoizing decorator. It'll blow up if the args aren't immutable,
|
||||||
|
# among other "problems".
|
||||||
|
class memoize:
|
||||||
|
def __init__(self, func):
|
||||||
|
self.func = func
|
||||||
|
self.cache = {}
|
||||||
|
|
||||||
|
def __call__(self, *args):
|
||||||
|
try:
|
||||||
|
return self.cache[args]
|
||||||
|
except KeyError:
|
||||||
|
result = self.func(*args)
|
||||||
|
self.cache[args] = result
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class GypError(Exception):
|
||||||
|
"""Error class representing an error, which is to be presented
|
||||||
|
to the user. The main entry point will catch and display this.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def ExceptionAppend(e, msg):
|
||||||
|
"""Append a message to the given exception's message."""
|
||||||
|
if not e.args:
|
||||||
|
e.args = (msg,)
|
||||||
|
elif len(e.args) == 1:
|
||||||
|
e.args = (str(e.args[0]) + " " + msg,)
|
||||||
|
else:
|
||||||
|
e.args = (str(e.args[0]) + " " + msg,) + e.args[1:]
|
||||||
|
|
||||||
|
|
||||||
|
def FindQualifiedTargets(target, qualified_list):
|
||||||
|
"""
|
||||||
|
Given a list of qualified targets, return the qualified targets for the
|
||||||
|
specified |target|.
|
||||||
|
"""
|
||||||
|
return [t for t in qualified_list if ParseQualifiedTarget(t)[1] == target]
|
||||||
|
|
||||||
|
|
||||||
|
def ParseQualifiedTarget(target):
|
||||||
|
# Splits a qualified target into a build file, target name and toolset.
|
||||||
|
|
||||||
|
# NOTE: rsplit is used to disambiguate the Windows drive letter separator.
|
||||||
|
target_split = target.rsplit(":", 1)
|
||||||
|
if len(target_split) == 2:
|
||||||
|
[build_file, target] = target_split
|
||||||
|
else:
|
||||||
|
build_file = None
|
||||||
|
|
||||||
|
target_split = target.rsplit("#", 1)
|
||||||
|
if len(target_split) == 2:
|
||||||
|
[target, toolset] = target_split
|
||||||
|
else:
|
||||||
|
toolset = None
|
||||||
|
|
||||||
|
return [build_file, target, toolset]
|
||||||
|
|
||||||
|
|
||||||
|
def ResolveTarget(build_file, target, toolset):
|
||||||
|
# This function resolves a target into a canonical form:
|
||||||
|
# - a fully defined build file, either absolute or relative to the current
|
||||||
|
# directory
|
||||||
|
# - a target name
|
||||||
|
# - a toolset
|
||||||
|
#
|
||||||
|
# build_file is the file relative to which 'target' is defined.
|
||||||
|
# target is the qualified target.
|
||||||
|
# toolset is the default toolset for that target.
|
||||||
|
[parsed_build_file, target, parsed_toolset] = ParseQualifiedTarget(target)
|
||||||
|
|
||||||
|
if parsed_build_file:
|
||||||
|
if build_file:
|
||||||
|
# If a relative path, parsed_build_file is relative to the directory
|
||||||
|
# containing build_file. If build_file is not in the current directory,
|
||||||
|
# parsed_build_file is not a usable path as-is. Resolve it by
|
||||||
|
# interpreting it as relative to build_file. If parsed_build_file is
|
||||||
|
# absolute, it is usable as a path regardless of the current directory,
|
||||||
|
# and os.path.join will return it as-is.
|
||||||
|
build_file = os.path.normpath(
|
||||||
|
os.path.join(os.path.dirname(build_file), parsed_build_file)
|
||||||
|
)
|
||||||
|
# Further (to handle cases like ../cwd), make it relative to cwd)
|
||||||
|
if not os.path.isabs(build_file):
|
||||||
|
build_file = RelativePath(build_file, ".")
|
||||||
|
else:
|
||||||
|
build_file = parsed_build_file
|
||||||
|
|
||||||
|
if parsed_toolset:
|
||||||
|
toolset = parsed_toolset
|
||||||
|
|
||||||
|
return [build_file, target, toolset]
|
||||||
|
|
||||||
|
|
||||||
|
def BuildFile(fully_qualified_target):
|
||||||
|
# Extracts the build file from the fully qualified target.
|
||||||
|
return ParseQualifiedTarget(fully_qualified_target)[0]
|
||||||
|
|
||||||
|
|
||||||
|
def GetEnvironFallback(var_list, default):
|
||||||
|
"""Look up a key in the environment, with fallback to secondary keys
|
||||||
|
and finally falling back to a default value."""
|
||||||
|
for var in var_list:
|
||||||
|
if var in os.environ:
|
||||||
|
return os.environ[var]
|
||||||
|
return default
|
||||||
|
|
||||||
|
|
||||||
|
def QualifiedTarget(build_file, target, toolset):
|
||||||
|
# "Qualified" means the file that a target was defined in and the target
|
||||||
|
# name, separated by a colon, suffixed by a # and the toolset name:
|
||||||
|
# /path/to/file.gyp:target_name#toolset
|
||||||
|
fully_qualified = build_file + ":" + target
|
||||||
|
if toolset:
|
||||||
|
fully_qualified = fully_qualified + "#" + toolset
|
||||||
|
return fully_qualified
|
||||||
|
|
||||||
|
|
||||||
|
@memoize
|
||||||
|
def RelativePath(path, relative_to, follow_path_symlink=True):
|
||||||
|
# Assuming both |path| and |relative_to| are relative to the current
|
||||||
|
# directory, returns a relative path that identifies path relative to
|
||||||
|
# relative_to.
|
||||||
|
# If |follow_symlink_path| is true (default) and |path| is a symlink, then
|
||||||
|
# this method returns a path to the real file represented by |path|. If it is
|
||||||
|
# false, this method returns a path to the symlink. If |path| is not a
|
||||||
|
# symlink, this option has no effect.
|
||||||
|
|
||||||
|
# Convert to normalized (and therefore absolute paths).
|
||||||
|
path = os.path.realpath(path) if follow_path_symlink else os.path.abspath(path)
|
||||||
|
relative_to = os.path.realpath(relative_to)
|
||||||
|
|
||||||
|
# On Windows, we can't create a relative path to a different drive, so just
|
||||||
|
# use the absolute path.
|
||||||
|
if sys.platform == "win32" and (
|
||||||
|
os.path.splitdrive(path)[0].lower()
|
||||||
|
!= os.path.splitdrive(relative_to)[0].lower()
|
||||||
|
):
|
||||||
|
return path
|
||||||
|
|
||||||
|
# Split the paths into components.
|
||||||
|
path_split = path.split(os.path.sep)
|
||||||
|
relative_to_split = relative_to.split(os.path.sep)
|
||||||
|
|
||||||
|
# Determine how much of the prefix the two paths share.
|
||||||
|
prefix_len = len(os.path.commonprefix([path_split, relative_to_split]))
|
||||||
|
|
||||||
|
# Put enough ".." components to back up out of relative_to to the common
|
||||||
|
# prefix, and then append the part of path_split after the common prefix.
|
||||||
|
relative_split = [os.path.pardir] * (
|
||||||
|
len(relative_to_split) - prefix_len
|
||||||
|
) + path_split[prefix_len:]
|
||||||
|
|
||||||
|
if len(relative_split) == 0:
|
||||||
|
# The paths were the same.
|
||||||
|
return ""
|
||||||
|
|
||||||
|
# Turn it back into a string and we're done.
|
||||||
|
return os.path.join(*relative_split)
|
||||||
|
|
||||||
|
|
||||||
|
@memoize
|
||||||
|
def InvertRelativePath(path, toplevel_dir=None):
|
||||||
|
"""Given a path like foo/bar that is relative to toplevel_dir, return
|
||||||
|
the inverse relative path back to the toplevel_dir.
|
||||||
|
|
||||||
|
E.g. os.path.normpath(os.path.join(path, InvertRelativePath(path)))
|
||||||
|
should always produce the empty string, unless the path contains symlinks.
|
||||||
|
"""
|
||||||
|
if not path:
|
||||||
|
return path
|
||||||
|
toplevel_dir = "." if toplevel_dir is None else toplevel_dir
|
||||||
|
return RelativePath(toplevel_dir, os.path.join(toplevel_dir, path))
|
||||||
|
|
||||||
|
|
||||||
|
def FixIfRelativePath(path, relative_to):
|
||||||
|
# Like RelativePath but returns |path| unchanged if it is absolute.
|
||||||
|
if os.path.isabs(path):
|
||||||
|
return path
|
||||||
|
return RelativePath(path, relative_to)
|
||||||
|
|
||||||
|
|
||||||
|
def UnrelativePath(path, relative_to):
|
||||||
|
# Assuming that |relative_to| is relative to the current directory, and |path|
|
||||||
|
# is a path relative to the dirname of |relative_to|, returns a path that
|
||||||
|
# identifies |path| relative to the current directory.
|
||||||
|
rel_dir = os.path.dirname(relative_to)
|
||||||
|
return os.path.normpath(os.path.join(rel_dir, path))
|
||||||
|
|
||||||
|
|
||||||
|
# re objects used by EncodePOSIXShellArgument. See IEEE 1003.1 XCU.2.2 at
|
||||||
|
# http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_02
|
||||||
|
# and the documentation for various shells.
|
||||||
|
|
||||||
|
# _quote is a pattern that should match any argument that needs to be quoted
|
||||||
|
# with double-quotes by EncodePOSIXShellArgument. It matches the following
|
||||||
|
# characters appearing anywhere in an argument:
|
||||||
|
# \t, \n, space parameter separators
|
||||||
|
# # comments
|
||||||
|
# $ expansions (quoted to always expand within one argument)
|
||||||
|
# % called out by IEEE 1003.1 XCU.2.2
|
||||||
|
# & job control
|
||||||
|
# ' quoting
|
||||||
|
# (, ) subshell execution
|
||||||
|
# *, ?, [ pathname expansion
|
||||||
|
# ; command delimiter
|
||||||
|
# <, >, | redirection
|
||||||
|
# = assignment
|
||||||
|
# {, } brace expansion (bash)
|
||||||
|
# ~ tilde expansion
|
||||||
|
# It also matches the empty string, because "" (or '') is the only way to
|
||||||
|
# represent an empty string literal argument to a POSIX shell.
|
||||||
|
#
|
||||||
|
# This does not match the characters in _escape, because those need to be
|
||||||
|
# backslash-escaped regardless of whether they appear in a double-quoted
|
||||||
|
# string.
|
||||||
|
_quote = re.compile("[\t\n #$%&'()*;<=>?[{|}~]|^$")
|
||||||
|
|
||||||
|
# _escape is a pattern that should match any character that needs to be
|
||||||
|
# escaped with a backslash, whether or not the argument matched the _quote
|
||||||
|
# pattern. _escape is used with re.sub to backslash anything in _escape's
|
||||||
|
# first match group, hence the (parentheses) in the regular expression.
|
||||||
|
#
|
||||||
|
# _escape matches the following characters appearing anywhere in an argument:
|
||||||
|
# " to prevent POSIX shells from interpreting this character for quoting
|
||||||
|
# \ to prevent POSIX shells from interpreting this character for escaping
|
||||||
|
# ` to prevent POSIX shells from interpreting this character for command
|
||||||
|
# substitution
|
||||||
|
# Missing from this list is $, because the desired behavior of
|
||||||
|
# EncodePOSIXShellArgument is to permit parameter (variable) expansion.
|
||||||
|
#
|
||||||
|
# Also missing from this list is !, which bash will interpret as the history
|
||||||
|
# expansion character when history is enabled. bash does not enable history
|
||||||
|
# by default in non-interactive shells, so this is not thought to be a problem.
|
||||||
|
# ! was omitted from this list because bash interprets "\!" as a literal string
|
||||||
|
# including the backslash character (avoiding history expansion but retaining
|
||||||
|
# the backslash), which would not be correct for argument encoding. Handling
|
||||||
|
# this case properly would also be problematic because bash allows the history
|
||||||
|
# character to be changed with the histchars shell variable. Fortunately,
|
||||||
|
# as history is not enabled in non-interactive shells and
|
||||||
|
# EncodePOSIXShellArgument is only expected to encode for non-interactive
|
||||||
|
# shells, there is no room for error here by ignoring !.
|
||||||
|
_escape = re.compile(r'(["\\`])')
|
||||||
|
|
||||||
|
|
||||||
|
def EncodePOSIXShellArgument(argument):
|
||||||
|
"""Encodes |argument| suitably for consumption by POSIX shells.
|
||||||
|
|
||||||
|
argument may be quoted and escaped as necessary to ensure that POSIX shells
|
||||||
|
treat the returned value as a literal representing the argument passed to
|
||||||
|
this function. Parameter (variable) expansions beginning with $ are allowed
|
||||||
|
to remain intact without escaping the $, to allow the argument to contain
|
||||||
|
references to variables to be expanded by the shell.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not isinstance(argument, str):
|
||||||
|
argument = str(argument)
|
||||||
|
|
||||||
|
quote = '"' if _quote.search(argument) else ""
|
||||||
|
|
||||||
|
encoded = quote + re.sub(_escape, r"\\\1", argument) + quote
|
||||||
|
|
||||||
|
return encoded
|
||||||
|
|
||||||
|
|
||||||
|
def EncodePOSIXShellList(list):
|
||||||
|
"""Encodes |list| suitably for consumption by POSIX shells.
|
||||||
|
|
||||||
|
Returns EncodePOSIXShellArgument for each item in list, and joins them
|
||||||
|
together using the space character as an argument separator.
|
||||||
|
"""
|
||||||
|
|
||||||
|
encoded_arguments = []
|
||||||
|
for argument in list:
|
||||||
|
encoded_arguments.append(EncodePOSIXShellArgument(argument))
|
||||||
|
return " ".join(encoded_arguments)
|
||||||
|
|
||||||
|
|
||||||
|
def DeepDependencyTargets(target_dicts, roots):
|
||||||
|
"""Returns the recursive list of target dependencies."""
|
||||||
|
dependencies = set()
|
||||||
|
pending = set(roots)
|
||||||
|
while pending:
|
||||||
|
# Pluck out one.
|
||||||
|
r = pending.pop()
|
||||||
|
# Skip if visited already.
|
||||||
|
if r in dependencies:
|
||||||
|
continue
|
||||||
|
# Add it.
|
||||||
|
dependencies.add(r)
|
||||||
|
# Add its children.
|
||||||
|
spec = target_dicts[r]
|
||||||
|
pending.update(set(spec.get("dependencies", [])))
|
||||||
|
pending.update(set(spec.get("dependencies_original", [])))
|
||||||
|
return list(dependencies - set(roots))
|
||||||
|
|
||||||
|
|
||||||
|
def BuildFileTargets(target_list, build_file):
|
||||||
|
"""From a target_list, returns the subset from the specified build_file."""
|
||||||
|
return [p for p in target_list if BuildFile(p) == build_file]
|
||||||
|
|
||||||
|
|
||||||
|
def AllTargets(target_list, target_dicts, build_file):
|
||||||
|
"""Returns all targets (direct and dependencies) for the specified build_file."""
|
||||||
|
bftargets = BuildFileTargets(target_list, build_file)
|
||||||
|
deptargets = DeepDependencyTargets(target_dicts, bftargets)
|
||||||
|
return bftargets + deptargets
|
||||||
|
|
||||||
|
|
||||||
|
def WriteOnDiff(filename):
|
||||||
|
"""Write to a file only if the new contents differ.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
filename: name of the file to potentially write to.
|
||||||
|
Returns:
|
||||||
|
A file like object which will write to temporary file and only overwrite
|
||||||
|
the target if it differs (on close).
|
||||||
|
"""
|
||||||
|
|
||||||
|
class Writer:
|
||||||
|
"""Wrapper around file which only covers the target if it differs."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
# On Cygwin remove the "dir" argument
|
||||||
|
# `C:` prefixed paths are treated as relative,
|
||||||
|
# consequently ending up with current dir "/cygdrive/c/..."
|
||||||
|
# being prefixed to those, which was
|
||||||
|
# obviously a non-existent path,
|
||||||
|
# for example: "/cygdrive/c/<some folder>/C:\<my win style abs path>".
|
||||||
|
# For more details see:
|
||||||
|
# https://docs.python.org/2/library/tempfile.html#tempfile.mkstemp
|
||||||
|
base_temp_dir = "" if IsCygwin() else os.path.dirname(filename)
|
||||||
|
# Pick temporary file.
|
||||||
|
tmp_fd, self.tmp_path = tempfile.mkstemp(
|
||||||
|
suffix=".tmp",
|
||||||
|
prefix=os.path.split(filename)[1] + ".gyp.",
|
||||||
|
dir=base_temp_dir,
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
self.tmp_file = os.fdopen(tmp_fd, "wb")
|
||||||
|
except Exception:
|
||||||
|
# Don't leave turds behind.
|
||||||
|
os.unlink(self.tmp_path)
|
||||||
|
raise
|
||||||
|
|
||||||
|
def __getattr__(self, attrname):
|
||||||
|
# Delegate everything else to self.tmp_file
|
||||||
|
return getattr(self.tmp_file, attrname)
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
try:
|
||||||
|
# Close tmp file.
|
||||||
|
self.tmp_file.close()
|
||||||
|
# Determine if different.
|
||||||
|
same = False
|
||||||
|
try:
|
||||||
|
same = filecmp.cmp(self.tmp_path, filename, False)
|
||||||
|
except OSError as e:
|
||||||
|
if e.errno != errno.ENOENT:
|
||||||
|
raise
|
||||||
|
|
||||||
|
if same:
|
||||||
|
# The new file is identical to the old one, just get rid of the new
|
||||||
|
# one.
|
||||||
|
os.unlink(self.tmp_path)
|
||||||
|
else:
|
||||||
|
# The new file is different from the old one,
|
||||||
|
# or there is no old one.
|
||||||
|
# Rename the new file to the permanent name.
|
||||||
|
#
|
||||||
|
# tempfile.mkstemp uses an overly restrictive mode, resulting in a
|
||||||
|
# file that can only be read by the owner, regardless of the umask.
|
||||||
|
# There's no reason to not respect the umask here,
|
||||||
|
# which means that an extra hoop is required
|
||||||
|
# to fetch it and reset the new file's mode.
|
||||||
|
#
|
||||||
|
# No way to get the umask without setting a new one? Set a safe one
|
||||||
|
# and then set it back to the old value.
|
||||||
|
umask = os.umask(0o77)
|
||||||
|
os.umask(umask)
|
||||||
|
os.chmod(self.tmp_path, 0o666 & ~umask)
|
||||||
|
if sys.platform == "win32" and os.path.exists(filename):
|
||||||
|
# NOTE: on windows (but not cygwin) rename will not replace an
|
||||||
|
# existing file, so it must be preceded with a remove.
|
||||||
|
# Sadly there is no way to make the switch atomic.
|
||||||
|
os.remove(filename)
|
||||||
|
os.rename(self.tmp_path, filename)
|
||||||
|
except Exception:
|
||||||
|
# Don't leave turds behind.
|
||||||
|
os.unlink(self.tmp_path)
|
||||||
|
raise
|
||||||
|
|
||||||
|
def write(self, s):
|
||||||
|
self.tmp_file.write(s.encode("utf-8"))
|
||||||
|
|
||||||
|
return Writer()
|
||||||
|
|
||||||
|
|
||||||
|
def EnsureDirExists(path):
|
||||||
|
"""Make sure the directory for |path| exists."""
|
||||||
|
try:
|
||||||
|
os.makedirs(os.path.dirname(path))
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def GetCompilerPredefines(): # -> dict
|
||||||
|
cmd = []
|
||||||
|
defines = {}
|
||||||
|
|
||||||
|
# shlex.split() will eat '\' in posix mode, but
|
||||||
|
# setting posix=False will preserve extra '"' cause CreateProcess fail on Windows
|
||||||
|
# this makes '\' in %CC_target% and %CFLAGS% work
|
||||||
|
def replace_sep(s):
|
||||||
|
return s.replace(os.sep, "/") if os.sep != "/" else s
|
||||||
|
|
||||||
|
if CC := os.environ.get("CC_target") or os.environ.get("CC"):
|
||||||
|
cmd += shlex.split(replace_sep(CC))
|
||||||
|
if CFLAGS := os.environ.get("CFLAGS"):
|
||||||
|
cmd += shlex.split(replace_sep(CFLAGS))
|
||||||
|
elif CXX := os.environ.get("CXX_target") or os.environ.get("CXX"):
|
||||||
|
cmd += shlex.split(replace_sep(CXX))
|
||||||
|
if CXXFLAGS := os.environ.get("CXXFLAGS"):
|
||||||
|
cmd += shlex.split(replace_sep(CXXFLAGS))
|
||||||
|
else:
|
||||||
|
return defines
|
||||||
|
|
||||||
|
if sys.platform == "win32":
|
||||||
|
fd, input = tempfile.mkstemp(suffix=".c")
|
||||||
|
real_cmd = [*cmd, "-dM", "-E", "-x", "c", input]
|
||||||
|
try:
|
||||||
|
os.close(fd)
|
||||||
|
stdout = subprocess.run(
|
||||||
|
real_cmd, shell=True, capture_output=True, check=True
|
||||||
|
).stdout
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(
|
||||||
|
"Warning: failed to get compiler predefines\n"
|
||||||
|
"cmd: %s\n"
|
||||||
|
"status: %d" % (e.cmd, e.returncode),
|
||||||
|
file=sys.stderr,
|
||||||
|
)
|
||||||
|
return defines
|
||||||
|
finally:
|
||||||
|
os.unlink(input)
|
||||||
|
else:
|
||||||
|
input = "/dev/null"
|
||||||
|
real_cmd = [*cmd, "-dM", "-E", "-x", "c", input]
|
||||||
|
try:
|
||||||
|
stdout = subprocess.run(
|
||||||
|
real_cmd, shell=False, capture_output=True, check=True
|
||||||
|
).stdout
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(
|
||||||
|
"Warning: failed to get compiler predefines\n"
|
||||||
|
"cmd: %s\n"
|
||||||
|
"status: %d" % (e.cmd, e.returncode),
|
||||||
|
file=sys.stderr,
|
||||||
|
)
|
||||||
|
return defines
|
||||||
|
|
||||||
|
lines = stdout.decode("utf-8").replace("\r\n", "\n").split("\n")
|
||||||
|
for line in lines:
|
||||||
|
if (line or "").startswith("#define "):
|
||||||
|
_, key, *value = line.split(" ")
|
||||||
|
defines[key] = " ".join(value)
|
||||||
|
return defines
|
||||||
|
|
||||||
|
|
||||||
|
def GetFlavorByPlatform():
|
||||||
|
"""Returns |params.flavor| if it's set, the system's default flavor else."""
|
||||||
|
flavors = {
|
||||||
|
"cygwin": "win",
|
||||||
|
"win32": "win",
|
||||||
|
"darwin": "mac",
|
||||||
|
}
|
||||||
|
|
||||||
|
if sys.platform in flavors:
|
||||||
|
return flavors[sys.platform]
|
||||||
|
if sys.platform.startswith("sunos"):
|
||||||
|
return "solaris"
|
||||||
|
if sys.platform.startswith(("dragonfly", "freebsd")):
|
||||||
|
return "freebsd"
|
||||||
|
if sys.platform.startswith("openbsd"):
|
||||||
|
return "openbsd"
|
||||||
|
if sys.platform.startswith("netbsd"):
|
||||||
|
return "netbsd"
|
||||||
|
if sys.platform.startswith("aix"):
|
||||||
|
return "aix"
|
||||||
|
if sys.platform.startswith(("os390", "zos")):
|
||||||
|
return "zos"
|
||||||
|
if sys.platform == "os400":
|
||||||
|
return "os400"
|
||||||
|
|
||||||
|
return "linux"
|
||||||
|
|
||||||
|
|
||||||
|
def GetFlavor(params):
|
||||||
|
if "flavor" in params:
|
||||||
|
return params["flavor"]
|
||||||
|
|
||||||
|
defines = GetCompilerPredefines()
|
||||||
|
if "__EMSCRIPTEN__" in defines:
|
||||||
|
return "emscripten"
|
||||||
|
if "__wasm__" in defines:
|
||||||
|
return "wasi" if "__wasi__" in defines else "wasm"
|
||||||
|
|
||||||
|
return GetFlavorByPlatform()
|
||||||
|
|
||||||
|
|
||||||
|
def CopyTool(flavor, out_path, generator_flags={}):
|
||||||
|
"""Finds (flock|mac|win)_tool.gyp in the gyp directory and copies it
|
||||||
|
to |out_path|."""
|
||||||
|
# aix and solaris just need flock emulation. mac and win use more complicated
|
||||||
|
# support scripts.
|
||||||
|
prefix = {
|
||||||
|
"aix": "flock",
|
||||||
|
"os400": "flock",
|
||||||
|
"solaris": "flock",
|
||||||
|
"mac": "mac",
|
||||||
|
"ios": "mac",
|
||||||
|
"win": "win",
|
||||||
|
}.get(flavor, None)
|
||||||
|
if not prefix:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Slurp input file.
|
||||||
|
source_path = os.path.join(
|
||||||
|
os.path.dirname(os.path.abspath(__file__)), "%s_tool.py" % prefix
|
||||||
|
)
|
||||||
|
with open(source_path) as source_file:
|
||||||
|
source = source_file.readlines()
|
||||||
|
|
||||||
|
# Set custom header flags.
|
||||||
|
header = "# Generated by gyp. Do not edit.\n"
|
||||||
|
mac_toolchain_dir = generator_flags.get("mac_toolchain_dir", None)
|
||||||
|
if flavor == "mac" and mac_toolchain_dir:
|
||||||
|
header += "import os;\nos.environ['DEVELOPER_DIR']='%s'\n" % mac_toolchain_dir
|
||||||
|
|
||||||
|
# Add header and write it out.
|
||||||
|
tool_path = os.path.join(out_path, "gyp-%s-tool" % prefix)
|
||||||
|
with open(tool_path, "w") as tool_file:
|
||||||
|
tool_file.write("".join([source[0], header] + source[1:]))
|
||||||
|
|
||||||
|
# Make file executable.
|
||||||
|
os.chmod(tool_path, 0o755)
|
||||||
|
|
||||||
|
|
||||||
|
# From Alex Martelli,
|
||||||
|
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52560
|
||||||
|
# ASPN: Python Cookbook: Remove duplicates from a sequence
|
||||||
|
# First comment, dated 2001/10/13.
|
||||||
|
# (Also in the printed Python Cookbook.)
|
||||||
|
|
||||||
|
|
||||||
|
def uniquer(seq, idfun=lambda x: x):
|
||||||
|
seen = {}
|
||||||
|
result = []
|
||||||
|
for item in seq:
|
||||||
|
marker = idfun(item)
|
||||||
|
if marker in seen:
|
||||||
|
continue
|
||||||
|
seen[marker] = 1
|
||||||
|
result.append(item)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
# Based on http://code.activestate.com/recipes/576694/.
|
||||||
|
class OrderedSet(MutableSet): # noqa: PLW1641
|
||||||
|
# TODO (cclauss): Fix eq-without-hash ruff rule PLW1641
|
||||||
|
def __init__(self, iterable=None):
|
||||||
|
self.end = end = []
|
||||||
|
end += [None, end, end] # sentinel node for doubly linked list
|
||||||
|
self.map = {} # key --> [key, prev, next]
|
||||||
|
if iterable is not None:
|
||||||
|
self |= iterable
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.map)
|
||||||
|
|
||||||
|
def __contains__(self, key):
|
||||||
|
return key in self.map
|
||||||
|
|
||||||
|
def add(self, key):
|
||||||
|
if key not in self.map:
|
||||||
|
end = self.end
|
||||||
|
curr = end[1]
|
||||||
|
curr[2] = end[1] = self.map[key] = [key, curr, end]
|
||||||
|
|
||||||
|
def discard(self, key):
|
||||||
|
if key in self.map:
|
||||||
|
key, prev_item, next_item = self.map.pop(key)
|
||||||
|
prev_item[2] = next_item
|
||||||
|
next_item[1] = prev_item
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
end = self.end
|
||||||
|
curr = end[2]
|
||||||
|
while curr is not end:
|
||||||
|
yield curr[0]
|
||||||
|
curr = curr[2]
|
||||||
|
|
||||||
|
def __reversed__(self):
|
||||||
|
end = self.end
|
||||||
|
curr = end[1]
|
||||||
|
while curr is not end:
|
||||||
|
yield curr[0]
|
||||||
|
curr = curr[1]
|
||||||
|
|
||||||
|
# The second argument is an addition that causes a pylint warning.
|
||||||
|
def pop(self, last=True): # pylint: disable=W0221
|
||||||
|
if not self:
|
||||||
|
raise KeyError("set is empty")
|
||||||
|
key = self.end[1][0] if last else self.end[2][0]
|
||||||
|
self.discard(key)
|
||||||
|
return key
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
if not self:
|
||||||
|
return f"{self.__class__.__name__}()"
|
||||||
|
return f"{self.__class__.__name__}({list(self)!r})"
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
if isinstance(other, OrderedSet):
|
||||||
|
return len(self) == len(other) and list(self) == list(other)
|
||||||
|
return set(self) == set(other)
|
||||||
|
|
||||||
|
# Extensions to the recipe.
|
||||||
|
def update(self, iterable):
|
||||||
|
for i in iterable:
|
||||||
|
if i not in self:
|
||||||
|
self.add(i)
|
||||||
|
|
||||||
|
|
||||||
|
class CycleError(Exception):
|
||||||
|
"""An exception raised when an unexpected cycle is detected."""
|
||||||
|
|
||||||
|
def __init__(self, nodes):
|
||||||
|
self.nodes = nodes
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "CycleError: cycle involving: " + str(self.nodes)
|
||||||
|
|
||||||
|
|
||||||
|
def TopologicallySorted(graph, get_edges):
|
||||||
|
r"""Topologically sort based on a user provided edge definition.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
graph: A list of node names.
|
||||||
|
get_edges: A function mapping from node name to a hashable collection
|
||||||
|
of node names which this node has outgoing edges to.
|
||||||
|
Returns:
|
||||||
|
A list containing all of the node in graph in topological order.
|
||||||
|
It is assumed that calling get_edges once for each node and caching is
|
||||||
|
cheaper than repeatedly calling get_edges.
|
||||||
|
Raises:
|
||||||
|
CycleError in the event of a cycle.
|
||||||
|
Example:
|
||||||
|
graph = {'a': '$(b) $(c)', 'b': 'hi', 'c': '$(b)'}
|
||||||
|
def GetEdges(node):
|
||||||
|
return re.findall(r'\$\(([^))]\)', graph[node])
|
||||||
|
print TopologicallySorted(graph.keys(), GetEdges)
|
||||||
|
==>
|
||||||
|
['a', 'c', b']
|
||||||
|
"""
|
||||||
|
get_edges = memoize(get_edges)
|
||||||
|
visited = set()
|
||||||
|
visiting = set()
|
||||||
|
ordered_nodes = []
|
||||||
|
|
||||||
|
def Visit(node):
|
||||||
|
if node in visiting:
|
||||||
|
raise CycleError(visiting)
|
||||||
|
if node in visited:
|
||||||
|
return
|
||||||
|
visited.add(node)
|
||||||
|
visiting.add(node)
|
||||||
|
for neighbor in get_edges(node):
|
||||||
|
Visit(neighbor)
|
||||||
|
visiting.remove(node)
|
||||||
|
ordered_nodes.insert(0, node)
|
||||||
|
|
||||||
|
for node in sorted(graph):
|
||||||
|
Visit(node)
|
||||||
|
return ordered_nodes
|
||||||
|
|
||||||
|
|
||||||
|
def CrossCompileRequested():
|
||||||
|
# TODO: figure out how to not build extra host objects in the
|
||||||
|
# non-cross-compile case when this is enabled, and enable unconditionally.
|
||||||
|
return (
|
||||||
|
os.environ.get("GYP_CROSSCOMPILE")
|
||||||
|
or os.environ.get("AR_host")
|
||||||
|
or os.environ.get("CC_host")
|
||||||
|
or os.environ.get("CXX_host")
|
||||||
|
or os.environ.get("AR_target")
|
||||||
|
or os.environ.get("CC_target")
|
||||||
|
or os.environ.get("CXX_target")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def IsCygwin():
|
||||||
|
try:
|
||||||
|
out = subprocess.Popen(
|
||||||
|
"uname", stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
||||||
|
)
|
||||||
|
stdout = out.communicate()[0].decode("utf-8")
|
||||||
|
return "CYGWIN" in str(stdout)
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
186
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/common_test.py
generated
vendored
Normal file
186
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/common_test.py
generated
vendored
Normal file
|
|
@ -0,0 +1,186 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Copyright (c) 2012 Google Inc. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
"""Unit tests for the common.py file."""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
|
import gyp.common
|
||||||
|
|
||||||
|
|
||||||
|
class TestTopologicallySorted(unittest.TestCase):
|
||||||
|
def test_Valid(self):
|
||||||
|
"""Test that sorting works on a valid graph with one possible order."""
|
||||||
|
graph = {
|
||||||
|
"a": ["b", "c"],
|
||||||
|
"b": [],
|
||||||
|
"c": ["d"],
|
||||||
|
"d": ["b"],
|
||||||
|
}
|
||||||
|
|
||||||
|
def GetEdge(node):
|
||||||
|
return tuple(graph[node])
|
||||||
|
|
||||||
|
assert gyp.common.TopologicallySorted(graph.keys(), GetEdge) == [
|
||||||
|
"a",
|
||||||
|
"c",
|
||||||
|
"d",
|
||||||
|
"b",
|
||||||
|
]
|
||||||
|
|
||||||
|
def test_Cycle(self):
|
||||||
|
"""Test that an exception is thrown on a cyclic graph."""
|
||||||
|
graph = {
|
||||||
|
"a": ["b"],
|
||||||
|
"b": ["c"],
|
||||||
|
"c": ["d"],
|
||||||
|
"d": ["a"],
|
||||||
|
}
|
||||||
|
|
||||||
|
def GetEdge(node):
|
||||||
|
return tuple(graph[node])
|
||||||
|
|
||||||
|
self.assertRaises(
|
||||||
|
gyp.common.CycleError, gyp.common.TopologicallySorted, graph.keys(), GetEdge
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestGetFlavor(unittest.TestCase):
|
||||||
|
"""Test that gyp.common.GetFlavor works as intended"""
|
||||||
|
|
||||||
|
original_platform = ""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.original_platform = sys.platform
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
sys.platform = self.original_platform
|
||||||
|
|
||||||
|
def assertFlavor(self, expected, argument, param):
|
||||||
|
sys.platform = argument
|
||||||
|
assert expected == gyp.common.GetFlavor(param)
|
||||||
|
|
||||||
|
def test_platform_default(self):
|
||||||
|
self.assertFlavor("freebsd", "freebsd9", {})
|
||||||
|
self.assertFlavor("freebsd", "freebsd10", {})
|
||||||
|
self.assertFlavor("openbsd", "openbsd5", {})
|
||||||
|
self.assertFlavor("solaris", "sunos5", {})
|
||||||
|
self.assertFlavor("solaris", "sunos", {})
|
||||||
|
self.assertFlavor("linux", "linux2", {})
|
||||||
|
self.assertFlavor("linux", "linux3", {})
|
||||||
|
self.assertFlavor("linux", "linux", {})
|
||||||
|
|
||||||
|
def test_param(self):
|
||||||
|
self.assertFlavor("foobar", "linux2", {"flavor": "foobar"})
|
||||||
|
|
||||||
|
class MockCommunicate:
|
||||||
|
def __init__(self, stdout):
|
||||||
|
self.stdout = stdout
|
||||||
|
|
||||||
|
def decode(self, encoding):
|
||||||
|
return self.stdout
|
||||||
|
|
||||||
|
@patch("os.close")
|
||||||
|
@patch("os.unlink")
|
||||||
|
@patch("tempfile.mkstemp")
|
||||||
|
def test_GetCompilerPredefines(self, mock_mkstemp, mock_unlink, mock_close):
|
||||||
|
mock_close.return_value = None
|
||||||
|
mock_unlink.return_value = None
|
||||||
|
mock_mkstemp.return_value = (0, "temp.c")
|
||||||
|
|
||||||
|
def mock_run(env, defines_stdout, expected_cmd, throws=False):
|
||||||
|
with patch("subprocess.run") as mock_run:
|
||||||
|
expected_input = "temp.c" if sys.platform == "win32" else "/dev/null"
|
||||||
|
if throws:
|
||||||
|
mock_run.side_effect = subprocess.CalledProcessError(
|
||||||
|
returncode=1,
|
||||||
|
cmd=[*expected_cmd, "-dM", "-E", "-x", "c", expected_input],
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
mock_process = MagicMock()
|
||||||
|
mock_process.returncode = 0
|
||||||
|
mock_process.stdout = TestGetFlavor.MockCommunicate(defines_stdout)
|
||||||
|
mock_run.return_value = mock_process
|
||||||
|
with patch.dict(os.environ, env):
|
||||||
|
try:
|
||||||
|
defines = gyp.common.GetCompilerPredefines()
|
||||||
|
except Exception as e:
|
||||||
|
self.fail(f"GetCompilerPredefines raised an exception: {e}")
|
||||||
|
flavor = gyp.common.GetFlavor({})
|
||||||
|
if env.get("CC_target") or env.get("CC"):
|
||||||
|
mock_run.assert_called_with(
|
||||||
|
[*expected_cmd, "-dM", "-E", "-x", "c", expected_input],
|
||||||
|
shell=sys.platform == "win32",
|
||||||
|
capture_output=True,
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
return [defines, flavor]
|
||||||
|
|
||||||
|
[defines0, _] = mock_run({"CC": "cl.exe"}, "", ["cl.exe"], True)
|
||||||
|
assert defines0 == {}
|
||||||
|
|
||||||
|
[defines1, _] = mock_run({}, "", [])
|
||||||
|
assert defines1 == {}
|
||||||
|
|
||||||
|
[defines2, flavor2] = mock_run(
|
||||||
|
{"CC_target": "/opt/wasi-sdk/bin/clang"},
|
||||||
|
"#define __wasm__ 1\n#define __wasi__ 1\n",
|
||||||
|
["/opt/wasi-sdk/bin/clang"],
|
||||||
|
)
|
||||||
|
assert defines2 == {"__wasm__": "1", "__wasi__": "1"}
|
||||||
|
assert flavor2 == "wasi"
|
||||||
|
|
||||||
|
[defines3, flavor3] = mock_run(
|
||||||
|
{"CC_target": "/opt/wasi-sdk/bin/clang --target=wasm32"},
|
||||||
|
"#define __wasm__ 1\n",
|
||||||
|
["/opt/wasi-sdk/bin/clang", "--target=wasm32"],
|
||||||
|
)
|
||||||
|
assert defines3 == {"__wasm__": "1"}
|
||||||
|
assert flavor3 == "wasm"
|
||||||
|
|
||||||
|
[defines4, flavor4] = mock_run(
|
||||||
|
{"CC_target": "/emsdk/upstream/emscripten/emcc"},
|
||||||
|
"#define __EMSCRIPTEN__ 1\n",
|
||||||
|
["/emsdk/upstream/emscripten/emcc"],
|
||||||
|
)
|
||||||
|
assert defines4 == {"__EMSCRIPTEN__": "1"}
|
||||||
|
assert flavor4 == "emscripten"
|
||||||
|
|
||||||
|
# Test path which include white space
|
||||||
|
[defines5, flavor5] = mock_run(
|
||||||
|
{
|
||||||
|
"CC_target": '"/Users/Toyo Li/wasi-sdk/bin/clang" -O3',
|
||||||
|
"CFLAGS": "--target=wasm32-wasi-threads -pthread",
|
||||||
|
},
|
||||||
|
"#define __wasm__ 1\n#define __wasi__ 1\n#define _REENTRANT 1\n",
|
||||||
|
[
|
||||||
|
"/Users/Toyo Li/wasi-sdk/bin/clang",
|
||||||
|
"-O3",
|
||||||
|
"--target=wasm32-wasi-threads",
|
||||||
|
"-pthread",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
assert defines5 == {"__wasm__": "1", "__wasi__": "1", "_REENTRANT": "1"}
|
||||||
|
assert flavor5 == "wasi"
|
||||||
|
|
||||||
|
original_sep = os.sep
|
||||||
|
os.sep = "\\"
|
||||||
|
[defines6, flavor6] = mock_run(
|
||||||
|
{"CC_target": '"C:\\Program Files\\wasi-sdk\\clang.exe"'},
|
||||||
|
"#define __wasm__ 1\n#define __wasi__ 1\n",
|
||||||
|
["C:/Program Files/wasi-sdk/clang.exe"],
|
||||||
|
)
|
||||||
|
os.sep = original_sep
|
||||||
|
assert defines6 == {"__wasm__": "1", "__wasi__": "1"}
|
||||||
|
assert flavor6 == "wasi"
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
170
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/easy_xml.py
generated
vendored
Normal file
170
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/easy_xml.py
generated
vendored
Normal file
|
|
@ -0,0 +1,170 @@
|
||||||
|
# Copyright (c) 2011 Google Inc. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
import locale
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from functools import reduce
|
||||||
|
|
||||||
|
|
||||||
|
def XmlToString(content, encoding="utf-8", pretty=False):
|
||||||
|
"""Writes the XML content to disk, touching the file only if it has changed.
|
||||||
|
|
||||||
|
Visual Studio files have a lot of pre-defined structures. This function makes
|
||||||
|
it easy to represent these structures as Python data structures, instead of
|
||||||
|
having to create a lot of function calls.
|
||||||
|
|
||||||
|
Each XML element of the content is represented as a list composed of:
|
||||||
|
1. The name of the element, a string,
|
||||||
|
2. The attributes of the element, a dictionary (optional), and
|
||||||
|
3+. The content of the element, if any. Strings are simple text nodes and
|
||||||
|
lists are child elements.
|
||||||
|
|
||||||
|
Example 1:
|
||||||
|
<test/>
|
||||||
|
becomes
|
||||||
|
['test']
|
||||||
|
|
||||||
|
Example 2:
|
||||||
|
<myelement a='value1' b='value2'>
|
||||||
|
<childtype>This is</childtype>
|
||||||
|
<childtype>it!</childtype>
|
||||||
|
</myelement>
|
||||||
|
|
||||||
|
becomes
|
||||||
|
['myelement', {'a':'value1', 'b':'value2'},
|
||||||
|
['childtype', 'This is'],
|
||||||
|
['childtype', 'it!'],
|
||||||
|
]
|
||||||
|
|
||||||
|
Args:
|
||||||
|
content: The structured content to be converted.
|
||||||
|
encoding: The encoding to report on the first XML line.
|
||||||
|
pretty: True if we want pretty printing with indents and new lines.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The XML content as a string.
|
||||||
|
"""
|
||||||
|
# We create a huge list of all the elements of the file.
|
||||||
|
xml_parts = ['<?xml version="1.0" encoding="%s"?>' % encoding]
|
||||||
|
if pretty:
|
||||||
|
xml_parts.append("\n")
|
||||||
|
_ConstructContentList(xml_parts, content, pretty)
|
||||||
|
|
||||||
|
# Convert it to a string
|
||||||
|
return "".join(xml_parts)
|
||||||
|
|
||||||
|
|
||||||
|
def _ConstructContentList(xml_parts, specification, pretty, level=0):
|
||||||
|
"""Appends the XML parts corresponding to the specification.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
xml_parts: A list of XML parts to be appended to.
|
||||||
|
specification: The specification of the element. See EasyXml docs.
|
||||||
|
pretty: True if we want pretty printing with indents and new lines.
|
||||||
|
level: Indentation level.
|
||||||
|
"""
|
||||||
|
# The first item in a specification is the name of the element.
|
||||||
|
if pretty:
|
||||||
|
indentation = " " * level
|
||||||
|
new_line = "\n"
|
||||||
|
else:
|
||||||
|
indentation = ""
|
||||||
|
new_line = ""
|
||||||
|
name = specification[0]
|
||||||
|
if not isinstance(name, str):
|
||||||
|
raise Exception(
|
||||||
|
"The first item of an EasyXml specification should be "
|
||||||
|
"a string. Specification was " + str(specification)
|
||||||
|
)
|
||||||
|
xml_parts.append(indentation + "<" + name)
|
||||||
|
|
||||||
|
# Optionally in second position is a dictionary of the attributes.
|
||||||
|
rest = specification[1:]
|
||||||
|
if rest and isinstance(rest[0], dict):
|
||||||
|
for at, val in sorted(rest[0].items()):
|
||||||
|
xml_parts.append(f' {at}="{_XmlEscape(val, attr=True)}"')
|
||||||
|
rest = rest[1:]
|
||||||
|
if rest:
|
||||||
|
xml_parts.append(">")
|
||||||
|
all_strings = reduce(lambda x, y: x and isinstance(y, str), rest, True)
|
||||||
|
multi_line = not all_strings
|
||||||
|
if multi_line and new_line:
|
||||||
|
xml_parts.append(new_line)
|
||||||
|
for child_spec in rest:
|
||||||
|
# If it's a string, append a text node.
|
||||||
|
# Otherwise recurse over that child definition
|
||||||
|
if isinstance(child_spec, str):
|
||||||
|
xml_parts.append(_XmlEscape(child_spec))
|
||||||
|
else:
|
||||||
|
_ConstructContentList(xml_parts, child_spec, pretty, level + 1)
|
||||||
|
if multi_line and indentation:
|
||||||
|
xml_parts.append(indentation)
|
||||||
|
xml_parts.append(f"</{name}>{new_line}")
|
||||||
|
else:
|
||||||
|
xml_parts.append("/>%s" % new_line)
|
||||||
|
|
||||||
|
|
||||||
|
def WriteXmlIfChanged(
|
||||||
|
content, path, encoding="utf-8", pretty=False, win32=(sys.platform == "win32")
|
||||||
|
):
|
||||||
|
"""Writes the XML content to disk, touching the file only if it has changed.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
content: The structured content to be written.
|
||||||
|
path: Location of the file.
|
||||||
|
encoding: The encoding to report on the first line of the XML file.
|
||||||
|
pretty: True if we want pretty printing with indents and new lines.
|
||||||
|
"""
|
||||||
|
xml_string = XmlToString(content, encoding, pretty)
|
||||||
|
if win32 and os.linesep != "\r\n":
|
||||||
|
xml_string = xml_string.replace("\n", "\r\n")
|
||||||
|
|
||||||
|
try: # getdefaultlocale() was removed in Python 3.11
|
||||||
|
default_encoding = locale.getdefaultlocale()[1]
|
||||||
|
except AttributeError:
|
||||||
|
default_encoding = locale.getencoding()
|
||||||
|
|
||||||
|
if default_encoding and default_encoding.upper() != encoding.upper():
|
||||||
|
xml_string = xml_string.encode(encoding)
|
||||||
|
|
||||||
|
# Get the old content
|
||||||
|
try:
|
||||||
|
with open(path) as file:
|
||||||
|
existing = file.read()
|
||||||
|
except OSError:
|
||||||
|
existing = None
|
||||||
|
|
||||||
|
# It has changed, write it
|
||||||
|
if existing != xml_string:
|
||||||
|
with open(path, "wb") as file:
|
||||||
|
file.write(xml_string)
|
||||||
|
|
||||||
|
|
||||||
|
_xml_escape_map = {
|
||||||
|
'"': """,
|
||||||
|
"'": "'",
|
||||||
|
"<": "<",
|
||||||
|
">": ">",
|
||||||
|
"&": "&",
|
||||||
|
"\n": "
",
|
||||||
|
"\r": "
",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_xml_escape_re = re.compile("(%s)" % "|".join(map(re.escape, _xml_escape_map.keys())))
|
||||||
|
|
||||||
|
|
||||||
|
def _XmlEscape(value, attr=False):
|
||||||
|
"""Escape a string for inclusion in XML."""
|
||||||
|
|
||||||
|
def replace(match):
|
||||||
|
m = match.string[match.start() : match.end()]
|
||||||
|
# don't replace single quotes in attrs
|
||||||
|
if attr and m == "'":
|
||||||
|
return m
|
||||||
|
return _xml_escape_map[m]
|
||||||
|
|
||||||
|
return _xml_escape_re.sub(replace, value)
|
||||||
113
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/easy_xml_test.py
generated
vendored
Normal file
113
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/easy_xml_test.py
generated
vendored
Normal file
|
|
@ -0,0 +1,113 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Copyright (c) 2011 Google Inc. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
"""Unit tests for the easy_xml.py file."""
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from io import StringIO
|
||||||
|
|
||||||
|
from gyp import easy_xml
|
||||||
|
|
||||||
|
|
||||||
|
class TestSequenceFunctions(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.stderr = StringIO()
|
||||||
|
|
||||||
|
def test_EasyXml_simple(self):
|
||||||
|
self.assertEqual(
|
||||||
|
easy_xml.XmlToString(["test"]),
|
||||||
|
'<?xml version="1.0" encoding="utf-8"?><test/>',
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
easy_xml.XmlToString(["test"], encoding="Windows-1252"),
|
||||||
|
'<?xml version="1.0" encoding="Windows-1252"?><test/>',
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_EasyXml_simple_with_attributes(self):
|
||||||
|
self.assertEqual(
|
||||||
|
easy_xml.XmlToString(["test2", {"a": "value1", "b": "value2"}]),
|
||||||
|
'<?xml version="1.0" encoding="utf-8"?><test2 a="value1" b="value2"/>',
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_EasyXml_escaping(self):
|
||||||
|
original = "<test>'\"\r&\nfoo"
|
||||||
|
converted = "<test>'"
&
foo"
|
||||||
|
converted_apos = converted.replace("'", "'")
|
||||||
|
self.assertEqual(
|
||||||
|
easy_xml.XmlToString(["test3", {"a": original}, original]),
|
||||||
|
'<?xml version="1.0" encoding="utf-8"?><test3 a="%s">%s</test3>'
|
||||||
|
% (converted, converted_apos),
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_EasyXml_pretty(self):
|
||||||
|
self.assertEqual(
|
||||||
|
easy_xml.XmlToString(
|
||||||
|
["test3", ["GrandParent", ["Parent1", ["Child"]], ["Parent2"]]],
|
||||||
|
pretty=True,
|
||||||
|
),
|
||||||
|
'<?xml version="1.0" encoding="utf-8"?>\n'
|
||||||
|
"<test3>\n"
|
||||||
|
" <GrandParent>\n"
|
||||||
|
" <Parent1>\n"
|
||||||
|
" <Child/>\n"
|
||||||
|
" </Parent1>\n"
|
||||||
|
" <Parent2/>\n"
|
||||||
|
" </GrandParent>\n"
|
||||||
|
"</test3>\n",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_EasyXml_complex(self):
|
||||||
|
# We want to create:
|
||||||
|
target = (
|
||||||
|
'<?xml version="1.0" encoding="utf-8"?>'
|
||||||
|
"<Project>"
|
||||||
|
'<PropertyGroup Label="Globals">'
|
||||||
|
"<ProjectGuid>{D2250C20-3A94-4FB9-AF73-11BC5B73884B}</ProjectGuid>"
|
||||||
|
"<Keyword>Win32Proj</Keyword>"
|
||||||
|
"<RootNamespace>automated_ui_tests</RootNamespace>"
|
||||||
|
"</PropertyGroup>"
|
||||||
|
'<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.props"/>'
|
||||||
|
"<PropertyGroup "
|
||||||
|
"Condition=\"'$(Configuration)|$(Platform)'=="
|
||||||
|
'\'Debug|Win32\'" Label="Configuration">'
|
||||||
|
"<ConfigurationType>Application</ConfigurationType>"
|
||||||
|
"<CharacterSet>Unicode</CharacterSet>"
|
||||||
|
"<SpectreMitigation>SpectreLoadCF</SpectreMitigation>"
|
||||||
|
"<VCToolsVersion>14.36.32532</VCToolsVersion>"
|
||||||
|
"</PropertyGroup>"
|
||||||
|
"</Project>"
|
||||||
|
)
|
||||||
|
|
||||||
|
xml = easy_xml.XmlToString(
|
||||||
|
[
|
||||||
|
"Project",
|
||||||
|
[
|
||||||
|
"PropertyGroup",
|
||||||
|
{"Label": "Globals"},
|
||||||
|
["ProjectGuid", "{D2250C20-3A94-4FB9-AF73-11BC5B73884B}"],
|
||||||
|
["Keyword", "Win32Proj"],
|
||||||
|
["RootNamespace", "automated_ui_tests"],
|
||||||
|
],
|
||||||
|
["Import", {"Project": "$(VCTargetsPath)\\Microsoft.Cpp.props"}],
|
||||||
|
[
|
||||||
|
"PropertyGroup",
|
||||||
|
{
|
||||||
|
"Condition": "'$(Configuration)|$(Platform)'=='Debug|Win32'",
|
||||||
|
"Label": "Configuration",
|
||||||
|
},
|
||||||
|
["ConfigurationType", "Application"],
|
||||||
|
["CharacterSet", "Unicode"],
|
||||||
|
["SpectreMitigation", "SpectreLoadCF"],
|
||||||
|
["VCToolsVersion", "14.36.32532"],
|
||||||
|
],
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.assertEqual(xml, target)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
55
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/flock_tool.py
generated
vendored
Normal file
55
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/flock_tool.py
generated
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# Copyright (c) 2011 Google Inc. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
"""These functions are executed via gyp-flock-tool when using the Makefile
|
||||||
|
generator. Used on systems that don't have a built-in flock."""
|
||||||
|
|
||||||
|
import fcntl
|
||||||
|
import os
|
||||||
|
import struct
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def main(args):
|
||||||
|
executor = FlockTool()
|
||||||
|
executor.Dispatch(args)
|
||||||
|
|
||||||
|
|
||||||
|
class FlockTool:
|
||||||
|
"""This class emulates the 'flock' command."""
|
||||||
|
|
||||||
|
def Dispatch(self, args):
|
||||||
|
"""Dispatches a string command to a method."""
|
||||||
|
if len(args) < 1:
|
||||||
|
raise Exception("Not enough arguments")
|
||||||
|
|
||||||
|
method = "Exec%s" % self._CommandifyName(args[0])
|
||||||
|
getattr(self, method)(*args[1:])
|
||||||
|
|
||||||
|
def _CommandifyName(self, name_string):
|
||||||
|
"""Transforms a tool name like copy-info-plist to CopyInfoPlist"""
|
||||||
|
return name_string.title().replace("-", "")
|
||||||
|
|
||||||
|
def ExecFlock(self, lockfile, *cmd_list):
|
||||||
|
"""Emulates the most basic behavior of Linux's flock(1)."""
|
||||||
|
# Rely on exception handling to report errors.
|
||||||
|
# Note that the stock python on SunOS has a bug
|
||||||
|
# where fcntl.flock(fd, LOCK_EX) always fails
|
||||||
|
# with EBADF, that's why we use this F_SETLK
|
||||||
|
# hack instead.
|
||||||
|
fd = os.open(lockfile, os.O_WRONLY | os.O_NOCTTY | os.O_CREAT, 0o666)
|
||||||
|
if sys.platform.startswith("aix") or sys.platform == "os400":
|
||||||
|
# Python on AIX is compiled with LARGEFILE support, which changes the
|
||||||
|
# struct size.
|
||||||
|
op = struct.pack("hhIllqq", fcntl.F_WRLCK, 0, 0, 0, 0, 0, 0)
|
||||||
|
else:
|
||||||
|
op = struct.pack("hhllhhl", fcntl.F_WRLCK, 0, 0, 0, 0, 0, 0)
|
||||||
|
fcntl.fcntl(fd, fcntl.F_SETLK, op)
|
||||||
|
return subprocess.call(cmd_list)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main(sys.argv[1:]))
|
||||||
0
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/__init__.py
generated
vendored
Normal file
0
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/__init__.py
generated
vendored
Normal file
805
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/analyzer.py
generated
vendored
Normal file
805
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/analyzer.py
generated
vendored
Normal file
|
|
@ -0,0 +1,805 @@
|
||||||
|
# Copyright (c) 2014 Google Inc. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
"""
|
||||||
|
This script is intended for use as a GYP_GENERATOR. It takes as input (by way of
|
||||||
|
the generator flag config_path) the path of a json file that dictates the files
|
||||||
|
and targets to search for. The following keys are supported:
|
||||||
|
files: list of paths (relative) of the files to search for.
|
||||||
|
test_targets: unqualified target names to search for. Any target in this list
|
||||||
|
that depends upon a file in |files| is output regardless of the type of target
|
||||||
|
or chain of dependencies.
|
||||||
|
additional_compile_targets: Unqualified targets to search for in addition to
|
||||||
|
test_targets. Targets in the combined list that depend upon a file in |files|
|
||||||
|
are not necessarily output. For example, if the target is of type none then the
|
||||||
|
target is not output (but one of the descendants of the target will be).
|
||||||
|
|
||||||
|
The following is output:
|
||||||
|
error: only supplied if there is an error.
|
||||||
|
compile_targets: minimal set of targets that directly or indirectly (for
|
||||||
|
targets of type none) depend on the files in |files| and is one of the
|
||||||
|
supplied targets or a target that one of the supplied targets depends on.
|
||||||
|
The expectation is this set of targets is passed into a build step. This list
|
||||||
|
always contains the output of test_targets as well.
|
||||||
|
test_targets: set of targets from the supplied |test_targets| that either
|
||||||
|
directly or indirectly depend upon a file in |files|. This list if useful
|
||||||
|
if additional processing needs to be done for certain targets after the
|
||||||
|
build, such as running tests.
|
||||||
|
status: outputs one of three values: none of the supplied files were found,
|
||||||
|
one of the include files changed so that it should be assumed everything
|
||||||
|
changed (in this case test_targets and compile_targets are not output) or at
|
||||||
|
least one file was found.
|
||||||
|
invalid_targets: list of supplied targets that were not found.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
Consider a graph like the following:
|
||||||
|
A D
|
||||||
|
/ \
|
||||||
|
B C
|
||||||
|
A depends upon both B and C, A is of type none and B and C are executables.
|
||||||
|
D is an executable, has no dependencies and nothing depends on it.
|
||||||
|
If |additional_compile_targets| = ["A"], |test_targets| = ["B", "C"] and
|
||||||
|
files = ["b.cc", "d.cc"] (B depends upon b.cc and D depends upon d.cc), then
|
||||||
|
the following is output:
|
||||||
|
|compile_targets| = ["B"] B must built as it depends upon the changed file b.cc
|
||||||
|
and the supplied target A depends upon it. A is not output as a build_target
|
||||||
|
as it is of type none with no rules and actions.
|
||||||
|
|test_targets| = ["B"] B directly depends upon the change file b.cc.
|
||||||
|
|
||||||
|
Even though the file d.cc, which D depends upon, has changed D is not output
|
||||||
|
as it was not supplied by way of |additional_compile_targets| or |test_targets|.
|
||||||
|
|
||||||
|
If the generator flag analyzer_output_path is specified, output is written
|
||||||
|
there. Otherwise output is written to stdout.
|
||||||
|
|
||||||
|
In Gyp the "all" target is shorthand for the root targets in the files passed
|
||||||
|
to gyp. For example, if file "a.gyp" contains targets "a1" and
|
||||||
|
"a2", and file "b.gyp" contains targets "b1" and "b2" and "a2" has a dependency
|
||||||
|
on "b2" and gyp is supplied "a.gyp" then "all" consists of "a1" and "a2".
|
||||||
|
Notice that "b1" and "b2" are not in the "all" target as "b.gyp" was not
|
||||||
|
directly supplied to gyp. OTOH if both "a.gyp" and "b.gyp" are supplied to gyp
|
||||||
|
then the "all" target includes "b1" and "b2".
|
||||||
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import posixpath
|
||||||
|
|
||||||
|
import gyp.common
|
||||||
|
|
||||||
|
debug = False
|
||||||
|
|
||||||
|
found_dependency_string = "Found dependency"
|
||||||
|
no_dependency_string = "No dependencies"
|
||||||
|
# Status when it should be assumed that everything has changed.
|
||||||
|
all_changed_string = "Found dependency (all)"
|
||||||
|
|
||||||
|
# MatchStatus is used indicate if and how a target depends upon the supplied
|
||||||
|
# sources.
|
||||||
|
# The target's sources contain one of the supplied paths.
|
||||||
|
MATCH_STATUS_MATCHES = 1
|
||||||
|
# The target has a dependency on another target that contains one of the
|
||||||
|
# supplied paths.
|
||||||
|
MATCH_STATUS_MATCHES_BY_DEPENDENCY = 2
|
||||||
|
# The target's sources weren't in the supplied paths and none of the target's
|
||||||
|
# dependencies depend upon a target that matched.
|
||||||
|
MATCH_STATUS_DOESNT_MATCH = 3
|
||||||
|
# The target doesn't contain the source, but the dependent targets have not yet
|
||||||
|
# been visited to determine a more specific status yet.
|
||||||
|
MATCH_STATUS_TBD = 4
|
||||||
|
|
||||||
|
generator_supports_multiple_toolsets = gyp.common.CrossCompileRequested()
|
||||||
|
|
||||||
|
generator_wants_static_library_dependencies_adjusted = False
|
||||||
|
|
||||||
|
generator_default_variables = {}
|
||||||
|
for dirname in [
|
||||||
|
"INTERMEDIATE_DIR",
|
||||||
|
"SHARED_INTERMEDIATE_DIR",
|
||||||
|
"PRODUCT_DIR",
|
||||||
|
"LIB_DIR",
|
||||||
|
"SHARED_LIB_DIR",
|
||||||
|
]:
|
||||||
|
generator_default_variables[dirname] = "!!!"
|
||||||
|
|
||||||
|
for unused in [
|
||||||
|
"RULE_INPUT_PATH",
|
||||||
|
"RULE_INPUT_ROOT",
|
||||||
|
"RULE_INPUT_NAME",
|
||||||
|
"RULE_INPUT_DIRNAME",
|
||||||
|
"RULE_INPUT_EXT",
|
||||||
|
"EXECUTABLE_PREFIX",
|
||||||
|
"EXECUTABLE_SUFFIX",
|
||||||
|
"STATIC_LIB_PREFIX",
|
||||||
|
"STATIC_LIB_SUFFIX",
|
||||||
|
"SHARED_LIB_PREFIX",
|
||||||
|
"SHARED_LIB_SUFFIX",
|
||||||
|
"CONFIGURATION_NAME",
|
||||||
|
]:
|
||||||
|
generator_default_variables[unused] = ""
|
||||||
|
|
||||||
|
|
||||||
|
def _ToGypPath(path):
|
||||||
|
"""Converts a path to the format used by gyp."""
|
||||||
|
if os.sep == "\\" and os.altsep == "/":
|
||||||
|
return path.replace("\\", "/")
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def _ResolveParent(path, base_path_components):
|
||||||
|
"""Resolves |path|, which starts with at least one '../'. Returns an empty
|
||||||
|
string if the path shouldn't be considered. See _AddSources() for a
|
||||||
|
description of |base_path_components|."""
|
||||||
|
depth = 0
|
||||||
|
while path.startswith("../"):
|
||||||
|
depth += 1
|
||||||
|
path = path[3:]
|
||||||
|
# Relative includes may go outside the source tree. For example, an action may
|
||||||
|
# have inputs in /usr/include, which are not in the source tree.
|
||||||
|
if depth > len(base_path_components):
|
||||||
|
return ""
|
||||||
|
if depth == len(base_path_components):
|
||||||
|
return path
|
||||||
|
return (
|
||||||
|
"/".join(base_path_components[0 : len(base_path_components) - depth])
|
||||||
|
+ "/"
|
||||||
|
+ path
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _AddSources(sources, base_path, base_path_components, result):
|
||||||
|
"""Extracts valid sources from |sources| and adds them to |result|. Each
|
||||||
|
source file is relative to |base_path|, but may contain '..'. To make
|
||||||
|
resolving '..' easier |base_path_components| contains each of the
|
||||||
|
directories in |base_path|. Additionally each source may contain variables.
|
||||||
|
Such sources are ignored as it is assumed dependencies on them are expressed
|
||||||
|
and tracked in some other means."""
|
||||||
|
# NOTE: gyp paths are always posix style.
|
||||||
|
for source in sources:
|
||||||
|
if not len(source) or source.startswith(("!!!", "$")):
|
||||||
|
continue
|
||||||
|
# variable expansion may lead to //.
|
||||||
|
org_source = source
|
||||||
|
source = source[0] + source[1:].replace("//", "/")
|
||||||
|
if source.startswith("../"):
|
||||||
|
source = _ResolveParent(source, base_path_components)
|
||||||
|
if len(source):
|
||||||
|
result.append(source)
|
||||||
|
continue
|
||||||
|
result.append(base_path + source)
|
||||||
|
if debug:
|
||||||
|
print("AddSource", org_source, result[len(result) - 1])
|
||||||
|
|
||||||
|
|
||||||
|
def _ExtractSourcesFromAction(action, base_path, base_path_components, results):
|
||||||
|
if "inputs" in action:
|
||||||
|
_AddSources(action["inputs"], base_path, base_path_components, results)
|
||||||
|
|
||||||
|
|
||||||
|
def _ToLocalPath(toplevel_dir, path):
|
||||||
|
"""Converts |path| to a path relative to |toplevel_dir|."""
|
||||||
|
if path == toplevel_dir:
|
||||||
|
return ""
|
||||||
|
if path.startswith(toplevel_dir + "/"):
|
||||||
|
return path[len(toplevel_dir) + len("/") :]
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def _ExtractSources(target, target_dict, toplevel_dir):
|
||||||
|
# |target| is either absolute or relative and in the format of the OS. Gyp
|
||||||
|
# source paths are always posix. Convert |target| to a posix path relative to
|
||||||
|
# |toplevel_dir_|. This is done to make it easy to build source paths.
|
||||||
|
base_path = posixpath.dirname(_ToLocalPath(toplevel_dir, _ToGypPath(target)))
|
||||||
|
base_path_components = base_path.split("/")
|
||||||
|
|
||||||
|
# Add a trailing '/' so that _AddSources() can easily build paths.
|
||||||
|
if len(base_path):
|
||||||
|
base_path += "/"
|
||||||
|
|
||||||
|
if debug:
|
||||||
|
print("ExtractSources", target, base_path)
|
||||||
|
|
||||||
|
results = []
|
||||||
|
if "sources" in target_dict:
|
||||||
|
_AddSources(target_dict["sources"], base_path, base_path_components, results)
|
||||||
|
# Include the inputs from any actions. Any changes to these affect the
|
||||||
|
# resulting output.
|
||||||
|
if "actions" in target_dict:
|
||||||
|
for action in target_dict["actions"]:
|
||||||
|
_ExtractSourcesFromAction(action, base_path, base_path_components, results)
|
||||||
|
if "rules" in target_dict:
|
||||||
|
for rule in target_dict["rules"]:
|
||||||
|
_ExtractSourcesFromAction(rule, base_path, base_path_components, results)
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
class Target:
|
||||||
|
"""Holds information about a particular target:
|
||||||
|
deps: set of Targets this Target depends upon. This is not recursive, only the
|
||||||
|
direct dependent Targets.
|
||||||
|
match_status: one of the MatchStatus values.
|
||||||
|
back_deps: set of Targets that have a dependency on this Target.
|
||||||
|
visited: used during iteration to indicate whether we've visited this target.
|
||||||
|
This is used for two iterations, once in building the set of Targets and
|
||||||
|
again in _GetBuildTargets().
|
||||||
|
name: fully qualified name of the target.
|
||||||
|
requires_build: True if the target type is such that it needs to be built.
|
||||||
|
See _DoesTargetTypeRequireBuild for details.
|
||||||
|
added_to_compile_targets: used when determining if the target was added to the
|
||||||
|
set of targets that needs to be built.
|
||||||
|
in_roots: true if this target is a descendant of one of the root nodes.
|
||||||
|
is_executable: true if the type of target is executable.
|
||||||
|
is_static_library: true if the type of target is static_library.
|
||||||
|
is_or_has_linked_ancestor: true if the target does a link (eg executable), or
|
||||||
|
if there is a target in back_deps that does a link."""
|
||||||
|
|
||||||
|
def __init__(self, name):
|
||||||
|
self.deps = set()
|
||||||
|
self.match_status = MATCH_STATUS_TBD
|
||||||
|
self.back_deps = set()
|
||||||
|
self.name = name
|
||||||
|
# TODO(sky): I don't like hanging this off Target. This state is specific
|
||||||
|
# to certain functions and should be isolated there.
|
||||||
|
self.visited = False
|
||||||
|
self.requires_build = False
|
||||||
|
self.added_to_compile_targets = False
|
||||||
|
self.in_roots = False
|
||||||
|
self.is_executable = False
|
||||||
|
self.is_static_library = False
|
||||||
|
self.is_or_has_linked_ancestor = False
|
||||||
|
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
"""Details what we're looking for
|
||||||
|
files: set of files to search for
|
||||||
|
targets: see file description for details."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.files = []
|
||||||
|
self.targets = set()
|
||||||
|
self.additional_compile_target_names = set()
|
||||||
|
self.test_target_names = set()
|
||||||
|
|
||||||
|
def Init(self, params):
|
||||||
|
"""Initializes Config. This is a separate method as it raises an exception
|
||||||
|
if there is a parse error."""
|
||||||
|
generator_flags = params.get("generator_flags", {})
|
||||||
|
config_path = generator_flags.get("config_path", None)
|
||||||
|
if not config_path:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
f = open(config_path)
|
||||||
|
config = json.load(f)
|
||||||
|
f.close()
|
||||||
|
except OSError:
|
||||||
|
raise Exception("Unable to open file " + config_path)
|
||||||
|
except ValueError as e:
|
||||||
|
raise Exception("Unable to parse config file " + config_path + str(e))
|
||||||
|
if not isinstance(config, dict):
|
||||||
|
raise Exception("config_path must be a JSON file containing a dictionary")
|
||||||
|
self.files = config.get("files", [])
|
||||||
|
self.additional_compile_target_names = set(
|
||||||
|
config.get("additional_compile_targets", [])
|
||||||
|
)
|
||||||
|
self.test_target_names = set(config.get("test_targets", []))
|
||||||
|
|
||||||
|
|
||||||
|
def _WasBuildFileModified(build_file, data, files, toplevel_dir):
|
||||||
|
"""Returns true if the build file |build_file| is either in |files| or
|
||||||
|
one of the files included by |build_file| is in |files|. |toplevel_dir| is
|
||||||
|
the root of the source tree."""
|
||||||
|
if _ToLocalPath(toplevel_dir, _ToGypPath(build_file)) in files:
|
||||||
|
if debug:
|
||||||
|
print("gyp file modified", build_file)
|
||||||
|
return True
|
||||||
|
|
||||||
|
# First element of included_files is the file itself.
|
||||||
|
if len(data[build_file]["included_files"]) <= 1:
|
||||||
|
return False
|
||||||
|
|
||||||
|
for include_file in data[build_file]["included_files"][1:]:
|
||||||
|
# |included_files| are relative to the directory of the |build_file|.
|
||||||
|
rel_include_file = _ToGypPath(
|
||||||
|
gyp.common.UnrelativePath(include_file, build_file)
|
||||||
|
)
|
||||||
|
if _ToLocalPath(toplevel_dir, rel_include_file) in files:
|
||||||
|
if debug:
|
||||||
|
print(
|
||||||
|
"included gyp file modified, gyp_file=",
|
||||||
|
build_file,
|
||||||
|
"included file=",
|
||||||
|
rel_include_file,
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def _GetOrCreateTargetByName(targets, target_name):
|
||||||
|
"""Creates or returns the Target at targets[target_name]. If there is no
|
||||||
|
Target for |target_name| one is created. Returns a tuple of whether a new
|
||||||
|
Target was created and the Target."""
|
||||||
|
if target_name in targets:
|
||||||
|
return False, targets[target_name]
|
||||||
|
target = Target(target_name)
|
||||||
|
targets[target_name] = target
|
||||||
|
return True, target
|
||||||
|
|
||||||
|
|
||||||
|
def _DoesTargetTypeRequireBuild(target_dict):
|
||||||
|
"""Returns true if the target type is such that it needs to be built."""
|
||||||
|
# If a 'none' target has rules or actions we assume it requires a build.
|
||||||
|
return bool(
|
||||||
|
target_dict["type"] != "none"
|
||||||
|
or target_dict.get("actions")
|
||||||
|
or target_dict.get("rules")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _GenerateTargets(data, target_list, target_dicts, toplevel_dir, files, build_files):
|
||||||
|
"""Returns a tuple of the following:
|
||||||
|
. A dictionary mapping from fully qualified name to Target.
|
||||||
|
. A list of the targets that have a source file in |files|.
|
||||||
|
. Targets that constitute the 'all' target. See description at top of file
|
||||||
|
for details on the 'all' target.
|
||||||
|
This sets the |match_status| of the targets that contain any of the source
|
||||||
|
files in |files| to MATCH_STATUS_MATCHES.
|
||||||
|
|toplevel_dir| is the root of the source tree."""
|
||||||
|
# Maps from target name to Target.
|
||||||
|
name_to_target = {}
|
||||||
|
|
||||||
|
# Targets that matched.
|
||||||
|
matching_targets = []
|
||||||
|
|
||||||
|
# Queue of targets to visit.
|
||||||
|
targets_to_visit = target_list[:]
|
||||||
|
|
||||||
|
# Maps from build file to a boolean indicating whether the build file is in
|
||||||
|
# |files|.
|
||||||
|
build_file_in_files = {}
|
||||||
|
|
||||||
|
# Root targets across all files.
|
||||||
|
roots = set()
|
||||||
|
|
||||||
|
# Set of Targets in |build_files|.
|
||||||
|
build_file_targets = set()
|
||||||
|
|
||||||
|
while len(targets_to_visit) > 0:
|
||||||
|
target_name = targets_to_visit.pop()
|
||||||
|
created_target, target = _GetOrCreateTargetByName(name_to_target, target_name)
|
||||||
|
if created_target:
|
||||||
|
roots.add(target)
|
||||||
|
elif target.visited:
|
||||||
|
continue
|
||||||
|
|
||||||
|
target.visited = True
|
||||||
|
target.requires_build = _DoesTargetTypeRequireBuild(target_dicts[target_name])
|
||||||
|
target_type = target_dicts[target_name]["type"]
|
||||||
|
target.is_executable = target_type == "executable"
|
||||||
|
target.is_static_library = target_type == "static_library"
|
||||||
|
target.is_or_has_linked_ancestor = target_type in {
|
||||||
|
"executable",
|
||||||
|
"shared_library",
|
||||||
|
}
|
||||||
|
|
||||||
|
build_file = gyp.common.ParseQualifiedTarget(target_name)[0]
|
||||||
|
if build_file not in build_file_in_files:
|
||||||
|
build_file_in_files[build_file] = _WasBuildFileModified(
|
||||||
|
build_file, data, files, toplevel_dir
|
||||||
|
)
|
||||||
|
|
||||||
|
if build_file in build_files:
|
||||||
|
build_file_targets.add(target)
|
||||||
|
|
||||||
|
# If a build file (or any of its included files) is modified we assume all
|
||||||
|
# targets in the file are modified.
|
||||||
|
if build_file_in_files[build_file]:
|
||||||
|
print("matching target from modified build file", target_name)
|
||||||
|
target.match_status = MATCH_STATUS_MATCHES
|
||||||
|
matching_targets.append(target)
|
||||||
|
else:
|
||||||
|
sources = _ExtractSources(
|
||||||
|
target_name, target_dicts[target_name], toplevel_dir
|
||||||
|
)
|
||||||
|
for source in sources:
|
||||||
|
if _ToGypPath(os.path.normpath(source)) in files:
|
||||||
|
print("target", target_name, "matches", source)
|
||||||
|
target.match_status = MATCH_STATUS_MATCHES
|
||||||
|
matching_targets.append(target)
|
||||||
|
break
|
||||||
|
|
||||||
|
# Add dependencies to visit as well as updating back pointers for deps.
|
||||||
|
for dep in target_dicts[target_name].get("dependencies", []):
|
||||||
|
targets_to_visit.append(dep)
|
||||||
|
|
||||||
|
created_dep_target, dep_target = _GetOrCreateTargetByName(
|
||||||
|
name_to_target, dep
|
||||||
|
)
|
||||||
|
if not created_dep_target:
|
||||||
|
roots.discard(dep_target)
|
||||||
|
|
||||||
|
target.deps.add(dep_target)
|
||||||
|
dep_target.back_deps.add(target)
|
||||||
|
|
||||||
|
return name_to_target, matching_targets, roots & build_file_targets
|
||||||
|
|
||||||
|
|
||||||
|
def _GetUnqualifiedToTargetMapping(all_targets, to_find):
|
||||||
|
"""Returns a tuple of the following:
|
||||||
|
. mapping (dictionary) from unqualified name to Target for all the
|
||||||
|
Targets in |to_find|.
|
||||||
|
. any target names not found. If this is empty all targets were found."""
|
||||||
|
result = {}
|
||||||
|
if not to_find:
|
||||||
|
return {}, []
|
||||||
|
to_find = set(to_find)
|
||||||
|
for target_name in all_targets:
|
||||||
|
extracted = gyp.common.ParseQualifiedTarget(target_name)
|
||||||
|
if len(extracted) > 1 and extracted[1] in to_find:
|
||||||
|
to_find.remove(extracted[1])
|
||||||
|
result[extracted[1]] = all_targets[target_name]
|
||||||
|
if not to_find:
|
||||||
|
return result, []
|
||||||
|
return result, list(to_find)
|
||||||
|
|
||||||
|
|
||||||
|
def _DoesTargetDependOnMatchingTargets(target):
|
||||||
|
"""Returns true if |target| or any of its dependencies is one of the
|
||||||
|
targets containing the files supplied as input to analyzer. This updates
|
||||||
|
|matches| of the Targets as it recurses.
|
||||||
|
target: the Target to look for."""
|
||||||
|
if target.match_status == MATCH_STATUS_DOESNT_MATCH:
|
||||||
|
return False
|
||||||
|
if target.match_status in {
|
||||||
|
MATCH_STATUS_MATCHES,
|
||||||
|
MATCH_STATUS_MATCHES_BY_DEPENDENCY,
|
||||||
|
}:
|
||||||
|
return True
|
||||||
|
for dep in target.deps:
|
||||||
|
if _DoesTargetDependOnMatchingTargets(dep):
|
||||||
|
target.match_status = MATCH_STATUS_MATCHES_BY_DEPENDENCY
|
||||||
|
print("\t", target.name, "matches by dep", dep.name)
|
||||||
|
return True
|
||||||
|
target.match_status = MATCH_STATUS_DOESNT_MATCH
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def _GetTargetsDependingOnMatchingTargets(possible_targets):
|
||||||
|
"""Returns the list of Targets in |possible_targets| that depend (either
|
||||||
|
directly on indirectly) on at least one of the targets containing the files
|
||||||
|
supplied as input to analyzer.
|
||||||
|
possible_targets: targets to search from."""
|
||||||
|
found = []
|
||||||
|
print("Targets that matched by dependency:")
|
||||||
|
for target in possible_targets:
|
||||||
|
if _DoesTargetDependOnMatchingTargets(target):
|
||||||
|
found.append(target)
|
||||||
|
return found
|
||||||
|
|
||||||
|
|
||||||
|
def _AddCompileTargets(target, roots, add_if_no_ancestor, result):
|
||||||
|
"""Recurses through all targets that depend on |target|, adding all targets
|
||||||
|
that need to be built (and are in |roots|) to |result|.
|
||||||
|
roots: set of root targets.
|
||||||
|
add_if_no_ancestor: If true and there are no ancestors of |target| then add
|
||||||
|
|target| to |result|. |target| must still be in |roots|.
|
||||||
|
result: targets that need to be built are added here."""
|
||||||
|
if target.visited:
|
||||||
|
return
|
||||||
|
|
||||||
|
target.visited = True
|
||||||
|
target.in_roots = target in roots
|
||||||
|
|
||||||
|
for back_dep_target in target.back_deps:
|
||||||
|
_AddCompileTargets(back_dep_target, roots, False, result)
|
||||||
|
target.added_to_compile_targets |= back_dep_target.added_to_compile_targets
|
||||||
|
target.in_roots |= back_dep_target.in_roots
|
||||||
|
target.is_or_has_linked_ancestor |= back_dep_target.is_or_has_linked_ancestor
|
||||||
|
|
||||||
|
# Always add 'executable' targets. Even though they may be built by other
|
||||||
|
# targets that depend upon them it makes detection of what is going to be
|
||||||
|
# built easier.
|
||||||
|
# And always add static_libraries that have no dependencies on them from
|
||||||
|
# linkables. This is necessary as the other dependencies on them may be
|
||||||
|
# static libraries themselves, which are not compile time dependencies.
|
||||||
|
if target.in_roots and (
|
||||||
|
target.is_executable
|
||||||
|
or (
|
||||||
|
not target.added_to_compile_targets
|
||||||
|
and (add_if_no_ancestor or target.requires_build)
|
||||||
|
)
|
||||||
|
or (
|
||||||
|
target.is_static_library
|
||||||
|
and add_if_no_ancestor
|
||||||
|
and not target.is_or_has_linked_ancestor
|
||||||
|
)
|
||||||
|
):
|
||||||
|
print(
|
||||||
|
"\t\tadding to compile targets",
|
||||||
|
target.name,
|
||||||
|
"executable",
|
||||||
|
target.is_executable,
|
||||||
|
"added_to_compile_targets",
|
||||||
|
target.added_to_compile_targets,
|
||||||
|
"add_if_no_ancestor",
|
||||||
|
add_if_no_ancestor,
|
||||||
|
"requires_build",
|
||||||
|
target.requires_build,
|
||||||
|
"is_static_library",
|
||||||
|
target.is_static_library,
|
||||||
|
"is_or_has_linked_ancestor",
|
||||||
|
target.is_or_has_linked_ancestor,
|
||||||
|
)
|
||||||
|
result.add(target)
|
||||||
|
target.added_to_compile_targets = True
|
||||||
|
|
||||||
|
|
||||||
|
def _GetCompileTargets(matching_targets, supplied_targets):
|
||||||
|
"""Returns the set of Targets that require a build.
|
||||||
|
matching_targets: targets that changed and need to be built.
|
||||||
|
supplied_targets: set of targets supplied to analyzer to search from."""
|
||||||
|
result = set()
|
||||||
|
for target in matching_targets:
|
||||||
|
print("finding compile targets for match", target.name)
|
||||||
|
_AddCompileTargets(target, supplied_targets, True, result)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def _WriteOutput(params, **values):
|
||||||
|
"""Writes the output, either to stdout or a file is specified."""
|
||||||
|
if "error" in values:
|
||||||
|
print("Error:", values["error"])
|
||||||
|
if "status" in values:
|
||||||
|
print(values["status"])
|
||||||
|
if "targets" in values:
|
||||||
|
values["targets"].sort()
|
||||||
|
print("Supplied targets that depend on changed files:")
|
||||||
|
for target in values["targets"]:
|
||||||
|
print("\t", target)
|
||||||
|
if "invalid_targets" in values:
|
||||||
|
values["invalid_targets"].sort()
|
||||||
|
print("The following targets were not found:")
|
||||||
|
for target in values["invalid_targets"]:
|
||||||
|
print("\t", target)
|
||||||
|
if "build_targets" in values:
|
||||||
|
values["build_targets"].sort()
|
||||||
|
print("Targets that require a build:")
|
||||||
|
for target in values["build_targets"]:
|
||||||
|
print("\t", target)
|
||||||
|
if "compile_targets" in values:
|
||||||
|
values["compile_targets"].sort()
|
||||||
|
print("Targets that need to be built:")
|
||||||
|
for target in values["compile_targets"]:
|
||||||
|
print("\t", target)
|
||||||
|
if "test_targets" in values:
|
||||||
|
values["test_targets"].sort()
|
||||||
|
print("Test targets:")
|
||||||
|
for target in values["test_targets"]:
|
||||||
|
print("\t", target)
|
||||||
|
|
||||||
|
output_path = params.get("generator_flags", {}).get("analyzer_output_path", None)
|
||||||
|
if not output_path:
|
||||||
|
print(json.dumps(values))
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
f = open(output_path, "w")
|
||||||
|
f.write(json.dumps(values) + "\n")
|
||||||
|
f.close()
|
||||||
|
except OSError as e:
|
||||||
|
print("Error writing to output file", output_path, str(e))
|
||||||
|
|
||||||
|
|
||||||
|
def _WasGypIncludeFileModified(params, files):
|
||||||
|
"""Returns true if one of the files in |files| is in the set of included
|
||||||
|
files."""
|
||||||
|
if params["options"].includes:
|
||||||
|
for include in params["options"].includes:
|
||||||
|
if _ToGypPath(os.path.normpath(include)) in files:
|
||||||
|
print("Include file modified, assuming all changed", include)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def _NamesNotIn(names, mapping):
|
||||||
|
"""Returns a list of the values in |names| that are not in |mapping|."""
|
||||||
|
return [name for name in names if name not in mapping]
|
||||||
|
|
||||||
|
|
||||||
|
def _LookupTargets(names, mapping):
|
||||||
|
"""Returns a list of the mapping[name] for each value in |names| that is in
|
||||||
|
|mapping|."""
|
||||||
|
return [mapping[name] for name in names if name in mapping]
|
||||||
|
|
||||||
|
|
||||||
|
def CalculateVariables(default_variables, params):
|
||||||
|
"""Calculate additional variables for use in the build (called by gyp)."""
|
||||||
|
flavor = gyp.common.GetFlavor(params)
|
||||||
|
if flavor == "mac":
|
||||||
|
default_variables.setdefault("OS", "mac")
|
||||||
|
elif flavor == "win":
|
||||||
|
default_variables.setdefault("OS", "win")
|
||||||
|
gyp.msvs_emulation.CalculateCommonVariables(default_variables, params)
|
||||||
|
else:
|
||||||
|
operating_system = flavor
|
||||||
|
if flavor == "android":
|
||||||
|
operating_system = "linux" # Keep this legacy behavior for now.
|
||||||
|
default_variables.setdefault("OS", operating_system)
|
||||||
|
|
||||||
|
|
||||||
|
class TargetCalculator:
|
||||||
|
"""Calculates the matching test_targets and matching compile_targets."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
files,
|
||||||
|
additional_compile_target_names,
|
||||||
|
test_target_names,
|
||||||
|
data,
|
||||||
|
target_list,
|
||||||
|
target_dicts,
|
||||||
|
toplevel_dir,
|
||||||
|
build_files,
|
||||||
|
):
|
||||||
|
self._additional_compile_target_names = set(additional_compile_target_names)
|
||||||
|
self._test_target_names = set(test_target_names)
|
||||||
|
(
|
||||||
|
self._name_to_target,
|
||||||
|
self._changed_targets,
|
||||||
|
self._root_targets,
|
||||||
|
) = _GenerateTargets(
|
||||||
|
data, target_list, target_dicts, toplevel_dir, frozenset(files), build_files
|
||||||
|
)
|
||||||
|
(
|
||||||
|
self._unqualified_mapping,
|
||||||
|
self.invalid_targets,
|
||||||
|
) = _GetUnqualifiedToTargetMapping(
|
||||||
|
self._name_to_target, self._supplied_target_names_no_all()
|
||||||
|
)
|
||||||
|
|
||||||
|
def _supplied_target_names(self):
|
||||||
|
return self._additional_compile_target_names | self._test_target_names
|
||||||
|
|
||||||
|
def _supplied_target_names_no_all(self):
|
||||||
|
"""Returns the supplied test targets without 'all'."""
|
||||||
|
result = self._supplied_target_names()
|
||||||
|
result.discard("all")
|
||||||
|
return result
|
||||||
|
|
||||||
|
def is_build_impacted(self):
|
||||||
|
"""Returns true if the supplied files impact the build at all."""
|
||||||
|
return self._changed_targets
|
||||||
|
|
||||||
|
def find_matching_test_target_names(self):
|
||||||
|
"""Returns the set of output test targets."""
|
||||||
|
assert self.is_build_impacted()
|
||||||
|
# Find the test targets first. 'all' is special cased to mean all the
|
||||||
|
# root targets. To deal with all the supplied |test_targets| are expanded
|
||||||
|
# to include the root targets during lookup. If any of the root targets
|
||||||
|
# match, we remove it and replace it with 'all'.
|
||||||
|
test_target_names_no_all = set(self._test_target_names)
|
||||||
|
test_target_names_no_all.discard("all")
|
||||||
|
test_targets_no_all = _LookupTargets(
|
||||||
|
test_target_names_no_all, self._unqualified_mapping
|
||||||
|
)
|
||||||
|
test_target_names_contains_all = "all" in self._test_target_names
|
||||||
|
if test_target_names_contains_all:
|
||||||
|
test_targets = list(set(test_targets_no_all) | set(self._root_targets))
|
||||||
|
else:
|
||||||
|
test_targets = list(test_targets_no_all)
|
||||||
|
print("supplied test_targets")
|
||||||
|
for target_name in self._test_target_names:
|
||||||
|
print("\t", target_name)
|
||||||
|
print("found test_targets")
|
||||||
|
for target in test_targets:
|
||||||
|
print("\t", target.name)
|
||||||
|
print("searching for matching test targets")
|
||||||
|
matching_test_targets = _GetTargetsDependingOnMatchingTargets(test_targets)
|
||||||
|
matching_test_targets_contains_all = test_target_names_contains_all and set(
|
||||||
|
matching_test_targets
|
||||||
|
) & set(self._root_targets)
|
||||||
|
if matching_test_targets_contains_all:
|
||||||
|
# Remove any of the targets for all that were not explicitly supplied,
|
||||||
|
# 'all' is subsequently added to the matching names below.
|
||||||
|
matching_test_targets = list(
|
||||||
|
set(matching_test_targets) & set(test_targets_no_all)
|
||||||
|
)
|
||||||
|
print("matched test_targets")
|
||||||
|
for target in matching_test_targets:
|
||||||
|
print("\t", target.name)
|
||||||
|
matching_target_names = [
|
||||||
|
gyp.common.ParseQualifiedTarget(target.name)[1]
|
||||||
|
for target in matching_test_targets
|
||||||
|
]
|
||||||
|
if matching_test_targets_contains_all:
|
||||||
|
matching_target_names.append("all")
|
||||||
|
print("\tall")
|
||||||
|
return matching_target_names
|
||||||
|
|
||||||
|
def find_matching_compile_target_names(self):
|
||||||
|
"""Returns the set of output compile targets."""
|
||||||
|
assert self.is_build_impacted()
|
||||||
|
# Compile targets are found by searching up from changed targets.
|
||||||
|
# Reset the visited status for _GetBuildTargets.
|
||||||
|
for target in self._name_to_target.values():
|
||||||
|
target.visited = False
|
||||||
|
|
||||||
|
supplied_targets = _LookupTargets(
|
||||||
|
self._supplied_target_names_no_all(), self._unqualified_mapping
|
||||||
|
)
|
||||||
|
if "all" in self._supplied_target_names():
|
||||||
|
supplied_targets = list(set(supplied_targets) | set(self._root_targets))
|
||||||
|
print("Supplied test_targets & compile_targets")
|
||||||
|
for target in supplied_targets:
|
||||||
|
print("\t", target.name)
|
||||||
|
print("Finding compile targets")
|
||||||
|
compile_targets = _GetCompileTargets(self._changed_targets, supplied_targets)
|
||||||
|
return [
|
||||||
|
gyp.common.ParseQualifiedTarget(target.name)[1]
|
||||||
|
for target in compile_targets
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def GenerateOutput(target_list, target_dicts, data, params):
|
||||||
|
"""Called by gyp as the final stage. Outputs results."""
|
||||||
|
config = Config()
|
||||||
|
try:
|
||||||
|
config.Init(params)
|
||||||
|
|
||||||
|
if not config.files:
|
||||||
|
raise Exception(
|
||||||
|
"Must specify files to analyze via config_path generator flag"
|
||||||
|
)
|
||||||
|
|
||||||
|
toplevel_dir = _ToGypPath(os.path.abspath(params["options"].toplevel_dir))
|
||||||
|
if debug:
|
||||||
|
print("toplevel_dir", toplevel_dir)
|
||||||
|
|
||||||
|
if _WasGypIncludeFileModified(params, config.files):
|
||||||
|
result_dict = {
|
||||||
|
"status": all_changed_string,
|
||||||
|
"test_targets": list(config.test_target_names),
|
||||||
|
"compile_targets": list(
|
||||||
|
config.additional_compile_target_names | config.test_target_names
|
||||||
|
),
|
||||||
|
}
|
||||||
|
_WriteOutput(params, **result_dict)
|
||||||
|
return
|
||||||
|
|
||||||
|
calculator = TargetCalculator(
|
||||||
|
config.files,
|
||||||
|
config.additional_compile_target_names,
|
||||||
|
config.test_target_names,
|
||||||
|
data,
|
||||||
|
target_list,
|
||||||
|
target_dicts,
|
||||||
|
toplevel_dir,
|
||||||
|
params["build_files"],
|
||||||
|
)
|
||||||
|
if not calculator.is_build_impacted():
|
||||||
|
result_dict = {
|
||||||
|
"status": no_dependency_string,
|
||||||
|
"test_targets": [],
|
||||||
|
"compile_targets": [],
|
||||||
|
}
|
||||||
|
if calculator.invalid_targets:
|
||||||
|
result_dict["invalid_targets"] = calculator.invalid_targets
|
||||||
|
_WriteOutput(params, **result_dict)
|
||||||
|
return
|
||||||
|
|
||||||
|
test_target_names = calculator.find_matching_test_target_names()
|
||||||
|
compile_target_names = calculator.find_matching_compile_target_names()
|
||||||
|
found_at_least_one_target = compile_target_names or test_target_names
|
||||||
|
result_dict = {
|
||||||
|
"test_targets": test_target_names,
|
||||||
|
"status": found_dependency_string
|
||||||
|
if found_at_least_one_target
|
||||||
|
else no_dependency_string,
|
||||||
|
"compile_targets": list(set(compile_target_names) | set(test_target_names)),
|
||||||
|
}
|
||||||
|
if calculator.invalid_targets:
|
||||||
|
result_dict["invalid_targets"] = calculator.invalid_targets
|
||||||
|
_WriteOutput(params, **result_dict)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
_WriteOutput(params, error=str(e))
|
||||||
1169
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py
generated
vendored
Normal file
1169
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1316
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py
generated
vendored
Normal file
1316
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
128
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/compile_commands_json.py
generated
vendored
Normal file
128
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/compile_commands_json.py
generated
vendored
Normal file
|
|
@ -0,0 +1,128 @@
|
||||||
|
# Copyright (c) 2016 Ben Noordhuis <info@bnoordhuis.nl>. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
import gyp.common
|
||||||
|
import gyp.xcode_emulation
|
||||||
|
|
||||||
|
generator_additional_non_configuration_keys = []
|
||||||
|
generator_additional_path_sections = []
|
||||||
|
generator_extra_sources_for_rules = []
|
||||||
|
generator_filelist_paths = None
|
||||||
|
generator_supports_multiple_toolsets = True
|
||||||
|
generator_wants_sorted_dependencies = False
|
||||||
|
|
||||||
|
# Lifted from make.py. The actual values don't matter much.
|
||||||
|
generator_default_variables = {
|
||||||
|
"CONFIGURATION_NAME": "$(BUILDTYPE)",
|
||||||
|
"EXECUTABLE_PREFIX": "",
|
||||||
|
"EXECUTABLE_SUFFIX": "",
|
||||||
|
"INTERMEDIATE_DIR": "$(obj).$(TOOLSET)/$(TARGET)/geni",
|
||||||
|
"PRODUCT_DIR": "$(builddir)",
|
||||||
|
"RULE_INPUT_DIRNAME": "%(INPUT_DIRNAME)s",
|
||||||
|
"RULE_INPUT_EXT": "$(suffix $<)",
|
||||||
|
"RULE_INPUT_NAME": "$(notdir $<)",
|
||||||
|
"RULE_INPUT_PATH": "$(abspath $<)",
|
||||||
|
"RULE_INPUT_ROOT": "%(INPUT_ROOT)s",
|
||||||
|
"SHARED_INTERMEDIATE_DIR": "$(obj)/gen",
|
||||||
|
"SHARED_LIB_PREFIX": "lib",
|
||||||
|
"STATIC_LIB_PREFIX": "lib",
|
||||||
|
"STATIC_LIB_SUFFIX": ".a",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def IsMac(params):
|
||||||
|
return gyp.common.GetFlavor(params) == "mac"
|
||||||
|
|
||||||
|
|
||||||
|
def CalculateVariables(default_variables, params):
|
||||||
|
default_variables.setdefault("OS", gyp.common.GetFlavor(params))
|
||||||
|
|
||||||
|
|
||||||
|
def AddCommandsForTarget(cwd, target, params, per_config_commands):
|
||||||
|
output_dir = params["generator_flags"].get("output_dir", "out")
|
||||||
|
for configuration_name, configuration in target["configurations"].items():
|
||||||
|
if IsMac(params):
|
||||||
|
xcode_settings = gyp.xcode_emulation.XcodeSettings(target)
|
||||||
|
cflags = xcode_settings.GetCflags(configuration_name)
|
||||||
|
cflags_c = xcode_settings.GetCflagsC(configuration_name)
|
||||||
|
cflags_cc = xcode_settings.GetCflagsCC(configuration_name)
|
||||||
|
else:
|
||||||
|
cflags = configuration.get("cflags", [])
|
||||||
|
cflags_c = configuration.get("cflags_c", [])
|
||||||
|
cflags_cc = configuration.get("cflags_cc", [])
|
||||||
|
|
||||||
|
cflags_c = cflags + cflags_c
|
||||||
|
cflags_cc = cflags + cflags_cc
|
||||||
|
|
||||||
|
defines = configuration.get("defines", [])
|
||||||
|
defines = ["-D" + s for s in defines]
|
||||||
|
|
||||||
|
# TODO(bnoordhuis) Handle generated source files.
|
||||||
|
extensions = (".c", ".cc", ".cpp", ".cxx")
|
||||||
|
sources = [s for s in target.get("sources", []) if s.endswith(extensions)]
|
||||||
|
|
||||||
|
def resolve(filename):
|
||||||
|
return os.path.abspath(os.path.join(cwd, filename))
|
||||||
|
|
||||||
|
# TODO(bnoordhuis) Handle generated header files.
|
||||||
|
include_dirs = configuration.get("include_dirs", [])
|
||||||
|
include_dirs = [s for s in include_dirs if not s.startswith("$(obj)")]
|
||||||
|
includes = ["-I" + resolve(s) for s in include_dirs]
|
||||||
|
|
||||||
|
defines = gyp.common.EncodePOSIXShellList(defines)
|
||||||
|
includes = gyp.common.EncodePOSIXShellList(includes)
|
||||||
|
cflags_c = gyp.common.EncodePOSIXShellList(cflags_c)
|
||||||
|
cflags_cc = gyp.common.EncodePOSIXShellList(cflags_cc)
|
||||||
|
|
||||||
|
commands = per_config_commands.setdefault(configuration_name, [])
|
||||||
|
for source in sources:
|
||||||
|
file = resolve(source)
|
||||||
|
isc = source.endswith(".c")
|
||||||
|
cc = "cc" if isc else "c++"
|
||||||
|
cflags = cflags_c if isc else cflags_cc
|
||||||
|
command = " ".join(
|
||||||
|
(
|
||||||
|
cc,
|
||||||
|
defines,
|
||||||
|
includes,
|
||||||
|
cflags,
|
||||||
|
"-c",
|
||||||
|
gyp.common.EncodePOSIXShellArgument(file),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
commands.append({"command": command, "directory": output_dir, "file": file})
|
||||||
|
|
||||||
|
|
||||||
|
def GenerateOutput(target_list, target_dicts, data, params):
|
||||||
|
per_config_commands = {}
|
||||||
|
for qualified_target, target in target_dicts.items():
|
||||||
|
build_file, _target_name, _toolset = gyp.common.ParseQualifiedTarget(
|
||||||
|
qualified_target
|
||||||
|
)
|
||||||
|
if IsMac(params):
|
||||||
|
settings = data[build_file]
|
||||||
|
gyp.xcode_emulation.MergeGlobalXcodeSettingsToSpec(settings, target)
|
||||||
|
cwd = os.path.dirname(build_file)
|
||||||
|
AddCommandsForTarget(cwd, target, params, per_config_commands)
|
||||||
|
|
||||||
|
output_dir = None
|
||||||
|
try:
|
||||||
|
# generator_output can be `None` on Windows machines, or even not
|
||||||
|
# defined in other cases
|
||||||
|
output_dir = params.get("options").generator_output
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
output_dir = output_dir or params["generator_flags"].get("output_dir", "out")
|
||||||
|
for configuration_name, commands in per_config_commands.items():
|
||||||
|
filename = os.path.join(output_dir, configuration_name, "compile_commands.json")
|
||||||
|
gyp.common.EnsureDirExists(filename)
|
||||||
|
fp = open(filename, "w")
|
||||||
|
json.dump(commands, fp=fp, indent=0, check_circular=False)
|
||||||
|
|
||||||
|
|
||||||
|
def PerformBuild(data, configurations, params):
|
||||||
|
pass
|
||||||
104
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/dump_dependency_json.py
generated
vendored
Normal file
104
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/dump_dependency_json.py
generated
vendored
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
# Copyright (c) 2012 Google Inc. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
import gyp
|
||||||
|
import gyp.common
|
||||||
|
import gyp.msvs_emulation
|
||||||
|
|
||||||
|
generator_supports_multiple_toolsets = True
|
||||||
|
|
||||||
|
generator_wants_static_library_dependencies_adjusted = False
|
||||||
|
|
||||||
|
generator_filelist_paths = {}
|
||||||
|
|
||||||
|
generator_default_variables = {}
|
||||||
|
for dirname in [
|
||||||
|
"INTERMEDIATE_DIR",
|
||||||
|
"SHARED_INTERMEDIATE_DIR",
|
||||||
|
"PRODUCT_DIR",
|
||||||
|
"LIB_DIR",
|
||||||
|
"SHARED_LIB_DIR",
|
||||||
|
]:
|
||||||
|
# Some gyp steps fail if these are empty(!).
|
||||||
|
generator_default_variables[dirname] = "dir"
|
||||||
|
for unused in [
|
||||||
|
"RULE_INPUT_PATH",
|
||||||
|
"RULE_INPUT_ROOT",
|
||||||
|
"RULE_INPUT_NAME",
|
||||||
|
"RULE_INPUT_DIRNAME",
|
||||||
|
"RULE_INPUT_EXT",
|
||||||
|
"EXECUTABLE_PREFIX",
|
||||||
|
"EXECUTABLE_SUFFIX",
|
||||||
|
"STATIC_LIB_PREFIX",
|
||||||
|
"STATIC_LIB_SUFFIX",
|
||||||
|
"SHARED_LIB_PREFIX",
|
||||||
|
"SHARED_LIB_SUFFIX",
|
||||||
|
"CONFIGURATION_NAME",
|
||||||
|
]:
|
||||||
|
generator_default_variables[unused] = ""
|
||||||
|
|
||||||
|
|
||||||
|
def CalculateVariables(default_variables, params):
|
||||||
|
generator_flags = params.get("generator_flags", {})
|
||||||
|
for key, val in generator_flags.items():
|
||||||
|
default_variables.setdefault(key, val)
|
||||||
|
default_variables.setdefault("OS", gyp.common.GetFlavor(params))
|
||||||
|
|
||||||
|
flavor = gyp.common.GetFlavor(params)
|
||||||
|
if flavor == "win":
|
||||||
|
gyp.msvs_emulation.CalculateCommonVariables(default_variables, params)
|
||||||
|
|
||||||
|
|
||||||
|
def CalculateGeneratorInputInfo(params):
|
||||||
|
"""Calculate the generator specific info that gets fed to input (called by
|
||||||
|
gyp)."""
|
||||||
|
generator_flags = params.get("generator_flags", {})
|
||||||
|
if generator_flags.get("adjust_static_libraries", False):
|
||||||
|
global generator_wants_static_library_dependencies_adjusted
|
||||||
|
generator_wants_static_library_dependencies_adjusted = True
|
||||||
|
|
||||||
|
toplevel = params["options"].toplevel_dir
|
||||||
|
generator_dir = os.path.relpath(params["options"].generator_output or ".")
|
||||||
|
# output_dir: relative path from generator_dir to the build directory.
|
||||||
|
output_dir = generator_flags.get("output_dir", "out")
|
||||||
|
qualified_out_dir = os.path.normpath(
|
||||||
|
os.path.join(toplevel, generator_dir, output_dir, "gypfiles")
|
||||||
|
)
|
||||||
|
global generator_filelist_paths
|
||||||
|
generator_filelist_paths = {
|
||||||
|
"toplevel": toplevel,
|
||||||
|
"qualified_out_dir": qualified_out_dir,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def GenerateOutput(target_list, target_dicts, data, params):
|
||||||
|
# Map of target -> list of targets it depends on.
|
||||||
|
edges = {}
|
||||||
|
|
||||||
|
# Queue of targets to visit.
|
||||||
|
targets_to_visit = target_list[:]
|
||||||
|
|
||||||
|
while len(targets_to_visit) > 0:
|
||||||
|
target = targets_to_visit.pop()
|
||||||
|
if target in edges:
|
||||||
|
continue
|
||||||
|
edges[target] = []
|
||||||
|
|
||||||
|
for dep in target_dicts[target].get("dependencies", []):
|
||||||
|
edges[target].append(dep)
|
||||||
|
targets_to_visit.append(dep)
|
||||||
|
|
||||||
|
try:
|
||||||
|
filepath = params["generator_flags"]["output_dir"]
|
||||||
|
except KeyError:
|
||||||
|
filepath = "."
|
||||||
|
filename = os.path.join(filepath, "dump.json")
|
||||||
|
f = open(filename, "w")
|
||||||
|
json.dump(edges, f)
|
||||||
|
f.close()
|
||||||
|
print("Wrote json to %s." % filename)
|
||||||
461
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py
generated
vendored
Normal file
461
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py
generated
vendored
Normal file
|
|
@ -0,0 +1,461 @@
|
||||||
|
# Copyright (c) 2012 Google Inc. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
"""GYP backend that generates Eclipse CDT settings files.
|
||||||
|
|
||||||
|
This backend DOES NOT generate Eclipse CDT projects. Instead, it generates XML
|
||||||
|
files that can be imported into an Eclipse CDT project. The XML file contains a
|
||||||
|
list of include paths and symbols (i.e. defines).
|
||||||
|
|
||||||
|
Because a full .cproject definition is not created by this generator, it's not
|
||||||
|
possible to properly define the include dirs and symbols for each file
|
||||||
|
individually. Instead, one set of includes/symbols is generated for the entire
|
||||||
|
project. This works fairly well (and is a vast improvement in general), but may
|
||||||
|
still result in a few indexer issues here and there.
|
||||||
|
|
||||||
|
This generator has no automated tests, so expect it to be broken.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os.path
|
||||||
|
import shlex
|
||||||
|
import subprocess
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
from xml.sax.saxutils import escape
|
||||||
|
|
||||||
|
import gyp
|
||||||
|
import gyp.common
|
||||||
|
import gyp.msvs_emulation
|
||||||
|
|
||||||
|
generator_wants_static_library_dependencies_adjusted = False
|
||||||
|
|
||||||
|
generator_default_variables = {}
|
||||||
|
|
||||||
|
for dirname in ["INTERMEDIATE_DIR", "PRODUCT_DIR", "LIB_DIR", "SHARED_LIB_DIR"]:
|
||||||
|
# Some gyp steps fail if these are empty(!), so we convert them to variables
|
||||||
|
generator_default_variables[dirname] = "$" + dirname
|
||||||
|
|
||||||
|
for unused in [
|
||||||
|
"RULE_INPUT_PATH",
|
||||||
|
"RULE_INPUT_ROOT",
|
||||||
|
"RULE_INPUT_NAME",
|
||||||
|
"RULE_INPUT_DIRNAME",
|
||||||
|
"RULE_INPUT_EXT",
|
||||||
|
"EXECUTABLE_PREFIX",
|
||||||
|
"EXECUTABLE_SUFFIX",
|
||||||
|
"STATIC_LIB_PREFIX",
|
||||||
|
"STATIC_LIB_SUFFIX",
|
||||||
|
"SHARED_LIB_PREFIX",
|
||||||
|
"SHARED_LIB_SUFFIX",
|
||||||
|
"CONFIGURATION_NAME",
|
||||||
|
]:
|
||||||
|
generator_default_variables[unused] = ""
|
||||||
|
|
||||||
|
# Include dirs will occasionally use the SHARED_INTERMEDIATE_DIR variable as
|
||||||
|
# part of the path when dealing with generated headers. This value will be
|
||||||
|
# replaced dynamically for each configuration.
|
||||||
|
generator_default_variables["SHARED_INTERMEDIATE_DIR"] = "$SHARED_INTERMEDIATE_DIR"
|
||||||
|
|
||||||
|
|
||||||
|
def CalculateVariables(default_variables, params):
|
||||||
|
generator_flags = params.get("generator_flags", {})
|
||||||
|
for key, val in generator_flags.items():
|
||||||
|
default_variables.setdefault(key, val)
|
||||||
|
flavor = gyp.common.GetFlavor(params)
|
||||||
|
default_variables.setdefault("OS", flavor)
|
||||||
|
if flavor == "win":
|
||||||
|
gyp.msvs_emulation.CalculateCommonVariables(default_variables, params)
|
||||||
|
|
||||||
|
|
||||||
|
def CalculateGeneratorInputInfo(params):
|
||||||
|
"""Calculate the generator specific info that gets fed to input (called by
|
||||||
|
gyp)."""
|
||||||
|
generator_flags = params.get("generator_flags", {})
|
||||||
|
if generator_flags.get("adjust_static_libraries", False):
|
||||||
|
global generator_wants_static_library_dependencies_adjusted
|
||||||
|
generator_wants_static_library_dependencies_adjusted = True
|
||||||
|
|
||||||
|
|
||||||
|
def GetAllIncludeDirectories(
|
||||||
|
target_list,
|
||||||
|
target_dicts,
|
||||||
|
shared_intermediate_dirs,
|
||||||
|
config_name,
|
||||||
|
params,
|
||||||
|
compiler_path,
|
||||||
|
):
|
||||||
|
"""Calculate the set of include directories to be used.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A list including all the include_dir's specified for every target followed
|
||||||
|
by any include directories that were added as cflag compiler options.
|
||||||
|
"""
|
||||||
|
|
||||||
|
gyp_includes_set = set()
|
||||||
|
compiler_includes_list = []
|
||||||
|
|
||||||
|
# Find compiler's default include dirs.
|
||||||
|
if compiler_path:
|
||||||
|
command = shlex.split(compiler_path)
|
||||||
|
command.extend(["-E", "-xc++", "-v", "-"])
|
||||||
|
proc = subprocess.Popen(
|
||||||
|
args=command,
|
||||||
|
stdin=subprocess.PIPE,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
)
|
||||||
|
output = proc.communicate()[1].decode("utf-8")
|
||||||
|
# Extract the list of include dirs from the output, which has this format:
|
||||||
|
# ...
|
||||||
|
# #include "..." search starts here:
|
||||||
|
# #include <...> search starts here:
|
||||||
|
# /usr/include/c++/4.6
|
||||||
|
# /usr/local/include
|
||||||
|
# End of search list.
|
||||||
|
# ...
|
||||||
|
in_include_list = False
|
||||||
|
for line in output.splitlines():
|
||||||
|
if line.startswith("#include"):
|
||||||
|
in_include_list = True
|
||||||
|
continue
|
||||||
|
if line.startswith("End of search list."):
|
||||||
|
break
|
||||||
|
if in_include_list:
|
||||||
|
include_dir = line.strip()
|
||||||
|
if include_dir not in compiler_includes_list:
|
||||||
|
compiler_includes_list.append(include_dir)
|
||||||
|
|
||||||
|
flavor = gyp.common.GetFlavor(params)
|
||||||
|
if flavor == "win":
|
||||||
|
generator_flags = params.get("generator_flags", {})
|
||||||
|
for target_name in target_list:
|
||||||
|
target = target_dicts[target_name]
|
||||||
|
if config_name in target["configurations"]:
|
||||||
|
config = target["configurations"][config_name]
|
||||||
|
|
||||||
|
# Look for any include dirs that were explicitly added via cflags. This
|
||||||
|
# may be done in gyp files to force certain includes to come at the end.
|
||||||
|
# TODO(jgreenwald): Change the gyp files to not abuse cflags for this, and
|
||||||
|
# remove this.
|
||||||
|
if flavor == "win":
|
||||||
|
msvs_settings = gyp.msvs_emulation.MsvsSettings(target, generator_flags)
|
||||||
|
cflags = msvs_settings.GetCflags(config_name)
|
||||||
|
else:
|
||||||
|
cflags = config["cflags"]
|
||||||
|
for cflag in cflags:
|
||||||
|
if cflag.startswith("-I"):
|
||||||
|
include_dir = cflag[2:]
|
||||||
|
if include_dir not in compiler_includes_list:
|
||||||
|
compiler_includes_list.append(include_dir)
|
||||||
|
|
||||||
|
# Find standard gyp include dirs.
|
||||||
|
if "include_dirs" in config:
|
||||||
|
include_dirs = config["include_dirs"]
|
||||||
|
for shared_intermediate_dir in shared_intermediate_dirs:
|
||||||
|
for include_dir in include_dirs:
|
||||||
|
include_dir = include_dir.replace(
|
||||||
|
"$SHARED_INTERMEDIATE_DIR", shared_intermediate_dir
|
||||||
|
)
|
||||||
|
if not os.path.isabs(include_dir):
|
||||||
|
base_dir = os.path.dirname(target_name)
|
||||||
|
|
||||||
|
include_dir = base_dir + "/" + include_dir
|
||||||
|
include_dir = os.path.abspath(include_dir)
|
||||||
|
|
||||||
|
gyp_includes_set.add(include_dir)
|
||||||
|
|
||||||
|
# Generate a list that has all the include dirs.
|
||||||
|
all_includes_list = list(gyp_includes_set)
|
||||||
|
all_includes_list.sort()
|
||||||
|
for compiler_include in compiler_includes_list:
|
||||||
|
if compiler_include not in gyp_includes_set:
|
||||||
|
all_includes_list.append(compiler_include)
|
||||||
|
|
||||||
|
# All done.
|
||||||
|
return all_includes_list
|
||||||
|
|
||||||
|
|
||||||
|
def GetCompilerPath(target_list, data, options):
|
||||||
|
"""Determine a command that can be used to invoke the compiler.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
If this is a gyp project that has explicit make settings, try to determine
|
||||||
|
the compiler from that. Otherwise, see if a compiler was specified via the
|
||||||
|
CC_target environment variable.
|
||||||
|
"""
|
||||||
|
# First, see if the compiler is configured in make's settings.
|
||||||
|
build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0])
|
||||||
|
make_global_settings_dict = data[build_file].get("make_global_settings", {})
|
||||||
|
for key, value in make_global_settings_dict:
|
||||||
|
if key in ["CC", "CXX"]:
|
||||||
|
return os.path.join(options.toplevel_dir, value)
|
||||||
|
|
||||||
|
# Check to see if the compiler was specified as an environment variable.
|
||||||
|
for key in ["CC_target", "CC", "CXX"]:
|
||||||
|
compiler = os.environ.get(key)
|
||||||
|
if compiler:
|
||||||
|
return compiler
|
||||||
|
|
||||||
|
return "gcc"
|
||||||
|
|
||||||
|
|
||||||
|
def GetAllDefines(target_list, target_dicts, data, config_name, params, compiler_path):
|
||||||
|
"""Calculate the defines for a project.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A dict that includes explicit defines declared in gyp files along with all
|
||||||
|
of the default defines that the compiler uses.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Get defines declared in the gyp files.
|
||||||
|
all_defines = {}
|
||||||
|
flavor = gyp.common.GetFlavor(params)
|
||||||
|
if flavor == "win":
|
||||||
|
generator_flags = params.get("generator_flags", {})
|
||||||
|
for target_name in target_list:
|
||||||
|
target = target_dicts[target_name]
|
||||||
|
|
||||||
|
if flavor == "win":
|
||||||
|
msvs_settings = gyp.msvs_emulation.MsvsSettings(target, generator_flags)
|
||||||
|
extra_defines = msvs_settings.GetComputedDefines(config_name)
|
||||||
|
else:
|
||||||
|
extra_defines = []
|
||||||
|
if config_name in target["configurations"]:
|
||||||
|
config = target["configurations"][config_name]
|
||||||
|
target_defines = config["defines"]
|
||||||
|
else:
|
||||||
|
target_defines = []
|
||||||
|
for define in target_defines + extra_defines:
|
||||||
|
split_define = define.split("=", 1)
|
||||||
|
if len(split_define) == 1:
|
||||||
|
split_define.append("1")
|
||||||
|
if split_define[0].strip() in all_defines:
|
||||||
|
# Already defined
|
||||||
|
continue
|
||||||
|
all_defines[split_define[0].strip()] = split_define[1].strip()
|
||||||
|
# Get default compiler defines (if possible).
|
||||||
|
if flavor == "win":
|
||||||
|
return all_defines # Default defines already processed in the loop above.
|
||||||
|
if compiler_path:
|
||||||
|
command = shlex.split(compiler_path)
|
||||||
|
command.extend(["-E", "-dM", "-"])
|
||||||
|
cpp_proc = subprocess.Popen(
|
||||||
|
args=command, cwd=".", stdin=subprocess.PIPE, stdout=subprocess.PIPE
|
||||||
|
)
|
||||||
|
cpp_output = cpp_proc.communicate()[0].decode("utf-8")
|
||||||
|
cpp_lines = cpp_output.split("\n")
|
||||||
|
for cpp_line in cpp_lines:
|
||||||
|
if not cpp_line.strip():
|
||||||
|
continue
|
||||||
|
cpp_line_parts = cpp_line.split(" ", 2)
|
||||||
|
key = cpp_line_parts[1]
|
||||||
|
val = cpp_line_parts[2] if len(cpp_line_parts) >= 3 else "1"
|
||||||
|
all_defines[key] = val
|
||||||
|
|
||||||
|
return all_defines
|
||||||
|
|
||||||
|
|
||||||
|
def WriteIncludePaths(out, eclipse_langs, include_dirs):
|
||||||
|
"""Write the includes section of a CDT settings export file."""
|
||||||
|
|
||||||
|
out.write(
|
||||||
|
' <section name="org.eclipse.cdt.internal.ui.wizards.'
|
||||||
|
'settingswizards.IncludePaths">\n'
|
||||||
|
)
|
||||||
|
out.write(' <language name="holder for library settings"></language>\n')
|
||||||
|
for lang in eclipse_langs:
|
||||||
|
out.write(' <language name="%s">\n' % lang)
|
||||||
|
for include_dir in include_dirs:
|
||||||
|
out.write(
|
||||||
|
' <includepath workspace_path="false">%s</includepath>\n'
|
||||||
|
% include_dir
|
||||||
|
)
|
||||||
|
out.write(" </language>\n")
|
||||||
|
out.write(" </section>\n")
|
||||||
|
|
||||||
|
|
||||||
|
def WriteMacros(out, eclipse_langs, defines):
|
||||||
|
"""Write the macros section of a CDT settings export file."""
|
||||||
|
|
||||||
|
out.write(
|
||||||
|
' <section name="org.eclipse.cdt.internal.ui.wizards.'
|
||||||
|
'settingswizards.Macros">\n'
|
||||||
|
)
|
||||||
|
out.write(' <language name="holder for library settings"></language>\n')
|
||||||
|
for lang in eclipse_langs:
|
||||||
|
out.write(' <language name="%s">\n' % lang)
|
||||||
|
for key in sorted(defines):
|
||||||
|
out.write(
|
||||||
|
" <macro><name>%s</name><value>%s</value></macro>\n"
|
||||||
|
% (escape(key), escape(defines[key]))
|
||||||
|
)
|
||||||
|
out.write(" </language>\n")
|
||||||
|
out.write(" </section>\n")
|
||||||
|
|
||||||
|
|
||||||
|
def GenerateOutputForConfig(target_list, target_dicts, data, params, config_name):
|
||||||
|
options = params["options"]
|
||||||
|
generator_flags = params.get("generator_flags", {})
|
||||||
|
|
||||||
|
# build_dir: relative path from source root to our output files.
|
||||||
|
# e.g. "out/Debug"
|
||||||
|
build_dir = os.path.join(generator_flags.get("output_dir", "out"), config_name)
|
||||||
|
|
||||||
|
toplevel_build = os.path.join(options.toplevel_dir, build_dir)
|
||||||
|
# Ninja uses out/Debug/gen while make uses out/Debug/obj/gen as the
|
||||||
|
# SHARED_INTERMEDIATE_DIR. Include both possible locations.
|
||||||
|
shared_intermediate_dirs = [
|
||||||
|
os.path.join(toplevel_build, "obj", "gen"),
|
||||||
|
os.path.join(toplevel_build, "gen"),
|
||||||
|
]
|
||||||
|
|
||||||
|
GenerateCdtSettingsFile(
|
||||||
|
target_list,
|
||||||
|
target_dicts,
|
||||||
|
data,
|
||||||
|
params,
|
||||||
|
config_name,
|
||||||
|
os.path.join(toplevel_build, "eclipse-cdt-settings.xml"),
|
||||||
|
options,
|
||||||
|
shared_intermediate_dirs,
|
||||||
|
)
|
||||||
|
GenerateClasspathFile(
|
||||||
|
target_list,
|
||||||
|
target_dicts,
|
||||||
|
options.toplevel_dir,
|
||||||
|
toplevel_build,
|
||||||
|
os.path.join(toplevel_build, "eclipse-classpath.xml"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def GenerateCdtSettingsFile(
|
||||||
|
target_list,
|
||||||
|
target_dicts,
|
||||||
|
data,
|
||||||
|
params,
|
||||||
|
config_name,
|
||||||
|
out_name,
|
||||||
|
options,
|
||||||
|
shared_intermediate_dirs,
|
||||||
|
):
|
||||||
|
gyp.common.EnsureDirExists(out_name)
|
||||||
|
with open(out_name, "w") as out:
|
||||||
|
out.write('<?xml version="1.0" encoding="UTF-8"?>\n')
|
||||||
|
out.write("<cdtprojectproperties>\n")
|
||||||
|
|
||||||
|
eclipse_langs = [
|
||||||
|
"C++ Source File",
|
||||||
|
"C Source File",
|
||||||
|
"Assembly Source File",
|
||||||
|
"GNU C++",
|
||||||
|
"GNU C",
|
||||||
|
"Assembly",
|
||||||
|
]
|
||||||
|
compiler_path = GetCompilerPath(target_list, data, options)
|
||||||
|
include_dirs = GetAllIncludeDirectories(
|
||||||
|
target_list,
|
||||||
|
target_dicts,
|
||||||
|
shared_intermediate_dirs,
|
||||||
|
config_name,
|
||||||
|
params,
|
||||||
|
compiler_path,
|
||||||
|
)
|
||||||
|
WriteIncludePaths(out, eclipse_langs, include_dirs)
|
||||||
|
defines = GetAllDefines(
|
||||||
|
target_list, target_dicts, data, config_name, params, compiler_path
|
||||||
|
)
|
||||||
|
WriteMacros(out, eclipse_langs, defines)
|
||||||
|
|
||||||
|
out.write("</cdtprojectproperties>\n")
|
||||||
|
|
||||||
|
|
||||||
|
def GenerateClasspathFile(
|
||||||
|
target_list, target_dicts, toplevel_dir, toplevel_build, out_name
|
||||||
|
):
|
||||||
|
"""Generates a classpath file suitable for symbol navigation and code
|
||||||
|
completion of Java code (such as in Android projects) by finding all
|
||||||
|
.java and .jar files used as action inputs."""
|
||||||
|
gyp.common.EnsureDirExists(out_name)
|
||||||
|
result = ET.Element("classpath")
|
||||||
|
|
||||||
|
def AddElements(kind, paths):
|
||||||
|
# First, we need to normalize the paths so they are all relative to the
|
||||||
|
# toplevel dir.
|
||||||
|
rel_paths = set()
|
||||||
|
for path in paths:
|
||||||
|
if os.path.isabs(path):
|
||||||
|
rel_paths.add(os.path.relpath(path, toplevel_dir))
|
||||||
|
else:
|
||||||
|
rel_paths.add(path)
|
||||||
|
|
||||||
|
for path in sorted(rel_paths):
|
||||||
|
entry_element = ET.SubElement(result, "classpathentry")
|
||||||
|
entry_element.set("kind", kind)
|
||||||
|
entry_element.set("path", path)
|
||||||
|
|
||||||
|
AddElements("lib", GetJavaJars(target_list, target_dicts, toplevel_dir))
|
||||||
|
AddElements("src", GetJavaSourceDirs(target_list, target_dicts, toplevel_dir))
|
||||||
|
# Include the standard JRE container and a dummy out folder
|
||||||
|
AddElements("con", ["org.eclipse.jdt.launching.JRE_CONTAINER"])
|
||||||
|
# Include a dummy out folder so that Eclipse doesn't use the default /bin
|
||||||
|
# folder in the root of the project.
|
||||||
|
AddElements("output", [os.path.join(toplevel_build, ".eclipse-java-build")])
|
||||||
|
|
||||||
|
ET.ElementTree(result).write(out_name)
|
||||||
|
|
||||||
|
|
||||||
|
def GetJavaJars(target_list, target_dicts, toplevel_dir):
|
||||||
|
"""Generates a sequence of all .jars used as inputs."""
|
||||||
|
for target_name in target_list:
|
||||||
|
target = target_dicts[target_name]
|
||||||
|
for action in target.get("actions", []):
|
||||||
|
for input_ in action["inputs"]:
|
||||||
|
if os.path.splitext(input_)[1] == ".jar" and not input_.startswith("$"):
|
||||||
|
if os.path.isabs(input_):
|
||||||
|
yield input_
|
||||||
|
else:
|
||||||
|
yield os.path.join(os.path.dirname(target_name), input_)
|
||||||
|
|
||||||
|
|
||||||
|
def GetJavaSourceDirs(target_list, target_dicts, toplevel_dir):
|
||||||
|
"""Generates a sequence of all likely java package root directories."""
|
||||||
|
for target_name in target_list:
|
||||||
|
target = target_dicts[target_name]
|
||||||
|
for action in target.get("actions", []):
|
||||||
|
for input_ in action["inputs"]:
|
||||||
|
if os.path.splitext(input_)[1] == ".java" and not input_.startswith(
|
||||||
|
"$"
|
||||||
|
):
|
||||||
|
dir_ = os.path.dirname(
|
||||||
|
os.path.join(os.path.dirname(target_name), input_)
|
||||||
|
)
|
||||||
|
# If there is a parent 'src' or 'java' folder, navigate up to it -
|
||||||
|
# these are canonical package root names in Chromium. This will
|
||||||
|
# break if 'src' or 'java' exists in the package structure. This
|
||||||
|
# could be further improved by inspecting the java file for the
|
||||||
|
# package name if this proves to be too fragile in practice.
|
||||||
|
parent_search = dir_
|
||||||
|
while os.path.basename(parent_search) not in ["src", "java"]:
|
||||||
|
parent_search, _ = os.path.split(parent_search)
|
||||||
|
if not parent_search or parent_search == toplevel_dir:
|
||||||
|
# Didn't find a known root, just return the original path
|
||||||
|
yield dir_
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
yield parent_search
|
||||||
|
|
||||||
|
|
||||||
|
def GenerateOutput(target_list, target_dicts, data, params):
|
||||||
|
"""Generate an XML settings file that can be imported into a CDT project."""
|
||||||
|
|
||||||
|
if params["options"].generator_output:
|
||||||
|
raise NotImplementedError("--generator_output not implemented for eclipse")
|
||||||
|
|
||||||
|
if user_config := params.get("generator_flags", {}).get("config", None):
|
||||||
|
GenerateOutputForConfig(target_list, target_dicts, data, params, user_config)
|
||||||
|
else:
|
||||||
|
config_names = target_dicts[target_list[0]]["configurations"]
|
||||||
|
for config_name in config_names:
|
||||||
|
GenerateOutputForConfig(
|
||||||
|
target_list, target_dicts, data, params, config_name
|
||||||
|
)
|
||||||
88
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/gypd.py
generated
vendored
Normal file
88
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/gypd.py
generated
vendored
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
# Copyright (c) 2011 Google Inc. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
"""gypd output module
|
||||||
|
|
||||||
|
This module produces gyp input as its output. Output files are given the
|
||||||
|
.gypd extension to avoid overwriting the .gyp files that they are generated
|
||||||
|
from. Internal references to .gyp files (such as those found in
|
||||||
|
"dependencies" sections) are not adjusted to point to .gypd files instead;
|
||||||
|
unlike other paths, which are relative to the .gyp or .gypd file, such paths
|
||||||
|
are relative to the directory from which gyp was run to create the .gypd file.
|
||||||
|
|
||||||
|
This generator module is intended to be a sample and a debugging aid, hence
|
||||||
|
the "d" for "debug" in .gypd. It is useful to inspect the results of the
|
||||||
|
various merges, expansions, and conditional evaluations performed by gyp
|
||||||
|
and to see a representation of what would be fed to a generator module.
|
||||||
|
|
||||||
|
It's not advisable to rename .gypd files produced by this module to .gyp,
|
||||||
|
because they will have all merges, expansions, and evaluations already
|
||||||
|
performed and the relevant constructs not present in the output; paths to
|
||||||
|
dependencies may be wrong; and various sections that do not belong in .gyp
|
||||||
|
files such as such as "included_files" and "*_excluded" will be present.
|
||||||
|
Output will also be stripped of comments. This is not intended to be a
|
||||||
|
general-purpose gyp pretty-printer; for that, you probably just want to
|
||||||
|
run "pprint.pprint(eval(open('source.gyp').read()))", which will still strip
|
||||||
|
comments but won't do all of the other things done to this module's output.
|
||||||
|
|
||||||
|
The specific formatting of the output generated by this module is subject
|
||||||
|
to change.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import pprint
|
||||||
|
|
||||||
|
import gyp.common
|
||||||
|
|
||||||
|
# These variables should just be spit back out as variable references.
|
||||||
|
_generator_identity_variables = [
|
||||||
|
"CONFIGURATION_NAME",
|
||||||
|
"EXECUTABLE_PREFIX",
|
||||||
|
"EXECUTABLE_SUFFIX",
|
||||||
|
"INTERMEDIATE_DIR",
|
||||||
|
"LIB_DIR",
|
||||||
|
"PRODUCT_DIR",
|
||||||
|
"RULE_INPUT_ROOT",
|
||||||
|
"RULE_INPUT_DIRNAME",
|
||||||
|
"RULE_INPUT_EXT",
|
||||||
|
"RULE_INPUT_NAME",
|
||||||
|
"RULE_INPUT_PATH",
|
||||||
|
"SHARED_INTERMEDIATE_DIR",
|
||||||
|
"SHARED_LIB_DIR",
|
||||||
|
"SHARED_LIB_PREFIX",
|
||||||
|
"SHARED_LIB_SUFFIX",
|
||||||
|
"STATIC_LIB_PREFIX",
|
||||||
|
"STATIC_LIB_SUFFIX",
|
||||||
|
]
|
||||||
|
|
||||||
|
# gypd doesn't define a default value for OS like many other generator
|
||||||
|
# modules. Specify "-D OS=whatever" on the command line to provide a value.
|
||||||
|
generator_default_variables = {}
|
||||||
|
|
||||||
|
# gypd supports multiple toolsets
|
||||||
|
generator_supports_multiple_toolsets = True
|
||||||
|
|
||||||
|
# TODO(mark): This always uses <, which isn't right. The input module should
|
||||||
|
# notify the generator to tell it which phase it is operating in, and this
|
||||||
|
# module should use < for the early phase and then switch to > for the late
|
||||||
|
# phase. Bonus points for carrying @ back into the output too.
|
||||||
|
for v in _generator_identity_variables:
|
||||||
|
generator_default_variables[v] = "<(%s)" % v
|
||||||
|
|
||||||
|
|
||||||
|
def GenerateOutput(target_list, target_dicts, data, params):
|
||||||
|
output_files = {}
|
||||||
|
for qualified_target in target_list:
|
||||||
|
[input_file, _target] = gyp.common.ParseQualifiedTarget(qualified_target)[0:2]
|
||||||
|
|
||||||
|
if input_file[-4:] != ".gyp":
|
||||||
|
continue
|
||||||
|
input_file_stem = input_file[:-4]
|
||||||
|
output_file = input_file_stem + params["options"].suffix + ".gypd"
|
||||||
|
|
||||||
|
output_files[output_file] = output_files.get(output_file, input_file)
|
||||||
|
|
||||||
|
for output_file, input_file in output_files.items():
|
||||||
|
output = open(output_file, "w")
|
||||||
|
pprint.pprint(data[input_file], output)
|
||||||
|
output.close()
|
||||||
55
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/gypsh.py
generated
vendored
Normal file
55
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/gypsh.py
generated
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
# Copyright (c) 2011 Google Inc. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
"""gypsh output module
|
||||||
|
|
||||||
|
gypsh is a GYP shell. It's not really a generator per se. All it does is
|
||||||
|
fire up an interactive Python session with a few local variables set to the
|
||||||
|
variables passed to the generator. Like gypd, it's intended as a debugging
|
||||||
|
aid, to facilitate the exploration of .gyp structures after being processed
|
||||||
|
by the input module.
|
||||||
|
|
||||||
|
The expected usage is "gyp -f gypsh -D OS=desired_os".
|
||||||
|
"""
|
||||||
|
|
||||||
|
import code
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# All of this stuff about generator variables was lovingly ripped from gypd.py.
|
||||||
|
# That module has a much better description of what's going on and why.
|
||||||
|
_generator_identity_variables = [
|
||||||
|
"EXECUTABLE_PREFIX",
|
||||||
|
"EXECUTABLE_SUFFIX",
|
||||||
|
"INTERMEDIATE_DIR",
|
||||||
|
"PRODUCT_DIR",
|
||||||
|
"RULE_INPUT_ROOT",
|
||||||
|
"RULE_INPUT_DIRNAME",
|
||||||
|
"RULE_INPUT_EXT",
|
||||||
|
"RULE_INPUT_NAME",
|
||||||
|
"RULE_INPUT_PATH",
|
||||||
|
"SHARED_INTERMEDIATE_DIR",
|
||||||
|
]
|
||||||
|
|
||||||
|
generator_default_variables = {}
|
||||||
|
|
||||||
|
for v in _generator_identity_variables:
|
||||||
|
generator_default_variables[v] = "<(%s)" % v
|
||||||
|
|
||||||
|
|
||||||
|
def GenerateOutput(target_list, target_dicts, data, params):
|
||||||
|
locals = {
|
||||||
|
"target_list": target_list,
|
||||||
|
"target_dicts": target_dicts,
|
||||||
|
"data": data,
|
||||||
|
}
|
||||||
|
|
||||||
|
# Use a banner that looks like the stock Python one and like what
|
||||||
|
# code.interact uses by default, but tack on something to indicate what
|
||||||
|
# locals are available, and identify gypsh.
|
||||||
|
banner = (
|
||||||
|
f"Python {sys.version} on {sys.platform}\nlocals.keys() = "
|
||||||
|
f"{sorted(locals.keys())!r}\ngypsh"
|
||||||
|
)
|
||||||
|
|
||||||
|
code.interact(banner, local=locals)
|
||||||
2755
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py
generated
vendored
Normal file
2755
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3970
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py
generated
vendored
Normal file
3970
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
44
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs_test.py
generated
vendored
Normal file
44
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs_test.py
generated
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# Copyright (c) 2012 Google Inc. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
"""Unit tests for the msvs.py file."""
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from io import StringIO
|
||||||
|
|
||||||
|
from gyp.generator import msvs
|
||||||
|
|
||||||
|
|
||||||
|
class TestSequenceFunctions(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.stderr = StringIO()
|
||||||
|
|
||||||
|
def test_GetLibraries(self):
|
||||||
|
self.assertEqual(msvs._GetLibraries({}), [])
|
||||||
|
self.assertEqual(msvs._GetLibraries({"libraries": []}), [])
|
||||||
|
self.assertEqual(
|
||||||
|
msvs._GetLibraries({"other": "foo", "libraries": ["a.lib"]}), ["a.lib"]
|
||||||
|
)
|
||||||
|
self.assertEqual(msvs._GetLibraries({"libraries": ["-la"]}), ["a.lib"])
|
||||||
|
self.assertEqual(
|
||||||
|
msvs._GetLibraries(
|
||||||
|
{
|
||||||
|
"libraries": [
|
||||||
|
"a.lib",
|
||||||
|
"b.lib",
|
||||||
|
"c.lib",
|
||||||
|
"-lb.lib",
|
||||||
|
"-lb.lib",
|
||||||
|
"d.lib",
|
||||||
|
"a.lib",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
),
|
||||||
|
["c.lib", "b.lib", "d.lib", "a.lib"],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
2956
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py
generated
vendored
Normal file
2956
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
67
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja_test.py
generated
vendored
Normal file
67
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja_test.py
generated
vendored
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Copyright (c) 2012 Google Inc. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
"""Unit tests for the ninja.py file."""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from gyp.generator import ninja
|
||||||
|
|
||||||
|
|
||||||
|
class TestPrefixesAndSuffixes(unittest.TestCase):
|
||||||
|
def test_BinaryNamesWindows(self):
|
||||||
|
# These cannot run on non-Windows as they require a VS installation to
|
||||||
|
# correctly handle variable expansion.
|
||||||
|
if sys.platform.startswith("win"):
|
||||||
|
writer = ninja.NinjaWriter(
|
||||||
|
"foo", "wee", ".", ".", "build.ninja", ".", "build.ninja", "win"
|
||||||
|
)
|
||||||
|
spec = {"target_name": "wee"}
|
||||||
|
self.assertTrue(
|
||||||
|
writer.ComputeOutputFileName(spec, "executable").endswith(".exe")
|
||||||
|
)
|
||||||
|
self.assertTrue(
|
||||||
|
writer.ComputeOutputFileName(spec, "shared_library").endswith(".dll")
|
||||||
|
)
|
||||||
|
self.assertTrue(
|
||||||
|
writer.ComputeOutputFileName(spec, "static_library").endswith(".lib")
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_BinaryNamesLinux(self):
|
||||||
|
writer = ninja.NinjaWriter(
|
||||||
|
"foo", "wee", ".", ".", "build.ninja", ".", "build.ninja", "linux"
|
||||||
|
)
|
||||||
|
spec = {"target_name": "wee"}
|
||||||
|
self.assertTrue("." not in writer.ComputeOutputFileName(spec, "executable"))
|
||||||
|
self.assertTrue(
|
||||||
|
writer.ComputeOutputFileName(spec, "shared_library").startswith("lib")
|
||||||
|
)
|
||||||
|
self.assertTrue(
|
||||||
|
writer.ComputeOutputFileName(spec, "static_library").startswith("lib")
|
||||||
|
)
|
||||||
|
self.assertTrue(
|
||||||
|
writer.ComputeOutputFileName(spec, "shared_library").endswith(".so")
|
||||||
|
)
|
||||||
|
self.assertTrue(
|
||||||
|
writer.ComputeOutputFileName(spec, "static_library").endswith(".a")
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_GenerateCompileDBWithNinja(self):
|
||||||
|
build_dir = (
|
||||||
|
Path(__file__).resolve().parent.parent.parent.parent / "data" / "ninja"
|
||||||
|
)
|
||||||
|
compile_db = ninja.GenerateCompileDBWithNinja(build_dir)
|
||||||
|
assert len(compile_db) == 1
|
||||||
|
assert compile_db[0]["directory"] == str(build_dir)
|
||||||
|
assert compile_db[0]["command"] == "cc my.in my.out"
|
||||||
|
assert compile_db[0]["file"] == "my.in"
|
||||||
|
assert compile_db[0]["output"] == "my.out"
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
1389
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode.py
generated
vendored
Normal file
1389
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode.py
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
26
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode_test.py
generated
vendored
Normal file
26
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode_test.py
generated
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Copyright (c) 2013 Google Inc. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
"""Unit tests for the xcode.py file."""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from gyp.generator import xcode
|
||||||
|
|
||||||
|
|
||||||
|
class TestEscapeXcodeDefine(unittest.TestCase):
|
||||||
|
if sys.platform == "darwin":
|
||||||
|
|
||||||
|
def test_InheritedRemainsUnescaped(self):
|
||||||
|
self.assertEqual(xcode.EscapeXcodeDefine("$(inherited)"), "$(inherited)")
|
||||||
|
|
||||||
|
def test_Escaping(self):
|
||||||
|
self.assertEqual(xcode.EscapeXcodeDefine('a b"c\\'), 'a\\ b\\"c\\\\')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
3097
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/input.py
generated
vendored
Normal file
3097
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/input.py
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
99
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/input_test.py
generated
vendored
Normal file
99
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/input_test.py
generated
vendored
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Copyright 2013 Google Inc. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
"""Unit tests for the input.py file."""
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
import gyp.input
|
||||||
|
|
||||||
|
|
||||||
|
class TestFindCycles(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.nodes = {}
|
||||||
|
for x in ("a", "b", "c", "d", "e"):
|
||||||
|
self.nodes[x] = gyp.input.DependencyGraphNode(x)
|
||||||
|
|
||||||
|
def _create_dependency(self, dependent, dependency):
|
||||||
|
dependent.dependencies.append(dependency)
|
||||||
|
dependency.dependents.append(dependent)
|
||||||
|
|
||||||
|
def test_no_cycle_empty_graph(self):
|
||||||
|
for label, node in self.nodes.items():
|
||||||
|
self.assertEqual([], node.FindCycles())
|
||||||
|
|
||||||
|
def test_no_cycle_line(self):
|
||||||
|
self._create_dependency(self.nodes["a"], self.nodes["b"])
|
||||||
|
self._create_dependency(self.nodes["b"], self.nodes["c"])
|
||||||
|
self._create_dependency(self.nodes["c"], self.nodes["d"])
|
||||||
|
|
||||||
|
for label, node in self.nodes.items():
|
||||||
|
self.assertEqual([], node.FindCycles())
|
||||||
|
|
||||||
|
def test_no_cycle_dag(self):
|
||||||
|
self._create_dependency(self.nodes["a"], self.nodes["b"])
|
||||||
|
self._create_dependency(self.nodes["a"], self.nodes["c"])
|
||||||
|
self._create_dependency(self.nodes["b"], self.nodes["c"])
|
||||||
|
|
||||||
|
for label, node in self.nodes.items():
|
||||||
|
self.assertEqual([], node.FindCycles())
|
||||||
|
|
||||||
|
def test_cycle_self_reference(self):
|
||||||
|
self._create_dependency(self.nodes["a"], self.nodes["a"])
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
[[self.nodes["a"], self.nodes["a"]]], self.nodes["a"].FindCycles()
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_cycle_two_nodes(self):
|
||||||
|
self._create_dependency(self.nodes["a"], self.nodes["b"])
|
||||||
|
self._create_dependency(self.nodes["b"], self.nodes["a"])
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
[[self.nodes["a"], self.nodes["b"], self.nodes["a"]]],
|
||||||
|
self.nodes["a"].FindCycles(),
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
[[self.nodes["b"], self.nodes["a"], self.nodes["b"]]],
|
||||||
|
self.nodes["b"].FindCycles(),
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_two_cycles(self):
|
||||||
|
self._create_dependency(self.nodes["a"], self.nodes["b"])
|
||||||
|
self._create_dependency(self.nodes["b"], self.nodes["a"])
|
||||||
|
|
||||||
|
self._create_dependency(self.nodes["b"], self.nodes["c"])
|
||||||
|
self._create_dependency(self.nodes["c"], self.nodes["b"])
|
||||||
|
|
||||||
|
cycles = self.nodes["a"].FindCycles()
|
||||||
|
self.assertTrue([self.nodes["a"], self.nodes["b"], self.nodes["a"]] in cycles)
|
||||||
|
self.assertTrue([self.nodes["b"], self.nodes["c"], self.nodes["b"]] in cycles)
|
||||||
|
self.assertEqual(2, len(cycles))
|
||||||
|
|
||||||
|
def test_big_cycle(self):
|
||||||
|
self._create_dependency(self.nodes["a"], self.nodes["b"])
|
||||||
|
self._create_dependency(self.nodes["b"], self.nodes["c"])
|
||||||
|
self._create_dependency(self.nodes["c"], self.nodes["d"])
|
||||||
|
self._create_dependency(self.nodes["d"], self.nodes["e"])
|
||||||
|
self._create_dependency(self.nodes["e"], self.nodes["a"])
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
[
|
||||||
|
[
|
||||||
|
self.nodes["a"],
|
||||||
|
self.nodes["b"],
|
||||||
|
self.nodes["c"],
|
||||||
|
self.nodes["d"],
|
||||||
|
self.nodes["e"],
|
||||||
|
self.nodes["a"],
|
||||||
|
]
|
||||||
|
],
|
||||||
|
self.nodes["a"].FindCycles(),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
765
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/mac_tool.py
generated
vendored
Normal file
765
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/mac_tool.py
generated
vendored
Normal file
|
|
@ -0,0 +1,765 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# Copyright (c) 2012 Google Inc. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
"""Utility functions to perform Xcode-style build steps.
|
||||||
|
|
||||||
|
These functions are executed via gyp-mac-tool when using the Makefile generator.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import fcntl
|
||||||
|
import fnmatch
|
||||||
|
import glob
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import plistlib
|
||||||
|
import re
|
||||||
|
import shutil
|
||||||
|
import struct
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
|
||||||
|
def main(args):
|
||||||
|
executor = MacTool()
|
||||||
|
if (exit_code := executor.Dispatch(args)) is not None:
|
||||||
|
sys.exit(exit_code)
|
||||||
|
|
||||||
|
|
||||||
|
class MacTool:
|
||||||
|
"""This class performs all the Mac tooling steps. The methods can either be
|
||||||
|
executed directly, or dispatched from an argument list."""
|
||||||
|
|
||||||
|
def Dispatch(self, args):
|
||||||
|
"""Dispatches a string command to a method."""
|
||||||
|
if len(args) < 1:
|
||||||
|
raise Exception("Not enough arguments")
|
||||||
|
|
||||||
|
method = "Exec%s" % self._CommandifyName(args[0])
|
||||||
|
return getattr(self, method)(*args[1:])
|
||||||
|
|
||||||
|
def _CommandifyName(self, name_string):
|
||||||
|
"""Transforms a tool name like copy-info-plist to CopyInfoPlist"""
|
||||||
|
return name_string.title().replace("-", "")
|
||||||
|
|
||||||
|
def ExecCopyBundleResource(self, source, dest, convert_to_binary):
|
||||||
|
"""Copies a resource file to the bundle/Resources directory, performing any
|
||||||
|
necessary compilation on each resource."""
|
||||||
|
convert_to_binary = convert_to_binary == "True"
|
||||||
|
extension = os.path.splitext(source)[1].lower()
|
||||||
|
if os.path.isdir(source):
|
||||||
|
# Copy tree.
|
||||||
|
# TODO(thakis): This copies file attributes like mtime, while the
|
||||||
|
# single-file branch below doesn't. This should probably be changed to
|
||||||
|
# be consistent with the single-file branch.
|
||||||
|
if os.path.exists(dest):
|
||||||
|
shutil.rmtree(dest)
|
||||||
|
shutil.copytree(source, dest)
|
||||||
|
elif extension in {".xib", ".storyboard"}:
|
||||||
|
return self._CopyXIBFile(source, dest)
|
||||||
|
elif extension == ".strings" and not convert_to_binary:
|
||||||
|
self._CopyStringsFile(source, dest)
|
||||||
|
else:
|
||||||
|
if os.path.exists(dest):
|
||||||
|
os.unlink(dest)
|
||||||
|
shutil.copy(source, dest)
|
||||||
|
|
||||||
|
if convert_to_binary and extension in {".plist", ".strings"}:
|
||||||
|
self._ConvertToBinary(dest)
|
||||||
|
|
||||||
|
def _CopyXIBFile(self, source, dest):
|
||||||
|
"""Compiles a XIB file with ibtool into a binary plist in the bundle."""
|
||||||
|
|
||||||
|
# ibtool sometimes crashes with relative paths. See crbug.com/314728.
|
||||||
|
base = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
if os.path.relpath(source):
|
||||||
|
source = os.path.join(base, source)
|
||||||
|
if os.path.relpath(dest):
|
||||||
|
dest = os.path.join(base, dest)
|
||||||
|
|
||||||
|
args = ["xcrun", "ibtool", "--errors", "--warnings", "--notices"]
|
||||||
|
|
||||||
|
if os.environ["XCODE_VERSION_ACTUAL"] > "0700":
|
||||||
|
args.extend(["--auto-activate-custom-fonts"])
|
||||||
|
if "IPHONEOS_DEPLOYMENT_TARGET" in os.environ:
|
||||||
|
args.extend(
|
||||||
|
[
|
||||||
|
"--target-device",
|
||||||
|
"iphone",
|
||||||
|
"--target-device",
|
||||||
|
"ipad",
|
||||||
|
"--minimum-deployment-target",
|
||||||
|
os.environ["IPHONEOS_DEPLOYMENT_TARGET"],
|
||||||
|
]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
args.extend(
|
||||||
|
[
|
||||||
|
"--target-device",
|
||||||
|
"mac",
|
||||||
|
"--minimum-deployment-target",
|
||||||
|
os.environ["MACOSX_DEPLOYMENT_TARGET"],
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
args.extend(
|
||||||
|
["--output-format", "human-readable-text", "--compile", dest, source]
|
||||||
|
)
|
||||||
|
|
||||||
|
ibtool_section_re = re.compile(r"/\*.*\*/")
|
||||||
|
ibtool_re = re.compile(r".*note:.*is clipping its content")
|
||||||
|
try:
|
||||||
|
stdout = subprocess.check_output(args)
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(e.output)
|
||||||
|
raise
|
||||||
|
current_section_header = None
|
||||||
|
for line in stdout.splitlines():
|
||||||
|
if ibtool_section_re.match(line):
|
||||||
|
current_section_header = line
|
||||||
|
elif not ibtool_re.match(line):
|
||||||
|
if current_section_header:
|
||||||
|
print(current_section_header)
|
||||||
|
current_section_header = None
|
||||||
|
print(line)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def _ConvertToBinary(self, dest):
|
||||||
|
subprocess.check_call(
|
||||||
|
["xcrun", "plutil", "-convert", "binary1", "-o", dest, dest]
|
||||||
|
)
|
||||||
|
|
||||||
|
def _CopyStringsFile(self, source, dest):
|
||||||
|
"""Copies a .strings file using iconv to reconvert the input into UTF-16."""
|
||||||
|
input_code = self._DetectInputEncoding(source) or "UTF-8"
|
||||||
|
|
||||||
|
# Xcode's CpyCopyStringsFile / builtin-copyStrings seems to call
|
||||||
|
# CFPropertyListCreateFromXMLData() behind the scenes; at least it prints
|
||||||
|
# CFPropertyListCreateFromXMLData(): Old-style plist parser: missing
|
||||||
|
# semicolon in dictionary.
|
||||||
|
# on invalid files. Do the same kind of validation.
|
||||||
|
import CoreFoundation # noqa: PLC0415
|
||||||
|
|
||||||
|
with open(source, "rb") as in_file:
|
||||||
|
s = in_file.read()
|
||||||
|
d = CoreFoundation.CFDataCreate(None, s, len(s))
|
||||||
|
_, error = CoreFoundation.CFPropertyListCreateFromXMLData(None, d, 0, None)
|
||||||
|
if error:
|
||||||
|
return
|
||||||
|
|
||||||
|
with open(dest, "wb") as fp:
|
||||||
|
fp.write(s.decode(input_code).encode("UTF-16"))
|
||||||
|
|
||||||
|
def _DetectInputEncoding(self, file_name):
|
||||||
|
"""Reads the first few bytes from file_name and tries to guess the text
|
||||||
|
encoding. Returns None as a guess if it can't detect it."""
|
||||||
|
with open(file_name, "rb") as fp:
|
||||||
|
try:
|
||||||
|
header = fp.read(3)
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
if header.startswith((b"\xfe\xff", b"\xff\xfe")):
|
||||||
|
return "UTF-16"
|
||||||
|
elif header.startswith(b"\xef\xbb\xbf"):
|
||||||
|
return "UTF-8"
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def ExecCopyInfoPlist(self, source, dest, convert_to_binary, *keys):
|
||||||
|
"""Copies the |source| Info.plist to the destination directory |dest|."""
|
||||||
|
# Read the source Info.plist into memory.
|
||||||
|
with open(source) as fd:
|
||||||
|
lines = fd.read()
|
||||||
|
|
||||||
|
# Insert synthesized key/value pairs (e.g. BuildMachineOSBuild).
|
||||||
|
plist = plistlib.readPlistFromString(lines)
|
||||||
|
if keys:
|
||||||
|
plist.update(json.loads(keys[0]))
|
||||||
|
lines = plistlib.writePlistToString(plist)
|
||||||
|
|
||||||
|
# Go through all the environment variables and replace them as variables in
|
||||||
|
# the file.
|
||||||
|
IDENT_RE = re.compile(r"[_/\s]")
|
||||||
|
for key in os.environ:
|
||||||
|
if key.startswith("_"):
|
||||||
|
continue
|
||||||
|
evar = "${%s}" % key
|
||||||
|
evalue = os.environ[key]
|
||||||
|
lines = lines.replace(lines, evar, evalue)
|
||||||
|
|
||||||
|
# Xcode supports various suffices on environment variables, which are
|
||||||
|
# all undocumented. :rfc1034identifier is used in the standard project
|
||||||
|
# template these days, and :identifier was used earlier. They are used to
|
||||||
|
# convert non-url characters into things that look like valid urls --
|
||||||
|
# except that the replacement character for :identifier, '_' isn't valid
|
||||||
|
# in a URL either -- oops, hence :rfc1034identifier was born.
|
||||||
|
evar = "${%s:identifier}" % key
|
||||||
|
evalue = IDENT_RE.sub("_", os.environ[key])
|
||||||
|
lines = lines.replace(lines, evar, evalue)
|
||||||
|
|
||||||
|
evar = "${%s:rfc1034identifier}" % key
|
||||||
|
evalue = IDENT_RE.sub("-", os.environ[key])
|
||||||
|
lines = lines.replace(lines, evar, evalue)
|
||||||
|
|
||||||
|
# Remove any keys with values that haven't been replaced.
|
||||||
|
lines = lines.splitlines()
|
||||||
|
for i in range(len(lines)):
|
||||||
|
if lines[i].strip().startswith("<string>${"):
|
||||||
|
lines[i] = None
|
||||||
|
lines[i - 1] = None
|
||||||
|
lines = "\n".join(line for line in lines if line is not None)
|
||||||
|
|
||||||
|
# Write out the file with variables replaced.
|
||||||
|
with open(dest, "w") as fd:
|
||||||
|
fd.write(lines)
|
||||||
|
|
||||||
|
# Now write out PkgInfo file now that the Info.plist file has been
|
||||||
|
# "compiled".
|
||||||
|
self._WritePkgInfo(dest)
|
||||||
|
|
||||||
|
if convert_to_binary == "True":
|
||||||
|
self._ConvertToBinary(dest)
|
||||||
|
|
||||||
|
def _WritePkgInfo(self, info_plist):
|
||||||
|
"""This writes the PkgInfo file from the data stored in Info.plist."""
|
||||||
|
plist = plistlib.readPlist(info_plist)
|
||||||
|
if not plist:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Only create PkgInfo for executable types.
|
||||||
|
package_type = plist["CFBundlePackageType"]
|
||||||
|
if package_type != "APPL":
|
||||||
|
return
|
||||||
|
|
||||||
|
# The format of PkgInfo is eight characters, representing the bundle type
|
||||||
|
# and bundle signature, each four characters. If that is missing, four
|
||||||
|
# '?' characters are used instead.
|
||||||
|
signature_code = plist.get("CFBundleSignature", "????")
|
||||||
|
if len(signature_code) != 4: # Wrong length resets everything, too.
|
||||||
|
signature_code = "?" * 4
|
||||||
|
|
||||||
|
dest = os.path.join(os.path.dirname(info_plist), "PkgInfo")
|
||||||
|
with open(dest, "w") as fp:
|
||||||
|
fp.write(f"{package_type}{signature_code}")
|
||||||
|
|
||||||
|
def ExecFlock(self, lockfile, *cmd_list):
|
||||||
|
"""Emulates the most basic behavior of Linux's flock(1)."""
|
||||||
|
# Rely on exception handling to report errors.
|
||||||
|
fd = os.open(lockfile, os.O_RDONLY | os.O_NOCTTY | os.O_CREAT, 0o666)
|
||||||
|
fcntl.flock(fd, fcntl.LOCK_EX)
|
||||||
|
return subprocess.call(cmd_list)
|
||||||
|
|
||||||
|
def ExecFilterLibtool(self, *cmd_list):
|
||||||
|
"""Calls libtool and filters out '/path/to/libtool: file: foo.o has no
|
||||||
|
symbols'."""
|
||||||
|
libtool_re = re.compile(
|
||||||
|
r"^.*libtool: (?:for architecture: \S* )?file: .* has no symbols$"
|
||||||
|
)
|
||||||
|
libtool_re5 = re.compile(
|
||||||
|
r"^.*libtool: warning for library: "
|
||||||
|
+ r".* the table of contents is empty "
|
||||||
|
+ r"\(no object file members in the library define global symbols\)$"
|
||||||
|
)
|
||||||
|
env = os.environ.copy()
|
||||||
|
# Ref:
|
||||||
|
# http://www.opensource.apple.com/source/cctools/cctools-809/misc/libtool.c
|
||||||
|
# The problem with this flag is that it resets the file mtime on the file to
|
||||||
|
# epoch=0, e.g. 1970-1-1 or 1969-12-31 depending on timezone.
|
||||||
|
env["ZERO_AR_DATE"] = "1"
|
||||||
|
libtoolout = subprocess.Popen(cmd_list, stderr=subprocess.PIPE, env=env)
|
||||||
|
err = libtoolout.communicate()[1].decode("utf-8")
|
||||||
|
for line in err.splitlines():
|
||||||
|
if not libtool_re.match(line) and not libtool_re5.match(line):
|
||||||
|
print(line, file=sys.stderr)
|
||||||
|
# Unconditionally touch the output .a file on the command line if present
|
||||||
|
# and the command succeeded. A bit hacky.
|
||||||
|
if not libtoolout.returncode:
|
||||||
|
for i in range(len(cmd_list) - 1):
|
||||||
|
if cmd_list[i] == "-o" and cmd_list[i + 1].endswith(".a"):
|
||||||
|
os.utime(cmd_list[i + 1], None)
|
||||||
|
break
|
||||||
|
return libtoolout.returncode
|
||||||
|
|
||||||
|
def ExecPackageIosFramework(self, framework):
|
||||||
|
# Find the name of the binary based on the part before the ".framework".
|
||||||
|
binary = os.path.basename(framework).split(".")[0]
|
||||||
|
module_path = os.path.join(framework, "Modules")
|
||||||
|
if not os.path.exists(module_path):
|
||||||
|
os.mkdir(module_path)
|
||||||
|
module_template = (
|
||||||
|
"framework module %s {\n"
|
||||||
|
' umbrella header "%s.h"\n'
|
||||||
|
"\n"
|
||||||
|
" export *\n"
|
||||||
|
" module * { export * }\n"
|
||||||
|
"}\n" % (binary, binary)
|
||||||
|
)
|
||||||
|
|
||||||
|
with open(os.path.join(module_path, "module.modulemap"), "w") as module_file:
|
||||||
|
module_file.write(module_template)
|
||||||
|
|
||||||
|
def ExecPackageFramework(self, framework, version):
|
||||||
|
"""Takes a path to Something.framework and the Current version of that and
|
||||||
|
sets up all the symlinks."""
|
||||||
|
# Find the name of the binary based on the part before the ".framework".
|
||||||
|
binary = os.path.basename(framework).split(".")[0]
|
||||||
|
|
||||||
|
CURRENT = "Current"
|
||||||
|
RESOURCES = "Resources"
|
||||||
|
VERSIONS = "Versions"
|
||||||
|
|
||||||
|
if not os.path.exists(os.path.join(framework, VERSIONS, version, binary)):
|
||||||
|
# Binary-less frameworks don't seem to contain symlinks (see e.g.
|
||||||
|
# chromium's out/Debug/org.chromium.Chromium.manifest/ bundle).
|
||||||
|
return
|
||||||
|
|
||||||
|
# Move into the framework directory to set the symlinks correctly.
|
||||||
|
pwd = os.getcwd()
|
||||||
|
os.chdir(framework)
|
||||||
|
|
||||||
|
# Set up the Current version.
|
||||||
|
self._Relink(version, os.path.join(VERSIONS, CURRENT))
|
||||||
|
|
||||||
|
# Set up the root symlinks.
|
||||||
|
self._Relink(os.path.join(VERSIONS, CURRENT, binary), binary)
|
||||||
|
self._Relink(os.path.join(VERSIONS, CURRENT, RESOURCES), RESOURCES)
|
||||||
|
|
||||||
|
# Back to where we were before!
|
||||||
|
os.chdir(pwd)
|
||||||
|
|
||||||
|
def _Relink(self, dest, link):
|
||||||
|
"""Creates a symlink to |dest| named |link|. If |link| already exists,
|
||||||
|
it is overwritten."""
|
||||||
|
if os.path.lexists(link):
|
||||||
|
os.remove(link)
|
||||||
|
os.symlink(dest, link)
|
||||||
|
|
||||||
|
def ExecCompileIosFrameworkHeaderMap(self, out, framework, *all_headers):
|
||||||
|
framework_name = os.path.basename(framework).split(".")[0]
|
||||||
|
all_headers = [os.path.abspath(header) for header in all_headers]
|
||||||
|
filelist = {}
|
||||||
|
for header in all_headers:
|
||||||
|
filename = os.path.basename(header)
|
||||||
|
filelist[filename] = header
|
||||||
|
filelist[os.path.join(framework_name, filename)] = header
|
||||||
|
WriteHmap(out, filelist)
|
||||||
|
|
||||||
|
def ExecCopyIosFrameworkHeaders(self, framework, *copy_headers):
|
||||||
|
header_path = os.path.join(framework, "Headers")
|
||||||
|
if not os.path.exists(header_path):
|
||||||
|
os.makedirs(header_path)
|
||||||
|
for header in copy_headers:
|
||||||
|
shutil.copy(header, os.path.join(header_path, os.path.basename(header)))
|
||||||
|
|
||||||
|
def ExecCompileXcassets(self, keys, *inputs):
|
||||||
|
"""Compiles multiple .xcassets files into a single .car file.
|
||||||
|
|
||||||
|
This invokes 'actool' to compile all the inputs .xcassets files. The
|
||||||
|
|keys| arguments is a json-encoded dictionary of extra arguments to
|
||||||
|
pass to 'actool' when the asset catalogs contains an application icon
|
||||||
|
or a launch image.
|
||||||
|
|
||||||
|
Note that 'actool' does not create the Assets.car file if the asset
|
||||||
|
catalogs does not contains imageset.
|
||||||
|
"""
|
||||||
|
command_line = [
|
||||||
|
"xcrun",
|
||||||
|
"actool",
|
||||||
|
"--output-format",
|
||||||
|
"human-readable-text",
|
||||||
|
"--compress-pngs",
|
||||||
|
"--notices",
|
||||||
|
"--warnings",
|
||||||
|
"--errors",
|
||||||
|
]
|
||||||
|
is_iphone_target = "IPHONEOS_DEPLOYMENT_TARGET" in os.environ
|
||||||
|
if is_iphone_target:
|
||||||
|
platform = os.environ["CONFIGURATION"].split("-")[-1]
|
||||||
|
if platform not in ("iphoneos", "iphonesimulator"):
|
||||||
|
platform = "iphonesimulator"
|
||||||
|
command_line.extend(
|
||||||
|
[
|
||||||
|
"--platform",
|
||||||
|
platform,
|
||||||
|
"--target-device",
|
||||||
|
"iphone",
|
||||||
|
"--target-device",
|
||||||
|
"ipad",
|
||||||
|
"--minimum-deployment-target",
|
||||||
|
os.environ["IPHONEOS_DEPLOYMENT_TARGET"],
|
||||||
|
"--compile",
|
||||||
|
os.path.abspath(os.environ["CONTENTS_FOLDER_PATH"]),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
command_line.extend(
|
||||||
|
[
|
||||||
|
"--platform",
|
||||||
|
"macosx",
|
||||||
|
"--target-device",
|
||||||
|
"mac",
|
||||||
|
"--minimum-deployment-target",
|
||||||
|
os.environ["MACOSX_DEPLOYMENT_TARGET"],
|
||||||
|
"--compile",
|
||||||
|
os.path.abspath(os.environ["UNLOCALIZED_RESOURCES_FOLDER_PATH"]),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
if keys:
|
||||||
|
keys = json.loads(keys)
|
||||||
|
for key, value in keys.items():
|
||||||
|
arg_name = "--" + key
|
||||||
|
if isinstance(value, bool):
|
||||||
|
if value:
|
||||||
|
command_line.append(arg_name)
|
||||||
|
elif isinstance(value, list):
|
||||||
|
for v in value:
|
||||||
|
command_line.append(arg_name)
|
||||||
|
command_line.append(str(v))
|
||||||
|
else:
|
||||||
|
command_line.append(arg_name)
|
||||||
|
command_line.append(str(value))
|
||||||
|
# Note: actool crashes if inputs path are relative, so use os.path.abspath
|
||||||
|
# to get absolute path name for inputs.
|
||||||
|
command_line.extend(map(os.path.abspath, inputs))
|
||||||
|
subprocess.check_call(command_line)
|
||||||
|
|
||||||
|
def ExecMergeInfoPlist(self, output, *inputs):
|
||||||
|
"""Merge multiple .plist files into a single .plist file."""
|
||||||
|
merged_plist = {}
|
||||||
|
for path in inputs:
|
||||||
|
plist = self._LoadPlistMaybeBinary(path)
|
||||||
|
self._MergePlist(merged_plist, plist)
|
||||||
|
plistlib.writePlist(merged_plist, output)
|
||||||
|
|
||||||
|
def ExecCodeSignBundle(self, key, entitlements, provisioning, path, preserve):
|
||||||
|
"""Code sign a bundle.
|
||||||
|
|
||||||
|
This function tries to code sign an iOS bundle, following the same
|
||||||
|
algorithm as Xcode:
|
||||||
|
1. pick the provisioning profile that best match the bundle identifier,
|
||||||
|
and copy it into the bundle as embedded.mobileprovision,
|
||||||
|
2. copy Entitlements.plist from user or SDK next to the bundle,
|
||||||
|
3. code sign the bundle.
|
||||||
|
"""
|
||||||
|
substitutions, overrides = self._InstallProvisioningProfile(
|
||||||
|
provisioning, self._GetCFBundleIdentifier()
|
||||||
|
)
|
||||||
|
entitlements_path = self._InstallEntitlements(
|
||||||
|
entitlements, substitutions, overrides
|
||||||
|
)
|
||||||
|
|
||||||
|
args = ["codesign", "--force", "--sign", key]
|
||||||
|
if preserve == "True":
|
||||||
|
args.extend(["--deep", "--preserve-metadata=identifier,entitlements"])
|
||||||
|
else:
|
||||||
|
args.extend(["--entitlements", entitlements_path])
|
||||||
|
args.extend(["--timestamp=none", path])
|
||||||
|
subprocess.check_call(args)
|
||||||
|
|
||||||
|
def _InstallProvisioningProfile(self, profile, bundle_identifier):
|
||||||
|
"""Installs embedded.mobileprovision into the bundle.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
profile: string, optional, short name of the .mobileprovision file
|
||||||
|
to use, if empty or the file is missing, the best file installed
|
||||||
|
will be used
|
||||||
|
bundle_identifier: string, value of CFBundleIdentifier from Info.plist
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A tuple containing two dictionary: variables substitutions and values
|
||||||
|
to overrides when generating the entitlements file.
|
||||||
|
"""
|
||||||
|
source_path, provisioning_data, team_id = self._FindProvisioningProfile(
|
||||||
|
profile, bundle_identifier
|
||||||
|
)
|
||||||
|
target_path = os.path.join(
|
||||||
|
os.environ["BUILT_PRODUCTS_DIR"],
|
||||||
|
os.environ["CONTENTS_FOLDER_PATH"],
|
||||||
|
"embedded.mobileprovision",
|
||||||
|
)
|
||||||
|
shutil.copy2(source_path, target_path)
|
||||||
|
substitutions = self._GetSubstitutions(bundle_identifier, team_id + ".")
|
||||||
|
return substitutions, provisioning_data["Entitlements"]
|
||||||
|
|
||||||
|
def _FindProvisioningProfile(self, profile, bundle_identifier):
|
||||||
|
"""Finds the .mobileprovision file to use for signing the bundle.
|
||||||
|
|
||||||
|
Checks all the installed provisioning profiles (or if the user specified
|
||||||
|
the PROVISIONING_PROFILE variable, only consult it) and select the most
|
||||||
|
specific that correspond to the bundle identifier.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
profile: string, optional, short name of the .mobileprovision file
|
||||||
|
to use, if empty or the file is missing, the best file installed
|
||||||
|
will be used
|
||||||
|
bundle_identifier: string, value of CFBundleIdentifier from Info.plist
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A tuple of the path to the selected provisioning profile, the data of
|
||||||
|
the embedded plist in the provisioning profile and the team identifier
|
||||||
|
to use for code signing.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
SystemExit: if no .mobileprovision can be used to sign the bundle.
|
||||||
|
"""
|
||||||
|
profiles_dir = os.path.join(
|
||||||
|
os.environ["HOME"], "Library", "MobileDevice", "Provisioning Profiles"
|
||||||
|
)
|
||||||
|
if not os.path.isdir(profiles_dir):
|
||||||
|
print(
|
||||||
|
"cannot find mobile provisioning for %s" % (bundle_identifier),
|
||||||
|
file=sys.stderr,
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
provisioning_profiles = None
|
||||||
|
if profile:
|
||||||
|
profile_path = os.path.join(profiles_dir, profile + ".mobileprovision")
|
||||||
|
if os.path.exists(profile_path):
|
||||||
|
provisioning_profiles = [profile_path]
|
||||||
|
if not provisioning_profiles:
|
||||||
|
provisioning_profiles = glob.glob(
|
||||||
|
os.path.join(profiles_dir, "*.mobileprovision")
|
||||||
|
)
|
||||||
|
valid_provisioning_profiles = {}
|
||||||
|
for profile_path in provisioning_profiles:
|
||||||
|
profile_data = self._LoadProvisioningProfile(profile_path)
|
||||||
|
app_id_pattern = profile_data.get("Entitlements", {}).get(
|
||||||
|
"application-identifier", ""
|
||||||
|
)
|
||||||
|
for team_identifier in profile_data.get("TeamIdentifier", []):
|
||||||
|
app_id = f"{team_identifier}.{bundle_identifier}"
|
||||||
|
if fnmatch.fnmatch(app_id, app_id_pattern):
|
||||||
|
valid_provisioning_profiles[app_id_pattern] = (
|
||||||
|
profile_path,
|
||||||
|
profile_data,
|
||||||
|
team_identifier,
|
||||||
|
)
|
||||||
|
if not valid_provisioning_profiles:
|
||||||
|
print(
|
||||||
|
"cannot find mobile provisioning for %s" % (bundle_identifier),
|
||||||
|
file=sys.stderr,
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
# If the user has multiple provisioning profiles installed that can be
|
||||||
|
# used for ${bundle_identifier}, pick the most specific one (ie. the
|
||||||
|
# provisioning profile whose pattern is the longest).
|
||||||
|
selected_key = max(valid_provisioning_profiles, key=lambda v: len(v))
|
||||||
|
return valid_provisioning_profiles[selected_key]
|
||||||
|
|
||||||
|
def _LoadProvisioningProfile(self, profile_path):
|
||||||
|
"""Extracts the plist embedded in a provisioning profile.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
profile_path: string, path to the .mobileprovision file
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Content of the plist embedded in the provisioning profile as a dictionary.
|
||||||
|
"""
|
||||||
|
with tempfile.NamedTemporaryFile() as temp:
|
||||||
|
subprocess.check_call(
|
||||||
|
["security", "cms", "-D", "-i", profile_path, "-o", temp.name]
|
||||||
|
)
|
||||||
|
return self._LoadPlistMaybeBinary(temp.name)
|
||||||
|
|
||||||
|
def _MergePlist(self, merged_plist, plist):
|
||||||
|
"""Merge |plist| into |merged_plist|."""
|
||||||
|
for key, value in plist.items():
|
||||||
|
if isinstance(value, dict):
|
||||||
|
merged_value = merged_plist.get(key, {})
|
||||||
|
if isinstance(merged_value, dict):
|
||||||
|
self._MergePlist(merged_value, value)
|
||||||
|
merged_plist[key] = merged_value
|
||||||
|
else:
|
||||||
|
merged_plist[key] = value
|
||||||
|
else:
|
||||||
|
merged_plist[key] = value
|
||||||
|
|
||||||
|
def _LoadPlistMaybeBinary(self, plist_path):
|
||||||
|
"""Loads into a memory a plist possibly encoded in binary format.
|
||||||
|
|
||||||
|
This is a wrapper around plistlib.readPlist that tries to convert the
|
||||||
|
plist to the XML format if it can't be parsed (assuming that it is in
|
||||||
|
the binary format).
|
||||||
|
|
||||||
|
Args:
|
||||||
|
plist_path: string, path to a plist file, in XML or binary format
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Content of the plist as a dictionary.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# First, try to read the file using plistlib that only supports XML,
|
||||||
|
# and if an exception is raised, convert a temporary copy to XML and
|
||||||
|
# load that copy.
|
||||||
|
return plistlib.readPlist(plist_path)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
with tempfile.NamedTemporaryFile() as temp:
|
||||||
|
shutil.copy2(plist_path, temp.name)
|
||||||
|
subprocess.check_call(["plutil", "-convert", "xml1", temp.name])
|
||||||
|
return plistlib.readPlist(temp.name)
|
||||||
|
|
||||||
|
def _GetSubstitutions(self, bundle_identifier, app_identifier_prefix):
|
||||||
|
"""Constructs a dictionary of variable substitutions for Entitlements.plist.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
bundle_identifier: string, value of CFBundleIdentifier from Info.plist
|
||||||
|
app_identifier_prefix: string, value for AppIdentifierPrefix
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dictionary of substitutions to apply when generating Entitlements.plist.
|
||||||
|
"""
|
||||||
|
return {
|
||||||
|
"CFBundleIdentifier": bundle_identifier,
|
||||||
|
"AppIdentifierPrefix": app_identifier_prefix,
|
||||||
|
}
|
||||||
|
|
||||||
|
def _GetCFBundleIdentifier(self):
|
||||||
|
"""Extracts CFBundleIdentifier value from Info.plist in the bundle.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Value of CFBundleIdentifier in the Info.plist located in the bundle.
|
||||||
|
"""
|
||||||
|
info_plist_path = os.path.join(
|
||||||
|
os.environ["TARGET_BUILD_DIR"], os.environ["INFOPLIST_PATH"]
|
||||||
|
)
|
||||||
|
info_plist_data = self._LoadPlistMaybeBinary(info_plist_path)
|
||||||
|
return info_plist_data["CFBundleIdentifier"]
|
||||||
|
|
||||||
|
def _InstallEntitlements(self, entitlements, substitutions, overrides):
|
||||||
|
"""Generates and install the ${BundleName}.xcent entitlements file.
|
||||||
|
|
||||||
|
Expands variables "$(variable)" pattern in the source entitlements file,
|
||||||
|
add extra entitlements defined in the .mobileprovision file and the copy
|
||||||
|
the generated plist to "${BundlePath}.xcent".
|
||||||
|
|
||||||
|
Args:
|
||||||
|
entitlements: string, optional, path to the Entitlements.plist template
|
||||||
|
to use, defaults to "${SDKROOT}/Entitlements.plist"
|
||||||
|
substitutions: dictionary, variable substitutions
|
||||||
|
overrides: dictionary, values to add to the entitlements
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Path to the generated entitlements file.
|
||||||
|
"""
|
||||||
|
source_path = entitlements
|
||||||
|
target_path = os.path.join(
|
||||||
|
os.environ["BUILT_PRODUCTS_DIR"], os.environ["PRODUCT_NAME"] + ".xcent"
|
||||||
|
)
|
||||||
|
if not source_path:
|
||||||
|
source_path = os.path.join(os.environ["SDKROOT"], "Entitlements.plist")
|
||||||
|
shutil.copy2(source_path, target_path)
|
||||||
|
data = self._LoadPlistMaybeBinary(target_path)
|
||||||
|
data = self._ExpandVariables(data, substitutions)
|
||||||
|
if overrides:
|
||||||
|
for key in overrides:
|
||||||
|
if key not in data:
|
||||||
|
data[key] = overrides[key]
|
||||||
|
plistlib.writePlist(data, target_path)
|
||||||
|
return target_path
|
||||||
|
|
||||||
|
def _ExpandVariables(self, data, substitutions):
|
||||||
|
"""Expands variables "$(variable)" in data.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
data: object, can be either string, list or dictionary
|
||||||
|
substitutions: dictionary, variable substitutions to perform
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Copy of data where each references to "$(variable)" has been replaced
|
||||||
|
by the corresponding value found in substitutions, or left intact if
|
||||||
|
the key was not found.
|
||||||
|
"""
|
||||||
|
if isinstance(data, str):
|
||||||
|
for key, value in substitutions.items():
|
||||||
|
data = data.replace("$(%s)" % key, value)
|
||||||
|
return data
|
||||||
|
if isinstance(data, list):
|
||||||
|
return [self._ExpandVariables(v, substitutions) for v in data]
|
||||||
|
if isinstance(data, dict):
|
||||||
|
return {k: self._ExpandVariables(data[k], substitutions) for k in data}
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def NextGreaterPowerOf2(x):
|
||||||
|
return 2 ** (x).bit_length()
|
||||||
|
|
||||||
|
|
||||||
|
def WriteHmap(output_name, filelist):
|
||||||
|
"""Generates a header map based on |filelist|.
|
||||||
|
|
||||||
|
Per Mark Mentovai:
|
||||||
|
A header map is structured essentially as a hash table, keyed by names used
|
||||||
|
in #includes, and providing pathnames to the actual files.
|
||||||
|
|
||||||
|
The implementation below and the comment above comes from inspecting:
|
||||||
|
http://www.opensource.apple.com/source/distcc/distcc-2503/distcc_dist/include_server/headermap.py?txt
|
||||||
|
while also looking at the implementation in clang in:
|
||||||
|
https://llvm.org/svn/llvm-project/cfe/trunk/lib/Lex/HeaderMap.cpp
|
||||||
|
"""
|
||||||
|
magic = 1751998832
|
||||||
|
version = 1
|
||||||
|
_reserved = 0
|
||||||
|
count = len(filelist)
|
||||||
|
capacity = NextGreaterPowerOf2(count)
|
||||||
|
strings_offset = 24 + (12 * capacity)
|
||||||
|
max_value_length = max(len(value) for value in filelist.values())
|
||||||
|
|
||||||
|
out = open(output_name, "wb")
|
||||||
|
out.write(
|
||||||
|
struct.pack(
|
||||||
|
"<LHHLLLL",
|
||||||
|
magic,
|
||||||
|
version,
|
||||||
|
_reserved,
|
||||||
|
strings_offset,
|
||||||
|
count,
|
||||||
|
capacity,
|
||||||
|
max_value_length,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create empty hashmap buckets.
|
||||||
|
buckets = [None] * capacity
|
||||||
|
for file, path in filelist.items():
|
||||||
|
key = 0
|
||||||
|
for c in file:
|
||||||
|
key += ord(c.lower()) * 13
|
||||||
|
|
||||||
|
# Fill next empty bucket.
|
||||||
|
while buckets[key & capacity - 1] is not None:
|
||||||
|
key = key + 1
|
||||||
|
buckets[key & capacity - 1] = (file, path)
|
||||||
|
|
||||||
|
next_offset = 1
|
||||||
|
for bucket in buckets:
|
||||||
|
if bucket is None:
|
||||||
|
out.write(struct.pack("<LLL", 0, 0, 0))
|
||||||
|
else:
|
||||||
|
(file, path) = bucket
|
||||||
|
key_offset = next_offset
|
||||||
|
prefix_offset = key_offset + len(file) + 1
|
||||||
|
suffix_offset = prefix_offset + len(os.path.dirname(path) + os.sep) + 1
|
||||||
|
next_offset = suffix_offset + len(os.path.basename(path)) + 1
|
||||||
|
out.write(struct.pack("<LLL", key_offset, prefix_offset, suffix_offset))
|
||||||
|
|
||||||
|
# Pad byte since next offset starts at 1.
|
||||||
|
out.write(struct.pack("<x"))
|
||||||
|
|
||||||
|
for bucket in buckets:
|
||||||
|
if bucket is not None:
|
||||||
|
(file, path) = bucket
|
||||||
|
out.write(struct.pack("<%ds" % len(file), file))
|
||||||
|
out.write(struct.pack("<s", "\0"))
|
||||||
|
base = os.path.dirname(path) + os.sep
|
||||||
|
out.write(struct.pack("<%ds" % len(base), base))
|
||||||
|
out.write(struct.pack("<s", "\0"))
|
||||||
|
path = os.path.basename(path)
|
||||||
|
out.write(struct.pack("<%ds" % len(path), path))
|
||||||
|
out.write(struct.pack("<s", "\0"))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main(sys.argv[1:]))
|
||||||
1255
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py
generated
vendored
Normal file
1255
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
174
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/ninja_syntax.py
generated
vendored
Normal file
174
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/ninja_syntax.py
generated
vendored
Normal file
|
|
@ -0,0 +1,174 @@
|
||||||
|
# This file comes from
|
||||||
|
# https://github.com/martine/ninja/blob/master/misc/ninja_syntax.py
|
||||||
|
# Do not edit! Edit the upstream one instead.
|
||||||
|
|
||||||
|
"""Python module for generating .ninja files.
|
||||||
|
|
||||||
|
Note that this is emphatically not a required piece of Ninja; it's
|
||||||
|
just a helpful utility for build-file-generation systems that already
|
||||||
|
use Python.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import textwrap
|
||||||
|
|
||||||
|
|
||||||
|
def escape_path(word):
|
||||||
|
return word.replace("$ ", "$$ ").replace(" ", "$ ").replace(":", "$:")
|
||||||
|
|
||||||
|
|
||||||
|
class Writer:
|
||||||
|
def __init__(self, output, width=78):
|
||||||
|
self.output = output
|
||||||
|
self.width = width
|
||||||
|
|
||||||
|
def newline(self):
|
||||||
|
self.output.write("\n")
|
||||||
|
|
||||||
|
def comment(self, text):
|
||||||
|
for line in textwrap.wrap(text, self.width - 2):
|
||||||
|
self.output.write("# " + line + "\n")
|
||||||
|
|
||||||
|
def variable(self, key, value, indent=0):
|
||||||
|
if value is None:
|
||||||
|
return
|
||||||
|
if isinstance(value, list):
|
||||||
|
value = " ".join(filter(None, value)) # Filter out empty strings.
|
||||||
|
self._line(f"{key} = {value}", indent)
|
||||||
|
|
||||||
|
def pool(self, name, depth):
|
||||||
|
self._line("pool %s" % name)
|
||||||
|
self.variable("depth", depth, indent=1)
|
||||||
|
|
||||||
|
def rule(
|
||||||
|
self,
|
||||||
|
name,
|
||||||
|
command,
|
||||||
|
description=None,
|
||||||
|
depfile=None,
|
||||||
|
generator=False,
|
||||||
|
pool=None,
|
||||||
|
restat=False,
|
||||||
|
rspfile=None,
|
||||||
|
rspfile_content=None,
|
||||||
|
deps=None,
|
||||||
|
):
|
||||||
|
self._line("rule %s" % name)
|
||||||
|
self.variable("command", command, indent=1)
|
||||||
|
if description:
|
||||||
|
self.variable("description", description, indent=1)
|
||||||
|
if depfile:
|
||||||
|
self.variable("depfile", depfile, indent=1)
|
||||||
|
if generator:
|
||||||
|
self.variable("generator", "1", indent=1)
|
||||||
|
if pool:
|
||||||
|
self.variable("pool", pool, indent=1)
|
||||||
|
if restat:
|
||||||
|
self.variable("restat", "1", indent=1)
|
||||||
|
if rspfile:
|
||||||
|
self.variable("rspfile", rspfile, indent=1)
|
||||||
|
if rspfile_content:
|
||||||
|
self.variable("rspfile_content", rspfile_content, indent=1)
|
||||||
|
if deps:
|
||||||
|
self.variable("deps", deps, indent=1)
|
||||||
|
|
||||||
|
def build(
|
||||||
|
self, outputs, rule, inputs=None, implicit=None, order_only=None, variables=None
|
||||||
|
):
|
||||||
|
outputs = self._as_list(outputs)
|
||||||
|
all_inputs = self._as_list(inputs)[:]
|
||||||
|
out_outputs = list(map(escape_path, outputs))
|
||||||
|
all_inputs = list(map(escape_path, all_inputs))
|
||||||
|
|
||||||
|
if implicit:
|
||||||
|
implicit = map(escape_path, self._as_list(implicit))
|
||||||
|
all_inputs.append("|")
|
||||||
|
all_inputs.extend(implicit)
|
||||||
|
if order_only:
|
||||||
|
order_only = map(escape_path, self._as_list(order_only))
|
||||||
|
all_inputs.append("||")
|
||||||
|
all_inputs.extend(order_only)
|
||||||
|
|
||||||
|
self._line(
|
||||||
|
"build {}: {}".format(" ".join(out_outputs), " ".join([rule] + all_inputs))
|
||||||
|
)
|
||||||
|
|
||||||
|
if variables:
|
||||||
|
if isinstance(variables, dict):
|
||||||
|
iterator = iter(variables.items())
|
||||||
|
else:
|
||||||
|
iterator = iter(variables)
|
||||||
|
|
||||||
|
for key, val in iterator:
|
||||||
|
self.variable(key, val, indent=1)
|
||||||
|
|
||||||
|
return outputs
|
||||||
|
|
||||||
|
def include(self, path):
|
||||||
|
self._line("include %s" % path)
|
||||||
|
|
||||||
|
def subninja(self, path):
|
||||||
|
self._line("subninja %s" % path)
|
||||||
|
|
||||||
|
def default(self, paths):
|
||||||
|
self._line("default %s" % " ".join(self._as_list(paths)))
|
||||||
|
|
||||||
|
def _count_dollars_before_index(self, s, i):
|
||||||
|
"""Returns the number of '$' characters right in front of s[i]."""
|
||||||
|
dollar_count = 0
|
||||||
|
dollar_index = i - 1
|
||||||
|
while dollar_index > 0 and s[dollar_index] == "$":
|
||||||
|
dollar_count += 1
|
||||||
|
dollar_index -= 1
|
||||||
|
return dollar_count
|
||||||
|
|
||||||
|
def _line(self, text, indent=0):
|
||||||
|
"""Write 'text' word-wrapped at self.width characters."""
|
||||||
|
leading_space = " " * indent
|
||||||
|
while len(leading_space) + len(text) > self.width:
|
||||||
|
# The text is too wide; wrap if possible.
|
||||||
|
|
||||||
|
# Find the rightmost space that would obey our width constraint and
|
||||||
|
# that's not an escaped space.
|
||||||
|
available_space = self.width - len(leading_space) - len(" $")
|
||||||
|
space = available_space
|
||||||
|
while True:
|
||||||
|
space = text.rfind(" ", 0, space)
|
||||||
|
if space < 0 or self._count_dollars_before_index(text, space) % 2 == 0:
|
||||||
|
break
|
||||||
|
|
||||||
|
if space < 0:
|
||||||
|
# No such space; just use the first unescaped space we can find.
|
||||||
|
space = available_space - 1
|
||||||
|
while True:
|
||||||
|
space = text.find(" ", space + 1)
|
||||||
|
if (
|
||||||
|
space < 0
|
||||||
|
or self._count_dollars_before_index(text, space) % 2 == 0
|
||||||
|
):
|
||||||
|
break
|
||||||
|
if space < 0:
|
||||||
|
# Give up on breaking.
|
||||||
|
break
|
||||||
|
|
||||||
|
self.output.write(leading_space + text[0:space] + " $\n")
|
||||||
|
text = text[space + 1 :]
|
||||||
|
|
||||||
|
# Subsequent lines are continuations, so indent them.
|
||||||
|
leading_space = " " * (indent + 2)
|
||||||
|
|
||||||
|
self.output.write(leading_space + text + "\n")
|
||||||
|
|
||||||
|
def _as_list(self, input):
|
||||||
|
if input is None:
|
||||||
|
return []
|
||||||
|
if isinstance(input, list):
|
||||||
|
return input
|
||||||
|
return [input]
|
||||||
|
|
||||||
|
|
||||||
|
def escape(string):
|
||||||
|
"""Escape a string such that it can be embedded into a Ninja file without
|
||||||
|
further interpretation."""
|
||||||
|
assert "\n" not in string, "Ninja syntax does not allow newlines"
|
||||||
|
# We only have one special metacharacter: '$'.
|
||||||
|
return string.replace("$", "$$")
|
||||||
61
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/simple_copy.py
generated
vendored
Normal file
61
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/simple_copy.py
generated
vendored
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
# Copyright 2014 Google Inc. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
"""A clone of the default copy.deepcopy that doesn't handle cyclic
|
||||||
|
structures or complex types except for dicts and lists. This is
|
||||||
|
because gyp copies so large structure that small copy overhead ends up
|
||||||
|
taking seconds in a project the size of Chromium."""
|
||||||
|
|
||||||
|
|
||||||
|
class Error(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = ["Error", "deepcopy"]
|
||||||
|
|
||||||
|
|
||||||
|
def deepcopy(x):
|
||||||
|
"""Deep copy operation on gyp objects such as strings, ints, dicts
|
||||||
|
and lists. More than twice as fast as copy.deepcopy but much less
|
||||||
|
generic."""
|
||||||
|
|
||||||
|
try:
|
||||||
|
return _deepcopy_dispatch[type(x)](x)
|
||||||
|
except KeyError:
|
||||||
|
raise Error(
|
||||||
|
"Unsupported type %s for deepcopy. Use copy.deepcopy "
|
||||||
|
+ "or expand simple_copy support." % type(x)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_deepcopy_dispatch = d = {}
|
||||||
|
|
||||||
|
|
||||||
|
def _deepcopy_atomic(x):
|
||||||
|
return x
|
||||||
|
|
||||||
|
|
||||||
|
types = bool, float, int, str, type, type(None)
|
||||||
|
|
||||||
|
for x in types:
|
||||||
|
d[x] = _deepcopy_atomic
|
||||||
|
|
||||||
|
|
||||||
|
def _deepcopy_list(x):
|
||||||
|
return [deepcopy(a) for a in x]
|
||||||
|
|
||||||
|
|
||||||
|
d[list] = _deepcopy_list
|
||||||
|
|
||||||
|
|
||||||
|
def _deepcopy_dict(x):
|
||||||
|
y = {}
|
||||||
|
for key, value in x.items():
|
||||||
|
y[deepcopy(key)] = deepcopy(value)
|
||||||
|
return y
|
||||||
|
|
||||||
|
|
||||||
|
d[dict] = _deepcopy_dict
|
||||||
|
|
||||||
|
del d
|
||||||
371
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py
generated
vendored
Normal file
371
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py
generated
vendored
Normal file
|
|
@ -0,0 +1,371 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Copyright (c) 2012 Google Inc. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
"""Utility functions for Windows builds.
|
||||||
|
|
||||||
|
These functions are executed via gyp-win-tool when using the ninja generator.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import shutil
|
||||||
|
import stat
|
||||||
|
import string
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
# A regex matching an argument corresponding to the output filename passed to
|
||||||
|
# link.exe.
|
||||||
|
_LINK_EXE_OUT_ARG = re.compile("/OUT:(?P<out>.+)$", re.IGNORECASE)
|
||||||
|
|
||||||
|
|
||||||
|
def main(args):
|
||||||
|
executor = WinTool()
|
||||||
|
if (exit_code := executor.Dispatch(args)) is not None:
|
||||||
|
sys.exit(exit_code)
|
||||||
|
|
||||||
|
|
||||||
|
class WinTool:
|
||||||
|
"""This class performs all the Windows tooling steps. The methods can either
|
||||||
|
be executed directly, or dispatched from an argument list."""
|
||||||
|
|
||||||
|
def _UseSeparateMspdbsrv(self, env, args):
|
||||||
|
"""Allows to use a unique instance of mspdbsrv.exe per linker instead of a
|
||||||
|
shared one."""
|
||||||
|
if len(args) < 1:
|
||||||
|
raise Exception("Not enough arguments")
|
||||||
|
|
||||||
|
if args[0] != "link.exe":
|
||||||
|
return
|
||||||
|
|
||||||
|
# Use the output filename passed to the linker to generate an endpoint name
|
||||||
|
# for mspdbsrv.exe.
|
||||||
|
endpoint_name = None
|
||||||
|
for arg in args:
|
||||||
|
m = _LINK_EXE_OUT_ARG.match(arg)
|
||||||
|
if m:
|
||||||
|
endpoint_name = re.sub(
|
||||||
|
r"\W+", "", "%s_%d" % (m.group("out"), os.getpid())
|
||||||
|
)
|
||||||
|
break
|
||||||
|
|
||||||
|
if endpoint_name is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Adds the appropriate environment variable. This will be read by link.exe
|
||||||
|
# to know which instance of mspdbsrv.exe it should connect to (if it's
|
||||||
|
# not set then the default endpoint is used).
|
||||||
|
env["_MSPDBSRV_ENDPOINT_"] = endpoint_name
|
||||||
|
|
||||||
|
def Dispatch(self, args):
|
||||||
|
"""Dispatches a string command to a method."""
|
||||||
|
if len(args) < 1:
|
||||||
|
raise Exception("Not enough arguments")
|
||||||
|
|
||||||
|
method = "Exec%s" % self._CommandifyName(args[0])
|
||||||
|
return getattr(self, method)(*args[1:])
|
||||||
|
|
||||||
|
def _CommandifyName(self, name_string):
|
||||||
|
"""Transforms a tool name like recursive-mirror to RecursiveMirror."""
|
||||||
|
return name_string.title().replace("-", "")
|
||||||
|
|
||||||
|
def _GetEnv(self, arch):
|
||||||
|
"""Gets the saved environment from a file for a given architecture."""
|
||||||
|
# The environment is saved as an "environment block" (see CreateProcess
|
||||||
|
# and msvs_emulation for details). We convert to a dict here.
|
||||||
|
# Drop last 2 NULs, one for list terminator, one for trailing vs. separator.
|
||||||
|
pairs = open(arch).read()[:-2].split("\0")
|
||||||
|
kvs = [item.split("=", 1) for item in pairs]
|
||||||
|
return dict(kvs)
|
||||||
|
|
||||||
|
def ExecStamp(self, path):
|
||||||
|
"""Simple stamp command."""
|
||||||
|
open(path, "w").close()
|
||||||
|
|
||||||
|
def ExecRecursiveMirror(self, source, dest):
|
||||||
|
"""Emulation of rm -rf out && cp -af in out."""
|
||||||
|
if os.path.exists(dest):
|
||||||
|
if os.path.isdir(dest):
|
||||||
|
|
||||||
|
def _on_error(fn, path, excinfo):
|
||||||
|
# The operation failed, possibly because the file is set to
|
||||||
|
# read-only. If that's why, make it writable and try the op again.
|
||||||
|
if not os.access(path, os.W_OK):
|
||||||
|
os.chmod(path, stat.S_IWRITE)
|
||||||
|
fn(path)
|
||||||
|
|
||||||
|
shutil.rmtree(dest, onerror=_on_error)
|
||||||
|
else:
|
||||||
|
if not os.access(dest, os.W_OK):
|
||||||
|
# Attempt to make the file writable before deleting it.
|
||||||
|
os.chmod(dest, stat.S_IWRITE)
|
||||||
|
os.unlink(dest)
|
||||||
|
|
||||||
|
if os.path.isdir(source):
|
||||||
|
shutil.copytree(source, dest)
|
||||||
|
else:
|
||||||
|
shutil.copy2(source, dest)
|
||||||
|
|
||||||
|
def ExecLinkWrapper(self, arch, use_separate_mspdbsrv, *args):
|
||||||
|
"""Filter diagnostic output from link that looks like:
|
||||||
|
' Creating library ui.dll.lib and object ui.dll.exp'
|
||||||
|
This happens when there are exports from the dll or exe.
|
||||||
|
"""
|
||||||
|
env = self._GetEnv(arch)
|
||||||
|
if use_separate_mspdbsrv == "True":
|
||||||
|
self._UseSeparateMspdbsrv(env, args)
|
||||||
|
if sys.platform == "win32":
|
||||||
|
args = list(args) # *args is a tuple by default, which is read-only.
|
||||||
|
args[0] = args[0].replace("/", "\\")
|
||||||
|
# https://docs.python.org/2/library/subprocess.html:
|
||||||
|
# "On Unix with shell=True [...] if args is a sequence, the first item
|
||||||
|
# specifies the command string, and any additional items will be treated as
|
||||||
|
# additional arguments to the shell itself. That is to say, Popen does the
|
||||||
|
# equivalent of:
|
||||||
|
# Popen(['/bin/sh', '-c', args[0], args[1], ...])"
|
||||||
|
# For that reason, since going through the shell doesn't seem necessary on
|
||||||
|
# non-Windows don't do that there.
|
||||||
|
link = subprocess.Popen(
|
||||||
|
args,
|
||||||
|
shell=sys.platform == "win32",
|
||||||
|
env=env,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.STDOUT,
|
||||||
|
)
|
||||||
|
out = link.communicate()[0].decode("utf-8")
|
||||||
|
for line in out.splitlines():
|
||||||
|
if (
|
||||||
|
not line.startswith(" Creating library ")
|
||||||
|
and not line.startswith("Generating code")
|
||||||
|
and not line.startswith("Finished generating code")
|
||||||
|
):
|
||||||
|
print(line)
|
||||||
|
return link.returncode
|
||||||
|
|
||||||
|
def ExecLinkWithManifests(
|
||||||
|
self,
|
||||||
|
arch,
|
||||||
|
embed_manifest,
|
||||||
|
out,
|
||||||
|
ldcmd,
|
||||||
|
resname,
|
||||||
|
mt,
|
||||||
|
rc,
|
||||||
|
intermediate_manifest,
|
||||||
|
*manifests,
|
||||||
|
):
|
||||||
|
"""A wrapper for handling creating a manifest resource and then executing
|
||||||
|
a link command."""
|
||||||
|
# The 'normal' way to do manifests is to have link generate a manifest
|
||||||
|
# based on gathering dependencies from the object files, then merge that
|
||||||
|
# manifest with other manifests supplied as sources, convert the merged
|
||||||
|
# manifest to a resource, and then *relink*, including the compiled
|
||||||
|
# version of the manifest resource. This breaks incremental linking, and
|
||||||
|
# is generally overly complicated. Instead, we merge all the manifests
|
||||||
|
# provided (along with one that includes what would normally be in the
|
||||||
|
# linker-generated one, see msvs_emulation.py), and include that into the
|
||||||
|
# first and only link. We still tell link to generate a manifest, but we
|
||||||
|
# only use that to assert that our simpler process did not miss anything.
|
||||||
|
variables = {
|
||||||
|
"python": sys.executable,
|
||||||
|
"arch": arch,
|
||||||
|
"out": out,
|
||||||
|
"ldcmd": ldcmd,
|
||||||
|
"resname": resname,
|
||||||
|
"mt": mt,
|
||||||
|
"rc": rc,
|
||||||
|
"intermediate_manifest": intermediate_manifest,
|
||||||
|
"manifests": " ".join(manifests),
|
||||||
|
}
|
||||||
|
add_to_ld = ""
|
||||||
|
if manifests:
|
||||||
|
subprocess.check_call(
|
||||||
|
"%(python)s gyp-win-tool manifest-wrapper %(arch)s %(mt)s -nologo "
|
||||||
|
"-manifest %(manifests)s -out:%(out)s.manifest" % variables
|
||||||
|
)
|
||||||
|
if embed_manifest == "True":
|
||||||
|
subprocess.check_call(
|
||||||
|
"%(python)s gyp-win-tool manifest-to-rc %(arch)s %(out)s.manifest"
|
||||||
|
" %(out)s.manifest.rc %(resname)s" % variables
|
||||||
|
)
|
||||||
|
subprocess.check_call(
|
||||||
|
"%(python)s gyp-win-tool rc-wrapper %(arch)s %(rc)s "
|
||||||
|
"%(out)s.manifest.rc" % variables
|
||||||
|
)
|
||||||
|
add_to_ld = " %(out)s.manifest.res" % variables
|
||||||
|
subprocess.check_call(ldcmd + add_to_ld)
|
||||||
|
|
||||||
|
# Run mt.exe on the theoretically complete manifest we generated, merging
|
||||||
|
# it with the one the linker generated to confirm that the linker
|
||||||
|
# generated one does not add anything. This is strictly unnecessary for
|
||||||
|
# correctness, it's only to verify that e.g. /MANIFESTDEPENDENCY was not
|
||||||
|
# used in a #pragma comment.
|
||||||
|
if manifests:
|
||||||
|
# Merge the intermediate one with ours to .assert.manifest, then check
|
||||||
|
# that .assert.manifest is identical to ours.
|
||||||
|
subprocess.check_call(
|
||||||
|
"%(python)s gyp-win-tool manifest-wrapper %(arch)s %(mt)s -nologo "
|
||||||
|
"-manifest %(out)s.manifest %(intermediate_manifest)s "
|
||||||
|
"-out:%(out)s.assert.manifest" % variables
|
||||||
|
)
|
||||||
|
assert_manifest = "%(out)s.assert.manifest" % variables
|
||||||
|
our_manifest = "%(out)s.manifest" % variables
|
||||||
|
# Load and normalize the manifests. mt.exe sometimes removes whitespace,
|
||||||
|
# and sometimes doesn't unfortunately.
|
||||||
|
with open(our_manifest) as our_f, open(assert_manifest) as assert_f:
|
||||||
|
translator = str.maketrans("", "", string.whitespace)
|
||||||
|
our_data = our_f.read().translate(translator)
|
||||||
|
assert_data = assert_f.read().translate(translator)
|
||||||
|
if our_data != assert_data:
|
||||||
|
os.unlink(out)
|
||||||
|
|
||||||
|
def dump(filename):
|
||||||
|
print(filename, file=sys.stderr)
|
||||||
|
print("-----", file=sys.stderr)
|
||||||
|
with open(filename) as f:
|
||||||
|
print(f.read(), file=sys.stderr)
|
||||||
|
print("-----", file=sys.stderr)
|
||||||
|
|
||||||
|
dump(intermediate_manifest)
|
||||||
|
dump(our_manifest)
|
||||||
|
dump(assert_manifest)
|
||||||
|
sys.stderr.write(
|
||||||
|
'Linker generated manifest "%s" added to final manifest "%s" '
|
||||||
|
'(result in "%s"). '
|
||||||
|
"Were /MANIFEST switches used in #pragma statements? "
|
||||||
|
% (intermediate_manifest, our_manifest, assert_manifest)
|
||||||
|
)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def ExecManifestWrapper(self, arch, *args):
|
||||||
|
"""Run manifest tool with environment set. Strip out undesirable warning
|
||||||
|
(some XML blocks are recognized by the OS loader, but not the manifest
|
||||||
|
tool)."""
|
||||||
|
env = self._GetEnv(arch)
|
||||||
|
popen = subprocess.Popen(
|
||||||
|
args, shell=True, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
||||||
|
)
|
||||||
|
out = popen.communicate()[0].decode("utf-8")
|
||||||
|
for line in out.splitlines():
|
||||||
|
if line and "manifest authoring warning 81010002" not in line:
|
||||||
|
print(line)
|
||||||
|
return popen.returncode
|
||||||
|
|
||||||
|
def ExecManifestToRc(self, arch, *args):
|
||||||
|
"""Creates a resource file pointing a SxS assembly manifest.
|
||||||
|
|args| is tuple containing path to resource file, path to manifest file
|
||||||
|
and resource name which can be "1" (for executables) or "2" (for DLLs)."""
|
||||||
|
manifest_path, resource_path, resource_name = args
|
||||||
|
with open(resource_path, "w") as output:
|
||||||
|
output.write(
|
||||||
|
'#include <windows.h>\n%s RT_MANIFEST "%s"'
|
||||||
|
% (resource_name, os.path.abspath(manifest_path).replace("\\", "/"))
|
||||||
|
)
|
||||||
|
|
||||||
|
def ExecMidlWrapper(self, arch, outdir, tlb, h, dlldata, iid, proxy, idl, *flags):
|
||||||
|
"""Filter noisy filenames output from MIDL compile step that isn't
|
||||||
|
quietable via command line flags.
|
||||||
|
"""
|
||||||
|
args = (
|
||||||
|
["midl", "/nologo"]
|
||||||
|
+ list(flags)
|
||||||
|
+ [
|
||||||
|
"/out",
|
||||||
|
outdir,
|
||||||
|
"/tlb",
|
||||||
|
tlb,
|
||||||
|
"/h",
|
||||||
|
h,
|
||||||
|
"/dlldata",
|
||||||
|
dlldata,
|
||||||
|
"/iid",
|
||||||
|
iid,
|
||||||
|
"/proxy",
|
||||||
|
proxy,
|
||||||
|
idl,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
env = self._GetEnv(arch)
|
||||||
|
popen = subprocess.Popen(
|
||||||
|
args, shell=True, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
||||||
|
)
|
||||||
|
out = popen.communicate()[0].decode("utf-8")
|
||||||
|
# Filter junk out of stdout, and write filtered versions. Output we want
|
||||||
|
# to filter is pairs of lines that look like this:
|
||||||
|
# Processing C:\Program Files (x86)\Microsoft SDKs\...\include\objidl.idl
|
||||||
|
# objidl.idl
|
||||||
|
lines = out.splitlines()
|
||||||
|
prefixes = ("Processing ", "64 bit Processing ")
|
||||||
|
processing = {os.path.basename(x) for x in lines if x.startswith(prefixes)}
|
||||||
|
for line in lines:
|
||||||
|
if not line.startswith(prefixes) and line not in processing:
|
||||||
|
print(line)
|
||||||
|
return popen.returncode
|
||||||
|
|
||||||
|
def ExecAsmWrapper(self, arch, *args):
|
||||||
|
"""Filter logo banner from invocations of asm.exe."""
|
||||||
|
env = self._GetEnv(arch)
|
||||||
|
popen = subprocess.Popen(
|
||||||
|
args, shell=True, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
||||||
|
)
|
||||||
|
out = popen.communicate()[0].decode("utf-8")
|
||||||
|
for line in out.splitlines():
|
||||||
|
if (
|
||||||
|
not line.startswith("Copyright (C) Microsoft Corporation")
|
||||||
|
and not line.startswith("Microsoft (R) Macro Assembler")
|
||||||
|
and not line.startswith(" Assembling: ")
|
||||||
|
and line
|
||||||
|
):
|
||||||
|
print(line)
|
||||||
|
return popen.returncode
|
||||||
|
|
||||||
|
def ExecRcWrapper(self, arch, *args):
|
||||||
|
"""Filter logo banner from invocations of rc.exe. Older versions of RC
|
||||||
|
don't support the /nologo flag."""
|
||||||
|
env = self._GetEnv(arch)
|
||||||
|
popen = subprocess.Popen(
|
||||||
|
args, shell=True, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
||||||
|
)
|
||||||
|
out = popen.communicate()[0].decode("utf-8")
|
||||||
|
for line in out.splitlines():
|
||||||
|
if (
|
||||||
|
not line.startswith("Microsoft (R) Windows (R) Resource Compiler")
|
||||||
|
and not line.startswith("Copyright (C) Microsoft Corporation")
|
||||||
|
and line
|
||||||
|
):
|
||||||
|
print(line)
|
||||||
|
return popen.returncode
|
||||||
|
|
||||||
|
def ExecActionWrapper(self, arch, rspfile, *dir):
|
||||||
|
"""Runs an action command line from a response file using the environment
|
||||||
|
for |arch|. If |dir| is supplied, use that as the working directory."""
|
||||||
|
env = self._GetEnv(arch)
|
||||||
|
# TODO(scottmg): This is a temporary hack to get some specific variables
|
||||||
|
# through to actions that are set after gyp-time. http://crbug.com/333738.
|
||||||
|
for k, v in os.environ.items():
|
||||||
|
if k not in env:
|
||||||
|
env[k] = v
|
||||||
|
args = open(rspfile).read()
|
||||||
|
dir = dir[0] if dir else None
|
||||||
|
return subprocess.call(args, shell=True, env=env, cwd=dir)
|
||||||
|
|
||||||
|
def ExecClCompile(self, project_dir, selected_files):
|
||||||
|
"""Executed by msvs-ninja projects when the 'ClCompile' target is used to
|
||||||
|
build selected C/C++ files."""
|
||||||
|
project_dir = os.path.relpath(project_dir, BASE_DIR)
|
||||||
|
selected_files = selected_files.split(";")
|
||||||
|
ninja_targets = [
|
||||||
|
os.path.join(project_dir, filename) + "^^" for filename in selected_files
|
||||||
|
]
|
||||||
|
cmd = ["ninja.exe"]
|
||||||
|
cmd.extend(ninja_targets)
|
||||||
|
return subprocess.call(cmd, shell=True, cwd=BASE_DIR)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main(sys.argv[1:]))
|
||||||
1936
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py
generated
vendored
Normal file
1936
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
54
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation_test.py
generated
vendored
Normal file
54
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation_test.py
generated
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
"""Unit tests for the xcode_emulation.py file."""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from gyp.xcode_emulation import XcodeSettings
|
||||||
|
|
||||||
|
|
||||||
|
class TestXcodeSettings(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
if sys.platform != "darwin":
|
||||||
|
self.skipTest("This test only runs on macOS")
|
||||||
|
|
||||||
|
def test_GetCflags(self):
|
||||||
|
target = {
|
||||||
|
"type": "static_library",
|
||||||
|
"configurations": {
|
||||||
|
"Release": {},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
configuration_name = "Release"
|
||||||
|
xcode_settings = XcodeSettings(target)
|
||||||
|
cflags = xcode_settings.GetCflags(configuration_name, "arm64")
|
||||||
|
|
||||||
|
# Do not quote `-arch arm64` with spaces in one string.
|
||||||
|
self.assertEqual(
|
||||||
|
cflags,
|
||||||
|
["-fasm-blocks", "-mpascal-strings", "-Os", "-gdwarf-2", "-arch", "arm64"],
|
||||||
|
)
|
||||||
|
|
||||||
|
def GypToBuildPath(self, path):
|
||||||
|
return path
|
||||||
|
|
||||||
|
def test_GetLdflags(self):
|
||||||
|
target = {
|
||||||
|
"type": "static_library",
|
||||||
|
"configurations": {
|
||||||
|
"Release": {},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
configuration_name = "Release"
|
||||||
|
xcode_settings = XcodeSettings(target)
|
||||||
|
ldflags = xcode_settings.GetLdflags(
|
||||||
|
configuration_name, "PRODUCT_DIR", self.GypToBuildPath, "arm64"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Do not quote `-arch arm64` with spaces in one string.
|
||||||
|
self.assertEqual(ldflags, ["-arch", "arm64", "-LPRODUCT_DIR"])
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
301
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/xcode_ninja.py
generated
vendored
Normal file
301
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/xcode_ninja.py
generated
vendored
Normal file
|
|
@ -0,0 +1,301 @@
|
||||||
|
# Copyright (c) 2014 Google Inc. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
"""Xcode-ninja wrapper project file generator.
|
||||||
|
|
||||||
|
This updates the data structures passed to the Xcode gyp generator to build
|
||||||
|
with ninja instead. The Xcode project itself is transformed into a list of
|
||||||
|
executable targets, each with a build step to build with ninja, and a target
|
||||||
|
with every source and resource file. This appears to sidestep some of the
|
||||||
|
major performance headaches experienced using complex projects and large number
|
||||||
|
of targets within Xcode.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import errno
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import xml.sax.saxutils
|
||||||
|
|
||||||
|
import gyp.generator.ninja
|
||||||
|
|
||||||
|
|
||||||
|
def _WriteWorkspace(main_gyp, sources_gyp, params):
|
||||||
|
"""Create a workspace to wrap main and sources gyp paths."""
|
||||||
|
(build_file_root, _build_file_ext) = os.path.splitext(main_gyp)
|
||||||
|
workspace_path = build_file_root + ".xcworkspace"
|
||||||
|
options = params["options"]
|
||||||
|
if options.generator_output:
|
||||||
|
workspace_path = os.path.join(options.generator_output, workspace_path)
|
||||||
|
try:
|
||||||
|
os.makedirs(workspace_path)
|
||||||
|
except OSError as e:
|
||||||
|
if e.errno != errno.EEXIST:
|
||||||
|
raise
|
||||||
|
output_string = (
|
||||||
|
'<?xml version="1.0" encoding="UTF-8"?>\n' + '<Workspace version = "1.0">\n'
|
||||||
|
)
|
||||||
|
for gyp_name in [main_gyp, sources_gyp]:
|
||||||
|
name = os.path.splitext(os.path.basename(gyp_name))[0] + ".xcodeproj"
|
||||||
|
name = xml.sax.saxutils.quoteattr("group:" + name)
|
||||||
|
output_string += " <FileRef location = %s></FileRef>\n" % name
|
||||||
|
output_string += "</Workspace>\n"
|
||||||
|
|
||||||
|
workspace_file = os.path.join(workspace_path, "contents.xcworkspacedata")
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(workspace_file) as input_file:
|
||||||
|
input_string = input_file.read()
|
||||||
|
if input_string == output_string:
|
||||||
|
return
|
||||||
|
except OSError:
|
||||||
|
# Ignore errors if the file doesn't exist.
|
||||||
|
pass
|
||||||
|
|
||||||
|
with open(workspace_file, "w") as output_file:
|
||||||
|
output_file.write(output_string)
|
||||||
|
|
||||||
|
|
||||||
|
def _TargetFromSpec(old_spec, params):
|
||||||
|
"""Create fake target for xcode-ninja wrapper."""
|
||||||
|
# Determine ninja top level build dir (e.g. /path/to/out).
|
||||||
|
ninja_toplevel = None
|
||||||
|
jobs = 0
|
||||||
|
if params:
|
||||||
|
options = params["options"]
|
||||||
|
ninja_toplevel = os.path.join(
|
||||||
|
options.toplevel_dir, gyp.generator.ninja.ComputeOutputDir(params)
|
||||||
|
)
|
||||||
|
jobs = params.get("generator_flags", {}).get("xcode_ninja_jobs", 0)
|
||||||
|
|
||||||
|
target_name = old_spec.get("target_name")
|
||||||
|
product_name = old_spec.get("product_name", target_name)
|
||||||
|
|
||||||
|
ninja_target = {}
|
||||||
|
ninja_target["target_name"] = target_name
|
||||||
|
ninja_target["product_name"] = product_name
|
||||||
|
if product_extension := old_spec.get("product_extension"):
|
||||||
|
ninja_target["product_extension"] = product_extension
|
||||||
|
ninja_target["toolset"] = old_spec.get("toolset")
|
||||||
|
ninja_target["default_configuration"] = old_spec.get("default_configuration")
|
||||||
|
ninja_target["configurations"] = {}
|
||||||
|
|
||||||
|
# Tell Xcode to look in |ninja_toplevel| for build products.
|
||||||
|
new_xcode_settings = {}
|
||||||
|
if ninja_toplevel:
|
||||||
|
new_xcode_settings["CONFIGURATION_BUILD_DIR"] = (
|
||||||
|
"%s/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)" % ninja_toplevel
|
||||||
|
)
|
||||||
|
|
||||||
|
if "configurations" in old_spec:
|
||||||
|
for config in old_spec["configurations"]:
|
||||||
|
old_xcode_settings = old_spec["configurations"][config].get(
|
||||||
|
"xcode_settings", {}
|
||||||
|
)
|
||||||
|
if "IPHONEOS_DEPLOYMENT_TARGET" in old_xcode_settings:
|
||||||
|
new_xcode_settings["CODE_SIGNING_REQUIRED"] = "NO"
|
||||||
|
new_xcode_settings["IPHONEOS_DEPLOYMENT_TARGET"] = old_xcode_settings[
|
||||||
|
"IPHONEOS_DEPLOYMENT_TARGET"
|
||||||
|
]
|
||||||
|
for key in ["BUNDLE_LOADER", "TEST_HOST"]:
|
||||||
|
if key in old_xcode_settings:
|
||||||
|
new_xcode_settings[key] = old_xcode_settings[key]
|
||||||
|
|
||||||
|
ninja_target["configurations"][config] = {}
|
||||||
|
ninja_target["configurations"][config]["xcode_settings"] = (
|
||||||
|
new_xcode_settings
|
||||||
|
)
|
||||||
|
|
||||||
|
ninja_target["mac_bundle"] = old_spec.get("mac_bundle", 0)
|
||||||
|
ninja_target["mac_xctest_bundle"] = old_spec.get("mac_xctest_bundle", 0)
|
||||||
|
ninja_target["ios_app_extension"] = old_spec.get("ios_app_extension", 0)
|
||||||
|
ninja_target["ios_watchkit_extension"] = old_spec.get("ios_watchkit_extension", 0)
|
||||||
|
ninja_target["ios_watchkit_app"] = old_spec.get("ios_watchkit_app", 0)
|
||||||
|
ninja_target["type"] = old_spec["type"]
|
||||||
|
if ninja_toplevel:
|
||||||
|
ninja_target["actions"] = [
|
||||||
|
{
|
||||||
|
"action_name": "Compile and copy %s via ninja" % target_name,
|
||||||
|
"inputs": [],
|
||||||
|
"outputs": [],
|
||||||
|
"action": [
|
||||||
|
"env",
|
||||||
|
"PATH=%s" % os.environ["PATH"],
|
||||||
|
"ninja",
|
||||||
|
"-C",
|
||||||
|
new_xcode_settings["CONFIGURATION_BUILD_DIR"],
|
||||||
|
target_name,
|
||||||
|
],
|
||||||
|
"message": "Compile and copy %s via ninja" % target_name,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
if jobs > 0:
|
||||||
|
ninja_target["actions"][0]["action"].extend(("-j", jobs))
|
||||||
|
return ninja_target
|
||||||
|
|
||||||
|
|
||||||
|
def IsValidTargetForWrapper(target_extras, executable_target_pattern, spec):
|
||||||
|
"""Limit targets for Xcode wrapper.
|
||||||
|
|
||||||
|
Xcode sometimes performs poorly with too many targets, so only include
|
||||||
|
proper executable targets, with filters to customize.
|
||||||
|
Arguments:
|
||||||
|
target_extras: Regular expression to always add, matching any target.
|
||||||
|
executable_target_pattern: Regular expression limiting executable targets.
|
||||||
|
spec: Specifications for target.
|
||||||
|
"""
|
||||||
|
target_name = spec.get("target_name")
|
||||||
|
# Always include targets matching target_extras.
|
||||||
|
if target_extras is not None and re.search(target_extras, target_name):
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Otherwise just show executable targets and xc_tests.
|
||||||
|
if int(spec.get("mac_xctest_bundle", 0)) != 0 or (
|
||||||
|
spec.get("type", "") == "executable"
|
||||||
|
and spec.get("product_extension", "") != "bundle"
|
||||||
|
):
|
||||||
|
# If there is a filter and the target does not match, exclude the target.
|
||||||
|
if executable_target_pattern is not None:
|
||||||
|
if not re.search(executable_target_pattern, target_name):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def CreateWrapper(target_list, target_dicts, data, params):
|
||||||
|
"""Initialize targets for the ninja wrapper.
|
||||||
|
|
||||||
|
This sets up the necessary variables in the targets to generate Xcode projects
|
||||||
|
that use ninja as an external builder.
|
||||||
|
Arguments:
|
||||||
|
target_list: List of target pairs: 'base/base.gyp:base'.
|
||||||
|
target_dicts: Dict of target properties keyed on target pair.
|
||||||
|
data: Dict of flattened build files keyed on gyp path.
|
||||||
|
params: Dict of global options for gyp.
|
||||||
|
"""
|
||||||
|
orig_gyp = params["build_files"][0]
|
||||||
|
for gyp_name, gyp_dict in data.items():
|
||||||
|
if gyp_name == orig_gyp:
|
||||||
|
depth = gyp_dict["_DEPTH"]
|
||||||
|
|
||||||
|
# Check for custom main gyp name, otherwise use the default CHROMIUM_GYP_FILE
|
||||||
|
# and prepend .ninja before the .gyp extension.
|
||||||
|
generator_flags = params.get("generator_flags", {})
|
||||||
|
main_gyp = generator_flags.get("xcode_ninja_main_gyp", None)
|
||||||
|
if main_gyp is None:
|
||||||
|
(build_file_root, build_file_ext) = os.path.splitext(orig_gyp)
|
||||||
|
main_gyp = build_file_root + ".ninja" + build_file_ext
|
||||||
|
|
||||||
|
# Create new |target_list|, |target_dicts| and |data| data structures.
|
||||||
|
new_target_list = []
|
||||||
|
new_target_dicts = {}
|
||||||
|
new_data = {}
|
||||||
|
|
||||||
|
# Set base keys needed for |data|.
|
||||||
|
new_data[main_gyp] = {}
|
||||||
|
new_data[main_gyp]["included_files"] = []
|
||||||
|
new_data[main_gyp]["targets"] = []
|
||||||
|
new_data[main_gyp]["xcode_settings"] = data[orig_gyp].get("xcode_settings", {})
|
||||||
|
|
||||||
|
# Normally the xcode-ninja generator includes only valid executable targets.
|
||||||
|
# If |xcode_ninja_executable_target_pattern| is set, that list is reduced to
|
||||||
|
# executable targets that match the pattern. (Default all)
|
||||||
|
executable_target_pattern = generator_flags.get(
|
||||||
|
"xcode_ninja_executable_target_pattern", None
|
||||||
|
)
|
||||||
|
|
||||||
|
# For including other non-executable targets, add the matching target name
|
||||||
|
# to the |xcode_ninja_target_pattern| regular expression. (Default none)
|
||||||
|
target_extras = generator_flags.get("xcode_ninja_target_pattern", None)
|
||||||
|
|
||||||
|
for old_qualified_target in target_list:
|
||||||
|
spec = target_dicts[old_qualified_target]
|
||||||
|
if IsValidTargetForWrapper(target_extras, executable_target_pattern, spec):
|
||||||
|
# Add to new_target_list.
|
||||||
|
target_name = spec.get("target_name")
|
||||||
|
new_target_name = f"{main_gyp}:{target_name}#target"
|
||||||
|
new_target_list.append(new_target_name)
|
||||||
|
|
||||||
|
# Add to new_target_dicts.
|
||||||
|
new_target_dicts[new_target_name] = _TargetFromSpec(spec, params)
|
||||||
|
|
||||||
|
# Add to new_data.
|
||||||
|
for old_target in data[old_qualified_target.split(":")[0]]["targets"]:
|
||||||
|
if old_target["target_name"] == target_name:
|
||||||
|
new_data_target = {}
|
||||||
|
new_data_target["target_name"] = old_target["target_name"]
|
||||||
|
new_data_target["toolset"] = old_target["toolset"]
|
||||||
|
new_data[main_gyp]["targets"].append(new_data_target)
|
||||||
|
|
||||||
|
# Create sources target.
|
||||||
|
sources_target_name = "sources_for_indexing"
|
||||||
|
sources_target = _TargetFromSpec(
|
||||||
|
{
|
||||||
|
"target_name": sources_target_name,
|
||||||
|
"toolset": "target",
|
||||||
|
"default_configuration": "Default",
|
||||||
|
"mac_bundle": "0",
|
||||||
|
"type": "executable",
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Tell Xcode to look everywhere for headers.
|
||||||
|
sources_target["configurations"] = {"Default": {"include_dirs": [depth]}}
|
||||||
|
|
||||||
|
# Put excluded files into the sources target so they can be opened in Xcode.
|
||||||
|
skip_excluded_files = not generator_flags.get(
|
||||||
|
"xcode_ninja_list_excluded_files", True
|
||||||
|
)
|
||||||
|
|
||||||
|
sources = []
|
||||||
|
for target, target_dict in target_dicts.items():
|
||||||
|
base = os.path.dirname(target)
|
||||||
|
files = target_dict.get("sources", []) + target_dict.get(
|
||||||
|
"mac_bundle_resources", []
|
||||||
|
)
|
||||||
|
|
||||||
|
if not skip_excluded_files:
|
||||||
|
files.extend(
|
||||||
|
target_dict.get("sources_excluded", [])
|
||||||
|
+ target_dict.get("mac_bundle_resources_excluded", [])
|
||||||
|
)
|
||||||
|
|
||||||
|
for action in target_dict.get("actions", []):
|
||||||
|
files.extend(action.get("inputs", []))
|
||||||
|
|
||||||
|
if not skip_excluded_files:
|
||||||
|
files.extend(action.get("inputs_excluded", []))
|
||||||
|
|
||||||
|
# Remove files starting with $. These are mostly intermediate files for the
|
||||||
|
# build system.
|
||||||
|
files = [file for file in files if not file.startswith("$")]
|
||||||
|
|
||||||
|
# Make sources relative to root build file.
|
||||||
|
relative_path = os.path.dirname(main_gyp)
|
||||||
|
sources += [
|
||||||
|
os.path.relpath(os.path.join(base, file), relative_path) for file in files
|
||||||
|
]
|
||||||
|
|
||||||
|
sources_target["sources"] = sorted(set(sources))
|
||||||
|
|
||||||
|
# Put sources_to_index in it's own gyp.
|
||||||
|
sources_gyp = os.path.join(os.path.dirname(main_gyp), sources_target_name + ".gyp")
|
||||||
|
fully_qualified_target_name = f"{sources_gyp}:{sources_target_name}#target"
|
||||||
|
|
||||||
|
# Add to new_target_list, new_target_dicts and new_data.
|
||||||
|
new_target_list.append(fully_qualified_target_name)
|
||||||
|
new_target_dicts[fully_qualified_target_name] = sources_target
|
||||||
|
new_data_target = {}
|
||||||
|
new_data_target["target_name"] = sources_target["target_name"]
|
||||||
|
new_data_target["_DEPTH"] = depth
|
||||||
|
new_data_target["toolset"] = "target"
|
||||||
|
new_data[sources_gyp] = {}
|
||||||
|
new_data[sources_gyp]["targets"] = []
|
||||||
|
new_data[sources_gyp]["included_files"] = []
|
||||||
|
new_data[sources_gyp]["xcode_settings"] = data[orig_gyp].get("xcode_settings", {})
|
||||||
|
new_data[sources_gyp]["targets"].append(new_data_target)
|
||||||
|
|
||||||
|
# Write workspace to file.
|
||||||
|
_WriteWorkspace(main_gyp, sources_gyp, params)
|
||||||
|
return (new_target_list, new_target_dicts, new_data)
|
||||||
3180
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/xcodeproj_file.py
generated
vendored
Normal file
3180
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/xcodeproj_file.py
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
64
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/xml_fix.py
generated
vendored
Normal file
64
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/gyp/xml_fix.py
generated
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
# Copyright (c) 2011 Google Inc. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
"""Applies a fix to CR LF TAB handling in xml.dom.
|
||||||
|
|
||||||
|
Fixes this: http://code.google.com/p/chromium/issues/detail?id=76293
|
||||||
|
Working around this: http://bugs.python.org/issue5752
|
||||||
|
TODO(bradnelson): Consider dropping this when we drop XP support.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import xml.dom.minidom
|
||||||
|
|
||||||
|
|
||||||
|
def _Replacement_write_data(writer, data, is_attrib=False):
|
||||||
|
"""Writes datachars to writer."""
|
||||||
|
data = data.replace("&", "&").replace("<", "<")
|
||||||
|
data = data.replace('"', """).replace(">", ">")
|
||||||
|
if is_attrib:
|
||||||
|
data = data.replace("\r", "
").replace("\n", "
").replace("\t", "	")
|
||||||
|
writer.write(data)
|
||||||
|
|
||||||
|
|
||||||
|
def _Replacement_writexml(self, writer, indent="", addindent="", newl=""):
|
||||||
|
# indent = current indentation
|
||||||
|
# addindent = indentation to add to higher levels
|
||||||
|
# newl = newline string
|
||||||
|
writer.write(indent + "<" + self.tagName)
|
||||||
|
|
||||||
|
attrs = self._get_attributes()
|
||||||
|
a_names = sorted(attrs.keys())
|
||||||
|
|
||||||
|
for a_name in a_names:
|
||||||
|
writer.write(' %s="' % a_name)
|
||||||
|
_Replacement_write_data(writer, attrs[a_name].value, is_attrib=True)
|
||||||
|
writer.write('"')
|
||||||
|
if self.childNodes:
|
||||||
|
writer.write(">%s" % newl)
|
||||||
|
for node in self.childNodes:
|
||||||
|
node.writexml(writer, indent + addindent, addindent, newl)
|
||||||
|
writer.write(f"{indent}</{self.tagName}>{newl}")
|
||||||
|
else:
|
||||||
|
writer.write("/>%s" % newl)
|
||||||
|
|
||||||
|
|
||||||
|
class XmlFix:
|
||||||
|
"""Object to manage temporary patching of xml.dom.minidom."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
# Preserve current xml.dom.minidom functions.
|
||||||
|
self.write_data = xml.dom.minidom._write_data
|
||||||
|
self.writexml = xml.dom.minidom.Element.writexml
|
||||||
|
# Inject replacement versions of a function and a method.
|
||||||
|
xml.dom.minidom._write_data = _Replacement_write_data
|
||||||
|
xml.dom.minidom.Element.writexml = _Replacement_writexml
|
||||||
|
|
||||||
|
def Cleanup(self):
|
||||||
|
if self.write_data:
|
||||||
|
xml.dom.minidom._write_data = self.write_data
|
||||||
|
xml.dom.minidom.Element.writexml = self.writexml
|
||||||
|
self.write_data = None
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
self.Cleanup()
|
||||||
3
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/packaging/LICENSE
generated
vendored
Normal file
3
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/packaging/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
This software is made available under the terms of *either* of the licenses
|
||||||
|
found in LICENSE.APACHE or LICENSE.BSD. Contributions to this software is made
|
||||||
|
under the terms of *both* these licenses.
|
||||||
177
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/packaging/LICENSE.APACHE
generated
vendored
Normal file
177
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/packaging/LICENSE.APACHE
generated
vendored
Normal file
|
|
@ -0,0 +1,177 @@
|
||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
23
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/packaging/LICENSE.BSD
generated
vendored
Normal file
23
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/packaging/LICENSE.BSD
generated
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
Copyright (c) Donald Stufft and individual contributors.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
15
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/packaging/__init__.py
generated
vendored
Normal file
15
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/packaging/__init__.py
generated
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
# This file is dual licensed under the terms of the Apache License, Version
|
||||||
|
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||||
|
# for complete details.
|
||||||
|
|
||||||
|
__title__ = "packaging"
|
||||||
|
__summary__ = "Core utilities for Python packages"
|
||||||
|
__uri__ = "https://github.com/pypa/packaging"
|
||||||
|
|
||||||
|
__version__ = "23.3.dev0"
|
||||||
|
|
||||||
|
__author__ = "Donald Stufft and individual contributors"
|
||||||
|
__email__ = "donald@stufft.io"
|
||||||
|
|
||||||
|
__license__ = "BSD-2-Clause or Apache-2.0"
|
||||||
|
__copyright__ = "2014 %s" % __author__
|
||||||
107
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/packaging/_elffile.py
generated
vendored
Normal file
107
.yarn/unplugged/node-gyp-npm-12.2.0-11f8fe84f1/node_modules/node-gyp/gyp/pylib/packaging/_elffile.py
generated
vendored
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
"""
|
||||||
|
ELF file parser.
|
||||||
|
|
||||||
|
This provides a class ``ELFFile`` that parses an ELF executable in a similar
|
||||||
|
interface to ``ZipFile``. Only the read interface is implemented.
|
||||||
|
|
||||||
|
Based on: https://gist.github.com/lyssdod/f51579ae8d93c8657a5564aefc2ffbca
|
||||||
|
ELF header: https://refspecs.linuxfoundation.org/elf/gabi4+/ch4.eheader.html
|
||||||
|
"""
|
||||||
|
|
||||||
|
import enum
|
||||||
|
import os
|
||||||
|
import struct
|
||||||
|
from typing import IO, Optional, Tuple
|
||||||
|
|
||||||
|
|
||||||
|
class ELFInvalid(ValueError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class EIClass(enum.IntEnum):
|
||||||
|
C32 = 1
|
||||||
|
C64 = 2
|
||||||
|
|
||||||
|
|
||||||
|
class EIData(enum.IntEnum):
|
||||||
|
Lsb = 1
|
||||||
|
Msb = 2
|
||||||
|
|
||||||
|
|
||||||
|
class EMachine(enum.IntEnum):
|
||||||
|
I386 = 3
|
||||||
|
S390 = 22
|
||||||
|
Arm = 40
|
||||||
|
X8664 = 62
|
||||||
|
AArc64 = 183
|
||||||
|
|
||||||
|
|
||||||
|
class ELFFile:
|
||||||
|
"""
|
||||||
|
Representation of an ELF executable.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, f: IO[bytes]) -> None:
|
||||||
|
self._f = f
|
||||||
|
|
||||||
|
try:
|
||||||
|
ident = self._read("16B")
|
||||||
|
except struct.error:
|
||||||
|
raise ELFInvalid("unable to parse identification")
|
||||||
|
if (magic := bytes(ident[:4])) != b"\x7fELF":
|
||||||
|
raise ELFInvalid(f"invalid magic: {magic!r}")
|
||||||
|
|
||||||
|
self.capacity = ident[4] # Format for program header (bitness).
|
||||||
|
self.encoding = ident[5] # Data structure encoding (endianness).
|
||||||
|
|
||||||
|
try:
|
||||||
|
# e_fmt: Format for program header.
|
||||||
|
# p_fmt: Format for section header.
|
||||||
|
# p_idx: Indexes to find p_type, p_offset, and p_filesz.
|
||||||
|
e_fmt, self._p_fmt, self._p_idx = {
|
||||||
|
(1, 1): ("<HHIIIIIHHH", "<IIIIIIII", (0, 1, 4)), # 32-bit LSB.
|
||||||
|
(1, 2): (">HHIIIIIHHH", ">IIIIIIII", (0, 1, 4)), # 32-bit MSB.
|
||||||
|
(2, 1): ("<HHIQQQIHHH", "<IIQQQQQQ", (0, 2, 5)), # 64-bit LSB.
|
||||||
|
(2, 2): (">HHIQQQIHHH", ">IIQQQQQQ", (0, 2, 5)), # 64-bit MSB.
|
||||||
|
}[(self.capacity, self.encoding)]
|
||||||
|
except KeyError:
|
||||||
|
raise ELFInvalid(
|
||||||
|
f"unrecognized capacity ({self.capacity}) or "
|
||||||
|
f"encoding ({self.encoding})"
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
(
|
||||||
|
_,
|
||||||
|
self.machine, # Architecture type.
|
||||||
|
_,
|
||||||
|
_,
|
||||||
|
self._e_phoff, # Offset of program header.
|
||||||
|
_,
|
||||||
|
self.flags, # Processor-specific flags.
|
||||||
|
_,
|
||||||
|
self._e_phentsize, # Size of section.
|
||||||
|
self._e_phnum, # Number of sections.
|
||||||
|
) = self._read(e_fmt)
|
||||||
|
except struct.error as e:
|
||||||
|
raise ELFInvalid("unable to parse machine and section information") from e
|
||||||
|
|
||||||
|
def _read(self, fmt: str) -> Tuple[int, ...]:
|
||||||
|
return struct.unpack(fmt, self._f.read(struct.calcsize(fmt)))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def interpreter(self) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
The path recorded in the ``PT_INTERP`` section header.
|
||||||
|
"""
|
||||||
|
for index in range(self._e_phnum):
|
||||||
|
self._f.seek(self._e_phoff + self._e_phentsize * index)
|
||||||
|
try:
|
||||||
|
data = self._read(self._p_fmt)
|
||||||
|
except struct.error:
|
||||||
|
continue
|
||||||
|
if data[self._p_idx[0]] != 3: # Not PT_INTERP.
|
||||||
|
continue
|
||||||
|
self._f.seek(data[self._p_idx[1]])
|
||||||
|
return os.fsdecode(self._f.read(data[self._p_idx[2]])).strip("\0")
|
||||||
|
return None
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue