Files
Web_FreeCAD_Bitbybit/scripts/configure-freecad-naming-sdk-candidate.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

106 lines
7.4 KiB
JavaScript

import { mkdir, writeFile } from 'node:fs/promises'
import { execFile } from 'node:child_process'
import { promisify } from 'node:util'
import { resolve } from 'node:path'
const root = resolve(new URL('..', import.meta.url).pathname)
const run = promisify(execFile)
const sourceDir = resolve(root, '.cache/toolchains/freecad-naming-sdk/source-occt8')
const buildDir = resolve(root, '.cache/toolchains/freecad-naming-sdk/build-wasm')
const installDir = resolve(root, '.cache/toolchains/freecad-naming-sdk/install-wasm')
const qtPrefix = resolve(root, '.cache/toolchains/qt6/install-wasm-freecad')
const yamlPrefix = resolve(root, '.cache/toolchains/yaml-cpp/install-wasm')
const icuPrefix = resolve(root, '.cache/toolchains/icu/install-wasm')
const pythonPrefix = resolve(root, '.cache/toolchains/python/install-wasm')
const xercesPrefix = resolve(root, '.cache/toolchains/xerces-c/install-wasm')
const occtBuild = resolve(root, '.cache/bitbybit/occt-history-build-offline')
const occtSource = resolve(root, '.cache/occt/occt')
const offlineSysroot = resolve(root, '.cache/offline-sysroot')
const boostPrefix = resolve(root, '.cache/toolchains/boost/install-wasm')
const reportPath = resolve(root, '.cache/toolchains/freecad-naming-sdk/configure-report.json')
const command = [
'emcmake', 'cmake', '--fresh', '-S', sourceDir, '-B', buildDir, '-G', 'Ninja',
'-DCMAKE_BUILD_TYPE=Release',
`-DCMAKE_INSTALL_PREFIX=${installDir}`,
`-DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=${resolve(root, 'config/freecad-wasm-sdk-bootstrap.cmake')}`,
'-DBUILD_GUI=OFF', '-DBUILD_PART=ON', '-DBUILD_MATERIAL=ON', '-DBUILD_BIM=OFF', '-DBUILD_FLAT_MESH=OFF',
'-DBUILD_PART_DESIGN=OFF', '-DBUILD_SKETCHER=OFF',
'-DBUILD_MESH=OFF', '-DBUILD_MESH_PART=OFF', '-DBUILD_FEM=OFF', '-DBUILD_CAM=OFF', '-DBUILD_ASSEMBLY=OFF',
'-DBUILD_DRAFT=OFF', '-DBUILD_DRAWING=OFF', '-DBUILD_HELP=OFF', '-DBUILD_IDF=OFF', '-DBUILD_IMPORT=OFF',
'-DBUILD_INSPECTION=OFF', '-DBUILD_OPENSCAD=OFF', '-DBUILD_PLOT=OFF', '-DBUILD_POINTS=OFF',
'-DBUILD_REVERSEENGINEERING=OFF', '-DBUILD_ROBOT=OFF', '-DBUILD_SHOW=OFF', '-DBUILD_SPREADSHEET=OFF',
'-DBUILD_START=OFF', '-DBUILD_SURFACE=OFF', '-DBUILD_TECHDRAW=OFF', '-DBUILD_TEST=OFF', '-DBUILD_TUX=OFF',
'-DBUILD_WEB=OFF', '-DBUILD_ADDONMGR=OFF', '-DBUILD_MEASURE=OFF', '-DBUILD_CLOUD=OFF', '-DBUILD_JTREADER=OFF',
'-DBUILD_VR=OFF', '-DBUILD_TEMPLATE=OFF', '-DBUILD_SANDBOX=OFF', '-DENABLE_DEVELOPER_TESTS=OFF',
'-DFREECAD_USE_FREETYPE=OFF', '-DFREECAD_USE_EXTERNAL_FMT=ON', '-DFREECAD_CHECK_PIVY=OFF',
'-DINSTALL_TO_SITEPACKAGES=OFF', '-DFREECAD_USE_CCACHE=OFF', '-DBUILD_DYNAMIC_LINK_PYTHON=OFF',
`-DFREECAD_WASM_OFFLINE_SYSROOT=${offlineSysroot}`,
`-DCMAKE_PREFIX_PATH=${qtPrefix};${yamlPrefix};${icuPrefix};${xercesPrefix}`,
`-DQt6_DIR=${resolve(qtPrefix, 'lib/cmake/Qt6')}`,
`-DQt6Core_DIR=${resolve(qtPrefix, 'lib/cmake/Qt6Core')}`,
`-DQt6Concurrent_DIR=${resolve(qtPrefix, 'lib/cmake/Qt6Concurrent')}`,
`-DQt6Network_DIR=${resolve(qtPrefix, 'lib/cmake/Qt6Network')}`,
`-DQt6Xml_DIR=${resolve(qtPrefix, 'lib/cmake/Qt6Xml')}`,
`-DQt6ZlibPrivate_DIR=${resolve(qtPrefix, 'lib/cmake/Qt6ZlibPrivate')}`,
`-DQt6BundledZLIB_DIR=${resolve(qtPrefix, 'lib/cmake/Qt6BundledZLIB')}`,
`-DQt6BundledPcre2_DIR=${resolve(qtPrefix, 'lib/cmake/Qt6BundledPcre2')}`,
`-DZLIB_INCLUDE_DIR=${resolve(qtPrefix, 'include/QtZlib')}`,
`-DZLIB_LIBRARY=${resolve(qtPrefix, 'lib/libQt6BundledZLIB.a')}`,
`-Dyaml-cpp_DIR=${resolve(yamlPrefix, 'lib/cmake/yaml-cpp')}`,
`-DICU_ROOT=${icuPrefix}`,
`-DICU_INCLUDE_DIR=${resolve(icuPrefix, 'include')}`,
`-DICU_UC_LIBRARY_RELEASE=${resolve(icuPrefix, 'lib/libicuuc.a')}`,
`-DICU_I18N_LIBRARY_RELEASE=${resolve(icuPrefix, 'lib/libicui18n.a')}`,
`-DXercesC_INCLUDE_DIR=${resolve(xercesPrefix, 'include')}`,
`-DXercesC_LIBRARY=${resolve(xercesPrefix, 'lib/libxerces-c.a')}`,
'-DPython3_EXECUTABLE=/usr/bin/python3.13',
`-DPython3_INCLUDE_DIR=${resolve(pythonPrefix, 'include/python3.13')}`,
`-DPython3_INCLUDE_DIRS=${resolve(pythonPrefix, 'include/python3.13')}`,
`-DPython3_LIBRARY=${resolve(pythonPrefix, 'lib/libpython3.13.a')}`,
'-DOCCT_CMAKE_FALLBACK=ON',
`-DOCC_INCLUDE_DIR=${resolve(occtBuild, 'include/opencascade')}`,
`-DOCC_LIBRARY=${resolve(occtBuild, 'lin32/clang/lib/libTKernel.a')}`,
`-DFREECAD_WASM_OCCT_COMPAT_INCLUDE=${resolve(occtSource, 'src/Deprecated/NCollectionAliases')}`,
`-DEIGEN3_INCLUDE_DIR=${resolve(offlineSysroot, 'include/eigen3')}`,
`-DBOOST_WASM_ROOT=${boostPrefix}`,
`-DBoost_DIR=${resolve(root, 'config/cmake/boost')}`,
'-DBoost_USE_STATIC_LIBS=ON',
'-DQT_HOST_PATH=/usr',
'-DQT_HOST_PATH_CMAKE_DIR=/usr/lib/x86_64-linux-gnu/cmake',
'-DFETCHCONTENT_FULLY_DISCONNECTED=ON',
`-DCMAKE_TOOLCHAIN_FILE=${resolve(root, 'config/emscripten-freecad-candidate-toolchain.cmake')}`,
'-DCMAKE_AR=emar', '-DCMAKE_RANLIB=emranlib',
'-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER', '-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY', '-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY',
]
const startedAt = new Date().toISOString()
let status = 'configured'
let exitCode = 0
let output = ''
try {
const result = await run(command[0], command.slice(1), { cwd: root, maxBuffer: 16 * 1024 * 1024 })
output = `${result.stdout}${result.stderr}`
} catch (error) {
status = 'blocked'
exitCode = error.status ?? 1
output = `${error.stdout ?? ''}${error.stderr ?? ''}`
}
const missing = []
if (status === 'blocked') {
if (output.includes('Could not find a valid Qt installation') || output.includes('Could NOT find Qt6')) missing.push('Qt6 wasm package configuration')
if (output.includes('Could NOT find Python3')) missing.push('Emscripten Python3 development target')
if (output.includes('Could NOT find ICU') || output.includes('Failed to find all ICU components')) missing.push('ICU wasm static libraries')
if (output.includes('Could NOT find XercesC') || output.includes('Failed to find XercesC')) missing.push('Xerces-C wasm static library')
if (output.includes('Could NOT find ZLIB')) missing.push('ZLIB wasm static library')
if (output.includes('Could NOT find OCC') || output.includes('OpenCASCADE not found')) missing.push('OpenCASCADE wasm SDK')
if (output.includes('Could NOT find Eigen3') || output.includes('Eigen3 not found')) missing.push('Eigen3 headers')
if (output.includes('Could NOT find Boost') || output.includes('provided by "Boost"')) missing.push('Boost wasm static libraries')
if (output.includes('Could NOT find yaml-cpp') || output.includes('provided by "yaml-cpp"')) missing.push('yaml-cpp wasm package')
if (output.includes('Unknown CMake command "qt_add_translation"')) missing.push('Qt translation cross-build adapter')
if (output.includes('Qt6::Core') && output.includes('mkspecs/wasm-emscripten') && output.includes('non-existent path')) missing.push('Qt6 wasm mkspec installation')
if (missing.length === 0) missing.push('unclassified CMake configure failure')
}
await mkdir(resolve(root, '.cache/toolchains/freecad-naming-sdk'), { recursive: true })
await writeFile(reportPath, `${JSON.stringify({ schemaVersion: 1, status, exitCode, startedAt, command, missing, buildDir, outputTail: output.slice(-12000), productionPublication: false, boundary: { freecadNamingBuildStatus: 'contract-only', exTsn02: 'in_progress', systemExact: false, workerLinked: false, callbacks: [] } }, null, 2)}\n`)
console.log(JSON.stringify({ status, exitCode, report: reportPath, missing, productionPublication: false }, null, 2))
if (status !== 'configured') process.exit(exitCode)