Files
Web_FreeCAD_Bitbybit/scripts/generate-freecad-naming-sdk-manifest.mjs
wangdequan f97eae4153
Some checks failed
real-verification / chrome (push) Has been cancelled
real-verification / freecad-oracle (push) Has been cancelled
real-verification / wasm (push) Has been cancelled
feat: add candidate FreeCAD naming SDK and attachment oracles
Build and verify the candidate-only FreeCAD naming bridge and OCCT worker path, including three-stage StringHasher restoration. Add Datum, ShapeBinder, attachment-mode, and PartDesign structure oracles plus offline SDK build plans and CI boundary checks.
2026-08-13 17:16:07 -04:00

93 lines
3.9 KiB
JavaScript

import { mkdir, writeFile } from 'node:fs/promises'
import { resolve, relative } from 'node:path'
import {
REQUIRED_FREECAD_NAMING_CALLBACKS,
REQUIRED_FREECAD_NAMING_DEFINITIONS,
inspectIncludeDirectory,
inspectPlannedLibrary,
inspectPlannedRuntimeAsset,
loadSdkPlan,
resolveFrom,
exists,
sha256File,
} from './freecad-naming-sdk-lib.mjs'
const root = resolve(new URL('..', import.meta.url).pathname)
const outputRoot = process.env.FREECAD_WASM_SDK_OUTPUT_DIR
? resolve(root, process.env.FREECAD_WASM_SDK_OUTPUT_DIR)
: resolve(root, '.cache/toolchains/freecad-naming-sdk')
const plan = await loadSdkPlan(root)
const fail = (message) => { throw new Error(`FreeCAD WASM SDK manifest generation: ${message}`) }
const libraries = []
for (const library of [...(plan.libraries ?? []), ...(plan.linkDependencies ?? [])]) {
const inspected = await inspectPlannedLibrary(root, library)
if (inspected.status !== 'verified') fail(`missing ${library.name} wasm static library: ${resolveFrom(root, library.path)}`)
libraries.push({
name: library.name,
path: relative(outputRoot, resolveFrom(root, library.path)),
sha256: inspected.sha256,
})
}
const includeDirs = []
for (const includeDir of plan.includeDirs ?? []) {
const inspected = await inspectIncludeDirectory(root, includeDir)
if (inspected.status !== 'verified') fail(`include directory ${includeDir.name} is incomplete: ${inspected.missingHeaders.join(', ')}`)
includeDirs.push(relative(outputRoot, resolveFrom(root, includeDir.path)))
}
const bridge = resolveFrom(root, plan.namingBridge.path)
if (!await exists(bridge)) fail(`missing naming bridge source: ${bridge}`)
const hostAdapter = resolveFrom(root, plan.namingBridge.hostAdapter)
if (!await exists(hostAdapter)) fail(`missing naming host adapter: ${hostAdapter}`)
const forceInclude = resolveFrom(root, plan.compileOptions.forceInclude)
if (!await exists(forceInclude)) fail(`missing force-include header: ${forceInclude}`)
if (plan.compileOptions.cxxStandard !== 'c++20' || plan.compileOptions.pthread !== true || JSON.stringify(plan.compileOptions.definitions) !== JSON.stringify(REQUIRED_FREECAD_NAMING_DEFINITIONS)) fail('compile options do not match the locked SDK contract')
const bridgeSha256 = await sha256File(bridge)
const runtimeAssets = []
for (const asset of plan.runtimeAssets ?? []) {
const inspected = await inspectPlannedRuntimeAsset(root, asset)
if (inspected.status !== 'verified') fail(`runtime asset ${asset.name} is incomplete: ${inspected.missingFiles.join(', ')}`)
runtimeAssets.push({
name: asset.name,
path: relative(outputRoot, resolveFrom(root, asset.path)),
preloadTo: asset.preloadTo,
files: inspected.files,
})
}
const manifest = {
schemaVersion: 1,
freecadVersion: plan.baseline.freecadVersion,
sourceCommit: plan.baseline.sourceCommit,
emscriptenVersion: plan.baseline.emscriptenVersion,
qtTarget: plan.baseline.target,
pythonTarget: plan.baseline.target,
includeDirs,
libraries,
namingBridge: {
source: relative(outputRoot, bridge),
sha256: bridgeSha256,
hostAdapter: relative(outputRoot, hostAdapter),
hostAdapterSha256: await sha256File(hostAdapter),
exports: [...REQUIRED_FREECAD_NAMING_CALLBACKS],
},
compileOptions: {
cxxStandard: plan.compileOptions.cxxStandard,
pthread: plan.compileOptions.pthread,
forceInclude: relative(outputRoot, forceInclude),
forceIncludeSha256: await sha256File(forceInclude),
definitions: [...plan.compileOptions.definitions],
},
runtimeAssets,
productionPublication: false,
boundary: { ...plan.boundary },
}
await mkdir(outputRoot, { recursive: true })
const output = resolve(outputRoot, 'manifest.json')
await writeFile(output, `${JSON.stringify(manifest, null, 2)}\n`)
console.log(JSON.stringify({
status: 'freecad-naming-sdk-manifest-generated',
output,
productionPublished: false,
systemExact: false,
}, null, 2))