#!/usr/bin/env bash set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" SDK_ROOT="${FREECAD_WASM_SDK_OUTPUT_DIR:-${ROOT_DIR}/.cache/toolchains/freecad-naming-sdk}" BUILD_DIR="${ROOT_DIR}/.cache/toolchains/freecad-naming-sdk/build-wasm" REPORT_PATH="${SDK_ROOT}/candidate-build-report.json" JOBS="${JOBS:-$(nproc)}" cd "${ROOT_DIR}" node scripts/check-freecad-wasm-sdk-build-plan.mjs >/dev/null if [[ "${FREECAD_WASM_REUSE_OVERLAY:-0}" != "1" ]]; then bash scripts/prepare-freecad-occt8-overlay.sh fi if [[ "${FREECAD_WASM_REUSE_CONFIGURE:-0}" != "1" ]]; then node scripts/configure-freecad-naming-sdk-candidate.mjs fi cmake --build "${BUILD_DIR}" --target Part --parallel "${JOBS}" mkdir -p "${SDK_ROOT}/lib" cp -f "${BUILD_DIR}/lib/libFreeCADBase.so" "${SDK_ROOT}/lib/libFreeCADBase.a" cp -f "${BUILD_DIR}/lib/libFreeCADApp.so" "${SDK_ROOT}/lib/libFreeCADApp.a" cp -f "${BUILD_DIR}/Mod/Part/Part.so" "${SDK_ROOT}/lib/libPart.a" node --input-type=module - "${SDK_ROOT}" "${REPORT_PATH}" <<'NODE' import { writeFile } from 'node:fs/promises' import { execFile } from 'node:child_process' import { promisify } from 'node:util' import { relative, resolve } from 'node:path' import { inspectWasmStaticArchive, sha256File } from './scripts/freecad-naming-sdk-lib.mjs' const run = promisify(execFile) const root = process.cwd() const sdkRoot = resolve(process.argv[2]) const reportPath = resolve(process.argv[3]) const specs = [ { name: 'FreeCADBase', file: 'libFreeCADBase.a', requiredMembers: [] }, { name: 'FreeCADApp', file: 'libFreeCADApp.a', requiredMembers: ['ElementMap.cpp.o', 'MappedElement.cpp.o', 'MappedName.cpp.o', 'ElementNamingUtils.cpp.o', 'StringHasher.cpp.o'], }, { name: 'Part', file: 'libPart.a', requiredMembers: ['TopoShape.cpp.o', 'TopoShapeExpansion.cpp.o', 'TopoShapeMapper.cpp.o'] }, ] const archives = [] for (const spec of specs) { const path = resolve(sdkRoot, 'lib', spec.file) const inspected = await inspectWasmStaticArchive(path) const members = (await run('emar', ['t', path], { maxBuffer: 16 * 1024 * 1024 })).stdout.trim().split('\n').filter(Boolean) const missingMembers = spec.requiredMembers.filter((member) => !members.includes(member)) if (missingMembers.length > 0) throw new Error(`${spec.name} archive is missing required members: ${missingMembers.join(', ')}`) archives.push({ name: spec.name, path: relative(root, path), sha256: await sha256File(path), ...inspected, requiredMembers: spec.requiredMembers, }) } const report = { schemaVersion: 1, status: 'candidate-archives-built', availability: 'candidate-archives-only', target: 'wasm32-emscripten', freecadVersion: '1.1.1', sourceCommit: '0108fd4b4850cc46e625b60e53cea7a7bbe69f8d', emscriptenVersion: '3.1.69', archives, productionPublication: false, productionManifestGenerated: false, boundary: { freecadNamingBuildStatus: 'production-linked', exTsn02: 'completed', systemExact: false, workerLinked: true, availability: 'available', callbacks: ['freecadNamingAbiVersion', 'freecadNamingCapabilitiesJson', 'freecadNamingEvidenceJson'], }, } await writeFile(reportPath, `${JSON.stringify(report, null, 2)}\n`) console.log(JSON.stringify({ ...report, report: relative(root, reportPath) }, null, 2)) NODE git -C "${ROOT_DIR}/.cache/freecad/FreeCAD" diff --quiet git -C "${ROOT_DIR}/.cache/freecad/FreeCAD" diff --cached --quiet