@git.zone/tsrust 1.13.0 → 1.14.0
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/.smartconfig.json +4 -0
- package/assets/notices/gcc-gpl-3.0.txt +674 -0
- package/assets/notices/gcc-runtime-library-exception-3.1.txt +73 -0
- package/assets/notices/glibc-lgpl-2.1.txt +502 -0
- package/assets/notices/musl-copyright.txt +193 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/index.d.ts +1 -0
- package/dist_ts/index.js +2 -1
- package/dist_ts/mod_cargo/classes.cargorunner.d.ts +1 -0
- package/dist_ts/mod_cargo/classes.cargorunner.js +47 -39
- package/dist_ts/mod_cargo/classes.targetcache.d.ts +10 -0
- package/dist_ts/mod_cargo/classes.targetcache.js +94 -75
- package/dist_ts/mod_cargo/classes.targetguard.d.ts +4 -0
- package/dist_ts/mod_cargo/classes.targetguard.js +83 -0
- package/dist_ts/mod_cli/classes.tsrustcli.d.ts +10 -0
- package/dist_ts/mod_cli/classes.tsrustcli.js +191 -106
- package/dist_ts/mod_cli/helpers.targets.d.ts +2 -0
- package/dist_ts/mod_cli/helpers.targets.js +1 -1
- package/dist_ts/mod_matrix/classes.nativematrixbuilder.d.ts +6 -0
- package/dist_ts/mod_matrix/classes.nativematrixbuilder.js +44 -1
- package/dist_ts/mod_notices/classes.nativenoticesgenerator.d.ts +96 -0
- package/dist_ts/mod_notices/classes.nativenoticesgenerator.js +912 -0
- package/dist_ts/mod_notices/classes.noticetoolchain.d.ts +30 -0
- package/dist_ts/mod_notices/classes.noticetoolchain.js +69 -0
- package/dist_ts/mod_notices/helpers.licensetext.d.ts +12 -0
- package/dist_ts/mod_notices/helpers.licensetext.js +81 -0
- package/dist_ts/mod_notices/helpers.muslversion.d.ts +6 -0
- package/dist_ts/mod_notices/helpers.muslversion.js +47 -0
- package/dist_ts/mod_notices/helpers.noticesconfig.d.ts +51 -0
- package/dist_ts/mod_notices/helpers.noticesconfig.js +113 -0
- package/dist_ts/mod_notices/helpers.runtimetexts.d.ts +9 -0
- package/dist_ts/mod_notices/helpers.runtimetexts.js +45 -0
- package/dist_ts/mod_notices/helpers.spdx.d.ts +21 -0
- package/dist_ts/mod_notices/helpers.spdx.js +88 -0
- package/dist_ts/mod_notices/helpers.staticglibc.d.ts +26 -0
- package/dist_ts/mod_notices/helpers.staticglibc.js +45 -0
- package/dist_ts/mod_notices/index.d.ts +8 -0
- package/dist_ts/mod_notices/index.js +9 -0
- package/dist_ts/plugins.d.ts +6 -1
- package/dist_ts/plugins.js +7 -2
- package/package.json +5 -5
- package/readme.md +115 -13
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/index.ts +1 -0
- package/ts/mod_cargo/classes.cargorunner.ts +52 -43
- package/ts/mod_cargo/classes.targetcache.ts +78 -79
- package/ts/mod_cargo/classes.targetguard.ts +63 -0
- package/ts/mod_cli/classes.tsrustcli.ts +227 -128
- package/ts/mod_cli/helpers.targets.ts +2 -0
- package/ts/mod_matrix/classes.nativematrixbuilder.ts +44 -0
- package/ts/mod_notices/classes.nativenoticesgenerator.ts +1151 -0
- package/ts/mod_notices/classes.noticetoolchain.ts +92 -0
- package/ts/mod_notices/helpers.licensetext.ts +111 -0
- package/ts/mod_notices/helpers.muslversion.ts +46 -0
- package/ts/mod_notices/helpers.noticesconfig.ts +190 -0
- package/ts/mod_notices/helpers.runtimetexts.ts +63 -0
- package/ts/mod_notices/helpers.spdx.ts +107 -0
- package/ts/mod_notices/helpers.staticglibc.ts +79 -0
- package/ts/mod_notices/index.ts +8 -0
- package/ts/plugins.ts +6 -0
- package/readme.hints.md +0 -27
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { withTargetCacheLock } from '../mod_cargo/classes.targetguard.js';
|
|
1
2
|
import * as fs from 'fs';
|
|
2
3
|
import * as path from 'path';
|
|
3
4
|
import * as os from 'os';
|
|
@@ -23,9 +24,15 @@ import {
|
|
|
23
24
|
} from '../mod_provenance/index.js';
|
|
24
25
|
import { ToolchainManager } from '../mod_toolchain/index.js';
|
|
25
26
|
import { NativeMatrixBuilder } from '../mod_matrix/index.js';
|
|
27
|
+
import {
|
|
28
|
+
assertNoStaticGlibc,
|
|
29
|
+
createProjectNoticesGenerator,
|
|
30
|
+
staticGlibcArtifactError,
|
|
31
|
+
} from '../mod_notices/index.js';
|
|
26
32
|
import { commitinfo } from '../00_commitinfo_data.js';
|
|
27
33
|
import {
|
|
28
34
|
configuredAssemblyTargets,
|
|
35
|
+
friendlyTargetName,
|
|
29
36
|
normalizeTargets,
|
|
30
37
|
resolveBuildTargets,
|
|
31
38
|
type ITsrustConfig,
|
|
@@ -61,6 +68,7 @@ export class TsRustCli {
|
|
|
61
68
|
|
|
62
69
|
private registerCommands(): void {
|
|
63
70
|
this.registerStandardCommand();
|
|
71
|
+
this.registerNoticesCommand();
|
|
64
72
|
this.registerCleanCommand();
|
|
65
73
|
this.registerPruneCommand();
|
|
66
74
|
this.registerAssembleCommand();
|
|
@@ -121,7 +129,7 @@ export class TsRustCli {
|
|
|
121
129
|
* then falls back to a bundled toolchain at /tmp/tsrust_toolchain/.
|
|
122
130
|
* Returns the envPrefix string to prepend to shell commands.
|
|
123
131
|
*/
|
|
124
|
-
private async resolveToolchain(): Promise<string> {
|
|
132
|
+
private async resolveToolchain(installArg: boolean = true): Promise<string> {
|
|
125
133
|
// 1. Try system cargo
|
|
126
134
|
const systemRunner = new CargoRunner(this.cwd);
|
|
127
135
|
if (await systemRunner.checkCargoInstalled()) {
|
|
@@ -131,6 +139,12 @@ export class TsRustCli {
|
|
|
131
139
|
// 2. Fall back to bundled toolchain
|
|
132
140
|
console.log('System cargo not found. Checking for bundled toolchain...');
|
|
133
141
|
const toolchain = new ToolchainManager();
|
|
142
|
+
if (!installArg) {
|
|
143
|
+
if (!(await toolchain.isInstalled())) {
|
|
144
|
+
throw new Error('No Rust toolchain is installed; install rustup or run `tsrust notices` (checks install nothing)');
|
|
145
|
+
}
|
|
146
|
+
return toolchain.getEnvPrefix();
|
|
147
|
+
}
|
|
134
148
|
await toolchain.ensureInstalled();
|
|
135
149
|
return toolchain.getEnvPrefix();
|
|
136
150
|
}
|
|
@@ -175,7 +189,6 @@ export class TsRustCli {
|
|
|
175
189
|
const distDir = path.join(this.cwd, 'dist_rust');
|
|
176
190
|
const profile = isDebug ? 'debug' : 'release';
|
|
177
191
|
const managedTargetDir = resolveManagedTargetDir(this.cwd, this.config.targetDir);
|
|
178
|
-
await writeTargetCacheMarker(managedTargetDir);
|
|
179
192
|
|
|
180
193
|
// CLI targets override host-specific and legacy configured targets.
|
|
181
194
|
const cliTargets = (argvArg as any).target;
|
|
@@ -184,47 +197,172 @@ export class TsRustCli {
|
|
|
184
197
|
: undefined;
|
|
185
198
|
const hostTriple = new ToolchainManager().getHostTriple();
|
|
186
199
|
const resolvedTargets = resolveBuildTargets(this.config, hostTriple, cliTargetList);
|
|
187
|
-
|
|
188
200
|
const useStatic = !!(argvArg as any).static || !!this.config.static;
|
|
189
|
-
if (useStatic) {
|
|
190
|
-
console.log('Static linking enabled (crt-static for linux-gnu targets)');
|
|
191
|
-
}
|
|
192
201
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
202
|
+
// With native notices, static glibc is refused by every build. Matrix
|
|
203
|
+
// workers pass --no-notices-check, which skips only the bundle comparison:
|
|
204
|
+
// their coordinator verified the notices of the exact commit.
|
|
205
|
+
if (this.config.notices !== undefined) {
|
|
206
|
+
assertNoStaticGlibc({
|
|
207
|
+
targets: resolvedTargets.length > 0
|
|
208
|
+
? resolvedTargets
|
|
209
|
+
: [{ triple: hostTriple, friendly: friendlyTargetName(hostTriple) }],
|
|
210
|
+
staticLinking: useStatic,
|
|
211
|
+
rustflags: this.config.rustflags || [],
|
|
212
|
+
environment: process.env,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
if (this.config.notices !== undefined && (argvArg as any).noticesCheck !== false) {
|
|
216
|
+
const noticeTriples = new Set(configuredAssemblyTargets(this.config).map((target) => target.triple));
|
|
217
|
+
const uncovered = resolvedTargets.filter((target) => !noticeTriples.has(target.triple));
|
|
218
|
+
if (resolvedTargets.length === 0 || uncovered.length > 0) {
|
|
219
|
+
throw new Error(
|
|
220
|
+
`Native notices cover the configured targets only; cannot build ${
|
|
221
|
+
uncovered.map((target) => target.friendly).join(', ') || 'the native host target'
|
|
222
|
+
}`,
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
const bundle = await (await createProjectNoticesGenerator({
|
|
226
|
+
projectDir: this.cwd,
|
|
227
|
+
rustDir,
|
|
228
|
+
config: this.config,
|
|
229
|
+
staticLinking: useStatic,
|
|
230
|
+
envPrefix,
|
|
231
|
+
install: false,
|
|
232
|
+
})).check();
|
|
233
|
+
console.log(`Verified native notices: ${path.relative(this.cwd, bundle.directory)}`);
|
|
196
234
|
}
|
|
197
235
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
console.log(
|
|
201
|
-
`Cross-compiling for: ${resolvedTargets.map((target) => `${target.friendly} (${target.triple})`).join(', ')}`,
|
|
202
|
-
);
|
|
236
|
+
await withTargetCacheLock(managedTargetDir, async () => {
|
|
237
|
+
await writeTargetCacheMarker(managedTargetDir);
|
|
203
238
|
|
|
204
|
-
|
|
239
|
+
if (useStatic) {
|
|
240
|
+
console.log('Static linking enabled (crt-static for linux-gnu targets)');
|
|
241
|
+
}
|
|
205
242
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
243
|
+
const rustflags = this.buildRustflags(rustDir);
|
|
244
|
+
if (rustflags.length > 0) {
|
|
245
|
+
console.log(`Using additional Rust flags: ${rustflags.join(' ')}`);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (resolvedTargets.length > 0) {
|
|
249
|
+
// Cross-compilation mode
|
|
250
|
+
console.log(
|
|
251
|
+
`Cross-compiling for: ${resolvedTargets.map((target) => `${target.friendly} (${target.triple})`).join(', ')}`,
|
|
252
|
+
);
|
|
253
|
+
|
|
254
|
+
await FsHelpers.ensureEmptyDir(distDir);
|
|
255
|
+
|
|
256
|
+
for (const { triple, friendly } of resolvedTargets) {
|
|
257
|
+
console.log(`\n--- Building for ${friendly} (${triple}) ---`);
|
|
258
|
+
if (useStatic && !isLinuxTriple(triple)) {
|
|
259
|
+
console.log(
|
|
260
|
+
`Note: static linking is not applicable for ${triple}; building with default linkage.`,
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
const cargoRunner = new CargoRunner(rustDir, envPrefix);
|
|
264
|
+
const gitBefore = await captureGitSnapshot(this.cwd);
|
|
265
|
+
const provenanceBefore = this.collectBuildProvenance(gitBefore);
|
|
266
|
+
const buildResult = await cargoRunner.build({
|
|
267
|
+
debug: isDebug,
|
|
268
|
+
clean: shouldClean,
|
|
269
|
+
target: triple,
|
|
270
|
+
locked: this.config.locked === true,
|
|
271
|
+
crtStatic: useStatic && wantsCrtStatic(triple),
|
|
272
|
+
rustflags,
|
|
273
|
+
targetDir: managedTargetDir,
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
if (!buildResult.success) {
|
|
277
|
+
console.error(`Build failed for target ${triple} with exit code ${buildResult.exitCode}`);
|
|
278
|
+
process.exit(1);
|
|
279
|
+
}
|
|
280
|
+
const gitAfter = await captureGitSnapshot(this.cwd);
|
|
281
|
+
assertGitSnapshotUnchanged(gitBefore, gitAfter);
|
|
282
|
+
const provenanceAfter = this.collectBuildProvenance(gitAfter);
|
|
283
|
+
this.assertProjectIdentityUnchanged(provenanceBefore, provenanceAfter);
|
|
284
|
+
|
|
285
|
+
const targetDir = getCargoArtifactDir(managedTargetDir, profile, triple);
|
|
286
|
+
|
|
287
|
+
for (const binName of workspaceInfo.binTargets) {
|
|
288
|
+
const srcBinary = path.join(targetDir, binName);
|
|
289
|
+
const destName = `${binName}_${friendly}`;
|
|
290
|
+
const destBinary = path.join(distDir, destName);
|
|
291
|
+
|
|
292
|
+
if (!(await FsHelpers.fileExists(srcBinary))) {
|
|
293
|
+
console.warn(`Warning: Expected binary not found: ${srcBinary}`);
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (isDarwinTriple(triple)) {
|
|
298
|
+
const signatureResult = await ensureDarwinCodeSignature(srcBinary);
|
|
299
|
+
console.log(
|
|
300
|
+
`${signatureResult === 'applied' ? 'Applied' : 'Verified'} Darwin code signature: ${srcBinary}`,
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
await FsHelpers.copyFile(srcBinary, destBinary);
|
|
304
|
+
await FsHelpers.makeExecutable(destBinary);
|
|
305
|
+
|
|
306
|
+
const size = await FsHelpers.getFileSize(destBinary);
|
|
307
|
+
console.log(
|
|
308
|
+
`Copied ${binName} (${FsHelpers.formatFileSize(size)}) -> dist_rust/${destName}`,
|
|
309
|
+
);
|
|
310
|
+
await this.assertNoticesLinkage(destBinary, triple, friendly);
|
|
311
|
+
|
|
312
|
+
if (useStatic && isLinuxTriple(triple)) {
|
|
313
|
+
if (!(await ElfInspector.isStaticElf(destBinary))) {
|
|
314
|
+
console.error(
|
|
315
|
+
`Error: ${destName} is not statically linked (PT_INTERP present) although static linking was requested.`,
|
|
316
|
+
);
|
|
317
|
+
process.exit(1);
|
|
318
|
+
}
|
|
319
|
+
console.log(`Verified statically linked: dist_rust/${destName}`);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
await ProvenanceStore.write(destBinary, {
|
|
323
|
+
...provenanceBefore,
|
|
324
|
+
binary: binName,
|
|
325
|
+
target: friendly,
|
|
326
|
+
});
|
|
327
|
+
console.log(
|
|
328
|
+
`Wrote provenance: ${provenanceBefore.projectName}@${provenanceBefore.projectVersion} ${provenanceBefore.gitCommit.slice(0, 12)} (${friendly})`,
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Only clean on first iteration
|
|
333
|
+
if (shouldClean) {
|
|
334
|
+
shouldClean = false;
|
|
335
|
+
}
|
|
212
336
|
}
|
|
337
|
+
} else {
|
|
338
|
+
// Native build. When static linking is requested, build with an
|
|
339
|
+
// explicit host --target so RUSTFLAGS never reach host artifacts
|
|
340
|
+
// (proc-macros cannot build with +crt-static on linux-gnu).
|
|
341
|
+
let nativeTriple: string | undefined;
|
|
342
|
+
if (useStatic) {
|
|
343
|
+
nativeTriple = hostTriple;
|
|
344
|
+
if (!isLinuxTriple(nativeTriple)) {
|
|
345
|
+
console.log(
|
|
346
|
+
`Note: static linking is not applicable for ${nativeTriple}; building with default linkage.`,
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
213
351
|
const cargoRunner = new CargoRunner(rustDir, envPrefix);
|
|
214
352
|
const gitBefore = await captureGitSnapshot(this.cwd);
|
|
215
353
|
const provenanceBefore = this.collectBuildProvenance(gitBefore);
|
|
216
354
|
const buildResult = await cargoRunner.build({
|
|
217
355
|
debug: isDebug,
|
|
218
356
|
clean: shouldClean,
|
|
219
|
-
target:
|
|
357
|
+
target: nativeTriple,
|
|
220
358
|
locked: this.config.locked === true,
|
|
221
|
-
crtStatic:
|
|
359
|
+
crtStatic: !!nativeTriple && wantsCrtStatic(nativeTriple),
|
|
222
360
|
rustflags,
|
|
223
361
|
targetDir: managedTargetDir,
|
|
224
362
|
});
|
|
225
363
|
|
|
226
364
|
if (!buildResult.success) {
|
|
227
|
-
console.error(`Build failed
|
|
365
|
+
console.error(`Build failed with exit code ${buildResult.exitCode}`);
|
|
228
366
|
process.exit(1);
|
|
229
367
|
}
|
|
230
368
|
const gitAfter = await captureGitSnapshot(this.cwd);
|
|
@@ -232,19 +370,20 @@ export class TsRustCli {
|
|
|
232
370
|
const provenanceAfter = this.collectBuildProvenance(gitAfter);
|
|
233
371
|
this.assertProjectIdentityUnchanged(provenanceBefore, provenanceAfter);
|
|
234
372
|
|
|
235
|
-
const targetDir = getCargoArtifactDir(managedTargetDir, profile,
|
|
373
|
+
const targetDir = getCargoArtifactDir(managedTargetDir, profile, nativeTriple);
|
|
374
|
+
|
|
375
|
+
await FsHelpers.ensureEmptyDir(distDir);
|
|
236
376
|
|
|
237
377
|
for (const binName of workspaceInfo.binTargets) {
|
|
238
378
|
const srcBinary = path.join(targetDir, binName);
|
|
239
|
-
const
|
|
240
|
-
const destBinary = path.join(distDir, destName);
|
|
379
|
+
const destBinary = path.join(distDir, binName);
|
|
241
380
|
|
|
242
381
|
if (!(await FsHelpers.fileExists(srcBinary))) {
|
|
243
382
|
console.warn(`Warning: Expected binary not found: ${srcBinary}`);
|
|
244
383
|
continue;
|
|
245
384
|
}
|
|
246
385
|
|
|
247
|
-
if (isDarwinTriple(
|
|
386
|
+
if (isDarwinTriple(hostTriple)) {
|
|
248
387
|
const signatureResult = await ensureDarwinCodeSignature(srcBinary);
|
|
249
388
|
console.log(
|
|
250
389
|
`${signatureResult === 'applied' ? 'Applied' : 'Verified'} Darwin code signature: ${srcBinary}`,
|
|
@@ -255,130 +394,89 @@ export class TsRustCli {
|
|
|
255
394
|
|
|
256
395
|
const size = await FsHelpers.getFileSize(destBinary);
|
|
257
396
|
console.log(
|
|
258
|
-
`Copied ${binName} (${FsHelpers.formatFileSize(size)}) -> dist_rust/${
|
|
397
|
+
`Copied ${binName} (${FsHelpers.formatFileSize(size)}) -> dist_rust/${binName}`,
|
|
259
398
|
);
|
|
399
|
+
const builtTriple = nativeTriple || hostTriple;
|
|
400
|
+
await this.assertNoticesLinkage(destBinary, builtTriple, friendlyTargetName(builtTriple));
|
|
260
401
|
|
|
261
|
-
if (useStatic && isLinuxTriple(
|
|
402
|
+
if (useStatic && nativeTriple && isLinuxTriple(nativeTriple)) {
|
|
262
403
|
if (!(await ElfInspector.isStaticElf(destBinary))) {
|
|
263
404
|
console.error(
|
|
264
|
-
`Error: ${
|
|
405
|
+
`Error: ${binName} is not statically linked (PT_INTERP present) although static linking was requested.`,
|
|
265
406
|
);
|
|
266
407
|
process.exit(1);
|
|
267
408
|
}
|
|
268
|
-
console.log(`Verified statically linked: dist_rust/${
|
|
409
|
+
console.log(`Verified statically linked: dist_rust/${binName}`);
|
|
269
410
|
}
|
|
270
411
|
|
|
271
412
|
await ProvenanceStore.write(destBinary, {
|
|
272
413
|
...provenanceBefore,
|
|
273
414
|
binary: binName,
|
|
274
|
-
target:
|
|
415
|
+
target: nativeTriple || 'native',
|
|
275
416
|
});
|
|
276
417
|
console.log(
|
|
277
|
-
`Wrote provenance: ${provenanceBefore.projectName}@${provenanceBefore.projectVersion} ${provenanceBefore.gitCommit.slice(0, 12)} (${
|
|
278
|
-
);
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
// Only clean on first iteration
|
|
282
|
-
if (shouldClean) {
|
|
283
|
-
shouldClean = false;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
} else {
|
|
287
|
-
// Native build. When static linking is requested, build with an
|
|
288
|
-
// explicit host --target so RUSTFLAGS never reach host artifacts
|
|
289
|
-
// (proc-macros cannot build with +crt-static on linux-gnu).
|
|
290
|
-
let nativeTriple: string | undefined;
|
|
291
|
-
if (useStatic) {
|
|
292
|
-
nativeTriple = hostTriple;
|
|
293
|
-
if (!isLinuxTriple(nativeTriple)) {
|
|
294
|
-
console.log(
|
|
295
|
-
`Note: static linking is not applicable for ${nativeTriple}; building with default linkage.`,
|
|
418
|
+
`Wrote provenance: ${provenanceBefore.projectName}@${provenanceBefore.projectVersion} ${provenanceBefore.gitCommit.slice(0, 12)} (${nativeTriple || 'native'})`,
|
|
296
419
|
);
|
|
297
420
|
}
|
|
298
421
|
}
|
|
299
422
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
crtStatic: !!nativeTriple && wantsCrtStatic(nativeTriple),
|
|
309
|
-
rustflags,
|
|
310
|
-
targetDir: managedTargetDir,
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
if (!buildResult.success) {
|
|
314
|
-
console.error(`Build failed with exit code ${buildResult.exitCode}`);
|
|
315
|
-
process.exit(1);
|
|
423
|
+
if (this.shouldPruneAfterBuild()) {
|
|
424
|
+
const plan = await createTsrustPrunePlan({
|
|
425
|
+
workspace: this.cwd,
|
|
426
|
+
targetDir: managedTargetDir,
|
|
427
|
+
days: 0,
|
|
428
|
+
});
|
|
429
|
+
await applyTsrustPrunePlan(plan);
|
|
430
|
+
console.log('Pruned marked tsrust target cache after successful build.');
|
|
316
431
|
}
|
|
317
|
-
const gitAfter = await captureGitSnapshot(this.cwd);
|
|
318
|
-
assertGitSnapshotUnchanged(gitBefore, gitAfter);
|
|
319
|
-
const provenanceAfter = this.collectBuildProvenance(gitAfter);
|
|
320
|
-
this.assertProjectIdentityUnchanged(provenanceBefore, provenanceAfter);
|
|
321
|
-
|
|
322
|
-
const targetDir = getCargoArtifactDir(managedTargetDir, profile, nativeTriple);
|
|
323
|
-
|
|
324
|
-
await FsHelpers.ensureEmptyDir(distDir);
|
|
325
|
-
|
|
326
|
-
for (const binName of workspaceInfo.binTargets) {
|
|
327
|
-
const srcBinary = path.join(targetDir, binName);
|
|
328
|
-
const destBinary = path.join(distDir, binName);
|
|
329
432
|
|
|
330
|
-
|
|
331
|
-
console.warn(`Warning: Expected binary not found: ${srcBinary}`);
|
|
332
|
-
continue;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
if (isDarwinTriple(hostTriple)) {
|
|
336
|
-
const signatureResult = await ensureDarwinCodeSignature(srcBinary);
|
|
337
|
-
console.log(
|
|
338
|
-
`${signatureResult === 'applied' ? 'Applied' : 'Verified'} Darwin code signature: ${srcBinary}`,
|
|
339
|
-
);
|
|
340
|
-
}
|
|
341
|
-
await FsHelpers.copyFile(srcBinary, destBinary);
|
|
342
|
-
await FsHelpers.makeExecutable(destBinary);
|
|
433
|
+
});
|
|
343
434
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
435
|
+
const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
436
|
+
console.log(`\nDone in ${elapsed}s`);
|
|
437
|
+
});
|
|
438
|
+
}
|
|
348
439
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
440
|
+
/**
|
|
441
|
+
* With native notices, a Linux GNU binary must load glibc dynamically: a
|
|
442
|
+
* binary without an ELF interpreter is removed and the build fails.
|
|
443
|
+
*/
|
|
444
|
+
private async assertNoticesLinkage(binaryArg: string, tripleArg: string, friendlyArg: string): Promise<void> {
|
|
445
|
+
if (this.config.notices === undefined || !tripleArg.endsWith('-linux-gnu')) return;
|
|
446
|
+
if (await ElfInspector.isStaticElf(binaryArg)) {
|
|
447
|
+
await fs.promises.rm(binaryArg, { force: true });
|
|
448
|
+
throw staticGlibcArtifactError(friendlyArg, tripleArg);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
358
451
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
}
|
|
452
|
+
/**
|
|
453
|
+
* `tsrust notices` writes the third-party notices of the configured native
|
|
454
|
+
* targets; `tsrust notices --check` verifies them without writing.
|
|
455
|
+
*/
|
|
456
|
+
private registerNoticesCommand(): void {
|
|
457
|
+
this.cli.addCommand('notices').subscribe(async (argvArg) => {
|
|
458
|
+
if (this.config.notices === undefined) {
|
|
459
|
+
throw new Error('Native notices are not configured: add "notices" to the @git.zone/tsrust configuration');
|
|
368
460
|
}
|
|
369
|
-
|
|
370
|
-
if (
|
|
371
|
-
|
|
372
|
-
workspace: this.cwd,
|
|
373
|
-
targetDir: managedTargetDir,
|
|
374
|
-
days: 0,
|
|
375
|
-
});
|
|
376
|
-
await applyTsrustPrunePlan(plan);
|
|
377
|
-
console.log('Pruned marked tsrust target cache after successful build.');
|
|
461
|
+
const rustDir = await this.detectRustDir();
|
|
462
|
+
if (!rustDir) {
|
|
463
|
+
throw new Error('No rust/ or ts_rust/ directory found with a Cargo.toml');
|
|
378
464
|
}
|
|
379
|
-
|
|
380
|
-
const
|
|
381
|
-
|
|
465
|
+
const check = !!(argvArg as any).check;
|
|
466
|
+
const envPrefix = await this.resolveToolchain(!check);
|
|
467
|
+
const staticLinking = !!(argvArg as any).static || !!this.config.static;
|
|
468
|
+
const generator = await createProjectNoticesGenerator({
|
|
469
|
+
projectDir: this.cwd,
|
|
470
|
+
rustDir,
|
|
471
|
+
config: this.config,
|
|
472
|
+
staticLinking,
|
|
473
|
+
envPrefix,
|
|
474
|
+
install: !check,
|
|
475
|
+
});
|
|
476
|
+
const bundle = check ? await generator.check() : await generator.write();
|
|
477
|
+
console.log(
|
|
478
|
+
`${check ? 'Verified' : 'Wrote'} ${bundle.files.size} native notice files in ${path.relative(this.cwd, bundle.directory)}`,
|
|
479
|
+
);
|
|
382
480
|
});
|
|
383
481
|
}
|
|
384
482
|
|
|
@@ -551,11 +649,12 @@ export class TsRustCli {
|
|
|
551
649
|
const daysArg = (argvArg as any).days;
|
|
552
650
|
const days = daysArg === undefined ? 14 : Number(daysArg);
|
|
553
651
|
const maxSizeBytes = parseSizeToBytes((argvArg as any).maxSize as string | undefined);
|
|
652
|
+
if ((argvArg as any).maxSize !== undefined && maxSizeBytes === undefined) throw new Error('Invalid --max-size');
|
|
554
653
|
const apply = !!(argvArg as any).apply;
|
|
555
654
|
const plan = await createTsrustPrunePlan({
|
|
556
655
|
workspace,
|
|
557
656
|
targetDir: resolveManagedTargetDir(workspace, this.config.targetDir),
|
|
558
|
-
days
|
|
657
|
+
days,
|
|
559
658
|
maxSizeBytes,
|
|
560
659
|
});
|
|
561
660
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ITsrustMatrixConfig } from '../mod_matrix/helpers.matrixconfig.js';
|
|
2
|
+
import type { ITsrustNoticesConfig } from '../mod_notices/helpers.noticesconfig.js';
|
|
2
3
|
|
|
3
4
|
export const targetAliasMap: Record<string, string> = {
|
|
4
5
|
linux_amd64: 'x86_64-unknown-linux-gnu',
|
|
@@ -32,6 +33,7 @@ export interface ITsrustConfig {
|
|
|
32
33
|
targetDir?: string;
|
|
33
34
|
pruneAfterBuild?: boolean;
|
|
34
35
|
matrix?: ITsrustMatrixConfig;
|
|
36
|
+
notices?: ITsrustNoticesConfig;
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
export interface INormalizedTarget {
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
} from '../mod_provenance/index.js';
|
|
18
18
|
import { ToolchainManager } from '../mod_toolchain/index.js';
|
|
19
19
|
import { friendlyTargetName, type ITsrustConfig } from '../mod_cli/helpers.targets.js';
|
|
20
|
+
import { createProjectNoticesGenerator } from '../mod_notices/index.js';
|
|
20
21
|
import { commitinfo } from '../00_commitinfo_data.js';
|
|
21
22
|
import {
|
|
22
23
|
MatrixCommandRunner,
|
|
@@ -157,6 +158,8 @@ export interface INativeMatrixBuilderOptions {
|
|
|
157
158
|
config: ITsrustConfig;
|
|
158
159
|
environment?: NodeJS.ProcessEnv;
|
|
159
160
|
commandRunner?: IMatrixCommandRunner;
|
|
161
|
+
/** Verifies the native notices on the coordinator; defaults to `tsrust notices --check`. */
|
|
162
|
+
verifyNotices?: () => Promise<void>;
|
|
160
163
|
}
|
|
161
164
|
|
|
162
165
|
export interface INativeMatrixCheckResult {
|
|
@@ -221,9 +224,13 @@ export class NativeMatrixBuilder {
|
|
|
221
224
|
private readonly environment: NodeJS.ProcessEnv;
|
|
222
225
|
private readonly commandRunner: IMatrixCommandRunner;
|
|
223
226
|
private readonly plan: IResolvedMatrixPlan;
|
|
227
|
+
private readonly config: ITsrustConfig;
|
|
228
|
+
private readonly verifyNoticesOverride?: () => Promise<void>;
|
|
224
229
|
|
|
225
230
|
constructor(optionsArg: INativeMatrixBuilderOptions) {
|
|
226
231
|
this.workspace = path.resolve(optionsArg.workspace);
|
|
232
|
+
this.config = optionsArg.config;
|
|
233
|
+
this.verifyNoticesOverride = optionsArg.verifyNotices;
|
|
227
234
|
this.environment = { ...process.env, ...(optionsArg.environment || {}) };
|
|
228
235
|
this.commandRunner =
|
|
229
236
|
optionsArg.commandRunner || new MatrixCommandRunner(this.environment);
|
|
@@ -233,6 +240,7 @@ export class NativeMatrixBuilder {
|
|
|
233
240
|
|
|
234
241
|
public async check(): Promise<INativeMatrixCheckResult> {
|
|
235
242
|
await this.assertBundleCompatibleSource();
|
|
243
|
+
await this.verifyNotices();
|
|
236
244
|
await this.commandRunner.execute('git', ['--version'], {
|
|
237
245
|
cwd: this.workspace,
|
|
238
246
|
capture: true,
|
|
@@ -1008,9 +1016,45 @@ export class NativeMatrixBuilder {
|
|
|
1008
1016
|
'exec',
|
|
1009
1017
|
'tsrust',
|
|
1010
1018
|
...workerArg.targets.flatMap((target) => ['--target', target.friendly]),
|
|
1019
|
+
// The coordinator verified the notices of this commit in check().
|
|
1020
|
+
...(this.config.notices === undefined ? [] : ['--no-notices-check']),
|
|
1011
1021
|
];
|
|
1012
1022
|
}
|
|
1013
1023
|
|
|
1024
|
+
/** Native notices are verified once, here on the coordinator, for all targets. */
|
|
1025
|
+
private async verifyNotices(): Promise<void> {
|
|
1026
|
+
if (this.config.notices === undefined) return;
|
|
1027
|
+
if (this.verifyNoticesOverride) {
|
|
1028
|
+
await this.verifyNoticesOverride();
|
|
1029
|
+
return;
|
|
1030
|
+
}
|
|
1031
|
+
let envPrefix = '';
|
|
1032
|
+
try {
|
|
1033
|
+
await this.commandRunner.execute('cargo', ['--version'], {
|
|
1034
|
+
cwd: this.workspace,
|
|
1035
|
+
capture: true,
|
|
1036
|
+
timeoutMs: capabilityCommandTimeoutMs,
|
|
1037
|
+
});
|
|
1038
|
+
} catch {
|
|
1039
|
+
// The check installs nothing: use the bundled toolchain only if present.
|
|
1040
|
+
const toolchainManager = new ToolchainManager();
|
|
1041
|
+
if (!(await toolchainManager.isInstalled())) {
|
|
1042
|
+
throw new Error('Native notices check needs a Rust toolchain on the coordinator; install rustup or run `tsrust notices`');
|
|
1043
|
+
}
|
|
1044
|
+
envPrefix = toolchainManager.getEnvPrefix();
|
|
1045
|
+
}
|
|
1046
|
+
const generator = await createProjectNoticesGenerator({
|
|
1047
|
+
projectDir: this.workspace,
|
|
1048
|
+
rustDir: await this.detectRustDirectory(),
|
|
1049
|
+
config: this.config,
|
|
1050
|
+
staticLinking: this.config.static === true,
|
|
1051
|
+
envPrefix,
|
|
1052
|
+
install: false,
|
|
1053
|
+
});
|
|
1054
|
+
const bundle = await generator.check();
|
|
1055
|
+
console.log(`Verified native notices: ${path.relative(this.workspace, bundle.directory)}`);
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1014
1058
|
private workerVerificationArgs(workerArg: IResolvedMatrixWorker): string[] {
|
|
1015
1059
|
const bootstrap = "import { ToolchainManager } from './node_modules/@git.zone/tsrust/dist_ts/mod_toolchain/index.js'; await new ToolchainManager().ensureInstalled();";
|
|
1016
1060
|
return [
|