crossbind 2.0.0-beta.76 → 2.0.0-beta.77
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "crossbind",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.77",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"homepage": "https://crossbind.dev",
|
|
6
6
|
"repository": {
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"upath": "^3.0.8"
|
|
56
56
|
},
|
|
57
57
|
"optionalDependencies": {
|
|
58
|
-
"@crossbind/bridge-tools": "2.0.0-beta.
|
|
58
|
+
"@crossbind/bridge-tools": "2.0.0-beta.77"
|
|
59
59
|
},
|
|
60
60
|
"keywords": [
|
|
61
61
|
"webassembly",
|
|
@@ -4,10 +4,12 @@ import { fileURLToPath } from 'node:url';
|
|
|
4
4
|
import run from './run.js';
|
|
5
5
|
import getLinkInputs from './getLinkInputs.js';
|
|
6
6
|
import getData from './getData.js';
|
|
7
|
+
import copyNativeNotices from './nativeNotices.js';
|
|
7
8
|
import state from '../state/index.js';
|
|
8
9
|
import logger from '../utils/logger.js';
|
|
9
10
|
import { getContentHash, getFilesFingerprint } from '../utils/hash.js';
|
|
10
11
|
import { buildLinkLibArgs } from '../utils/linkLayout.js';
|
|
12
|
+
import resetCMakeCacheForSource from '../utils/resetCMakeCacheForSource.js';
|
|
11
13
|
|
|
12
14
|
const cpuCount = Math.max(1, os.cpus().length - 1);
|
|
13
15
|
const PROJECT_SOURCE = fileURLToPath(new URL('../assets/cmake/command', import.meta.url));
|
|
@@ -67,8 +69,10 @@ export default async function buildNativeCommand(target, options = {}) {
|
|
|
67
69
|
|
|
68
70
|
const platformPrefix = `Native-${buildType}`;
|
|
69
71
|
logger.startStep(target, 'native command');
|
|
72
|
+
const projectDir = stageProject(build);
|
|
73
|
+
resetCMakeCacheForSource(`${build}/${platformPrefix}/${target.path}`, projectDir, target);
|
|
70
74
|
run(null, [
|
|
71
|
-
'cmake',
|
|
75
|
+
'cmake', projectDir,
|
|
72
76
|
`-DCMAKE_BUILD_TYPE=${buildType}`,
|
|
73
77
|
`-DCROSSBIND_COMMAND_FILE=${target.commandName}`,
|
|
74
78
|
`-DCROSSBIND_LINK_ARGS=${linkArgs.join(';')}`,
|
|
@@ -76,6 +80,7 @@ export default async function buildNativeCommand(target, options = {}) {
|
|
|
76
80
|
`-DCROSSBIND_STATIC=${isStatic ? 'ON' : 'OFF'}`,
|
|
77
81
|
], platformPrefix, target);
|
|
78
82
|
run(null, ['cmake', '--build', '.', '-j', String(cpuCount)], platformPrefix, target, { exclusive: true });
|
|
83
|
+
copyNativeNotices(target);
|
|
79
84
|
fs.copyFileSync(`${build}/${platformPrefix}/${target.path}/${target.commandName}`, `${build}/${target.commandName}`);
|
|
80
85
|
logger.doneStep(target, 'native command');
|
|
81
86
|
|
package/src/actions/licenses.js
CHANGED
|
@@ -179,9 +179,9 @@ function toolchainNoticeTexts(platform, pattern) {
|
|
|
179
179
|
return texts.length > 0 ? texts.join('\n\n') : null;
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
-
// A Linux or Windows addon carries its C++ runtime; a Windows one also carries parts of the
|
|
182
|
+
// A Linux or Windows addon, app or executable carries its C++ runtime; a Windows one also carries parts of the
|
|
183
183
|
// mingw-w64 runtime and winpthreads, whose licenses ask for their notices in binary distributions.
|
|
184
|
-
// A macOS
|
|
184
|
+
// A macOS binary uses the system's C++ runtime. Their texts and versions are what the link copied out of its image.
|
|
185
185
|
function addonToolchainRows(platform) {
|
|
186
186
|
const shared = {
|
|
187
187
|
npmName: null, version: null, nativeVersion: null, sha256: null, licenseSelected: null, licenseText: null, isCopyleft: false,
|
|
@@ -219,10 +219,43 @@ function addonToolchainRows(platform) {
|
|
|
219
219
|
sourceUrl: 'https://github.com/mingw-w64/mingw-w64',
|
|
220
220
|
licenseNotes: 'the mingw-w64 startup code and winpthreads, statically linked into the binary; a binary distribution includes their notices: https://github.com/mingw-w64/mingw-w64/blob/master/COPYING.MinGW-w64-runtime/COPYING.MinGW-w64-runtime.txt and https://github.com/mingw-w64/mingw-w64/blob/master/mingw-w64-libraries/winpthreads/COPYING (the windows image carries both in /opt/licenses/llvm-mingw)',
|
|
221
221
|
licenseText: toolchainNoticeTexts('win32', MINGW_NOTICE),
|
|
222
|
+
isNoticeRequired: true,
|
|
222
223
|
},
|
|
223
224
|
];
|
|
224
225
|
}
|
|
225
226
|
|
|
227
|
+
// A static musl executable carries musl's libc, whose MIT license asks every copy for its notice. Its text and version
|
|
228
|
+
// are what the link copied out of its image; an addon and a library leave the C library to what runs them.
|
|
229
|
+
function muslRow() {
|
|
230
|
+
return {
|
|
231
|
+
npmName: null,
|
|
232
|
+
version: null,
|
|
233
|
+
sha256: null,
|
|
234
|
+
licenseSelected: null,
|
|
235
|
+
isCopyleft: false,
|
|
236
|
+
name: 'musl',
|
|
237
|
+
license: 'MIT',
|
|
238
|
+
licenseDeclared: 'MIT',
|
|
239
|
+
sourceUrl: 'https://git.musl-libc.org/cgit/musl',
|
|
240
|
+
nativeVersion: toolchainNotice('linuxmusl', NATIVE_NOTICES.muslVersion),
|
|
241
|
+
licenseText: toolchainNoticeText('linuxmusl', NATIVE_NOTICES.muslText),
|
|
242
|
+
licenseNotes: 'the musl libc of the linux toolchain image, statically linked into the executable',
|
|
243
|
+
isNoticeRequired: true,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const BINARY_KINDS = { node: 'addon', app: 'app', native: 'executable' };
|
|
248
|
+
|
|
249
|
+
// The runtimes a binary carries without the notice their licenses ask its distribution for, which its link copies out of
|
|
250
|
+
// the image. A list of no binary (no runtimeEnv), such as a static library's, leaves those notices to the binary's own.
|
|
251
|
+
export function missingNotices(rows, { platform, runtimeEnv }) {
|
|
252
|
+
const kind = BINARY_KINDS[runtimeEnv];
|
|
253
|
+
if (!kind) return [];
|
|
254
|
+
return rows
|
|
255
|
+
.filter((row) => row.isNoticeRequired && !row.licenseText)
|
|
256
|
+
.map((row) => `x ${row.name}: its license asks a distribution of the ${platform} ${kind} for its notices, and the list has none; build the ${platform} ${kind}, whose link copies them out of its toolchain image`);
|
|
257
|
+
}
|
|
258
|
+
|
|
226
259
|
const versionOf = (dir) => JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf8')).version;
|
|
227
260
|
const textOf = (file) => fs.readFileSync(file, 'utf8').trim();
|
|
228
261
|
|
|
@@ -613,7 +646,8 @@ export async function vendoringLibraries() {
|
|
|
613
646
|
// copies and the toolchain runtime, and for wasm crossbind's runtime, which the
|
|
614
647
|
// module's glue bundles. runtimeEnv 'node' adds the crossbind runtime an
|
|
615
648
|
// addon of that platform compiles in, or without a platform the one its loader bundles;
|
|
616
|
-
// runtimeEnv 'app' adds what an app's host carries
|
|
649
|
+
// runtimeEnv 'app' adds what an app's host carries; runtimeEnv 'native' adds the C library
|
|
650
|
+
// a static musl executable links.
|
|
617
651
|
export default async function collectLicenseRows(platform = null, { runtimeEnv = null } = {}) {
|
|
618
652
|
assertSourcesStaged();
|
|
619
653
|
// The root package is a component too when it is a port: leaf -wasi packages have no deps but ship
|
|
@@ -646,6 +680,7 @@ export default async function collectLicenseRows(platform = null, { runtimeEnv =
|
|
|
646
680
|
if (platform === 'wasi') rows.push(...wasiToolchainRows());
|
|
647
681
|
if (platform === 'wasm') rows.push(...wasmToolchainRows(), crossbindRow("crossbind's JavaScript runtime, which the module's glue bundles"));
|
|
648
682
|
if (['linux', 'linuxmusl', 'win32'].includes(platform)) rows.push(...addonToolchainRows(platform));
|
|
683
|
+
if (platform === 'linuxmusl' && runtimeEnv === 'native') rows.push(muslRow());
|
|
649
684
|
if (runtimeEnv === 'node') rows.push(...nodeRuntimeRows({ isAddon: platform !== null }));
|
|
650
685
|
if (runtimeEnv === 'app') {
|
|
651
686
|
rows.push(...appRuntimeRows(platform));
|
|
@@ -8,6 +8,7 @@ const MINGW_CLANG = '/opt/llvm-mingw/bin/clang';
|
|
|
8
8
|
// The x64 and arm64 targets share one mingw-w64 build.
|
|
9
9
|
const MINGW_VERSION_HEADER = '/opt/llvm-mingw/x86_64-w64-mingw32/include/_mingw_mac.h';
|
|
10
10
|
const LIBCXX_LICENSE = '/opt/licenses/linux-sysroot/libcxx-LICENSE.TXT';
|
|
11
|
+
const MUSL_LICENSE = '/opt/licenses/linux-sysroot/musl/musl-COPYRIGHT';
|
|
11
12
|
const NDK_CLANG = `${ANDROID_NDK}/toolchains/llvm/prebuilt/linux-x86_64/bin/clang`;
|
|
12
13
|
|
|
13
14
|
const ifFile = (file, command) => `if [ -f ${file} ]; then ${command}; fi`;
|
|
@@ -31,7 +32,16 @@ const SCRIPTS = {
|
|
|
31
32
|
},
|
|
32
33
|
android: (dir) => [clangVersion(NDK_CLANG, dir)],
|
|
33
34
|
};
|
|
34
|
-
|
|
35
|
+
// A static musl executable also carries musl's libc, whose notice every musl link keeps. musl records its version only
|
|
36
|
+
// in libc, as the one string of version.lo.
|
|
37
|
+
SCRIPTS.linuxmusl = (dir, target) => {
|
|
38
|
+
const libc = `/opt/crossbind/sysroots/${linuxTriple(target)}/usr/lib/libc.a`;
|
|
39
|
+
return [
|
|
40
|
+
...SCRIPTS.linux(dir, target),
|
|
41
|
+
ifFile(MUSL_LICENSE, `cp ${MUSL_LICENSE} ${dir}/${NATIVE_NOTICES.muslText}`),
|
|
42
|
+
ifFile(libc, `ar p ${libc} version.lo | tr -cs '[:print:]' '\\n' | grep -x -E '[0-9]+\\.[0-9]+\\.[0-9]+' > ${dir}/${NATIVE_NOTICES.muslVersion}`),
|
|
43
|
+
];
|
|
44
|
+
};
|
|
35
45
|
|
|
36
46
|
// Copies them beside the build after a link in the target's image, where crossbind licenses reads them. A host
|
|
37
47
|
// toolchain keeps none of these files, and its build goes on without them.
|
package/src/bin.js
CHANGED
|
@@ -48,7 +48,7 @@ import { cargoHome } from './utils/runCargo.js';
|
|
|
48
48
|
import { containerRootOf, sourceRoot } from './utils/runPackageSource.js';
|
|
49
49
|
import { importSchemesOf, sourceNamesOf } from './utils/packageSources.js';
|
|
50
50
|
import { cleanDepsCache } from './utils/dependencyRebuild.js';
|
|
51
|
-
import collectLicenseRows, { vendoringLibraries } from './actions/licenses.js';
|
|
51
|
+
import collectLicenseRows, { missingNotices, vendoringLibraries } from './actions/licenses.js';
|
|
52
52
|
import { formatNoticesMarkdown, formatCycloneDxSbom, validateSpdx } from './utils/licenseReport.js';
|
|
53
53
|
import { SBOM_FILE, nodePackageMeta, shippedRows, writeNodePackageLicense } from './utils/packageLicense.js';
|
|
54
54
|
import findFiles from './utils/findFiles.js';
|
|
@@ -225,9 +225,9 @@ program.command('licenses')
|
|
|
225
225
|
.description('list bundled native dependencies with SPDX license, versions and source URL')
|
|
226
226
|
.option('--notices [file]', 'write a THIRD-PARTY-NOTICES markdown file (default: THIRD-PARTY-NOTICES.md)')
|
|
227
227
|
.option('--sbom [file]', 'write a CycloneDX SBOM json file (default: sbom.cdx.json)')
|
|
228
|
-
.option('--check', 'exit non-zero when a license field is missing or not valid SPDX')
|
|
228
|
+
.option('--check', 'exit non-zero when a license field is missing or not valid SPDX, and with -e when the binary lacks a notice the license of a runtime it carries asks for')
|
|
229
229
|
.option('--platform <platform>', "also list what this platform's artifact statically links beyond the package graph (vendored copies, toolchain runtime)")
|
|
230
|
-
.addOption(new Option('-e, --runtime-env <runtimeEnv>', "also list the crossbind runtime an addon of --platform compiles in (without --platform the one its loader bundles),
|
|
230
|
+
.addOption(new Option('-e, --runtime-env <runtimeEnv>', "also list the crossbind runtime an addon of --platform compiles in (without --platform the one its loader bundles), what an app's host carries, or the C library a static musl executable links").choices(['node', 'app', 'native']))
|
|
231
231
|
.option('--json [file]', 'write the rows, license texts included, as JSON (default: licenses.json)')
|
|
232
232
|
.option('--package', "write this Node-API package's LICENSE, sbom.cdx.json and package.json license field (with -e node)")
|
|
233
233
|
.action(async (options) => {
|
|
@@ -280,7 +280,9 @@ program.command('licenses')
|
|
|
280
280
|
.map((row) => ({ row, result: validateSpdx(row.license) }))
|
|
281
281
|
.filter(({ result }) => !result.isValid);
|
|
282
282
|
invalid.forEach(({ row, result }) => console.error(`x ${row.name} (${row.npmName}): ${result.error}`));
|
|
283
|
-
|
|
283
|
+
const unnoticed = missingNotices(rows, { platform: options.platform, runtimeEnv: options.runtimeEnv });
|
|
284
|
+
unnoticed.forEach((problem) => console.error(problem));
|
|
285
|
+
if (invalid.length > 0 || unnoticed.length > 0) process.exit(1);
|
|
284
286
|
console.log('✓ all license fields are valid SPDX');
|
|
285
287
|
}
|
|
286
288
|
});
|
|
@@ -20,6 +20,8 @@ export const NATIVE_NOTICES = {
|
|
|
20
20
|
clangVersion: 'clang-version.txt',
|
|
21
21
|
libcxxVersion: 'libcxx-version.txt',
|
|
22
22
|
mingwVersion: 'mingw-w64-version.txt',
|
|
23
|
+
muslText: 'musl-COPYRIGHT',
|
|
24
|
+
muslVersion: 'musl-version.txt',
|
|
23
25
|
};
|
|
24
26
|
|
|
25
27
|
export const MINGW_NOTICE = /^COPYING/;
|