@scriptc/compiler 0.0.35 → 0.1.1
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/ambient/scriptc-node-fallback.d.ts +14 -11
- package/ambient/scriptc-overrides.d.ts +0 -7
- package/ambient/scriptc.d.ts +1 -1
- package/dist/backend/build-cache.d.ts +44 -0
- package/dist/backend/build-cache.js +241 -0
- package/dist/backend/build-cache.js.map +1 -0
- package/dist/backend/{emission/emit-async.d.ts → c/async.d.ts} +21 -30
- package/dist/backend/{emission/emit-async.js → c/async.js} +270 -286
- package/dist/backend/c/async.js.map +1 -0
- package/dist/backend/{emission/emitter.d.ts → c/c-emitter.d.ts} +6 -23
- package/dist/backend/{emission/emitter.js → c/c-emitter.js} +53 -107
- package/dist/backend/c/c-emitter.js.map +1 -0
- package/dist/backend/c/exprs.d.ts +8 -0
- package/dist/backend/c/exprs.js +7937 -0
- package/dist/backend/c/exprs.js.map +1 -0
- package/dist/backend/{emission/emit-island.d.ts → c/island.d.ts} +5 -5
- package/dist/backend/{emission/emit-island.js → c/island.js} +24 -22
- package/dist/backend/c/island.js.map +1 -0
- package/dist/backend/{emission → c}/may-throw.d.ts +1 -1
- package/dist/backend/{emission → c}/may-throw.js +4 -1
- package/dist/backend/c/may-throw.js.map +1 -0
- package/dist/backend/{emission/emit-shapes.d.ts → c/shapes.d.ts} +19 -19
- package/dist/backend/{emission/emit-shapes.js → c/shapes.js} +78 -87
- package/dist/backend/c/shapes.js.map +1 -0
- package/dist/backend/{emission/emit-stmts.d.ts → c/stmts.d.ts} +12 -12
- package/dist/backend/{emission/emit-stmts.js → c/stmts.js} +395 -343
- package/dist/backend/c/stmts.js.map +1 -0
- package/dist/backend/{emission/emit-types.d.ts → c/types.d.ts} +1 -1
- package/dist/backend/{emission/emit-types.js → c/types.js} +42 -286
- package/dist/backend/c/types.js.map +1 -0
- package/dist/backend/c/types.test.js +25 -0
- package/dist/backend/c/types.test.js.map +1 -0
- package/dist/backend/{emission/emit-walkers.d.ts → c/walkers.d.ts} +19 -41
- package/dist/backend/{emission/emit-walkers.js → c/walkers.js} +242 -304
- package/dist/backend/c/walkers.js.map +1 -0
- package/dist/backend/external-c.d.ts +33 -0
- package/dist/backend/external-c.js +51 -0
- package/dist/backend/external-c.js.map +1 -0
- package/dist/backend/ffi-callbacks.d.ts +1 -1
- package/dist/backend/ffi-callbacks.js +4 -3
- package/dist/backend/ffi-callbacks.js.map +1 -1
- package/dist/backend/{library-identity.d.ts → library-identity-markers.d.ts} +0 -4
- package/dist/backend/{library-identity.js → library-identity-markers.js} +10 -9
- package/dist/backend/library-identity-markers.js.map +1 -0
- package/dist/backend/link-plan.d.ts +37 -0
- package/dist/backend/link-plan.js +26 -0
- package/dist/backend/link-plan.js.map +1 -0
- package/dist/backend/linker.d.ts +22 -0
- package/dist/backend/linker.js +236 -0
- package/dist/backend/linker.js.map +1 -0
- package/dist/backend/llvm/blocks.d.ts +4 -0
- package/dist/backend/llvm/blocks.js +29 -0
- package/dist/backend/llvm/blocks.js.map +1 -1
- package/dist/backend/llvm/classes.d.ts +2 -19
- package/dist/backend/llvm/classes.js +20 -52
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/common.d.ts +4 -0
- package/dist/backend/llvm/common.js +27 -0
- package/dist/backend/llvm/common.js.map +1 -0
- package/dist/backend/llvm/dyn.d.ts +3 -8
- package/dist/backend/llvm/dyn.js +159 -224
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +4 -1
- package/dist/backend/llvm/emitter.js +548 -9988
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/expr-async.d.ts +4 -0
- package/dist/backend/llvm/expr-async.js +726 -0
- package/dist/backend/llvm/expr-async.js.map +1 -0
- package/dist/backend/llvm/expr-bytes.d.ts +13 -0
- package/dist/backend/llvm/expr-bytes.js +456 -0
- package/dist/backend/llvm/expr-bytes.js.map +1 -0
- package/dist/backend/llvm/expr-callbacks.d.ts +22 -0
- package/dist/backend/llvm/expr-callbacks.js +520 -0
- package/dist/backend/llvm/expr-callbacks.js.map +1 -0
- package/dist/backend/llvm/expr-calls.d.ts +2 -0
- package/dist/backend/llvm/expr-calls.js +618 -0
- package/dist/backend/llvm/expr-calls.js.map +1 -0
- package/dist/backend/llvm/expr-containers.d.ts +25 -0
- package/dist/backend/llvm/expr-containers.js +637 -0
- package/dist/backend/llvm/expr-containers.js.map +1 -0
- package/dist/backend/llvm/expr-context.d.ts +255 -0
- package/dist/backend/llvm/expr-context.js +2 -0
- package/dist/backend/llvm/expr-context.js.map +1 -0
- package/dist/backend/llvm/expr-control.d.ts +2 -0
- package/dist/backend/llvm/expr-control.js +473 -0
- package/dist/backend/llvm/expr-control.js.map +1 -0
- package/dist/backend/llvm/expr-dispatch.d.ts +4 -0
- package/dist/backend/llvm/expr-dispatch.js +153 -0
- package/dist/backend/llvm/expr-dispatch.js.map +1 -0
- package/dist/backend/llvm/expr-dynamic.d.ts +2 -0
- package/dist/backend/llvm/expr-dynamic.js +810 -0
- package/dist/backend/llvm/expr-dynamic.js.map +1 -0
- package/dist/backend/llvm/expr-island.d.ts +15 -0
- package/dist/backend/llvm/expr-island.js +690 -0
- package/dist/backend/llvm/expr-island.js.map +1 -0
- package/dist/backend/llvm/expr-primitives.d.ts +6 -0
- package/dist/backend/llvm/expr-primitives.js +642 -0
- package/dist/backend/llvm/expr-primitives.js.map +1 -0
- package/dist/backend/llvm/expr-records.d.ts +9 -0
- package/dist/backend/llvm/expr-records.js +299 -0
- package/dist/backend/llvm/expr-records.js.map +1 -0
- package/dist/backend/llvm/expr-stream-bridges.d.ts +13 -0
- package/dist/backend/llvm/expr-stream-bridges.js +420 -0
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -0
- package/dist/backend/llvm/expr-stream-callbacks.d.ts +12 -0
- package/dist/backend/llvm/expr-stream-callbacks.js +360 -0
- package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -0
- package/dist/backend/llvm/lib-dispatch.d.ts +5 -0
- package/dist/backend/llvm/lib-dispatch.js +267 -0
- package/dist/backend/llvm/lib-dispatch.js.map +1 -0
- package/dist/backend/llvm/lib-filesystem.d.ts +6 -0
- package/dist/backend/llvm/lib-filesystem.js +594 -0
- package/dist/backend/llvm/lib-filesystem.js.map +1 -0
- package/dist/backend/llvm/lib-network.d.ts +2 -0
- package/dist/backend/llvm/lib-network.js +429 -0
- package/dist/backend/llvm/lib-network.js.map +1 -0
- package/dist/backend/llvm/lib-process.d.ts +5 -0
- package/dist/backend/llvm/lib-process.js +585 -0
- package/dist/backend/llvm/lib-process.js.map +1 -0
- package/dist/backend/llvm/lib-shared.d.ts +6 -0
- package/dist/backend/llvm/lib-shared.js +687 -0
- package/dist/backend/llvm/lib-shared.js.map +1 -0
- package/dist/backend/llvm/lib-stream.d.ts +2 -0
- package/dist/backend/llvm/lib-stream.js +470 -0
- package/dist/backend/llvm/lib-stream.js.map +1 -0
- package/dist/backend/llvm/shapes.d.ts +12 -2
- package/dist/backend/llvm/shapes.js +66 -307
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/shapes.test.js +52 -0
- package/dist/backend/llvm/shapes.test.js.map +1 -0
- package/dist/backend/llvm/unsupported.d.ts +1 -1
- package/dist/backend/llvm/walkers.d.ts +2 -3
- package/dist/backend/llvm/walkers.js +195 -222
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/backend/native-codegen.d.ts +45 -0
- package/dist/backend/native-codegen.js +275 -0
- package/dist/backend/native-codegen.js.map +1 -0
- package/dist/backend/native-codegen.test.js +226 -0
- package/dist/backend/native-codegen.test.js.map +1 -0
- package/dist/backend/native-link-info.d.ts +96 -0
- package/dist/backend/native-link-info.js +243 -0
- package/dist/backend/native-link-info.js.map +1 -0
- package/dist/backend/native-link-info.test.d.ts +1 -0
- package/dist/backend/native-link-info.test.js +134 -0
- package/dist/backend/native-link-info.test.js.map +1 -0
- package/dist/backend/{cc.d.ts → native-toolchain.d.ts} +54 -34
- package/dist/backend/{cc.js → native-toolchain.js} +231 -810
- package/dist/backend/native-toolchain.js.map +1 -0
- package/dist/backend/native-toolchain.test.d.ts +1 -0
- package/dist/backend/{cc-cache.test.js → native-toolchain.test.js} +219 -7
- package/dist/backend/native-toolchain.test.js.map +1 -0
- package/dist/backend/object-localize.js +1 -1
- package/dist/backend/runtime-abi.d.ts +10 -0
- package/dist/backend/runtime-abi.js +11 -0
- package/dist/backend/runtime-abi.js.map +1 -0
- package/dist/backend/runtime-pack-targets.test.d.ts +1 -0
- package/dist/backend/runtime-pack-targets.test.js +54 -0
- package/dist/backend/runtime-pack-targets.test.js.map +1 -0
- package/dist/backend/runtime-pack.d.ts +112 -0
- package/dist/backend/runtime-pack.js +305 -0
- package/dist/backend/runtime-pack.js.map +1 -0
- package/dist/backend/runtime-pack.test.d.ts +1 -0
- package/dist/backend/runtime-pack.test.js +473 -0
- package/dist/backend/runtime-pack.test.js.map +1 -0
- package/dist/backend/targets.d.ts +76 -0
- package/dist/backend/targets.js +262 -0
- package/dist/backend/targets.js.map +1 -0
- package/dist/backend/targets.test.d.ts +1 -0
- package/dist/backend/targets.test.js +41 -0
- package/dist/backend/targets.test.js.map +1 -0
- package/dist/backend/vendor-archives.d.ts +41 -0
- package/dist/backend/vendor-archives.js +462 -0
- package/dist/backend/vendor-archives.js.map +1 -0
- package/dist/compat/fetch-profile.d.ts +0 -1
- package/dist/compat/fetch-profile.js +0 -1
- package/dist/compat/fetch-profile.js.map +1 -1
- package/dist/coverage/report.js +3 -3
- package/dist/coverage/report.js.map +1 -1
- package/dist/coverage/surface-manifest.js +35 -33
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +11 -12
- package/dist/diagnostics/diagnostic.js +19 -17
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/diagnostics/render.d.ts +1 -1
- package/dist/diagnostics/render.js +1 -1
- package/dist/diagnostics/render.js.map +1 -1
- package/dist/errors.d.ts +5 -0
- package/dist/errors.js +9 -0
- package/dist/errors.js.map +1 -0
- package/dist/executable/{early-cache.d.ts → executable-cache.d.ts} +2 -2
- package/dist/executable/{early-cache.js → executable-cache.js} +36 -98
- package/dist/executable/executable-cache.js.map +1 -0
- package/dist/executable/executable-cache.test.d.ts +1 -0
- package/dist/executable/{early-cache.test.js → executable-cache.test.js} +3 -3
- package/dist/executable/executable-cache.test.js.map +1 -0
- package/dist/ffi/{profile.js → ffi-manifest.js} +1 -1
- package/dist/ffi/ffi-manifest.js.map +1 -0
- package/dist/frontend/builtin-modules.d.ts +21 -0
- package/dist/frontend/builtin-modules.js +82 -0
- package/dist/frontend/builtin-modules.js.map +1 -0
- package/dist/frontend/cjs-lexer.d.ts +7 -0
- package/dist/frontend/cjs-lexer.js +15 -17
- package/dist/frontend/cjs-lexer.js.map +1 -1
- package/dist/frontend/dts-paths.d.ts +26 -0
- package/dist/frontend/dts-paths.js +41 -0
- package/dist/frontend/dts-paths.js.map +1 -0
- package/dist/frontend/input-tracker.d.ts +0 -2
- package/dist/frontend/input-tracker.js +1 -4
- package/dist/frontend/input-tracker.js.map +1 -1
- package/dist/frontend/lib-contract.d.ts +1 -5
- package/dist/frontend/lib-contract.js +1 -1
- package/dist/frontend/lib-contract.js.map +1 -1
- package/dist/frontend/lib-exports.d.ts +1 -1
- package/dist/frontend/lowering/array-values.d.ts +8 -0
- package/dist/frontend/lowering/array-values.js +60 -0
- package/dist/frontend/lowering/array-values.js.map +1 -0
- package/dist/frontend/lowering/call-position.d.ts +4 -0
- package/dist/frontend/lowering/call-position.js +7 -0
- package/dist/frontend/lowering/call-position.js.map +1 -0
- package/dist/frontend/lowering/callback-arg.d.ts +20 -0
- package/dist/frontend/lowering/callback-arg.js +44 -0
- package/dist/frontend/lowering/callback-arg.js.map +1 -0
- package/dist/frontend/lowering/lib-boundary.d.ts +1 -1
- package/dist/frontend/lowering/lib-boundary.js +34 -34
- package/dist/frontend/lowering/lib-boundary.js.map +1 -1
- package/dist/frontend/lowering/lower-array-sort.d.ts +22 -0
- package/dist/frontend/lowering/lower-array-sort.js +619 -0
- package/dist/frontend/lowering/lower-array-sort.js.map +1 -0
- package/dist/frontend/lowering/lower-assert.d.ts +3 -3
- package/dist/frontend/lowering/lower-assert.js +214 -241
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +74 -146
- package/dist/frontend/lowering/lower-builtins.js +1285 -1233
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +59 -192
- package/dist/frontend/lowering/lower-calls.js +1644 -1506
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +62 -125
- package/dist/frontend/lowering/lower-classes.js +832 -866
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-comptime.d.ts +5 -12
- package/dist/frontend/lowering/lower-comptime.js +32 -31
- package/dist/frontend/lowering/lower-comptime.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +35 -135
- package/dist/frontend/lowering/lower-containers.js +1984 -2227
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-dgram.d.ts +3 -7
- package/dist/frontend/lowering/lower-dgram.js +97 -111
- package/dist/frontend/lowering/lower-dgram.js.map +1 -1
- package/dist/frontend/lowering/lower-enums.d.ts +4 -4
- package/dist/frontend/lowering/lower-enums.js +30 -30
- package/dist/frontend/lowering/lower-enums.js.map +1 -1
- package/dist/frontend/lowering/{lower-emitter.d.ts → lower-event-emitter.d.ts} +7 -18
- package/dist/frontend/lowering/{lower-emitter.js → lower-event-emitter.js} +172 -174
- package/dist/frontend/lowering/lower-event-emitter.js.map +1 -0
- package/dist/frontend/lowering/lower-expando.d.ts +5 -5
- package/dist/frontend/lowering/lower-expando.js +40 -40
- package/dist/frontend/lowering/lower-expando.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +60 -264
- package/dist/frontend/lowering/lower-exprs.js +2361 -1765
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.d.ts +6 -6
- package/dist/frontend/lowering/lower-generators.js +73 -72
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.d.ts +5 -17
- package/dist/frontend/lowering/lower-inspect.js +273 -261
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +39 -49
- package/dist/frontend/lowering/lower-island.js +447 -513
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-mixins.d.ts +7 -10
- package/dist/frontend/lowering/lower-mixins.js +85 -85
- package/dist/frontend/lowering/lower-mixins.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.d.ts +12 -18
- package/dist/frontend/lowering/lower-modules.js +284 -283
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-namespaces.d.ts +23 -49
- package/dist/frontend/lowering/lower-namespaces.js +123 -115
- package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
- package/dist/frontend/lowering/lower-server.d.ts +18 -25
- package/dist/frontend/lowering/lower-server.js +909 -899
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +30 -149
- package/dist/frontend/lowering/lower-stmts.js +1463 -1285
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.d.ts +12 -12
- package/dist/frontend/lowering/lower-stream.js +300 -301
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lower-test.d.ts +5 -5
- package/dist/frontend/lowering/lower-test.js +82 -82
- package/dist/frontend/lowering/lower-test.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +134 -22
- package/dist/frontend/lowering/lowerer.js +1277 -126
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/pairs-snapshot.d.ts +11 -0
- package/dist/frontend/lowering/pairs-snapshot.js +85 -0
- package/dist/frontend/lowering/pairs-snapshot.js.map +1 -0
- package/dist/frontend/lowering/static-this.d.ts +6 -0
- package/dist/frontend/lowering/static-this.js +24 -0
- package/dist/frontend/lowering/static-this.js.map +1 -0
- package/dist/frontend/lowering/surfaces.d.ts +24 -35
- package/dist/frontend/lowering/surfaces.js +78 -66
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/npm-static-rewrite.js +6 -28
- package/dist/frontend/npm-static-rewrite.js.map +1 -1
- package/dist/frontend/npm-static.d.ts +0 -10
- package/dist/frontend/npm-static.js +4 -7
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/npm.d.ts +0 -24
- package/dist/frontend/npm.js +11 -85
- package/dist/frontend/npm.js.map +1 -1
- package/dist/frontend/program.d.ts +3 -1
- package/dist/frontend/program.js +9 -4
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/provenance-registry.d.ts +0 -2
- package/dist/frontend/provenance-registry.js +0 -10
- package/dist/frontend/provenance-registry.js.map +1 -1
- package/dist/frontend/provenance.js +4 -7
- package/dist/frontend/provenance.js.map +1 -1
- package/dist/frontend/resolve.d.ts +7 -2
- package/dist/frontend/resolve.js +12 -17
- package/dist/frontend/resolve.js.map +1 -1
- package/dist/frontend/resolve.test.d.ts +1 -0
- package/dist/frontend/resolve.test.js +29 -0
- package/dist/frontend/resolve.test.js.map +1 -0
- package/dist/frontend/ts7/adapter.d.ts +2 -2
- package/dist/frontend/ts7/adapter.js +1 -1
- package/dist/frontend/ts7/adapter.js.map +1 -1
- package/dist/frontend/ts7/checker.js +2 -36
- package/dist/frontend/ts7/checker.js.map +1 -1
- package/dist/frontend/ts7/enums.js +2 -1
- package/dist/frontend/ts7/enums.js.map +1 -1
- package/dist/frontend/ts7/{program.js → program-adapter.js} +7 -6
- package/dist/frontend/ts7/program-adapter.js.map +1 -0
- package/dist/frontend/ts7/world-check.d.ts +1 -3
- package/dist/frontend/ts7/world-check.js +3 -1
- package/dist/frontend/ts7/world-check.js.map +1 -1
- package/dist/frontend/tsc-codes.d.ts +8 -0
- package/dist/frontend/tsc-codes.js +109 -0
- package/dist/frontend/tsc-codes.js.map +1 -0
- package/dist/frontend/{types.d.ts → type-mapper.d.ts} +2 -25
- package/dist/frontend/{types.js → type-mapper.js} +12 -11
- package/dist/frontend/type-mapper.js.map +1 -0
- package/dist/frontend/workspace-registry.d.ts +26 -0
- package/dist/frontend/workspace-registry.js +71 -0
- package/dist/frontend/workspace-registry.js.map +1 -0
- package/dist/index.d.ts +113 -31
- package/dist/index.js +536 -128
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.d.ts +37 -0
- package/dist/ir/analysis.js +118 -0
- package/dist/ir/analysis.js.map +1 -0
- package/dist/ir/analysis.test.d.ts +1 -0
- package/dist/ir/analysis.test.js +21 -0
- package/dist/ir/analysis.test.js.map +1 -0
- package/dist/ir/build.d.ts +9 -0
- package/dist/ir/build.js +33 -0
- package/dist/ir/build.js.map +1 -0
- package/dist/ir/integer-loops.d.ts +1 -1
- package/dist/ir/{nodes.d.ts → ir.d.ts} +119 -37
- package/dist/ir/{nodes.js → ir.js} +170 -166
- package/dist/ir/ir.js.map +1 -0
- package/dist/ir/ir.test.d.ts +1 -0
- package/dist/ir/ir.test.js +17 -0
- package/dist/ir/ir.test.js.map +1 -0
- package/dist/ir/serialize.d.ts +2 -2
- package/dist/ir/serialize.js +3 -2
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/validate.d.ts +1 -1
- package/dist/ir/validate.js +93 -41
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/cache-primitives.d.ts +24 -0
- package/dist/library/cache-primitives.js +83 -0
- package/dist/library/cache-primitives.js.map +1 -0
- package/dist/library/cache-reset.test.d.ts +1 -0
- package/dist/library/cache-reset.test.js +47 -0
- package/dist/library/cache-reset.test.js.map +1 -0
- package/dist/library/{implementation-identity.js → compiler-self-identity.js} +1 -1
- package/dist/library/compiler-self-identity.js.map +1 -0
- package/dist/library/fence-eval.d.ts +3 -1
- package/dist/library/fence-eval.js +8 -2
- package/dist/library/fence-eval.js.map +1 -1
- package/dist/library/int-infer.d.ts +1 -36
- package/dist/library/int-infer.js +29 -18
- package/dist/library/int-infer.js.map +1 -1
- package/dist/library/int-infer.test.js +4 -4
- package/dist/library/{early-cache.d.ts → library-cache.d.ts} +1 -1
- package/dist/library/{early-cache.js → library-cache.js} +34 -89
- package/dist/library/library-cache.js.map +1 -0
- package/dist/library/library-cache.test.d.ts +1 -0
- package/dist/library/{early-cache.test.js → library-cache.test.js} +7 -7
- package/dist/library/library-cache.test.js.map +1 -0
- package/dist/library/{profile.d.ts → library-profile.d.ts} +4 -7
- package/dist/library/{profile.js → library-profile.js} +18 -11
- package/dist/library/library-profile.js.map +1 -0
- package/dist/library/semantic-source.js +2 -1
- package/dist/library/semantic-source.js.map +1 -1
- package/dist/library/sidecar.d.ts +5 -2
- package/dist/library/sidecar.js +11 -5
- package/dist/library/sidecar.js.map +1 -1
- package/dist/startup-cache.d.ts +11 -3
- package/dist/startup-cache.js +17 -2
- package/dist/startup-cache.js.map +1 -1
- package/package.json +19 -2
- package/surface-manifest.json +5 -5
- package/dist/backend/cc-cache.test.js.map +0 -1
- package/dist/backend/cc.js.map +0 -1
- package/dist/backend/emission/emit-async.js.map +0 -1
- package/dist/backend/emission/emit-exprs.d.ts +0 -13
- package/dist/backend/emission/emit-exprs.js +0 -7407
- package/dist/backend/emission/emit-exprs.js.map +0 -1
- package/dist/backend/emission/emit-island.js.map +0 -1
- package/dist/backend/emission/emit-shapes.js.map +0 -1
- package/dist/backend/emission/emit-stmts.js.map +0 -1
- package/dist/backend/emission/emit-types.js.map +0 -1
- package/dist/backend/emission/emit-walkers.js.map +0 -1
- package/dist/backend/emission/emitter.js.map +0 -1
- package/dist/backend/emission/may-throw.js.map +0 -1
- package/dist/backend/library-identity.js.map +0 -1
- package/dist/executable/early-cache.js.map +0 -1
- package/dist/executable/early-cache.test.js.map +0 -1
- package/dist/ffi/profile.js.map +0 -1
- package/dist/frontend/lowering/lower-emitter.js.map +0 -1
- package/dist/frontend/shared.d.ts +0 -82
- package/dist/frontend/shared.js +0 -308
- package/dist/frontend/shared.js.map +0 -1
- package/dist/frontend/ts7/program.js.map +0 -1
- package/dist/frontend/types.js.map +0 -1
- package/dist/ir/nodes.js.map +0 -1
- package/dist/library/early-cache.js.map +0 -1
- package/dist/library/early-cache.test.js.map +0 -1
- package/dist/library/implementation-identity.js.map +0 -1
- package/dist/library/profile.js.map +0 -1
- /package/dist/backend/{cc-cache.test.d.ts → c/types.test.d.ts} +0 -0
- /package/dist/{executable/early-cache.test.d.ts → backend/llvm/shapes.test.d.ts} +0 -0
- /package/dist/{library/early-cache.test.d.ts → backend/native-codegen.test.d.ts} +0 -0
- /package/dist/ffi/{profile.d.ts → ffi-manifest.d.ts} +0 -0
- /package/dist/frontend/ts7/{program.d.ts → program-adapter.d.ts} +0 -0
- /package/dist/library/{implementation-identity.d.ts → compiler-self-identity.d.ts} +0 -0
|
@@ -1,16 +1,25 @@
|
|
|
1
|
+
import { InternalCompilerError } from "../errors.js";
|
|
1
2
|
import { execFile, spawnSync } from "node:child_process";
|
|
2
3
|
import { createHash, randomUUID } from "node:crypto";
|
|
3
4
|
import { constants as fsConstants, existsSync, readdirSync } from "node:fs";
|
|
4
5
|
import { createRequire } from "node:module";
|
|
5
|
-
import { access, chmod, copyFile, link, lstat, mkdir, mkdtemp, readdir, readFile, realpath, rename, rm, stat,
|
|
6
|
+
import { access, chmod, copyFile, link, lstat, mkdir, mkdtemp, readdir, readFile, realpath, rename, rm, stat, utimes, writeFile } from "node:fs/promises";
|
|
6
7
|
import { availableParallelism, homedir, tmpdir } from "node:os";
|
|
7
8
|
import { basename, delimiter, dirname, extname, isAbsolute, join, relative, resolve } from "node:path";
|
|
8
9
|
import { performance } from "node:perf_hooks";
|
|
9
10
|
import { fileURLToPath } from "node:url";
|
|
10
11
|
import { promisify } from "node:util";
|
|
11
12
|
import { localizeElfObject, mergeAndLocalizeCoffObjects } from "./object-localize.js";
|
|
13
|
+
import { createVendorArchives, MBEDTLS_VERSION, QJS_COMMIT, ZLIB_VERSION, } from "./vendor-archives.js";
|
|
14
|
+
import { cacheDigestPath, cacheRootDir, copyValidCachedFile, ensurePrivateCacheRoot, fileDigest, fileExists, installArtifact, privateSiblingPath, protectCachedArtifact, pruneCache, publishCachedFile, validCachedFile, } from "./build-cache.js";
|
|
15
|
+
export { buildCacheRoot, prepareBuildCacheRoot, pruneBuildCache, resolveBuildCacheRoot, } from "./build-cache.js";
|
|
12
16
|
const execFileAsync = promisify(execFile);
|
|
13
|
-
const
|
|
17
|
+
const NATIVE_TOOLCHAIN_IMPLEMENTATION_PATH = fileURLToPath(import.meta.url);
|
|
18
|
+
const NATIVE_RECIPE_IMPLEMENTATION_PATHS = [
|
|
19
|
+
NATIVE_TOOLCHAIN_IMPLEMENTATION_PATH,
|
|
20
|
+
join(dirname(NATIVE_TOOLCHAIN_IMPLEMENTATION_PATH), `build-cache${extname(NATIVE_TOOLCHAIN_IMPLEMENTATION_PATH)}`),
|
|
21
|
+
join(dirname(NATIVE_TOOLCHAIN_IMPLEMENTATION_PATH), `vendor-archives${extname(NATIVE_TOOLCHAIN_IMPLEMENTATION_PATH)}`),
|
|
22
|
+
];
|
|
14
23
|
/** Test lanes run against one immutable checkout and one immutable toolchain
|
|
15
24
|
* for the lifetime of each Vitest worker. Production deliberately rediscovers
|
|
16
25
|
* compiler/linker inputs on every invocation, but doing that thousands of
|
|
@@ -35,22 +44,43 @@ function stableTestMemo(cache, key, probe) {
|
|
|
35
44
|
});
|
|
36
45
|
return pending;
|
|
37
46
|
}
|
|
38
|
-
const
|
|
39
|
-
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
47
|
+
export const EXECUTABLE_RUNTIME_SOURCES = ["scr_number.c", "scr_string.c", "scr_array.c", "scr_bytes.c", "scr_bytes_io.c", "scr_map.c", "scr_closure.c", "scr_ffi.c", "scr_object.c", "scr_union.c", "scr_exception.c", "scr_error.c", "scr_console.c", "scr_lib.c", "scr_path.c", "scr_url.c", "scr_json.c", "scr_async.c", "scr_child.c", "scr_cycle.c"];
|
|
48
|
+
/**
|
|
49
|
+
* Per-executable section-elimination recipe. This belongs beside the native
|
|
50
|
+
* driver rather than a particular build path: one-shot compilation, cached
|
|
51
|
+
* runtime objects, external object recipes, and runtime packs must all agree
|
|
52
|
+
* on what their final executable linker is allowed to discard.
|
|
53
|
+
*
|
|
54
|
+
* Archives and compile-only object/library recipes deliberately do not use
|
|
55
|
+
* the link half. In particular, `--lib` preserves its established object and
|
|
56
|
+
* archive contract; section GC is an executable-link optimization only.
|
|
57
|
+
*/
|
|
58
|
+
export function executableSectionEliminationFlags(platform) {
|
|
59
|
+
switch (platform) {
|
|
60
|
+
case "darwin":
|
|
61
|
+
// ld64's symbol subsections make this sufficient for ordinary C/LLVM
|
|
62
|
+
// objects. Do not attach it only to --dynamic: static programs have the
|
|
63
|
+
// same unreachable runtime sections.
|
|
64
|
+
return { compile: [], link: ["-Wl,-dead_strip"] };
|
|
65
|
+
case "linux":
|
|
66
|
+
return {
|
|
67
|
+
compile: ["-ffunction-sections", "-fdata-sections"],
|
|
68
|
+
link: ["-Wl,--gc-sections"],
|
|
69
|
+
};
|
|
70
|
+
case "win32":
|
|
71
|
+
// clang's MinGW driver forwards this to GNU-flavor ld/lld. A direct
|
|
72
|
+
// local lld-link invocation instead uses /OPT:REF, but scriptc only
|
|
73
|
+
// drives the compiler's GNU-flavor route here.
|
|
74
|
+
return {
|
|
75
|
+
compile: ["-ffunction-sections", "-fdata-sections"],
|
|
76
|
+
link: ["-Wl,--gc-sections"],
|
|
77
|
+
};
|
|
78
|
+
// WASI has a distinct linker/runtime contract. Keep its existing object
|
|
79
|
+
// layout until its linker invocation is validated separately.
|
|
80
|
+
default:
|
|
81
|
+
return { compile: [], link: [] };
|
|
82
|
+
}
|
|
83
|
+
}
|
|
54
84
|
/** Environment variables consumed by clang, its linker/subtools, or the
|
|
55
85
|
* platform SDK selection. They are implicit command-line inputs: changing one
|
|
56
86
|
* must never reuse an artifact produced under the old toolchain posture. */
|
|
@@ -227,6 +257,12 @@ export function runtimeSrcDir() {
|
|
|
227
257
|
const require = createRequire(import.meta.url);
|
|
228
258
|
return join(dirname(require.resolve("@scriptc/runtime/package.json")), "src");
|
|
229
259
|
}
|
|
260
|
+
/** Whether the selected compiler driver is Zig. This is deliberately based on
|
|
261
|
+
* the executable prefix rather than target presence: targetless Zig is still
|
|
262
|
+
* a Zig build, while target presence is only the platform/target contract. */
|
|
263
|
+
export function isZigDriver(driver) {
|
|
264
|
+
return driver.argv[0] === "zig";
|
|
265
|
+
}
|
|
230
266
|
/* ── mobile targets (library mode) ─────────────────────────────────────────
|
|
231
267
|
* Three mobile triples are admitted, and only for LIBRARY-MODE archive
|
|
232
268
|
* builds — the consuming pattern is an embedding app linking the archive,
|
|
@@ -424,9 +460,9 @@ export function resolveCc(env = process.env, hostPlatform = process.platform) {
|
|
|
424
460
|
}
|
|
425
461
|
if (target === "")
|
|
426
462
|
return { argv: ["zig", "cc"], target: null, zigTarget: null, ...hostArgs };
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
463
|
+
// Validate the target spelling before any SDK/sysroot discovery. Source
|
|
464
|
+
// emission uses the same pure classifier without resolving this driver.
|
|
465
|
+
configuredTargetPlatform(env, hostPlatform);
|
|
430
466
|
const mobileRefusal = mobileTargetRefusal(target, hostPlatform);
|
|
431
467
|
if (mobileRefusal !== null)
|
|
432
468
|
throw new Error(mobileRefusal);
|
|
@@ -497,7 +533,7 @@ export function resolveCc(env = process.env, hostPlatform = process.platform) {
|
|
|
497
533
|
}
|
|
498
534
|
/** Musl intentionally has no predefined libc macro. The explicit Zig target
|
|
499
535
|
* is therefore the source of truth for selecting its small runtime shim. */
|
|
500
|
-
|
|
536
|
+
function isMuslTarget(driver) {
|
|
501
537
|
return driver.target?.includes("linux-musl") ?? false;
|
|
502
538
|
}
|
|
503
539
|
/** The OS the produced binary runs on: the triple's OS under SCRIPTC_TARGET,
|
|
@@ -506,21 +542,37 @@ export function isMuslTarget(driver) {
|
|
|
506
542
|
* analyze(): the FRONTEND consults it too (path.sep / os.EOL literals and
|
|
507
543
|
* the path-module binding follow the target — a win32 triple compiles
|
|
508
544
|
* Node-on-Windows semantics, path.win32 backing the bare module). */
|
|
509
|
-
export function
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
545
|
+
export function configuredTargetPlatform(env = process.env, hostPlatform = process.platform) {
|
|
546
|
+
const target = env["SCRIPTC_TARGET"] ?? "";
|
|
547
|
+
if (target === "")
|
|
548
|
+
return hostPlatform;
|
|
549
|
+
if (target === "wasm32-wasi")
|
|
513
550
|
return "wasi";
|
|
551
|
+
if (target.includes("wasi")) {
|
|
552
|
+
throw new Error(`unsupported WASI target '${target}' (supported: wasm32-wasi)`);
|
|
553
|
+
}
|
|
514
554
|
// iOS is a darwin-family target: Mach-O objects, ld64 localization,
|
|
515
555
|
// POSIX path/EOL semantics. Android falls to the linux arm below —
|
|
516
556
|
// bionic is a linux libc and its archives are ordinary ELF.
|
|
517
|
-
if (isIosTarget(
|
|
557
|
+
if (isIosTarget(target))
|
|
518
558
|
return "darwin";
|
|
519
|
-
if (
|
|
559
|
+
if (isAndroidTarget(target))
|
|
520
560
|
return "linux";
|
|
521
|
-
if (
|
|
561
|
+
if (/(?:^|-)(?:ios|tvos|watchos|visionos|android)/.test(target)) {
|
|
562
|
+
throw new Error(`unsupported mobile target '${target}' (supported: ${MOBILE_LIBRARY_TARGETS.join(", ")})`);
|
|
563
|
+
}
|
|
564
|
+
if (target.includes("linux"))
|
|
565
|
+
return "linux";
|
|
566
|
+
if (target.includes("windows"))
|
|
522
567
|
return "win32";
|
|
523
|
-
|
|
568
|
+
if (target.includes("macos") || target.includes("darwin"))
|
|
569
|
+
return "darwin";
|
|
570
|
+
throw new Error(`unsupported target '${target}' (supported OS families: linux, windows, macos/darwin, wasm32-wasi)`);
|
|
571
|
+
}
|
|
572
|
+
export function targetPlatform(driver) {
|
|
573
|
+
if (driver.target === null)
|
|
574
|
+
return process.platform;
|
|
575
|
+
return configuredTargetPlatform({ SCRIPTC_TARGET: driver.target });
|
|
524
576
|
}
|
|
525
577
|
/** Architecture identity for host-native cache entries. Explicit cross targets
|
|
526
578
|
* already name their complete target triple; native builds need the process
|
|
@@ -529,472 +581,6 @@ export function targetPlatform(driver) {
|
|
|
529
581
|
export function cacheTargetIdentity(driver, hostPlatform = process.platform, hostArch = process.arch) {
|
|
530
582
|
return driver.target === null ? `native:${hostPlatform}:${hostArch}` : `cross:${driver.target}`;
|
|
531
583
|
}
|
|
532
|
-
function vendorEngineDir() {
|
|
533
|
-
return join(runtimeSrcDir(), "..", "vendor", "quickjs-ng");
|
|
534
|
-
}
|
|
535
|
-
/** Vendor prerequisites follow the per-user build root when persistent cache
|
|
536
|
-
* validation succeeds. Keeping generated objects out of node_modules makes
|
|
537
|
-
* npm installations, read-only package stores, and explicit cache warming all
|
|
538
|
-
* share one writable cache. The test-only override remains the first choice;
|
|
539
|
-
* callers without a validated root retain the historical package-local
|
|
540
|
-
* default (ordinary builds give those callers a private transient root). */
|
|
541
|
-
function vendorBuildCacheRoot(buildRoot) {
|
|
542
|
-
const testRoot = process.env["SCRIPTC_TEST_VENDOR_CACHE_DIR"];
|
|
543
|
-
if (testRoot !== undefined)
|
|
544
|
-
return resolve(testRoot);
|
|
545
|
-
return buildRoot === undefined
|
|
546
|
-
? join(runtimeSrcDir(), "..", "vendor", ".cache")
|
|
547
|
-
: join(buildRoot, "vendor");
|
|
548
|
-
}
|
|
549
|
-
/** Cross targets already carry their architecture in the explicit triple.
|
|
550
|
-
* Host-native prerequisites need the same separation: a checkout/package can
|
|
551
|
-
* be used by both arm64 Node and Rosetta/x64 Node on macOS. */
|
|
552
|
-
export function vendorCacheTargetFlavor(driver, hostPlatform = process.platform, hostArch = process.arch) {
|
|
553
|
-
return driver.target === null ? `native-${hostPlatform}-${hostArch}` : driver.target;
|
|
554
|
-
}
|
|
555
|
-
/** Vendor prerequisites live outside the content-addressed build root, so
|
|
556
|
-
* their directory name must carry the environment, resolved compiler, owned
|
|
557
|
-
* source bytes, and build-recipe identity of the artifacts that consume them.
|
|
558
|
-
* The short digest keeps the cache path readable while preventing build-order
|
|
559
|
-
* and cross-installation contamination. */
|
|
560
|
-
export function vendorCacheBuildIdentity(environmentFingerprint, compilerIdentity, nativeSourceIdentity) {
|
|
561
|
-
return createHash("sha256")
|
|
562
|
-
.update("vendor-toolchain-v2\0")
|
|
563
|
-
.update(environmentFingerprint)
|
|
564
|
-
.update("\0")
|
|
565
|
-
.update(compilerIdentity)
|
|
566
|
-
.update("\0")
|
|
567
|
-
.update(nativeSourceIdentity)
|
|
568
|
-
.digest("hex")
|
|
569
|
-
.slice(0, 20);
|
|
570
|
-
}
|
|
571
|
-
const vendorCompilerIdentityFallbacks = new Map();
|
|
572
|
-
async function currentVendorCacheBuildIdentity(driver, environmentFingerprint) {
|
|
573
|
-
// Native vendor recipes additionally use bare clang/ar; cross
|
|
574
|
-
// recipes use the zig driver for compilation and `zig ar`. Include every
|
|
575
|
-
// executable that can affect the cached prerequisite, not just the
|
|
576
|
-
// final program's driver.
|
|
577
|
-
const commands = [
|
|
578
|
-
driver.argv[0] ?? "clang",
|
|
579
|
-
...(driver.target === null ? ["clang", "ar"] : []),
|
|
580
|
-
].filter((command, index, all) => all.indexOf(command) === index);
|
|
581
|
-
const identities = await Promise.all(commands.map(async (command) => {
|
|
582
|
-
const spellingKey = `${environmentFingerprint}\0${command}`;
|
|
583
|
-
const resolved = await resolvedToolIdentity(command);
|
|
584
|
-
if (resolved !== null)
|
|
585
|
-
vendorCompilerIdentityFallbacks.set(spellingKey, resolved);
|
|
586
|
-
return [
|
|
587
|
-
command,
|
|
588
|
-
resolved ??
|
|
589
|
-
vendorCompilerIdentityFallbacks.get(spellingKey) ??
|
|
590
|
-
`<unresolved>\0${command}`,
|
|
591
|
-
].join("\0");
|
|
592
|
-
}));
|
|
593
|
-
return vendorCacheBuildIdentity(environmentFingerprint, identities.join("\x1f"), await runtimeFingerprint(runtimeSrcDir()));
|
|
594
|
-
}
|
|
595
|
-
function engineArchivePath(sanitize, driver, buildIdentity, cacheRoot = vendorBuildCacheRoot()) {
|
|
596
|
-
const flavor = `${sanitize ? "asan" : "plain"}-${vendorCacheTargetFlavor(driver)}-${buildIdentity}`;
|
|
597
|
-
return join(cacheRoot, `${QJS_COMMIT.slice(0, 12)}-${flavor}`, "libqjs.a");
|
|
598
|
-
}
|
|
599
|
-
async function fileExists(path) {
|
|
600
|
-
return stat(path).then((s) => s.isFile(), () => false);
|
|
601
|
-
}
|
|
602
|
-
/** Vendor prerequisites are shared persistent cache entries, so they carry
|
|
603
|
-
* the same adjacent content digest as runtime objects and complete artifacts.
|
|
604
|
-
* Missing/invalid pairs are rebuilt. Do not remove them during validation: a
|
|
605
|
-
* concurrent publisher installs data before its digest, and that temporary
|
|
606
|
-
* invalid window must not let a reader unlink the publisher's data. */
|
|
607
|
-
async function validVendorArtifact(path) {
|
|
608
|
-
return validCachedFile(path);
|
|
609
|
-
}
|
|
610
|
-
function protectCachedArtifact(paths, path) {
|
|
611
|
-
paths?.add(path);
|
|
612
|
-
paths?.add(cacheDigestPath(path));
|
|
613
|
-
}
|
|
614
|
-
function privateSiblingPath(destination, label) {
|
|
615
|
-
// Keep the temporary component independent of the caller's basename. A
|
|
616
|
-
// destination can validly consume the filesystem's entire NAME_MAX budget;
|
|
617
|
-
// appending or prepending that basename would make the atomic install fail.
|
|
618
|
-
return join(dirname(destination), `.scriptc-${label}-${process.pid}-${Math.random().toString(36).slice(2)}`);
|
|
619
|
-
}
|
|
620
|
-
/** Copy an artifact through a private sibling name, then atomically install it.
|
|
621
|
-
* The source can live on another filesystem (cache/temp roots commonly do), so
|
|
622
|
-
* a direct rename is not portable. */
|
|
623
|
-
async function installArtifact(source, destination, mode) {
|
|
624
|
-
await mkdir(dirname(destination), { recursive: true });
|
|
625
|
-
const tmp = privateSiblingPath(destination, "install");
|
|
626
|
-
try {
|
|
627
|
-
await copyFile(source, tmp);
|
|
628
|
-
if (mode !== undefined)
|
|
629
|
-
await chmod(tmp, mode);
|
|
630
|
-
await rename(tmp, destination);
|
|
631
|
-
}
|
|
632
|
-
finally {
|
|
633
|
-
await rm(tmp, { force: true }).catch(() => undefined);
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
/** Publish one finished vendor prerequisite from disposable build scratch.
|
|
637
|
-
* The shared data and digest use the ordinary atomic cache publisher.
|
|
638
|
-
* Concurrent builders produce equivalent bytes; on platforms where rename
|
|
639
|
-
* cannot replace the winner, accept only a checksum-verified winner. */
|
|
640
|
-
async function publishVendorArtifact(source, destination) {
|
|
641
|
-
for (let attempt = 0; attempt < 2; attempt++) {
|
|
642
|
-
try {
|
|
643
|
-
await publishCachedFile(source, destination);
|
|
644
|
-
}
|
|
645
|
-
catch (error) {
|
|
646
|
-
// A concurrent equivalent publisher may have won on a platform where
|
|
647
|
-
// rename cannot replace an existing file. Accept only its verified pair.
|
|
648
|
-
if (await validCachedFile(destination))
|
|
649
|
-
return;
|
|
650
|
-
if (attempt > 0)
|
|
651
|
-
throw error;
|
|
652
|
-
// Otherwise the existing pair is genuinely stale/corrupt and blocked
|
|
653
|
-
// replacement (notably on Windows). Remove it only after a complete
|
|
654
|
-
// replacement is ready in private scratch, then retry once.
|
|
655
|
-
await Promise.all([
|
|
656
|
-
rm(destination, { force: true }).catch(() => undefined),
|
|
657
|
-
rm(cacheDigestPath(destination), { force: true }).catch(() => undefined),
|
|
658
|
-
]);
|
|
659
|
-
continue;
|
|
660
|
-
}
|
|
661
|
-
// Close publication races where another writer replaced only one member
|
|
662
|
-
// of the pair between this publisher's two atomic renames.
|
|
663
|
-
if (await validCachedFile(destination))
|
|
664
|
-
return;
|
|
665
|
-
}
|
|
666
|
-
throw new Error(`vendor cache publication failed integrity validation: ${destination}`);
|
|
667
|
-
}
|
|
668
|
-
/** Pin cache-backed vendor inputs under an invocation-private directory before
|
|
669
|
-
* linking/archiving. The shared LRU may unlink their cache names at any time;
|
|
670
|
-
* hard links (or copies where links are unavailable) keep active inputs alive.
|
|
671
|
-
* A sweep can race the initial pin, so rematerialize and retry once. */
|
|
672
|
-
async function stageVendorInputs(materialize, stageDir) {
|
|
673
|
-
let lastError = new Error("vendor cache input disappeared while staging");
|
|
674
|
-
for (let attempt = 0; attempt < 2; attempt++) {
|
|
675
|
-
await rm(stageDir, { recursive: true, force: true }).catch(() => undefined);
|
|
676
|
-
await mkdir(stageDir, { recursive: true });
|
|
677
|
-
const sources = await materialize();
|
|
678
|
-
try {
|
|
679
|
-
const now = new Date();
|
|
680
|
-
return await Promise.all(sources.map(async (source) => {
|
|
681
|
-
const destination = join(stageDir, basename(source));
|
|
682
|
-
try {
|
|
683
|
-
await link(source, destination);
|
|
684
|
-
}
|
|
685
|
-
catch {
|
|
686
|
-
await copyFile(source, destination);
|
|
687
|
-
}
|
|
688
|
-
// Vendor prerequisites share the cache root's mtime-based LRU. A
|
|
689
|
-
// successful stage is a cache read, so promote the shared source name
|
|
690
|
-
// best-effort (it may have raced an eviction after the hard link).
|
|
691
|
-
await utimes(source, now, now).catch(() => undefined);
|
|
692
|
-
return destination;
|
|
693
|
-
}));
|
|
694
|
-
}
|
|
695
|
-
catch (error) {
|
|
696
|
-
lastError = error;
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
throw lastError;
|
|
700
|
-
}
|
|
701
|
-
/** The engine archive for one flavor, built lazily on the first --dynamic
|
|
702
|
-
* compile and cached under <build-cache>/vendor/<commit>-<flavor>-<target>-<toolchain>/ — unlike
|
|
703
|
-
* the runtime's own sources (recompiled every build, ~100ms), the engine is
|
|
704
|
-
* far too big to rebuild per compile. The plain flavor is ALWAYS MinSizeRel
|
|
705
|
-
* regardless of the program's optimization level: measured binary delta is
|
|
706
|
-
* ~620KB vs ~900KB at -O2, and eval-in-an-island workloads don't earn the
|
|
707
|
-
* difference. The asan flavor (Debug + QJS_ENABLE_ASAN) exists so the
|
|
708
|
-
* sanitized test lane checks engine interop under instrumentation.
|
|
709
|
-
*
|
|
710
|
-
* Concurrency: parallel first builds (e.g. test workers) each build in a
|
|
711
|
-
* private temp dir and publish with an atomic rename — first one wins,
|
|
712
|
-
* losers discard their work and use the winner's archive.
|
|
713
|
-
*
|
|
714
|
-
* The qjs library target is just four TUs (QJS_ENGINE_SOURCES), so both host
|
|
715
|
-
* and cross builds use the same direct per-TU recipe. This removes CMake from
|
|
716
|
-
* the runtime dependency set and lets cache warming compile exactly the
|
|
717
|
-
* archive a later program consumes. Host builds use clang + ar; cross builds
|
|
718
|
-
* use the selected zig driver + zig ar. */
|
|
719
|
-
async function ensureEngineArchive(sanitize, driver, buildIdentity, cacheRoot = vendorBuildCacheRoot()) {
|
|
720
|
-
const archive = engineArchivePath(sanitize, driver, buildIdentity, cacheRoot);
|
|
721
|
-
const cacheDir = dirname(archive);
|
|
722
|
-
if (await validVendorArtifact(archive))
|
|
723
|
-
return archive;
|
|
724
|
-
return buildEngineArchiveDirect(sanitize, driver, cacheRoot, cacheDir);
|
|
725
|
-
}
|
|
726
|
-
/** The qjs library target's source list (CMakeLists.txt `qjs_sources` with
|
|
727
|
-
* QJS_BUILD_LIBC off — cutils is header-only): the cross-build recipe
|
|
728
|
-
* compiles exactly these. */
|
|
729
|
-
const QJS_ENGINE_SOURCES = ["dtoa.c", "libregexp.c", "libunicode.c", "quickjs.c"];
|
|
730
|
-
/** The engine archive for one target, per-TU compiler invocations plus ar.
|
|
731
|
-
* The flags mirror what the former CMake
|
|
732
|
-
* configurations apply to the qjs library target: gnu11 (CMAKE_C_EXTENSIONS
|
|
733
|
-
* ON), hidden visibility, -funsigned-char, -DQUICKJS_NG_BUILD and
|
|
734
|
-
* -D_GNU_SOURCE (qjs_defines; linux targetArgs already carry the latter),
|
|
735
|
-
* then MinSizeRel (-Os -DNDEBUG) for plain or Debug+QJS_ENABLE_ASAN
|
|
736
|
-
* (-O0 -ggdb -fno-omit-frame-pointer -fsanitize=address
|
|
737
|
-
* -fno-sanitize-recover=all) for asan. Same atomic-rename publish as every
|
|
738
|
-
* vendor cache. */
|
|
739
|
-
async function buildEngineArchiveDirect(sanitize, driver, cacheRoot, cacheDir) {
|
|
740
|
-
const vendor = vendorEngineDir();
|
|
741
|
-
const archive = join(cacheDir, "libqjs.a");
|
|
742
|
-
const compileArgv = driver.target === null ? ["clang"] : driver.argv;
|
|
743
|
-
const arArgv = driver.target === null ? ["ar"] : [...driver.argv.slice(0, 1), "ar"];
|
|
744
|
-
const cflags = [
|
|
745
|
-
"-std=gnu11",
|
|
746
|
-
...driver.targetArgs,
|
|
747
|
-
"-fvisibility=hidden",
|
|
748
|
-
"-funsigned-char",
|
|
749
|
-
"-DQUICKJS_NG_BUILD",
|
|
750
|
-
"-D_GNU_SOURCE",
|
|
751
|
-
// CMake's qjs_defines on WIN32 (quickjs.c's own _WIN32 arms cover the
|
|
752
|
-
// rest — timezoneapi, intrin, cutils.h's _msize usable-size probe).
|
|
753
|
-
...(targetPlatform(driver) === "win32" ? ["-DWIN32_LEAN_AND_MEAN", "-D_WIN32_WINNT=0x0601"] : []),
|
|
754
|
-
...(sanitize
|
|
755
|
-
? ["-O0", "-ggdb", "-fno-omit-frame-pointer", "-fsanitize=address", "-fno-sanitize-recover=all", "-DQJS_ENABLE_ASAN"]
|
|
756
|
-
: ["-Os", "-DNDEBUG"]),
|
|
757
|
-
"-I", vendor,
|
|
758
|
-
];
|
|
759
|
-
await mkdir(cacheRoot, { recursive: true });
|
|
760
|
-
const buildDir = await mkdtemp(join(tmpdir(), `scriptc-vendor-qjs-${driver.target ?? "host"}-`));
|
|
761
|
-
try {
|
|
762
|
-
const width = Math.min(QJS_ENGINE_SOURCES.length, availableParallelism());
|
|
763
|
-
for (let i = 0; i < QJS_ENGINE_SOURCES.length; i += width) {
|
|
764
|
-
await Promise.all(QJS_ENGINE_SOURCES.slice(i, i + width).map((src) => execFileAsync(compileArgv[0] ?? "clang", [...compileArgv.slice(1), ...cflags, "-c", join(vendor, src), "-o", join(buildDir, `${basename(src, ".c")}.o`)], { cwd: buildDir })));
|
|
765
|
-
}
|
|
766
|
-
await execFileAsync(arArgv[0] ?? "ar", [...arArgv.slice(1), "rcs", join(buildDir, "libqjs.a"), ...QJS_ENGINE_SOURCES.map((s) => join(buildDir, `${basename(s, ".c")}.o`))]);
|
|
767
|
-
await publishVendorArtifact(join(buildDir, "libqjs.a"), archive);
|
|
768
|
-
}
|
|
769
|
-
finally {
|
|
770
|
-
await rm(buildDir, { recursive: true, force: true });
|
|
771
|
-
}
|
|
772
|
-
return archive;
|
|
773
|
-
}
|
|
774
|
-
/** The vendor sources behind static-build regex support: quickjs-ng's
|
|
775
|
-
* libregexp and its unicode tables (cutils is header-only). Deliberately
|
|
776
|
-
* NOT the engine — a regex-using static binary links ~110KB of matcher,
|
|
777
|
-
* never the ~620KB island. */
|
|
778
|
-
const LRE_SOURCES = ["libregexp.c", "libunicode.c"];
|
|
779
|
-
function lreObjectPaths(sanitize, driver, buildIdentity, cacheRoot = vendorBuildCacheRoot()) {
|
|
780
|
-
const flavor = (sanitize ? "asan" : "plain") +
|
|
781
|
-
(driver.argv.length === 1 && driver.argv[0] === "clang" ? "" : "-zigcc") +
|
|
782
|
-
`-${vendorCacheTargetFlavor(driver)}-${buildIdentity}`;
|
|
783
|
-
const cacheDir = join(cacheRoot, `${QJS_COMMIT.slice(0, 12)}-lre-${flavor}`);
|
|
784
|
-
return LRE_SOURCES.map((f) => join(cacheDir, f.replace(/\.c$/, ".o")));
|
|
785
|
-
}
|
|
786
|
-
/** The libregexp objects for one flavor, compiled lazily on the first
|
|
787
|
-
* regex-using static build (~1s) and cached like the engine archive —
|
|
788
|
-
* <build-cache>/vendor/<commit>-lre-<flavor>-<target>-<toolchain>/*.o — with the same atomic-rename
|
|
789
|
-
* publish (parallel first builds race safely; losers discard their work).
|
|
790
|
-
* Plain is -Os (size class matters: the regex fence pins regex-using
|
|
791
|
-
* binaries well under the engine class); asan matches the final link so
|
|
792
|
-
* the sanitized lane instruments the matcher too. Cross targets get their
|
|
793
|
-
* own flavor directory, compiled with the SCRIPTC_CC driver and its target
|
|
794
|
-
* args — libregexp/libunicode are plain C11, so the cross story is exactly
|
|
795
|
-
* the runtime sources' (no host-built inputs); vendored SOURCES are
|
|
796
|
-
* untouched, only the build wiring knows about targets. */
|
|
797
|
-
async function ensureLreObjects(sanitize, driver, buildIdentity, cacheRoot = vendorBuildCacheRoot()) {
|
|
798
|
-
// The flavor keys the DRIVER as well as the target: a zig-cc-built object
|
|
799
|
-
// set must never be handed to a clang link (or vice versa) off a shared
|
|
800
|
-
// cache directory. Native targets include host platform + architecture so
|
|
801
|
-
// arm64 and Rosetta processes never exchange Mach-O objects.
|
|
802
|
-
const flavor = (sanitize ? "asan" : "plain") +
|
|
803
|
-
(driver.argv.length === 1 && driver.argv[0] === "clang" ? "" : "-zigcc") +
|
|
804
|
-
`-${vendorCacheTargetFlavor(driver)}-${buildIdentity}`;
|
|
805
|
-
const vendor = vendorEngineDir();
|
|
806
|
-
const objects = lreObjectPaths(sanitize, driver, buildIdentity, cacheRoot);
|
|
807
|
-
if ((await Promise.all(objects.map(validVendorArtifact))).every(Boolean))
|
|
808
|
-
return objects;
|
|
809
|
-
await mkdir(cacheRoot, { recursive: true });
|
|
810
|
-
const buildDir = await mkdtemp(join(tmpdir(), `scriptc-vendor-lre-${flavor}-`));
|
|
811
|
-
try {
|
|
812
|
-
// One -c per invocation: zig's COFF driver rejects multiple -c inputs
|
|
813
|
-
// in a single command ("coff does not support linking multiple
|
|
814
|
-
// objects"); per-file compiles produce the identical objects on every
|
|
815
|
-
// target.
|
|
816
|
-
for (const f of LRE_SOURCES) {
|
|
817
|
-
await execFileAsync(driver.argv[0] ?? "clang", [
|
|
818
|
-
...driver.argv.slice(1),
|
|
819
|
-
"-std=c11",
|
|
820
|
-
...driver.targetArgs,
|
|
821
|
-
...(sanitize ? ["-O1", "-fsanitize=address"] : ["-Os"]),
|
|
822
|
-
"-I", vendor,
|
|
823
|
-
"-c", join(vendor, f),
|
|
824
|
-
"-o", join(buildDir, f.replace(/\.c$/, ".o")),
|
|
825
|
-
], { cwd: buildDir });
|
|
826
|
-
}
|
|
827
|
-
await Promise.all(objects.map((destination) => publishVendorArtifact(join(buildDir, basename(destination)), destination)));
|
|
828
|
-
}
|
|
829
|
-
finally {
|
|
830
|
-
await rm(buildDir, { recursive: true, force: true });
|
|
831
|
-
}
|
|
832
|
-
return objects;
|
|
833
|
-
}
|
|
834
|
-
function vendorZlibDir() {
|
|
835
|
-
return join(runtimeSrcDir(), "..", "vendor", "zlib");
|
|
836
|
-
}
|
|
837
|
-
/** The vendored zlib TUs behind CROSS-target zlib support: every root *.c
|
|
838
|
-
* except the gzFile file-I/O units (gz*.c — nothing in scr_zlib.c
|
|
839
|
-
* references the gzFile API, and those TUs alone want unistd/io headers).
|
|
840
|
-
* Host builds never touch this list — they link the system libz. */
|
|
841
|
-
const ZLIB_SOURCES = ["adler32.c", "compress.c", "crc32.c", "deflate.c", "infback.c", "inffast.c", "inflate.c", "inftrees.c", "trees.c", "uncompr.c", "zutil.c"];
|
|
842
|
-
function zlibObjectPaths(sanitize, driver, buildIdentity, cacheRoot = vendorBuildCacheRoot()) {
|
|
843
|
-
const flavor = (sanitize ? "asan" : "plain") +
|
|
844
|
-
(driver.argv.length === 1 && driver.argv[0] === "clang" ? "" : "-zigcc") +
|
|
845
|
-
`-${vendorCacheTargetFlavor(driver)}-${buildIdentity}`;
|
|
846
|
-
const cacheDir = join(cacheRoot, `zlib-${ZLIB_VERSION}-${flavor}`);
|
|
847
|
-
return ZLIB_SOURCES.map((f) => join(cacheDir, f.replace(/\.c$/, ".o")));
|
|
848
|
-
}
|
|
849
|
-
/** The zlib objects for one flavor, compiled lazily on the first zlib-using
|
|
850
|
-
* CROSS build (~1s) and cached like the lre objects —
|
|
851
|
-
* <build-cache>/vendor/zlib-<version>-<flavor>-<target>-<toolchain>/*.o — with the same atomic-rename
|
|
852
|
-
* publish (parallel first builds race safely; losers discard their work).
|
|
853
|
-
* Plain is -Os, asan matches the final link so the sanitized lane
|
|
854
|
-
* instruments the codec too. The flavor keys the driver and target exactly
|
|
855
|
-
* like the lre flavor: only cross builds call this today, but the keying
|
|
856
|
-
* must never hand a zig-built object set to a clang link off a shared
|
|
857
|
-
* directory. */
|
|
858
|
-
async function ensureZlibObjects(sanitize, driver, buildIdentity, cacheRoot = vendorBuildCacheRoot()) {
|
|
859
|
-
const flavor = (sanitize ? "asan" : "plain") +
|
|
860
|
-
(driver.argv.length === 1 && driver.argv[0] === "clang" ? "" : "-zigcc") +
|
|
861
|
-
`-${vendorCacheTargetFlavor(driver)}-${buildIdentity}`;
|
|
862
|
-
const vendor = vendorZlibDir();
|
|
863
|
-
const objects = zlibObjectPaths(sanitize, driver, buildIdentity, cacheRoot);
|
|
864
|
-
if ((await Promise.all(objects.map(validVendorArtifact))).every(Boolean))
|
|
865
|
-
return objects;
|
|
866
|
-
await mkdir(cacheRoot, { recursive: true });
|
|
867
|
-
const buildDir = await mkdtemp(join(tmpdir(), `scriptc-vendor-zlib-${flavor}-`));
|
|
868
|
-
try {
|
|
869
|
-
// One -c per invocation, the lre recipe (zig's COFF driver rejects
|
|
870
|
-
// multiple -c inputs in a single command).
|
|
871
|
-
for (const f of ZLIB_SOURCES) {
|
|
872
|
-
await execFileAsync(driver.argv[0] ?? "clang", [
|
|
873
|
-
...driver.argv.slice(1),
|
|
874
|
-
"-std=c11",
|
|
875
|
-
...driver.targetArgs,
|
|
876
|
-
...(sanitize ? ["-O1", "-fsanitize=address"] : ["-Os"]),
|
|
877
|
-
"-I", vendor,
|
|
878
|
-
"-c", join(vendor, f),
|
|
879
|
-
"-o", join(buildDir, f.replace(/\.c$/, ".o")),
|
|
880
|
-
], { cwd: buildDir });
|
|
881
|
-
}
|
|
882
|
-
await Promise.all(objects.map((destination) => publishVendorArtifact(join(buildDir, basename(destination)), destination)));
|
|
883
|
-
}
|
|
884
|
-
finally {
|
|
885
|
-
await rm(buildDir, { recursive: true, force: true });
|
|
886
|
-
}
|
|
887
|
-
return objects;
|
|
888
|
-
}
|
|
889
|
-
function vendorCurlDir() {
|
|
890
|
-
return join(runtimeSrcDir(), "..", "vendor", "curl");
|
|
891
|
-
}
|
|
892
|
-
/** Every libcurl function scr_fetch_curl.c references — the generated import
|
|
893
|
-
* stub defines exactly these. A new curl call in scr_fetch_curl.c that is
|
|
894
|
-
* missing here fails the CROSS link immediately with the symbol's name
|
|
895
|
-
* (host builds resolve it from the real system libcurl and never look). */
|
|
896
|
-
const CURL_STUB_SYMBOLS = [
|
|
897
|
-
"curl_easy_cleanup", "curl_easy_getinfo", "curl_easy_init", "curl_easy_setopt", "curl_easy_strerror",
|
|
898
|
-
"curl_free", "curl_global_cleanup", "curl_global_init",
|
|
899
|
-
"curl_multi_add_handle", "curl_multi_cleanup", "curl_multi_info_read", "curl_multi_init",
|
|
900
|
-
"curl_multi_perform", "curl_multi_poll", "curl_multi_remove_handle",
|
|
901
|
-
"curl_slist_append", "curl_slist_free_all",
|
|
902
|
-
"curl_url", "curl_url_cleanup", "curl_url_get", "curl_url_set",
|
|
903
|
-
];
|
|
904
|
-
function curlStubDirPath(driver, buildIdentity, cacheRoot = vendorBuildCacheRoot()) {
|
|
905
|
-
return join(cacheRoot, `curl-stub-${driver.target}-${buildIdentity}`);
|
|
906
|
-
}
|
|
907
|
-
/** The libcurl import stub for one CROSS target, generated lazily on the
|
|
908
|
-
* first fetch-using cross build and cached like the zlib objects —
|
|
909
|
-
* <build-cache>/vendor/curl-stub-<target>-<toolchain>/libcurl.so, atomic-rename publish. The
|
|
910
|
-
* stub is empty definitions of CURL_STUB_SYMBOLS compiled `-shared` with
|
|
911
|
-
* `-soname libcurl.so.4`: linking against it satisfies scr_fetch_curl.c's
|
|
912
|
-
* references and records a plain `DT_NEEDED libcurl.so.4`, which the
|
|
913
|
-
* TARGET system's real libcurl satisfies at load time (curl's unversioned
|
|
914
|
-
* exports make the classic import-stub technique sound here — nothing
|
|
915
|
-
* from the stub's bodies ever ships in the binary). One stub per target,
|
|
916
|
-
* no sanitize flavor: the stub's code is never executed or instrumented,
|
|
917
|
-
* and asan links against plain shared libraries freely. */
|
|
918
|
-
async function ensureCurlStub(driver, buildIdentity, cacheRoot = vendorBuildCacheRoot()) {
|
|
919
|
-
const cacheDir = curlStubDirPath(driver, buildIdentity, cacheRoot);
|
|
920
|
-
const lib = join(cacheDir, "libcurl.so");
|
|
921
|
-
if (await validVendorArtifact(lib))
|
|
922
|
-
return cacheDir;
|
|
923
|
-
await mkdir(cacheRoot, { recursive: true });
|
|
924
|
-
const buildDir = await mkdtemp(join(tmpdir(), "scriptc-vendor-curl-stub-"));
|
|
925
|
-
try {
|
|
926
|
-
const src = join(buildDir, "stub.c");
|
|
927
|
-
await writeFile(src, CURL_STUB_SYMBOLS.map((s) => `void ${s}(void) {}\n`).join(""));
|
|
928
|
-
await execFileAsync(driver.argv[0] ?? "clang", [
|
|
929
|
-
...driver.argv.slice(1),
|
|
930
|
-
...driver.targetArgs,
|
|
931
|
-
"-shared", "-fPIC",
|
|
932
|
-
"-Wl,-soname,libcurl.so.4",
|
|
933
|
-
src,
|
|
934
|
-
"-o", join(buildDir, "libcurl.so"),
|
|
935
|
-
]);
|
|
936
|
-
await publishVendorArtifact(join(buildDir, "libcurl.so"), lib);
|
|
937
|
-
}
|
|
938
|
-
finally {
|
|
939
|
-
await rm(buildDir, { recursive: true, force: true });
|
|
940
|
-
}
|
|
941
|
-
return cacheDir;
|
|
942
|
-
}
|
|
943
|
-
function vendorTlsDir() {
|
|
944
|
-
return join(runtimeSrcDir(), "..", "vendor", "mbedtls");
|
|
945
|
-
}
|
|
946
|
-
function tlsArchivePath(sanitize, driver, buildIdentity, cacheRoot = vendorBuildCacheRoot()) {
|
|
947
|
-
const flavor = `${sanitize ? "asan" : "plain"}-${vendorCacheTargetFlavor(driver)}-${buildIdentity}`;
|
|
948
|
-
return join(cacheRoot, `mbedtls-${MBEDTLS_VERSION}-${flavor}`, "libmbedtls.a");
|
|
949
|
-
}
|
|
950
|
-
/** The mbedTLS archive for one flavor, compiled lazily on the first
|
|
951
|
-
* TLS-using build (~15s over ~110 TUs, parallelized) and cached like the
|
|
952
|
-
* engine archive — <build-cache>/vendor/mbedtls-<version>-<flavor>-<target>-<toolchain>/libmbedtls.a —
|
|
953
|
-
* with the same atomic-rename publish (parallel first builds race safely;
|
|
954
|
-
* losers discard their work). Plain is -Os (the TLS stack is link-gated
|
|
955
|
-
* but still wants its size class small); asan matches the final link so
|
|
956
|
-
* the sanitized lane instruments every TLS path too. No CMake: the stock
|
|
957
|
-
* config builds every library/*.c standalone with clang, so the recipe is
|
|
958
|
-
* per-TU `-c` compiles plus one `ar rcs` — vendored-build machinery the
|
|
959
|
-
* lre-objects cache already established.
|
|
960
|
-
*
|
|
961
|
-
* SCRIPTC_TARGET adds a per-target cache flavor (the lre-objects story):
|
|
962
|
-
* TUs compile with `zig cc -target <triple>` and the archive is packed
|
|
963
|
-
* with `zig ar` (llvm-ar — the host BSD ar has no business indexing ELF
|
|
964
|
-
* objects). Host builds keep the exact historical clang + ar recipe. */
|
|
965
|
-
async function ensureTlsArchive(sanitize, driver, buildIdentity, cacheRoot = vendorBuildCacheRoot()) {
|
|
966
|
-
const flavor = `${sanitize ? "asan" : "plain"}-${vendorCacheTargetFlavor(driver)}-${buildIdentity}`;
|
|
967
|
-
const compileArgv = driver.target !== null ? driver.argv : ["clang"];
|
|
968
|
-
const arArgv = driver.target !== null ? [...driver.argv.slice(0, 1), "ar"] : ["ar"];
|
|
969
|
-
const vendor = vendorTlsDir();
|
|
970
|
-
const archive = tlsArchivePath(sanitize, driver, buildIdentity, cacheRoot);
|
|
971
|
-
if (await validVendorArtifact(archive))
|
|
972
|
-
return archive;
|
|
973
|
-
await mkdir(cacheRoot, { recursive: true });
|
|
974
|
-
const buildDir = await mkdtemp(join(tmpdir(), `scriptc-vendor-mbedtls-${flavor}-`));
|
|
975
|
-
try {
|
|
976
|
-
const sources = (await readdir(join(vendor, "library")))
|
|
977
|
-
.filter((name) => !name.startsWith(".") && name.endsWith(".c"))
|
|
978
|
-
.sort();
|
|
979
|
-
const cflags = [
|
|
980
|
-
"-std=c11",
|
|
981
|
-
...driver.targetArgs,
|
|
982
|
-
...(sanitize ? ["-O1", "-fsanitize=address"] : ["-Os"]),
|
|
983
|
-
"-I", join(vendor, "include"),
|
|
984
|
-
"-I", join(vendor, "library"),
|
|
985
|
-
];
|
|
986
|
-
const width = availableParallelism();
|
|
987
|
-
for (let i = 0; i < sources.length; i += width) {
|
|
988
|
-
await Promise.all(sources.slice(i, i + width).map((src) => execFileAsync(compileArgv[0] ?? "clang", [...compileArgv.slice(1), ...cflags, "-c", join(vendor, "library", src), "-o", join(buildDir, `${basename(src, ".c")}.o`)])));
|
|
989
|
-
}
|
|
990
|
-
await execFileAsync(arArgv[0] ?? "ar", [...arArgv.slice(1), "rcs", join(buildDir, "libmbedtls.a"), ...sources.map((s) => join(buildDir, `${basename(s, ".c")}.o`))]);
|
|
991
|
-
await publishVendorArtifact(join(buildDir, "libmbedtls.a"), archive);
|
|
992
|
-
}
|
|
993
|
-
finally {
|
|
994
|
-
await rm(buildDir, { recursive: true, force: true });
|
|
995
|
-
}
|
|
996
|
-
return archive;
|
|
997
|
-
}
|
|
998
584
|
/* ── library mode: the static-archive artifact ────────────────────────────
|
|
999
585
|
* One `scriptc build --lib` invocation produces <name>.lib.a: the program TU
|
|
1000
586
|
* object plus exactly the runtime objects the program's IR gates in, every
|
|
@@ -1023,7 +609,7 @@ async function ensureTlsArchive(sanitize, driver, buildIdentity, cacheRoot = ven
|
|
|
1023
609
|
/** The library base: the executable lane's unconditional sources minus the
|
|
1024
610
|
* fiber/loop and child-process units, plus the library-mode TU. */
|
|
1025
611
|
const LIB_RUNTIME_SOURCES = [
|
|
1026
|
-
...
|
|
612
|
+
...EXECUTABLE_RUNTIME_SOURCES.filter((f) => f !== "scr_async.c" && f !== "scr_child.c" && f !== "scr_ffi.c"),
|
|
1027
613
|
"scr_library.c",
|
|
1028
614
|
];
|
|
1029
615
|
function updateProgramShardCacheIdentity(hash, shards, publicSymbols, mergeIdentity) {
|
|
@@ -1094,6 +680,7 @@ async function resolveProgramShardMergeIdentity(driver) {
|
|
|
1094
680
|
return null;
|
|
1095
681
|
}
|
|
1096
682
|
export async function compileLibArchive(opts) {
|
|
683
|
+
clearCcCaches();
|
|
1097
684
|
const rtDir = runtimeSrcDir();
|
|
1098
685
|
const driver = resolveCc();
|
|
1099
686
|
const shardNames = new Set();
|
|
@@ -1160,7 +747,7 @@ export async function compileLibArchive(opts) {
|
|
|
1160
747
|
? [...cflags, "-Wno-override-module"]
|
|
1161
748
|
: cflags;
|
|
1162
749
|
const programSourceExtension = opts.cPath.endsWith(".ll") ? ".ll" : ".c";
|
|
1163
|
-
const arArgv = driver
|
|
750
|
+
const arArgv = isZigDriver(driver) ? [driver.argv[0], "ar"] : ["ar"];
|
|
1164
751
|
const cachePolicy = toolchainEnvironmentCachePolicy();
|
|
1165
752
|
const configuredCacheRoot = cacheRootDir();
|
|
1166
753
|
const toolchainEnv = toolchainEnvironmentFingerprint();
|
|
@@ -1171,15 +758,16 @@ export async function compileLibArchive(opts) {
|
|
|
1171
758
|
// search variables cannot affect it, but any mutable compilation input or
|
|
1172
759
|
// opaque compiler wrapper makes every persistent tier unsafe to reuse. An
|
|
1173
760
|
// opaque archiver narrows only the completed-archive tier below.
|
|
1174
|
-
|
|
761
|
+
const cacheIdentity = opts.cacheIdentity;
|
|
762
|
+
let persistentCache = cacheIdentity === undefined || configuredCacheRoot === null || !persistentDriverCache
|
|
1175
763
|
? null
|
|
1176
|
-
: configuredCacheRoot;
|
|
1177
|
-
if (
|
|
764
|
+
: { root: configuredCacheRoot, identity: cacheIdentity };
|
|
765
|
+
if (persistentCache !== null) {
|
|
1178
766
|
try {
|
|
1179
|
-
await ensurePrivateCacheRoot(root, process.env["SCRIPTC_CACHE_DIR"] === undefined);
|
|
767
|
+
await ensurePrivateCacheRoot(persistentCache.root, process.env["SCRIPTC_CACHE_DIR"] === undefined);
|
|
1180
768
|
}
|
|
1181
769
|
catch {
|
|
1182
|
-
|
|
770
|
+
persistentCache = null;
|
|
1183
771
|
}
|
|
1184
772
|
}
|
|
1185
773
|
let implicitToolchain = null;
|
|
@@ -1195,10 +783,10 @@ export async function compileLibArchive(opts) {
|
|
|
1195
783
|
catch {
|
|
1196
784
|
// An identity probe is cache machinery, never a reason a valid native
|
|
1197
785
|
// compile should fail. Disable every persistent tier for this invocation.
|
|
1198
|
-
|
|
786
|
+
persistentCache = null;
|
|
1199
787
|
}
|
|
1200
788
|
}
|
|
1201
|
-
if (
|
|
789
|
+
if (persistentCache !== null) {
|
|
1202
790
|
try {
|
|
1203
791
|
runtimeCompilerInvocation = await effectiveCompilerInvocationFingerprint(driver, toolchainEnv, cflags);
|
|
1204
792
|
programCompilerInvocation = programSourceExtension === ".ll"
|
|
@@ -1208,7 +796,7 @@ export async function compileLibArchive(opts) {
|
|
|
1208
796
|
catch {
|
|
1209
797
|
// A wrapper that cannot expose its effective invocation can still build,
|
|
1210
798
|
// but its outputs cannot safely participate in a persistent cache.
|
|
1211
|
-
|
|
799
|
+
persistentCache = null;
|
|
1212
800
|
}
|
|
1213
801
|
}
|
|
1214
802
|
const vendorBuildIdentity = await currentVendorCacheBuildIdentity(driver, `${toolchainEnv}\0${implicitToolchain ?? "<uncached>"}`);
|
|
@@ -1218,7 +806,7 @@ export async function compileLibArchive(opts) {
|
|
|
1218
806
|
// fingerprint. The runtime-object tier still serves them (localization
|
|
1219
807
|
// consumes the same per-flavor objects).
|
|
1220
808
|
const cacheCompleteArchive = opts.localizeSymbols === undefined &&
|
|
1221
|
-
|
|
809
|
+
persistentCache !== null && await archiverSupportsPersistentCache(arArgv, driver);
|
|
1222
810
|
let cachedArchive = null;
|
|
1223
811
|
let compilerVersion = "";
|
|
1224
812
|
let archiverVersion = "";
|
|
@@ -1230,10 +818,10 @@ export async function compileLibArchive(opts) {
|
|
|
1230
818
|
const identityBytes = opts.identityCSource === undefined
|
|
1231
819
|
? null
|
|
1232
820
|
: Buffer.from(opts.identityCSource, "utf8");
|
|
1233
|
-
if (
|
|
821
|
+
if (persistentCache !== null) {
|
|
1234
822
|
try {
|
|
1235
823
|
const [cv, fingerprint, programBytes] = await Promise.all([
|
|
1236
|
-
|
|
824
|
+
ccVersion(driver.argv, toolchainEnv, true),
|
|
1237
825
|
runtimeFingerprint(rtDir),
|
|
1238
826
|
cachedProgramBytes === null ? readFile(opts.cPath) : Promise.resolve(cachedProgramBytes),
|
|
1239
827
|
]);
|
|
@@ -1256,7 +844,7 @@ export async function compileLibArchive(opts) {
|
|
|
1256
844
|
.update(runtimeCompilerInvocation).update("\0")
|
|
1257
845
|
.update(programCompilerInvocation).update("\0")
|
|
1258
846
|
.update(programDependencyHash).update("\0")
|
|
1259
|
-
.update(
|
|
847
|
+
.update(persistentCache.identity).update("\0")
|
|
1260
848
|
.update(driver.argv.join("\x1f")).update("\0")
|
|
1261
849
|
.update(cv).update("\0")
|
|
1262
850
|
.update(fingerprint).update("\0")
|
|
@@ -1276,7 +864,7 @@ export async function compileLibArchive(opts) {
|
|
|
1276
864
|
.update(identityBytes === null ? "<none>" : "<generated>").update("\0")
|
|
1277
865
|
.update(identityBytes ?? Buffer.alloc(0))
|
|
1278
866
|
.digest("hex");
|
|
1279
|
-
cachedArchive = join(root, "lib", keyHex);
|
|
867
|
+
cachedArchive = join(persistentCache.root, "lib", keyHex);
|
|
1280
868
|
const tmpOut = privateSiblingPath(opts.outPath, "lib-hit");
|
|
1281
869
|
try {
|
|
1282
870
|
await mkdir(dirname(opts.outPath), { recursive: true });
|
|
@@ -1301,10 +889,10 @@ export async function compileLibArchive(opts) {
|
|
|
1301
889
|
cachedArchive = null;
|
|
1302
890
|
}
|
|
1303
891
|
}
|
|
1304
|
-
const transientVendorRoot =
|
|
892
|
+
const transientVendorRoot = persistentCache !== null && implicitToolchain !== null
|
|
1305
893
|
? null
|
|
1306
894
|
: join(tmpdir(), `scriptc-lib-vendor-${process.pid}-${Math.random().toString(36).slice(2)}`);
|
|
1307
|
-
const vendorCacheRoot = transientVendorRoot ?? vendorBuildCacheRoot(root
|
|
895
|
+
const vendorCacheRoot = transientVendorRoot ?? vendorBuildCacheRoot(persistentCache?.root);
|
|
1308
896
|
try {
|
|
1309
897
|
const buildDir = await mkdtemp(join(tmpdir(), "scriptc-lib-"));
|
|
1310
898
|
try {
|
|
@@ -1348,7 +936,7 @@ export async function compileLibArchive(opts) {
|
|
|
1348
936
|
await writeFile(programSource, cachedProgramBytes);
|
|
1349
937
|
}
|
|
1350
938
|
let cachedProgramObject = null;
|
|
1351
|
-
if (
|
|
939
|
+
if (persistentCache !== null && cachedProgramBytes !== null && compilerVersion !== "" &&
|
|
1352
940
|
implicitToolchain !== null && programCompilerInvocation !== null) {
|
|
1353
941
|
const programKey = createHash("sha256")
|
|
1354
942
|
.update("lib-program-obj-v3\0")
|
|
@@ -1356,7 +944,7 @@ export async function compileLibArchive(opts) {
|
|
|
1356
944
|
.update(toolchainEnv).update("\0")
|
|
1357
945
|
.update(implicitToolchain).update("\0")
|
|
1358
946
|
.update(programCompilerInvocation).update("\0")
|
|
1359
|
-
.update(
|
|
947
|
+
.update(persistentCache.identity).update("\0")
|
|
1360
948
|
.update(driver.argv.join("\x1f")).update("\0")
|
|
1361
949
|
.update(compilerVersion).update("\0")
|
|
1362
950
|
.update(runtimeHash).update("\0")
|
|
@@ -1367,7 +955,7 @@ export async function compileLibArchive(opts) {
|
|
|
1367
955
|
.update(cachedProgramBytes);
|
|
1368
956
|
updateProgramShardCacheIdentity(programKey, programShards ?? undefined, programPublicSymbols, programShardMergeIdentity ?? undefined);
|
|
1369
957
|
const programKeyHex = programKey.digest("hex");
|
|
1370
|
-
cachedProgramObject = join(root, "program-obj", programKeyHex);
|
|
958
|
+
cachedProgramObject = join(persistentCache.root, "program-obj", programKeyHex);
|
|
1371
959
|
}
|
|
1372
960
|
const stagedProgramObject = join(buildDir, `${stem}.program.o`);
|
|
1373
961
|
let programObject;
|
|
@@ -1382,8 +970,8 @@ export async function compileLibArchive(opts) {
|
|
|
1382
970
|
const sourcePath = join(buildDir, shard.name);
|
|
1383
971
|
const staged = join(buildDir, `${stem}.program-${index.toString().padStart(3, "0")}.o`);
|
|
1384
972
|
let cachePath = null;
|
|
1385
|
-
if (
|
|
1386
|
-
programCompilerInvocation !== null) {
|
|
973
|
+
if (persistentCache !== null && compilerVersion !== "" &&
|
|
974
|
+
implicitCompileToolchain !== null && programCompilerInvocation !== null) {
|
|
1387
975
|
const key = createHash("sha256")
|
|
1388
976
|
// v2 removes the broad implicit-toolchain fingerprint: it
|
|
1389
977
|
// includes the linker selected by the driver, but raw shard
|
|
@@ -1397,7 +985,7 @@ export async function compileLibArchive(opts) {
|
|
|
1397
985
|
.update(toolchainEnv).update("\0")
|
|
1398
986
|
.update(implicitCompileToolchain).update("\0")
|
|
1399
987
|
.update(programCompilerInvocation).update("\0")
|
|
1400
|
-
.update(
|
|
988
|
+
.update(persistentCache.identity).update("\0")
|
|
1401
989
|
.update(driver.argv.join("\x1f")).update("\0")
|
|
1402
990
|
.update(compilerVersion).update("\0")
|
|
1403
991
|
.update(runtimeHash).update("\0")
|
|
@@ -1408,7 +996,7 @@ export async function compileLibArchive(opts) {
|
|
|
1408
996
|
.update(shard.name).update("\0")
|
|
1409
997
|
.update(shard.source)
|
|
1410
998
|
.digest("hex");
|
|
1411
|
-
cachePath = join(root, "program-shard", key);
|
|
999
|
+
cachePath = join(persistentCache.root, "program-shard", key);
|
|
1412
1000
|
}
|
|
1413
1001
|
return { ...shard, sourcePath, staged, cachePath, missed: false };
|
|
1414
1002
|
});
|
|
@@ -1436,7 +1024,7 @@ export async function compileLibArchive(opts) {
|
|
|
1436
1024
|
runtimeFingerprint(rtDir),
|
|
1437
1025
|
effectiveCompilerInvocationFingerprint(driver, toolchainEnv, programCompilerArgs, programSourceExtension),
|
|
1438
1026
|
translationUnitDependencyFingerprint(driver, cflags, opts.cPath, cachedProgramBytes, toolchainEnv),
|
|
1439
|
-
|
|
1027
|
+
ccVersion(driver.argv, toolchainEnv, true),
|
|
1440
1028
|
]);
|
|
1441
1029
|
const shardInputsStillMatch = currentRuntime === runtimeHash &&
|
|
1442
1030
|
currentInvocation === programCompilerInvocation &&
|
|
@@ -1487,7 +1075,7 @@ export async function compileLibArchive(opts) {
|
|
|
1487
1075
|
implicitToolchainFingerprint(driver, toolchainEnv),
|
|
1488
1076
|
effectiveCompilerInvocationFingerprint(driver, toolchainEnv, programCompilerArgs, programSourceExtension),
|
|
1489
1077
|
translationUnitDependencyFingerprint(driver, cflags, opts.cPath, cachedProgramBytes, toolchainEnv),
|
|
1490
|
-
|
|
1078
|
+
ccVersion(driver.argv, toolchainEnv, true),
|
|
1491
1079
|
]);
|
|
1492
1080
|
if (currentRuntime === runtimeHash &&
|
|
1493
1081
|
currentImplicit === implicitToolchain &&
|
|
@@ -1520,10 +1108,10 @@ export async function compileLibArchive(opts) {
|
|
|
1520
1108
|
currentInvocation === runtimeCompilerInvocation, () => false);
|
|
1521
1109
|
return objectImplicitVerification;
|
|
1522
1110
|
};
|
|
1523
|
-
if (
|
|
1111
|
+
if (persistentCache !== null && compilerVersion !== "" && runtimeHash !== "") {
|
|
1524
1112
|
try {
|
|
1525
1113
|
const sourcePaths = sources.map((f) => join(rtDir, f));
|
|
1526
|
-
const cached = await ensureRuntimeObjects(root, driver.argv, cflags, sourcePaths, `lib-obj-v5\0${cacheTargetIdentity(driver)}\0${toolchainEnv}\0${implicitToolchain}\0${runtimeCompilerInvocation}\0${driver.argv.join(" ")}\0${compilerVersion}\0${runtimeHash}\0`, async () => (await runtimeFingerprint(rtDir)) === runtimeHash &&
|
|
1114
|
+
const cached = await ensureRuntimeObjects(persistentCache.root, driver.argv, cflags, sourcePaths, `lib-obj-v5\0${cacheTargetIdentity(driver)}\0${toolchainEnv}\0${implicitToolchain}\0${runtimeCompilerInvocation}\0${driver.argv.join(" ")}\0${compilerVersion}\0${runtimeHash}\0`, async () => (await runtimeFingerprint(rtDir)) === runtimeHash &&
|
|
1527
1115
|
(await objectImplicitToolchainStillMatches()));
|
|
1528
1116
|
const staged = await stageRuntimeObjects(cached, join(buildDir, "cached-runtime"));
|
|
1529
1117
|
runtimeObjects = sourcePaths.map((path) => staged.get(path));
|
|
@@ -1570,7 +1158,7 @@ export async function compileLibArchive(opts) {
|
|
|
1570
1158
|
await installArtifact(archiveOutput, opts.outPath);
|
|
1571
1159
|
let runtimeStillMatchesKey = false;
|
|
1572
1160
|
if (cachedArchive !== null &&
|
|
1573
|
-
|
|
1161
|
+
persistentCache !== null &&
|
|
1574
1162
|
runtimeHash !== "" &&
|
|
1575
1163
|
programDependencyHash !== "" &&
|
|
1576
1164
|
compilerVersion !== "" &&
|
|
@@ -1581,7 +1169,7 @@ export async function compileLibArchive(opts) {
|
|
|
1581
1169
|
effectiveCompilerInvocationFingerprint(driver, toolchainEnv, cflags).catch(() => null),
|
|
1582
1170
|
effectiveCompilerInvocationFingerprint(driver, toolchainEnv, programCompilerArgs, programSourceExtension).catch(() => null),
|
|
1583
1171
|
translationUnitDependencyFingerprint(driver, cflags, opts.cPath, cachedProgramBytes, toolchainEnv).catch(() => null),
|
|
1584
|
-
|
|
1172
|
+
ccVersion(driver.argv, toolchainEnv, true).catch(() => null),
|
|
1585
1173
|
toolVersionOnce(arArgv, toolchainEnv, true).catch(() => null),
|
|
1586
1174
|
programShards === null
|
|
1587
1175
|
? Promise.resolve(null)
|
|
@@ -1599,7 +1187,7 @@ export async function compileLibArchive(opts) {
|
|
|
1599
1187
|
currentArchiver === archiverVersion &&
|
|
1600
1188
|
currentProgramShardMerge === programShardMergeIdentity;
|
|
1601
1189
|
}
|
|
1602
|
-
if (cachedArchive !== null &&
|
|
1190
|
+
if (cachedArchive !== null && persistentCache !== null && runtimeStillMatchesKey) {
|
|
1603
1191
|
try {
|
|
1604
1192
|
await publishCachedFile(archiveOutput, cachedArchive);
|
|
1605
1193
|
}
|
|
@@ -1617,8 +1205,9 @@ export async function compileLibArchive(opts) {
|
|
|
1617
1205
|
await rm(transientVendorRoot, { recursive: true, force: true }).catch(() => undefined);
|
|
1618
1206
|
}
|
|
1619
1207
|
}
|
|
1620
|
-
if (
|
|
1621
|
-
await pruneCache(root).catch(() => undefined);
|
|
1208
|
+
if (persistentCache !== null) {
|
|
1209
|
+
await pruneCache(persistentCache.root).catch(() => undefined);
|
|
1210
|
+
}
|
|
1622
1211
|
}
|
|
1623
1212
|
/* Multi-instance library mode's localization step: combine the program
|
|
1624
1213
|
* object with exactly the runtime/vendor members it reaches into ONE
|
|
@@ -1743,7 +1332,7 @@ async function localizeLibraryObjects(driver, arArgv, buildDir, rootObjects, sup
|
|
|
1743
1332
|
}
|
|
1744
1333
|
}
|
|
1745
1334
|
else {
|
|
1746
|
-
throw new
|
|
1335
|
+
throw new InternalCompilerError(`runtime symbol localization (abi.localize_runtime) has no ${platform} arm; compileLibrary admits darwin, linux, and win32 builds only`);
|
|
1747
1336
|
}
|
|
1748
1337
|
return combined;
|
|
1749
1338
|
}
|
|
@@ -1829,80 +1418,6 @@ async function localizeLibraryObjects(driver, arArgv, buildDir, rootObjects, sup
|
|
|
1829
1418
|
* oracle cache lives under the same root and is swept by the same pass. Cache
|
|
1830
1419
|
* trouble is never a build failure — every cache error falls back to a real
|
|
1831
1420
|
* compile. */
|
|
1832
|
-
/** Resolve the build cache without touching the filesystem. Exported from this
|
|
1833
|
-
* internal module so its platform and override behavior can be pinned directly. */
|
|
1834
|
-
export function resolveBuildCacheRoot(env = process.env, platform = process.platform, userHome = homedir()) {
|
|
1835
|
-
if (env["SCRIPTC_NO_CACHE"] === "1")
|
|
1836
|
-
return null;
|
|
1837
|
-
const configured = env["SCRIPTC_CACHE_DIR"];
|
|
1838
|
-
if (configured !== undefined)
|
|
1839
|
-
return configured === "" ? null : resolve(configured);
|
|
1840
|
-
const xdg = env["XDG_CACHE_HOME"];
|
|
1841
|
-
if (xdg !== undefined && xdg !== "")
|
|
1842
|
-
return resolve(xdg, "scriptc", "build");
|
|
1843
|
-
if (platform === "win32") {
|
|
1844
|
-
const local = env["LOCALAPPDATA"];
|
|
1845
|
-
if (local !== undefined && local !== "")
|
|
1846
|
-
return resolve(local, "scriptc", "cache", "build");
|
|
1847
|
-
}
|
|
1848
|
-
return platform === "darwin"
|
|
1849
|
-
? resolve(userHome, "Library", "Caches", "scriptc", "build")
|
|
1850
|
-
: resolve(userHome, ".cache", "scriptc", "build");
|
|
1851
|
-
}
|
|
1852
|
-
/** Shared persistent-cache root for compiler-level tiers. The early library
|
|
1853
|
-
* cache deliberately follows the native cache's activation and hard-disable
|
|
1854
|
-
* contract, while native compilation retains ownership of toolchain safety. */
|
|
1855
|
-
export function buildCacheRoot() {
|
|
1856
|
-
return resolveBuildCacheRoot();
|
|
1857
|
-
}
|
|
1858
|
-
/** Harden/create a compiler-level cache root using the same privacy policy as
|
|
1859
|
-
* the artifact caches. Failure disables only the optional caller's tier. */
|
|
1860
|
-
export async function prepareBuildCacheRoot(root) {
|
|
1861
|
-
if (root === null)
|
|
1862
|
-
return null;
|
|
1863
|
-
try {
|
|
1864
|
-
await ensurePrivateCacheRoot(root, process.env["SCRIPTC_CACHE_DIR"] === undefined);
|
|
1865
|
-
return root;
|
|
1866
|
-
}
|
|
1867
|
-
catch {
|
|
1868
|
-
return null;
|
|
1869
|
-
}
|
|
1870
|
-
}
|
|
1871
|
-
/** Register a successful compiler-level cache write with the shared bounded
|
|
1872
|
-
* LRU policy. */
|
|
1873
|
-
export async function pruneBuildCache(root) {
|
|
1874
|
-
if (root !== null)
|
|
1875
|
-
await pruneCache(root).catch(() => undefined);
|
|
1876
|
-
}
|
|
1877
|
-
function cacheRootDir() {
|
|
1878
|
-
return resolveBuildCacheRoot();
|
|
1879
|
-
}
|
|
1880
|
-
/** The production cache can contain complete user executables/archives with
|
|
1881
|
-
* embedded source literals or comptime values. Its root is therefore private
|
|
1882
|
-
* regardless of the caller's ordinary output umask. Windows inherits the
|
|
1883
|
-
* per-user LOCALAPPDATA ACL. POSIX platform-default roots are hardened for
|
|
1884
|
-
* upgrades; an arbitrary existing SCRIPTC_CACHE_DIR override is never chmod'd
|
|
1885
|
-
* and participates only when its caller-provided mode is already private. */
|
|
1886
|
-
async function ensurePrivateCacheRoot(root, hardenExisting) {
|
|
1887
|
-
const existing = await stat(root).then((info) => info, (error) => {
|
|
1888
|
-
if (error.code === "ENOENT")
|
|
1889
|
-
return null;
|
|
1890
|
-
throw error;
|
|
1891
|
-
});
|
|
1892
|
-
if (existing !== null && !existing.isDirectory()) {
|
|
1893
|
-
throw new Error("native cache root is not a directory");
|
|
1894
|
-
}
|
|
1895
|
-
if (process.platform !== "win32" &&
|
|
1896
|
-
existing !== null &&
|
|
1897
|
-
!hardenExisting &&
|
|
1898
|
-
(existing.mode & 0o077) !== 0) {
|
|
1899
|
-
throw new Error("existing native cache override is not private");
|
|
1900
|
-
}
|
|
1901
|
-
await mkdir(root, { recursive: true, mode: 0o700 });
|
|
1902
|
-
if (process.platform !== "win32" && (existing === null || hardenExisting)) {
|
|
1903
|
-
await chmod(root, 0o700);
|
|
1904
|
-
}
|
|
1905
|
-
}
|
|
1906
1421
|
const ccVersionMemos = new Map();
|
|
1907
1422
|
/** Identity of the compiler implementation and configuration selected by a
|
|
1908
1423
|
* fresh driver invocation. In particular, Darwin's stable /usr/bin/clang shim
|
|
@@ -2029,7 +1544,7 @@ function isAppleSystemClangHandoff(driver, effectiveCompiler) {
|
|
|
2029
1544
|
* can safely represent that behavior. Accept direct Clang/Zig drivers (plus
|
|
2030
1545
|
* Apple's system shim) and conservatively keep wrapper-driven builds on the
|
|
2031
1546
|
* uncached path. */
|
|
2032
|
-
async function compilerDriverSupportsPersistentCache(driver, environmentFingerprint) {
|
|
1547
|
+
export async function compilerDriverSupportsPersistentCache(driver, environmentFingerprint) {
|
|
2033
1548
|
// Cache-race tests exercise publication below an intentionally instrumented
|
|
2034
1549
|
// wrapper. This is deliberately undocumented and test-scoped.
|
|
2035
1550
|
if (process.env["SCRIPTC_TEST_TRUST_COMPILER_WRAPPER"] === "1")
|
|
@@ -2115,7 +1630,7 @@ async function archiverSupportsPersistentCache(arArgv, driver) {
|
|
|
2115
1630
|
return process.platform === "darwin" &&
|
|
2116
1631
|
/^\/Applications\/Xcode[^/]*\.app\/Contents\/Developer\/Toolchains\/[^/]+\.xctoolchain\/usr\/bin\/[^/]*ar$/.test(archiver.canonicalPath);
|
|
2117
1632
|
}
|
|
2118
|
-
export async function
|
|
1633
|
+
export async function ccVersion(argv, environmentFingerprint = toolchainEnvironmentFingerprint(), fresh = false) {
|
|
2119
1634
|
const spellingKey = `${environmentFingerprint}\0${argv.join("\x1f")}`;
|
|
2120
1635
|
const executableIdentity = await resolvedToolIdentity(argv[0] ?? "clang");
|
|
2121
1636
|
const key = `${spellingKey}\0${executableIdentity ?? "<unresolved>"}`;
|
|
@@ -2838,7 +2353,21 @@ function implicitLinkerFingerprint(driver, environmentFingerprint, linkArgs, eff
|
|
|
2838
2353
|
].join("\0");
|
|
2839
2354
|
return stableTestMemo(stableImplicitLinkerMemos, key, () => implicitLinkerFingerprintFresh(driver, environmentFingerprint, linkArgs, effectiveInvocationArgs, traceInvocationArgs));
|
|
2840
2355
|
}
|
|
2356
|
+
/** Resolve the exact files consumed by one compiler-driver link invocation.
|
|
2357
|
+
* Runtime packs reuse the native toolchain's strict dry-run plus real linker
|
|
2358
|
+
* trace so a PATH-selected Clang carries its own linker, SDK, compiler
|
|
2359
|
+
* runtime, and injected inputs into the executable cache proof. */
|
|
2360
|
+
export async function nativeLinkerDependencyPaths(linker, linkArgs) {
|
|
2361
|
+
const fingerprint = await implicitLinkerFingerprint({ argv: [linker], targetArgs: [], target: null }, toolchainEnvironmentFingerprint(), linkArgs);
|
|
2362
|
+
return fingerprintDependencyPaths(fingerprint);
|
|
2363
|
+
}
|
|
2841
2364
|
let ccacheMemo = null;
|
|
2365
|
+
/** Reset process observations whose validity is bounded to one public native
|
|
2366
|
+
* build. A long-lived caller may change PATH or install/remove ccache between
|
|
2367
|
+
* invocations; the next build must probe that environment again. */
|
|
2368
|
+
export function clearCcCaches() {
|
|
2369
|
+
ccacheMemo = null;
|
|
2370
|
+
}
|
|
2842
2371
|
function ccacheAvailable() {
|
|
2843
2372
|
ccacheMemo ??= execFileAsync("ccache", ["--version"]).then(() => true, () => false);
|
|
2844
2373
|
return ccacheMemo;
|
|
@@ -2855,8 +2384,10 @@ async function runtimeFingerprintFresh(rtDir) {
|
|
|
2855
2384
|
const h = createHash("sha256")
|
|
2856
2385
|
.update("native-owned-inputs-v2\0")
|
|
2857
2386
|
.update(QJS_COMMIT).update(MBEDTLS_VERSION).update(ZLIB_VERSION)
|
|
2858
|
-
.update("\0backend-recipe\0")
|
|
2859
|
-
|
|
2387
|
+
.update("\0backend-recipe\0");
|
|
2388
|
+
for (const path of NATIVE_RECIPE_IMPLEMENTATION_PATHS) {
|
|
2389
|
+
h.update(basename(path)).update("\0").update(await readFile(path)).update("\0");
|
|
2390
|
+
}
|
|
2860
2391
|
for (const group of groups) {
|
|
2861
2392
|
for (const n of group.names) {
|
|
2862
2393
|
h.update(group.label).update("/").update(n).update("\0").update(await readFile(join(group.dir, n))).update("\0");
|
|
@@ -2882,7 +2413,7 @@ async function runtimeFingerprintInputGroups(rtDir) {
|
|
|
2882
2413
|
async function runtimeFingerprintInputPaths(rtDir) {
|
|
2883
2414
|
return [
|
|
2884
2415
|
...(await runtimeFingerprintInputGroups(rtDir)).flatMap((group) => group.names.map((name) => join(group.dir, name))),
|
|
2885
|
-
|
|
2416
|
+
...NATIVE_RECIPE_IMPLEMENTATION_PATHS,
|
|
2886
2417
|
];
|
|
2887
2418
|
}
|
|
2888
2419
|
const stableRuntimeFingerprintMemos = new Map();
|
|
@@ -2890,89 +2421,20 @@ export function runtimeFingerprint(rtDir) {
|
|
|
2890
2421
|
const key = resolve(rtDir);
|
|
2891
2422
|
return stableTestMemo(stableRuntimeFingerprintMemos, key, () => runtimeFingerprintFresh(rtDir));
|
|
2892
2423
|
}
|
|
2424
|
+
const { vendorEngineDir, vendorTlsDir, vendorCurlDir, vendorBuildCacheRoot, vendorCacheTargetFlavor, vendorCacheBuildIdentity, currentVendorCacheBuildIdentity, engineArchivePath, stageVendorInputs, ensureEngineArchive, lreObjectPaths, ensureLreObjects, vendorZlibDir, zlibObjectPaths, ensureZlibObjects, curlStubDirPath, ensureCurlStub, tlsArchivePath, ensureTlsArchive, QJS_ENGINE_SOURCES, LRE_SOURCES, ZLIB_SOURCES, } = createVendorArchives({
|
|
2425
|
+
runtimeSrcDir,
|
|
2426
|
+
targetPlatform,
|
|
2427
|
+
isZigDriver,
|
|
2428
|
+
resolvedToolIdentity,
|
|
2429
|
+
runtimeFingerprint,
|
|
2430
|
+
});
|
|
2431
|
+
export { vendorCacheBuildIdentity, vendorCacheTargetFlavor };
|
|
2893
2432
|
class CacheInputsChangedError extends Error {
|
|
2894
2433
|
constructor() {
|
|
2895
2434
|
super("runtime inputs changed while populating the native object cache");
|
|
2896
2435
|
this.name = "CacheInputsChangedError";
|
|
2897
2436
|
}
|
|
2898
2437
|
}
|
|
2899
|
-
function cacheDigestPath(path) {
|
|
2900
|
-
return `${path}.sha256`;
|
|
2901
|
-
}
|
|
2902
|
-
async function fileDigest(path) {
|
|
2903
|
-
return createHash("sha256").update(await readFile(path)).digest("hex");
|
|
2904
|
-
}
|
|
2905
|
-
/** Cache entries are disposable data, not trusted compiler output. Atomic
|
|
2906
|
-
* rename prevents ordinary partial writes, while the adjacent digest catches
|
|
2907
|
-
* disk damage, manual truncation, and entries left by an interrupted/older
|
|
2908
|
-
* publisher before they reach clang, the linker, or `ar`. */
|
|
2909
|
-
async function validCachedFile(object) {
|
|
2910
|
-
try {
|
|
2911
|
-
const digestPath = cacheDigestPath(object);
|
|
2912
|
-
const expected = (await readFile(digestPath, "utf8")).trim();
|
|
2913
|
-
const valid = /^[0-9a-f]{64}$/.test(expected) && (await fileDigest(object)) === expected;
|
|
2914
|
-
if (valid) {
|
|
2915
|
-
const now = new Date();
|
|
2916
|
-
await Promise.all([
|
|
2917
|
-
utimes(object, now, now).catch(() => undefined),
|
|
2918
|
-
utimes(digestPath, now, now).catch(() => undefined),
|
|
2919
|
-
]);
|
|
2920
|
-
}
|
|
2921
|
-
return valid;
|
|
2922
|
-
}
|
|
2923
|
-
catch {
|
|
2924
|
-
return false;
|
|
2925
|
-
}
|
|
2926
|
-
}
|
|
2927
|
-
/** Copy a cache entry and verify the private copy before it can become a
|
|
2928
|
-
* caller-visible artifact. Verifying after the copy closes the gap between a
|
|
2929
|
-
* source-side digest check and a concurrent replacement/truncation. */
|
|
2930
|
-
async function copyValidCachedFile(source, destination) {
|
|
2931
|
-
try {
|
|
2932
|
-
const digestPath = cacheDigestPath(source);
|
|
2933
|
-
const expected = (await readFile(digestPath, "utf8")).trim();
|
|
2934
|
-
if (!/^[0-9a-f]{64}$/.test(expected))
|
|
2935
|
-
return false;
|
|
2936
|
-
await copyFile(source, destination);
|
|
2937
|
-
if ((await fileDigest(destination)) !== expected) {
|
|
2938
|
-
await rm(destination, { force: true }).catch(() => undefined);
|
|
2939
|
-
return false;
|
|
2940
|
-
}
|
|
2941
|
-
const now = new Date();
|
|
2942
|
-
await Promise.all([
|
|
2943
|
-
utimes(source, now, now).catch(() => undefined),
|
|
2944
|
-
utimes(digestPath, now, now).catch(() => undefined),
|
|
2945
|
-
]);
|
|
2946
|
-
return true;
|
|
2947
|
-
}
|
|
2948
|
-
catch {
|
|
2949
|
-
await rm(destination, { force: true }).catch(() => undefined);
|
|
2950
|
-
return false;
|
|
2951
|
-
}
|
|
2952
|
-
}
|
|
2953
|
-
/** Publish a complete executable/archive and its digest through private names.
|
|
2954
|
-
* Data is installed before its verifier, so a racing reader can only observe
|
|
2955
|
-
* an invalid/missing digest and take the fresh-build path. */
|
|
2956
|
-
async function publishCachedFile(source, destination) {
|
|
2957
|
-
const directory = dirname(destination);
|
|
2958
|
-
await mkdir(directory, { recursive: true });
|
|
2959
|
-
const nonce = `${process.pid}-${Math.random().toString(36).slice(2)}`;
|
|
2960
|
-
const tmp = join(directory, `.tmp-${basename(destination).slice(0, 8)}-${nonce}`);
|
|
2961
|
-
const tmpDigest = `${tmp}.sha256`;
|
|
2962
|
-
try {
|
|
2963
|
-
await copyFile(source, tmp);
|
|
2964
|
-
await chmod(tmp, 0o600);
|
|
2965
|
-
await writeFile(tmpDigest, `${await fileDigest(tmp)}\n`, { mode: 0o600 });
|
|
2966
|
-
await rename(tmp, destination);
|
|
2967
|
-
await rename(tmpDigest, cacheDigestPath(destination));
|
|
2968
|
-
}
|
|
2969
|
-
finally {
|
|
2970
|
-
await Promise.all([
|
|
2971
|
-
rm(tmp, { force: true }).catch(() => undefined),
|
|
2972
|
-
rm(tmpDigest, { force: true }).catch(() => undefined),
|
|
2973
|
-
]);
|
|
2974
|
-
}
|
|
2975
|
-
}
|
|
2976
2438
|
async function directoryTreeDigest(root, excludedPaths = []) {
|
|
2977
2439
|
const hash = createHash("sha256").update("native-dependency-tree-v1\0");
|
|
2978
2440
|
const visited = new Set();
|
|
@@ -3069,6 +2531,12 @@ async function snapshotLocalArtifactDependencies(dependencyPaths, recursiveDirec
|
|
|
3069
2531
|
const recursive = new Set(recursiveDirectories.map((path) => resolve(path)));
|
|
3070
2532
|
return Promise.all([...new Set(dependencyPaths)].sort().map((path) => snapshotLocalArtifactDependency(path, recursive.has(resolve(path)) ? recursiveExclusions : null)));
|
|
3071
2533
|
}
|
|
2534
|
+
/** Capture exact filesystem identities for inputs produced outside the C
|
|
2535
|
+
* toolchain but consumed by its cache proofs. Callers carry this snapshot
|
|
2536
|
+
* forward so later stages can prove the same inputs remained installed. */
|
|
2537
|
+
export async function snapshotNativeArtifactDependencies(dependencyPaths) {
|
|
2538
|
+
return snapshotLocalArtifactDependencies(dependencyPaths);
|
|
2539
|
+
}
|
|
3072
2540
|
export async function nativeArtifactDependenciesStillMatch(dependencies) {
|
|
3073
2541
|
if (!dependencies.every((dependency) => dependency !== null && typeof dependency === "object" &&
|
|
3074
2542
|
typeof dependency.path === "string" &&
|
|
@@ -3167,15 +2635,21 @@ function localArtifactIdentity(opts, driver, environmentFingerprint, compilerIde
|
|
|
3167
2635
|
// output-local fast-path identity.
|
|
3168
2636
|
.filter(([key, value]) => value !== undefined && key !== "programShards" && key !== "programPublicSymbols")
|
|
3169
2637
|
.sort(([a], [b]) => a.localeCompare(b)));
|
|
2638
|
+
const executableSectionFlags = executableSectionEliminationFlags(targetPlatform(driver));
|
|
3170
2639
|
const hash = createHash("sha256")
|
|
3171
|
-
.
|
|
2640
|
+
// v2 adds the executable section-GC recipe. A v1 output-local stamp can
|
|
2641
|
+
// name a same-source binary from before unused runtime sections were
|
|
2642
|
+
// eliminated, so it must never short-circuit the new linker invocation.
|
|
2643
|
+
.update("local-artifact-v2\0")
|
|
3172
2644
|
.update(cacheTargetIdentity(driver)).update("\0")
|
|
3173
2645
|
.update(environmentFingerprint).update("\0")
|
|
3174
2646
|
.update(compilerIdentity).update("\0")
|
|
3175
2647
|
.update(runtimeHash).update("\0")
|
|
3176
2648
|
.update(driver.argv.join("\x1f")).update("\0")
|
|
3177
2649
|
.update(driver.targetArgs.join("\x1f")).update("\0")
|
|
3178
|
-
.update(driver.linkArgs.join("\x1f")).update("\0")
|
|
2650
|
+
.update(driver.linkArgs.join("\x1f")).update("\0")
|
|
2651
|
+
.update(executableSectionFlags.compile.join("\x1f")).update("\0")
|
|
2652
|
+
.update(executableSectionFlags.link.join("\x1f")).update("\0");
|
|
3179
2653
|
if (programShardMerge !== null) {
|
|
3180
2654
|
updateProgramShardCacheIdentity(hash, opts.programShards, opts.programPublicSymbols, programShardMerge);
|
|
3181
2655
|
}
|
|
@@ -3374,71 +2848,15 @@ export async function stageRuntimeObjects(objects, stageDir) {
|
|
|
3374
2848
|
}));
|
|
3375
2849
|
return new Map(staged);
|
|
3376
2850
|
}
|
|
3377
|
-
/** Size-capped LRU sweep of the whole cache root. A caller-configured cap is
|
|
3378
|
-
* enforced after every successful cache write. The 4 GiB default is checked on
|
|
3379
|
-
* the first and every 64th write in a long-lived process: a full tree walk per
|
|
3380
|
-
* corpus program would otherwise become quadratic as the cache grows. Oldest-
|
|
3381
|
-
* mtime files go first until the tree is back under 75% of the cap; reads bump
|
|
3382
|
-
* mtimes. Active links use private staged names/hard links, so cache names can
|
|
3383
|
-
* be unlinked safely. */
|
|
3384
|
-
const rootWriteCounts = new Map();
|
|
3385
|
-
async function pruneCache(root, protectedPaths) {
|
|
3386
|
-
const configuredCap = process.env["SCRIPTC_CACHE_MAX_MB"];
|
|
3387
|
-
const writes = (rootWriteCounts.get(root) ?? 0) + 1;
|
|
3388
|
-
rootWriteCounts.set(root, writes);
|
|
3389
|
-
if (configuredCap === undefined && writes !== 1 && writes % 64 !== 0)
|
|
3390
|
-
return;
|
|
3391
|
-
const capBytes = Number(configuredCap ?? "4096") * 1024 * 1024;
|
|
3392
|
-
if (!Number.isFinite(capBytes) || capBytes <= 0)
|
|
3393
|
-
return;
|
|
3394
|
-
const files = [];
|
|
3395
|
-
const walk = async (dir) => {
|
|
3396
|
-
const entries = await readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
3397
|
-
for (const ent of entries) {
|
|
3398
|
-
const p = join(dir, ent.name);
|
|
3399
|
-
if (ent.isDirectory())
|
|
3400
|
-
await walk(p);
|
|
3401
|
-
else if (ent.isFile()) {
|
|
3402
|
-
// Atomic publishers use private names until their data/digest or
|
|
3403
|
-
// metadata stamp is complete. They are active writes, not LRU entries.
|
|
3404
|
-
if (ent.name.startsWith(".scriptc-") ||
|
|
3405
|
-
ent.name.startsWith(".tmp-") ||
|
|
3406
|
-
ent.name.includes(".tmp-"))
|
|
3407
|
-
continue;
|
|
3408
|
-
if (protectedPaths?.has(p))
|
|
3409
|
-
continue;
|
|
3410
|
-
const s = await stat(p).catch(() => null);
|
|
3411
|
-
if (s !== null)
|
|
3412
|
-
files.push({ path: p, size: s.size, mtimeMs: s.mtimeMs });
|
|
3413
|
-
}
|
|
3414
|
-
}
|
|
3415
|
-
};
|
|
3416
|
-
await walk(root);
|
|
3417
|
-
let total = files.reduce((n, f) => n + f.size, 0);
|
|
3418
|
-
if (total <= capBytes)
|
|
3419
|
-
return;
|
|
3420
|
-
files.sort((a, b) => a.mtimeMs - b.mtimeMs);
|
|
3421
|
-
for (const f of files) {
|
|
3422
|
-
if (total <= capBytes * 0.75)
|
|
3423
|
-
break;
|
|
3424
|
-
try {
|
|
3425
|
-
await unlink(f.path);
|
|
3426
|
-
total -= f.size;
|
|
3427
|
-
}
|
|
3428
|
-
catch {
|
|
3429
|
-
// A concurrent reader/publisher may already have moved the name.
|
|
3430
|
-
}
|
|
3431
|
-
}
|
|
3432
|
-
}
|
|
3433
2851
|
/** Compiles one C program together with the runtime sources.
|
|
3434
2852
|
* With caching disabled, the runtime (a dozen small files) is recompiled on
|
|
3435
|
-
* every build in one
|
|
2853
|
+
* every build in one clang invocation — no cached-archive
|
|
3436
2854
|
* staleness bugs. --dynamic additionally compiles
|
|
3437
2855
|
* scr_island.c under SCR_DYNAMIC and links the cached engine archive (built
|
|
3438
2856
|
* lazily, see above); regex-using programs additionally compile scr_regex.c
|
|
3439
2857
|
* and link libregexp (the cached objects, or the archive's own copy under
|
|
3440
|
-
* --dynamic).
|
|
3441
|
-
*
|
|
2858
|
+
* --dynamic). Executable links use the target's section-elimination recipe
|
|
2859
|
+
* independently of those feature gates.
|
|
3442
2860
|
*
|
|
3443
2861
|
* With a caller-supplied dependency identity and an enabled cache root,
|
|
3444
2862
|
* unchanged programs skip payload code generation/linking via the binary
|
|
@@ -3498,8 +2916,9 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
3498
2916
|
`compile with a library profile (SCRIPTC_CC=zigcc scriptc build --lib --profile <profile.json>) and link the archive from the app project.`);
|
|
3499
2917
|
}
|
|
3500
2918
|
const runtimeSources = targetPlatform(driver) === "wasi"
|
|
3501
|
-
?
|
|
3502
|
-
:
|
|
2919
|
+
? EXECUTABLE_RUNTIME_SOURCES.filter((source) => source !== "scr_child.c")
|
|
2920
|
+
: EXECUTABLE_RUNTIME_SOURCES;
|
|
2921
|
+
const executableSectionFlags = executableSectionEliminationFlags(targetPlatform(driver));
|
|
3503
2922
|
// scr_async.c submits callback-style filesystem work to a native worker.
|
|
3504
2923
|
// POSIX drivers need the thread compile/link mode; win32 uses CreateThread.
|
|
3505
2924
|
const threadArgs = targetPlatform(driver) === "win32" || targetPlatform(driver) === "wasi"
|
|
@@ -3547,15 +2966,16 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
3547
2966
|
// inputs may include caller-owned headers whose contents are not otherwise
|
|
3548
2967
|
// represented in this key, so they retain the fully uncached historical
|
|
3549
2968
|
// path unless the caller supplies its own complete dependency identity.
|
|
3550
|
-
|
|
2969
|
+
const cacheIdentity = opts.cacheIdentity;
|
|
2970
|
+
let persistentCache = cacheIdentity === undefined || configuredCacheRoot === null || !persistentDriverCache
|
|
3551
2971
|
? null
|
|
3552
|
-
: configuredCacheRoot;
|
|
3553
|
-
if (cacheWarmOnly &&
|
|
2972
|
+
: { root: configuredCacheRoot, identity: cacheIdentity };
|
|
2973
|
+
if (cacheWarmOnly && persistentCache === null) {
|
|
3554
2974
|
throw new Error("native cache warming requires a persistently cacheable compiler environment");
|
|
3555
2975
|
}
|
|
3556
|
-
if (
|
|
2976
|
+
if (persistentCache !== null) {
|
|
3557
2977
|
try {
|
|
3558
|
-
await ensurePrivateCacheRoot(root, process.env["SCRIPTC_CACHE_DIR"] === undefined);
|
|
2978
|
+
await ensurePrivateCacheRoot(persistentCache.root, process.env["SCRIPTC_CACHE_DIR"] === undefined);
|
|
3559
2979
|
}
|
|
3560
2980
|
catch (error) {
|
|
3561
2981
|
if (cacheWarmOnly) {
|
|
@@ -3563,7 +2983,7 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
3563
2983
|
cause: error,
|
|
3564
2984
|
});
|
|
3565
2985
|
}
|
|
3566
|
-
|
|
2986
|
+
persistentCache = null;
|
|
3567
2987
|
}
|
|
3568
2988
|
}
|
|
3569
2989
|
let localArtifact = null;
|
|
@@ -3573,9 +2993,9 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
3573
2993
|
// FFI/native-input builds and the public arbitrary-C cache API stay on the
|
|
3574
2994
|
// strict path because their dependency graphs are caller-owned.
|
|
3575
2995
|
if (!cacheWarmOnly &&
|
|
3576
|
-
|
|
2996
|
+
persistentCache !== null &&
|
|
3577
2997
|
cachePolicy.completeArtifacts &&
|
|
3578
|
-
|
|
2998
|
+
persistentCache.identity === "scriptc-generated-v1" &&
|
|
3579
2999
|
(opts.linkInputs?.length ?? 0) === 0 &&
|
|
3580
3000
|
(opts.systemLibraries?.length ?? 0) === 0 &&
|
|
3581
3001
|
process.env["SCRIPTC_TEST_TRUST_COMPILER_WRAPPER"] !== "1") {
|
|
@@ -3588,7 +3008,7 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
3588
3008
|
if (compiler !== null) {
|
|
3589
3009
|
const effectiveCompiler = directCompilerSelections.get(compilerDriverProbeKey(driver, toolchainEnv)) ?? compiler;
|
|
3590
3010
|
const key = localArtifactIdentity(opts, driver, toolchainEnv, `${compiler.cacheIdentity}\0${effectiveCompiler.cacheIdentity}`, runtimeHash, programBytes, programShardMergeIdentity);
|
|
3591
|
-
const stampPath = localArtifactStampPath(root, opts.outPath);
|
|
3011
|
+
const stampPath = localArtifactStampPath(persistentCache.root, opts.outPath);
|
|
3592
3012
|
localArtifact = {
|
|
3593
3013
|
stampPath,
|
|
3594
3014
|
key,
|
|
@@ -3612,11 +3032,11 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
3612
3032
|
let implicitToolchain = null;
|
|
3613
3033
|
let implicitCompileToolchain = null;
|
|
3614
3034
|
let toolchainMetadataStamp = null;
|
|
3615
|
-
const metadataCompiler =
|
|
3035
|
+
const metadataCompiler = persistentCache === null
|
|
3616
3036
|
? null
|
|
3617
3037
|
: await resolvedTool(driver.argv[0] ?? "clang");
|
|
3618
3038
|
const metadataEffectiveCompiler = directCompilerSelections.get(compilerDriverProbeKey(driver, toolchainEnv)) ?? metadataCompiler;
|
|
3619
|
-
const toolchainMetadataKey =
|
|
3039
|
+
const toolchainMetadataKey = persistentCache === null ||
|
|
3620
3040
|
metadataCompiler === null ||
|
|
3621
3041
|
metadataEffectiveCompiler === null ||
|
|
3622
3042
|
process.env["SCRIPTC_TEST_TRUST_COMPILER_WRAPPER"] === "1"
|
|
@@ -3633,9 +3053,9 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
3633
3053
|
if (persistentDriverCache) {
|
|
3634
3054
|
try {
|
|
3635
3055
|
toolchainMetadataStamp =
|
|
3636
|
-
|
|
3056
|
+
persistentCache === null || toolchainMetadataKey === null
|
|
3637
3057
|
? null
|
|
3638
|
-
: await readNativeMetadataStamp(root, toolchainMetadataKey);
|
|
3058
|
+
: await readNativeMetadataStamp(persistentCache.root, toolchainMetadataKey);
|
|
3639
3059
|
implicitToolchain = toolchainMetadataStamp?.values["implicitToolchain"] ?? null;
|
|
3640
3060
|
implicitCompileToolchain =
|
|
3641
3061
|
toolchainMetadataStamp?.values["implicitCompileToolchain"] ?? null;
|
|
@@ -3648,13 +3068,13 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
3648
3068
|
}
|
|
3649
3069
|
let compilerVersion = toolchainMetadataStamp?.values["compilerVersion"];
|
|
3650
3070
|
if (compilerVersion === undefined) {
|
|
3651
|
-
compilerVersion = await
|
|
3071
|
+
compilerVersion = await ccVersion(driver.argv, toolchainEnv, true);
|
|
3652
3072
|
}
|
|
3653
3073
|
if (toolchainMetadataStamp === null &&
|
|
3654
|
-
|
|
3074
|
+
persistentCache !== null &&
|
|
3655
3075
|
toolchainMetadataKey !== null) {
|
|
3656
3076
|
if (metadataCompiler !== null && metadataEffectiveCompiler !== null) {
|
|
3657
|
-
toolchainMetadataStamp = await publishNativeMetadataStamp(root, toolchainMetadataKey, {
|
|
3077
|
+
toolchainMetadataStamp = await publishNativeMetadataStamp(persistentCache.root, toolchainMetadataKey, {
|
|
3658
3078
|
implicitToolchain,
|
|
3659
3079
|
...(implicitCompileToolchain === null ? {} : { implicitCompileToolchain }),
|
|
3660
3080
|
compilerVersion,
|
|
@@ -3680,7 +3100,7 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
3680
3100
|
cause: error,
|
|
3681
3101
|
});
|
|
3682
3102
|
}
|
|
3683
|
-
|
|
3103
|
+
persistentCache = null;
|
|
3684
3104
|
}
|
|
3685
3105
|
}
|
|
3686
3106
|
const vendorBuildIdentity = await currentVendorCacheBuildIdentity(driver, `${toolchainEnv}\0${implicitToolchain ?? "<uncached>"}`);
|
|
@@ -3689,10 +3109,10 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
3689
3109
|
// must follow the same rule instead of silently surviving in the user cache.
|
|
3690
3110
|
// A private root gives this invocation the usual vendor build recipe
|
|
3691
3111
|
// without publishing or reusing those prerequisites.
|
|
3692
|
-
const transientVendorRoot =
|
|
3112
|
+
const transientVendorRoot = persistentCache !== null && implicitToolchain !== null
|
|
3693
3113
|
? null
|
|
3694
3114
|
: join(tmpdir(), `scriptc-vendor-${process.pid}-${Math.random().toString(36).slice(2)}`);
|
|
3695
|
-
const vendorCacheRoot = transientVendorRoot ?? vendorBuildCacheRoot(root
|
|
3115
|
+
const vendorCacheRoot = transientVendorRoot ?? vendorBuildCacheRoot(persistentCache?.root);
|
|
3696
3116
|
// Every vendor output path is deterministic from pins, flags, driver, and
|
|
3697
3117
|
// target. Build the command/key from those paths now, but do not materialize
|
|
3698
3118
|
// them until a complete-binary lookup has missed.
|
|
@@ -3708,10 +3128,10 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
3708
3128
|
let lreObjects = regex && !dynamic
|
|
3709
3129
|
? lreObjectPaths(sanitize, driver, vendorBuildIdentity, vendorCacheRoot)
|
|
3710
3130
|
: [];
|
|
3711
|
-
// Vendored zlib is the
|
|
3131
|
+
// Vendored zlib is the Zig story — default host-clang builds keep the exact
|
|
3712
3132
|
// historical `-lz` system link (see CcOptions.zlib). The native fetch's
|
|
3713
3133
|
// gzip decoder rides the same objects/link.
|
|
3714
|
-
let zlibObjects = ((opts.zlib ?? false) || nativeFetch) && driver
|
|
3134
|
+
let zlibObjects = ((opts.zlib ?? false) || nativeFetch) && isZigDriver(driver)
|
|
3715
3135
|
? zlibObjectPaths(sanitize, driver, vendorBuildIdentity, vendorCacheRoot)
|
|
3716
3136
|
: [];
|
|
3717
3137
|
// The libcurl import stub is likewise CROSS-only — host builds keep the
|
|
@@ -3721,7 +3141,7 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
3721
3141
|
? curlStubDirPath(driver, vendorBuildIdentity, vendorCacheRoot)
|
|
3722
3142
|
: null;
|
|
3723
3143
|
const materializeVendorPrerequisites = async (stageRoot, materializeCacheRoot = vendorCacheRoot) => {
|
|
3724
|
-
// Preserve
|
|
3144
|
+
// Preserve source order to avoid multiplying first-build resource
|
|
3725
3145
|
// pressure when several large vendor sets are cold simultaneously.
|
|
3726
3146
|
if (dynamic) {
|
|
3727
3147
|
const cachedArchive = engineArchivePath(sanitize, driver, vendorBuildIdentity, materializeCacheRoot);
|
|
@@ -3781,6 +3201,7 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
3781
3201
|
...(sanitize
|
|
3782
3202
|
? ["-O1", "-fsanitize=address", "-DSCR_RC_AUDIT"]
|
|
3783
3203
|
: [optimization === "dev" ? "-O0" : "-O2"]),
|
|
3204
|
+
...executableSectionFlags.compile,
|
|
3784
3205
|
...(opts.textDecoderLegacy ? ["-DSCR_TEXT_DECODER_LEGACY"] : []),
|
|
3785
3206
|
"-fno-math-errno",
|
|
3786
3207
|
// The emitted object model is deliberately type-punned C: a hierarchy
|
|
@@ -3822,14 +3243,14 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
3822
3243
|
...(opts.dc ? [rt(join(rtDir, "scr_dc.c"))] : []),
|
|
3823
3244
|
...(opts.dynAsync || opts.dynInvoke || opts.dc || nativeFetch ? [rt(join(rtDir, "scr_async_dyn.c"))] : []),
|
|
3824
3245
|
// The zlib UNIT (scr_zlib.c) gates on zlib.* IR use; the LINK (system
|
|
3825
|
-
// libz on
|
|
3246
|
+
// libz on the default host-clang build, vendored objects on Zig builds)
|
|
3826
3247
|
// also serves the native fetch's gzip decoder — spread exactly once.
|
|
3827
3248
|
...(opts.zlib
|
|
3828
|
-
? driver
|
|
3249
|
+
? isZigDriver(driver)
|
|
3829
3250
|
? ["-I", vendorZlibDir(), rt(join(rtDir, "scr_zlib.c")), ...zlibObjects]
|
|
3830
3251
|
: [rt(join(rtDir, "scr_zlib.c"))]
|
|
3831
3252
|
: nativeFetch
|
|
3832
|
-
? driver
|
|
3253
|
+
? isZigDriver(driver)
|
|
3833
3254
|
? ["-I", vendorZlibDir(), ...zlibObjects]
|
|
3834
3255
|
: []
|
|
3835
3256
|
: []),
|
|
@@ -3921,11 +3342,6 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
3921
3342
|
// left-to-right archive resolution. Other dynamic targets keep
|
|
3922
3343
|
// the historical engine-adjacent spelling.
|
|
3923
3344
|
...(driver.linkArgs.includes("-lm") ? [] : ["-lm"]),
|
|
3924
|
-
// ld64 dead-stripping claws back a chunk of the engine archive;
|
|
3925
|
-
// harmless elsewhere but only spelled this way on macOS. Keyed on
|
|
3926
|
-
// the TARGET platform (= the host on the default path, where this
|
|
3927
|
-
// expression is byte-identical to the historical one).
|
|
3928
|
-
...(targetPlatform(driver) === "darwin" ? ["-Wl,-dead_strip"] : []),
|
|
3929
3345
|
// The PE stack reserve, pinned to the 8MB POSIX main-stack
|
|
3930
3346
|
// geometry ISL_MAIN_STACK_BUDGET is sized against (4MB engine
|
|
3931
3347
|
// budget + 4MB excursion margin) — quickjs-ng's own CMake makes
|
|
@@ -3953,16 +3369,17 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
3953
3369
|
...(opts.linkInputs ?? []),
|
|
3954
3370
|
...(opts.systemLibraries ?? []).map((name) => `-l${name}`),
|
|
3955
3371
|
// GNU ld resolves libraries from left to right and commonly enables
|
|
3956
|
-
// --as-needed: host libz must follow scr_zlib.c/scr_fetch.c and every
|
|
3372
|
+
// --as-needed: host-clang libz must follow scr_zlib.c/scr_fetch.c and every
|
|
3957
3373
|
// generated/native input that references inflate symbols. Cross
|
|
3958
|
-
// builds use vendored zlib objects in the input section above.
|
|
3959
|
-
...(((opts.zlib ?? false) || nativeFetch) && driver
|
|
3374
|
+
// and targetless Zig builds use vendored zlib objects in the input section above.
|
|
3375
|
+
...(((opts.zlib ?? false) || nativeFetch) && !isZigDriver(driver)
|
|
3960
3376
|
? ["-lz"]
|
|
3961
3377
|
: []),
|
|
3962
3378
|
// glibc keeps libm separate from libc. This must trail the generated
|
|
3963
3379
|
// program and every native FFI input because GNU ld resolves archives
|
|
3964
3380
|
// from left to right.
|
|
3965
3381
|
...driver.linkArgs,
|
|
3382
|
+
...executableSectionFlags.link,
|
|
3966
3383
|
"-o", build.outPath ?? opts.outPath,
|
|
3967
3384
|
];
|
|
3968
3385
|
// Compile-only flags shared by runtime-object population and the caller-TU
|
|
@@ -3975,6 +3392,7 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
3975
3392
|
...(sanitize
|
|
3976
3393
|
? ["-O1", "-fsanitize=address", "-DSCR_RC_AUDIT"]
|
|
3977
3394
|
: [optimization === "dev" ? "-O0" : "-O2"]),
|
|
3395
|
+
...executableSectionFlags.compile,
|
|
3978
3396
|
...(opts.textDecoderLegacy ? ["-DSCR_TEXT_DECODER_LEGACY"] : []),
|
|
3979
3397
|
"-fno-math-errno",
|
|
3980
3398
|
"-fno-strict-aliasing", // the emitted object model type-puns — see buildArgs
|
|
@@ -4021,7 +3439,7 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
4021
3439
|
let programCompilerInvocation = null;
|
|
4022
3440
|
let payloadMetadata = null;
|
|
4023
3441
|
let compileMetadataStamp = null;
|
|
4024
|
-
const compileMetadataKey =
|
|
3442
|
+
const compileMetadataKey = persistentCache === null || process.env["SCRIPTC_TEST_TRUST_COMPILER_WRAPPER"] === "1"
|
|
4025
3443
|
? null
|
|
4026
3444
|
: nativeMetadataKey("compile", [
|
|
4027
3445
|
cacheTargetIdentity(driver),
|
|
@@ -4032,14 +3450,14 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
4032
3450
|
programCompilerArgs,
|
|
4033
3451
|
programSourceExtension,
|
|
4034
3452
|
]);
|
|
4035
|
-
if (
|
|
3453
|
+
if (persistentCache !== null) {
|
|
4036
3454
|
try {
|
|
4037
3455
|
// These probes inspect disjoint inputs. Start the payload reads here as
|
|
4038
3456
|
// well so runtime hashing and clang's dry-run traces overlap instead of
|
|
4039
3457
|
// forming a serial prelude before every cache lookup.
|
|
4040
3458
|
payloadMetadata = Promise.all([
|
|
4041
3459
|
Promise.resolve(toolchainMetadataStamp?.values["compilerVersion"] ??
|
|
4042
|
-
|
|
3460
|
+
ccVersion(driver.argv, toolchainEnv, true)),
|
|
4043
3461
|
localArtifact === null
|
|
4044
3462
|
? runtimeFingerprint(rtDir)
|
|
4045
3463
|
: Promise.resolve(localArtifact.runtimeHash),
|
|
@@ -4049,7 +3467,7 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
4049
3467
|
]);
|
|
4050
3468
|
compileMetadataStamp = compileMetadataKey === null
|
|
4051
3469
|
? null
|
|
4052
|
-
: await readNativeMetadataStamp(root, compileMetadataKey);
|
|
3470
|
+
: await readNativeMetadataStamp(persistentCache.root, compileMetadataKey);
|
|
4053
3471
|
if (compileMetadataStamp !== null) {
|
|
4054
3472
|
runtimeCompilerInvocation = compileMetadataStamp.values["runtimeInvocation"] ?? null;
|
|
4055
3473
|
programCompilerInvocation = compileMetadataStamp.values["programInvocation"] ?? null;
|
|
@@ -4067,7 +3485,7 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
4067
3485
|
runtimeCompilerInvocation = runtimeInvocation;
|
|
4068
3486
|
programCompilerInvocation = programInvocation ?? runtimeInvocation;
|
|
4069
3487
|
if (compileMetadataKey !== null) {
|
|
4070
|
-
compileMetadataStamp = await publishNativeMetadataStamp(root, compileMetadataKey, {
|
|
3488
|
+
compileMetadataStamp = await publishNativeMetadataStamp(persistentCache.root, compileMetadataKey, {
|
|
4071
3489
|
runtimeInvocation: runtimeCompilerInvocation,
|
|
4072
3490
|
programInvocation: programCompilerInvocation,
|
|
4073
3491
|
}, [
|
|
@@ -4085,11 +3503,11 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
4085
3503
|
cause: error,
|
|
4086
3504
|
});
|
|
4087
3505
|
}
|
|
4088
|
-
|
|
3506
|
+
persistentCache = null;
|
|
4089
3507
|
}
|
|
4090
3508
|
}
|
|
4091
|
-
if (
|
|
4092
|
-
// The
|
|
3509
|
+
if (persistentCache === null) {
|
|
3510
|
+
// The direct uncached command is the source-of-truth executable recipe.
|
|
4093
3511
|
await runUncachedBuild();
|
|
4094
3512
|
return;
|
|
4095
3513
|
}
|
|
@@ -4098,7 +3516,7 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
4098
3516
|
let cBytes;
|
|
4099
3517
|
try {
|
|
4100
3518
|
[cv, fingerprint, cBytes] = await (payloadMetadata ?? Promise.all([
|
|
4101
|
-
|
|
3519
|
+
ccVersion(driver.argv, toolchainEnv, true),
|
|
4102
3520
|
runtimeFingerprint(rtDir),
|
|
4103
3521
|
readFile(opts.cPath),
|
|
4104
3522
|
]));
|
|
@@ -4135,8 +3553,9 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
4135
3553
|
...(tlsCa && targetPlatform(driver) === "win32" ? ["-lcrypt32"] : []),
|
|
4136
3554
|
...(curlFetch && driver.target === null ? ["-lcurl"] : []),
|
|
4137
3555
|
...(dynamic && !driver.linkArgs.includes("-lm") ? ["-lm"] : []),
|
|
4138
|
-
...(((opts.zlib ?? false) || nativeFetch) && driver
|
|
3556
|
+
...(((opts.zlib ?? false) || nativeFetch) && !isZigDriver(driver) ? ["-lz"] : []),
|
|
4139
3557
|
...driver.linkArgs,
|
|
3558
|
+
...executableSectionFlags.link,
|
|
4140
3559
|
];
|
|
4141
3560
|
// Both the wrapper dry run and dependency trace need the real build's
|
|
4142
3561
|
// compile/link flag shape: wrappers commonly inject flags or native inputs
|
|
@@ -4151,12 +3570,12 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
4151
3570
|
...(curlStubDir !== null ? [`-L${curlStubDir}`] : []),
|
|
4152
3571
|
...(curlFetch && driver.target === null ? ["-lcurl"] : []),
|
|
4153
3572
|
...(dynamic && !driver.linkArgs.includes("-lm") ? ["-lm"] : []),
|
|
4154
|
-
...(dynamic && targetPlatform(driver) === "darwin" ? ["-Wl,-dead_strip"] : []),
|
|
4155
3573
|
...(dynamic && targetPlatform(driver) === "win32"
|
|
4156
3574
|
? ["-Wl,--stack,8388608"]
|
|
4157
3575
|
: []),
|
|
4158
|
-
...(((opts.zlib ?? false) || nativeFetch) && driver
|
|
3576
|
+
...(((opts.zlib ?? false) || nativeFetch) && !isZigDriver(driver) ? ["-lz"] : []),
|
|
4159
3577
|
...driver.linkArgs,
|
|
3578
|
+
...executableSectionFlags.link,
|
|
4160
3579
|
];
|
|
4161
3580
|
// A complete hit is checked before cross-target curl's generated import stub
|
|
4162
3581
|
// is materialized. Its -L spelling still joins the dry-run identity, while
|
|
@@ -4168,7 +3587,7 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
4168
3587
|
let preBuildDependencies = null;
|
|
4169
3588
|
let localArtifactDependencyPaths = null;
|
|
4170
3589
|
let linkMetadataStamp = null;
|
|
4171
|
-
const linkMetadataKey =
|
|
3590
|
+
const linkMetadataKey = process.env["SCRIPTC_TEST_TRUST_COMPILER_WRAPPER"] === "1"
|
|
4172
3591
|
? null
|
|
4173
3592
|
: nativeMetadataKey("link", [
|
|
4174
3593
|
cacheTargetIdentity(driver),
|
|
@@ -4189,7 +3608,7 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
4189
3608
|
// cache hits and ordinary edit/build misses without changing either key.
|
|
4190
3609
|
linkMetadataStamp = linkMetadataKey === null
|
|
4191
3610
|
? null
|
|
4192
|
-
: await readNativeMetadataStamp(root, linkMetadataKey);
|
|
3611
|
+
: await readNativeMetadataStamp(persistentCache.root, linkMetadataKey);
|
|
4193
3612
|
if (linkMetadataStamp !== null) {
|
|
4194
3613
|
implicitLinker = linkMetadataStamp.values["implicitLinker"] ?? null;
|
|
4195
3614
|
if (implicitLinker === null)
|
|
@@ -4202,7 +3621,7 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
4202
3621
|
: Promise.resolve(implicitLinker),
|
|
4203
3622
|
]);
|
|
4204
3623
|
if (linkMetadataStamp === null && linkMetadataKey !== null) {
|
|
4205
|
-
linkMetadataStamp = await publishNativeMetadataStamp(root, linkMetadataKey, { implicitLinker }, fingerprintDependencyPaths(implicitLinker), [implicitLinker]);
|
|
3624
|
+
linkMetadataStamp = await publishNativeMetadataStamp(persistentCache.root, linkMetadataKey, { implicitLinker }, fingerprintDependencyPaths(implicitLinker), [implicitLinker]);
|
|
4206
3625
|
}
|
|
4207
3626
|
preBuildDependencies = await snapshotLocalArtifactDependencies([
|
|
4208
3627
|
...(await runtimeFingerprintInputPaths(rtDir)),
|
|
@@ -4274,7 +3693,7 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
4274
3693
|
});
|
|
4275
3694
|
}
|
|
4276
3695
|
}
|
|
4277
|
-
const binDir = join(root, "bin");
|
|
3696
|
+
const binDir = join(persistentCache.root, "bin");
|
|
4278
3697
|
let keyHex = null;
|
|
4279
3698
|
let cachedBin = null;
|
|
4280
3699
|
if (cacheCompleteArtifact) {
|
|
@@ -4296,7 +3715,7 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
4296
3715
|
.update(programCompilerInvocation).update("\0")
|
|
4297
3716
|
.update(implicitLinker).update("\0")
|
|
4298
3717
|
.update(programDependencies).update("\0")
|
|
4299
|
-
.update(
|
|
3718
|
+
.update(persistentCache.identity).update("\0")
|
|
4300
3719
|
// Preserve both the spelling clang sees (__FILE__) and the location used
|
|
4301
3720
|
// to resolve relative includes. The top-level bytes are not sufficient.
|
|
4302
3721
|
.update(opts.cPath).update("\0")
|
|
@@ -4329,7 +3748,7 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
4329
3748
|
await chmod(tmpOut, 0o777 & ~process.umask());
|
|
4330
3749
|
await rename(tmpOut, opts.outPath);
|
|
4331
3750
|
if (localArtifact !== null && localArtifactDependencyPaths !== null) {
|
|
4332
|
-
const stamp = await publishLocalArtifactStamp(localArtifact.stampPath, opts.outPath, localArtifact.key, localArtifactDependencyPaths, [dirname(resolve(opts.cPath))], [root]).catch(() => null);
|
|
3751
|
+
const stamp = await publishLocalArtifactStamp(localArtifact.stampPath, opts.outPath, localArtifact.key, localArtifactDependencyPaths, [dirname(resolve(opts.cPath))], [persistentCache.root]).catch(() => null);
|
|
4333
3752
|
if (stamp !== null) {
|
|
4334
3753
|
await opts.onArtifactReady?.({ dependencies: stamp.dependencies }).catch(() => undefined);
|
|
4335
3754
|
}
|
|
@@ -4357,7 +3776,7 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
4357
3776
|
// between hashing and clang and publish one invocation's code under the
|
|
4358
3777
|
// other's key. The prefix map preserves the original __FILE__/debug-file
|
|
4359
3778
|
// spelling while clang reads this invocation-private snapshot.
|
|
4360
|
-
const programPath = join(buildDir, `program${
|
|
3779
|
+
const programPath = join(buildDir, `program${programSourceExtension}`);
|
|
4361
3780
|
// Preserve the caller-visible basename while keeping Darwin builds on a
|
|
4362
3781
|
// private inode: ld uses this spelling as the embedded ad-hoc signing
|
|
4363
3782
|
// identifier. Other targets retain the basename-independent cache key.
|
|
@@ -4387,7 +3806,7 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
4387
3806
|
return strictObjectVerification;
|
|
4388
3807
|
};
|
|
4389
3808
|
try {
|
|
4390
|
-
const cached = await ensureRuntimeObjects(root, driver.argv, cflags, rtInputs, `obj-v5\0${cacheTargetIdentity(driver)}\0${toolchainEnv}\0${implicitToolchain}\0${runtimeCompilerInvocation}\0${ccName}\0${cv}\0${fingerprint}\0`, async () => await objectImplicitToolchainStillMatches(), cacheWarmPaths);
|
|
3809
|
+
const cached = await ensureRuntimeObjects(persistentCache.root, driver.argv, cflags, rtInputs, `obj-v5\0${cacheTargetIdentity(driver)}\0${toolchainEnv}\0${implicitToolchain}\0${runtimeCompilerInvocation}\0${ccName}\0${cv}\0${fingerprint}\0`, async () => await objectImplicitToolchainStillMatches(), cacheWarmPaths);
|
|
4391
3810
|
objects = await stageRuntimeObjects(cached, join(buildDir, "runtime-objects"));
|
|
4392
3811
|
}
|
|
4393
3812
|
catch (err) {
|
|
@@ -4417,7 +3836,7 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
4417
3836
|
.update(toolchainEnv).update("\0")
|
|
4418
3837
|
.update(implicitCompileToolchain).update("\0")
|
|
4419
3838
|
.update(programCompilerInvocation).update("\0")
|
|
4420
|
-
.update(
|
|
3839
|
+
.update(persistentCache.identity).update("\0")
|
|
4421
3840
|
.update(driver.argv.join("\x1f")).update("\0")
|
|
4422
3841
|
.update(cv).update("\0")
|
|
4423
3842
|
.update(fingerprint).update("\0")
|
|
@@ -4432,7 +3851,7 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
4432
3851
|
...shard,
|
|
4433
3852
|
sourcePath,
|
|
4434
3853
|
staged,
|
|
4435
|
-
cachePath: join(root, "program-shard", key),
|
|
3854
|
+
cachePath: join(persistentCache.root, "program-shard", key),
|
|
4436
3855
|
missed: false,
|
|
4437
3856
|
};
|
|
4438
3857
|
});
|
|
@@ -4453,7 +3872,7 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
4453
3872
|
]);
|
|
4454
3873
|
}));
|
|
4455
3874
|
}
|
|
4456
|
-
const arArgv = driver
|
|
3875
|
+
const arArgv = isZigDriver(driver) ? [driver.argv[0], "ar"] : ["ar"];
|
|
4457
3876
|
const merged = await localizeLibraryObjects(driver, arArgv, buildDir, entries.map((entry) => entry.staged), [], programPublicSymbols, `${stem}.program`);
|
|
4458
3877
|
const publishable = entries.filter((entry) => entry.missed);
|
|
4459
3878
|
if (publishable.length > 0) {
|
|
@@ -4463,7 +3882,7 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
4463
3882
|
implicitToolchainFingerprints(driver, toolchainEnv),
|
|
4464
3883
|
effectiveCompilerInvocationFingerprint(driver, toolchainEnv, programCompilerArgs, ".ll"),
|
|
4465
3884
|
translationUnitDependencyFingerprint(driver, cflags, opts.cPath, cBytes, toolchainEnv),
|
|
4466
|
-
|
|
3885
|
+
ccVersion(driver.argv, toolchainEnv, true),
|
|
4467
3886
|
resolveProgramShardMergeIdentity(driver),
|
|
4468
3887
|
]);
|
|
4469
3888
|
if (currentRuntime === fingerprint &&
|
|
@@ -4511,7 +3930,7 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
4511
3930
|
effectiveCompilerInvocationFingerprint(driver, toolchainEnv, programCompilerArgs, programSourceExtension).catch(() => null),
|
|
4512
3931
|
translationUnitDependencyFingerprint(driver, cflags, opts.cPath, cBytes, toolchainEnv).catch(() => null),
|
|
4513
3932
|
implicitLinkerFingerprint(driver, toolchainEnv, linkProbeArgs, effectiveLinkInvocationArgs, linkTraceInvocationArgs).catch(() => null),
|
|
4514
|
-
|
|
3933
|
+
ccVersion(driver.argv, toolchainEnv, true).catch(() => null),
|
|
4515
3934
|
programShards === null
|
|
4516
3935
|
? Promise.resolve(null)
|
|
4517
3936
|
: resolveProgramShardMergeIdentity(driver).catch(() => null),
|
|
@@ -4544,7 +3963,7 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
4544
3963
|
localArtifactDependencyPaths !== null &&
|
|
4545
3964
|
cacheCompleteArtifact &&
|
|
4546
3965
|
cacheInputsStable) {
|
|
4547
|
-
const stamp = await publishLocalArtifactStamp(localArtifact.stampPath, opts.outPath, localArtifact.key, localArtifactDependencyPaths, [dirname(resolve(opts.cPath))], [root]).catch(() => null);
|
|
3966
|
+
const stamp = await publishLocalArtifactStamp(localArtifact.stampPath, opts.outPath, localArtifact.key, localArtifactDependencyPaths, [dirname(resolve(opts.cPath))], [persistentCache.root]).catch(() => null);
|
|
4548
3967
|
if (stamp !== null) {
|
|
4549
3968
|
await opts.onArtifactReady?.({ dependencies: stamp.dependencies }).catch(() => undefined);
|
|
4550
3969
|
}
|
|
@@ -4555,9 +3974,10 @@ async function compileCInternal(opts, cacheWarmOnly, cacheWarmPaths) {
|
|
|
4555
3974
|
}
|
|
4556
3975
|
// Runtime-object population is itself a cache write, including on builds
|
|
4557
3976
|
// whose native link inputs disable complete-artifact publication.
|
|
4558
|
-
await pruneCache(root, cacheWarmPaths).catch(() => undefined);
|
|
3977
|
+
await pruneCache(persistentCache.root, cacheWarmPaths).catch(() => undefined);
|
|
4559
3978
|
}
|
|
4560
3979
|
export async function compileC(opts) {
|
|
3980
|
+
clearCcCaches();
|
|
4561
3981
|
await compileCInternal(opts, false);
|
|
4562
3982
|
}
|
|
4563
3983
|
export function supportedNativeCacheWarmProfiles(driver) {
|
|
@@ -4571,6 +3991,7 @@ export function supportedNativeCacheWarmProfiles(driver) {
|
|
|
4571
3991
|
* before a developer's first program asks for them. Synthetic link products
|
|
4572
3992
|
* are discarded and never enter the complete-executable cache. */
|
|
4573
3993
|
export async function warmNativeCaches(options = {}) {
|
|
3994
|
+
clearCcCaches();
|
|
4574
3995
|
const cacheRoot = cacheRootDir();
|
|
4575
3996
|
if (cacheRoot === null) {
|
|
4576
3997
|
throw new Error("the native build cache is disabled (unset SCRIPTC_NO_CACHE and use a non-empty SCRIPTC_CACHE_DIR)");
|
|
@@ -4629,4 +4050,4 @@ export async function warmNativeCaches(options = {}) {
|
|
|
4629
4050
|
await rm(workDir, { recursive: true, force: true }).catch(() => undefined);
|
|
4630
4051
|
}
|
|
4631
4052
|
}
|
|
4632
|
-
//# sourceMappingURL=
|
|
4053
|
+
//# sourceMappingURL=native-toolchain.js.map
|