Real IFC2X3/IFC4 import tested. Full BIM authoring/export remains out of scope; 349-second building import performance remains to optimize.
48 lines
3.4 KiB
JavaScript
48 lines
3.4 KiB
JavaScript
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { spawn } from 'node:child_process';
|
|
import { createHash } from 'node:crypto';
|
|
|
|
const root=path.resolve(path.dirname(fileURLToPath(import.meta.url)),'..');
|
|
const dependencies=path.join(root,'freecad-source/build-web');
|
|
const source=process.env.FREECAD_IFC_SOURCE;
|
|
if(!source||!fs.existsSync(path.join(source,'cmake/CMakeLists.txt')))throw Error('Set FREECAD_IFC_SOURCE to a real IfcOpenShell source tree');
|
|
const build=path.resolve(process.env.FREECAD_IFC_BUILD??path.join(dependencies,'ifcopenshell-native/build'));
|
|
const output=path.join(root,'docs/current/user-tests-20260915',`ifc-build-${new Date().toISOString().replace(/[:.]/g,'-')}`);
|
|
fs.mkdirSync(output,{recursive:true});
|
|
const stages=[];
|
|
async function run(stage,command,args,timeout=1800000){
|
|
const started=performance.now(),log=fs.openSync(path.join(output,`${stage}.log`),'w');
|
|
const child=spawn(command,args,{cwd:root,stdio:['ignore',log,log],detached:true});
|
|
let timedOut=false;
|
|
const timer=setTimeout(()=>{timedOut=true;process.kill(-child.pid,'SIGTERM');},timeout);
|
|
const code=await new Promise(resolve=>{child.once('close',resolve);child.once('error',()=>resolve(-1));});
|
|
clearTimeout(timer);fs.closeSync(log);
|
|
stages.push({stage,command,args,exitCode:code,timedOut,seconds:(performance.now()-started)/1000});
|
|
fs.writeFileSync(path.join(output,'results.json'),JSON.stringify({source,build,stages},null,2)+'\n');
|
|
console.log(JSON.stringify(stages.at(-1)));
|
|
if(code!==0)throw Error(`${stage} failed; see ${output}`);
|
|
}
|
|
await run('configure','cmake',['-S',path.join(source,'cmake'),'-B',build,'-G','Ninja',
|
|
'-DCMAKE_TOOLCHAIN_FILE=/usr/share/emscripten/cmake/Modules/Platform/Emscripten.cmake',
|
|
'-DCMAKE_BUILD_TYPE=Release','-DCMAKE_CXX_FLAGS=-pthread -fexceptions','-DCMAKE_C_FLAGS=-pthread',
|
|
'-DCMAKE_CXX_FLAGS_RELEASE=-O1 -DNDEBUG','-DWASM_BUILD=ON','-DBUILD_SHARED_LIBS=OFF',
|
|
'-DBUILD_IFCPYTHON=OFF','-DBUILD_CONVERT=OFF','-DBUILD_GEOMSERVER=OFF','-DBUILD_IFCGEOM=ON',
|
|
'-DWITH_OPENCASCADE=ON','-DWITH_CGAL=OFF','-DCOLLADA_SUPPORT=OFF','-DHDF5_SUPPORT=OFF','-DIFCXML_SUPPORT=OFF',
|
|
'-DSCHEMA_VERSIONS=2x3;4','-DUSE_CCACHE=OFF','-DNO_WARN=ON',
|
|
`-DOCC_INCLUDE_DIR=${dependencies}/occt-pthread-install/include/opencascade`,
|
|
`-DOCC_LIBRARY_DIR=${dependencies}/occt-pthread-install/lib`,
|
|
`-DBOOST_ROOT=${dependencies}/boost-pthread-install`,'-DBoost_NO_SYSTEM_PATHS=ON',
|
|
'-DEigen3_DIR=/usr/share/eigen3/cmake','-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=NEVER',
|
|
'-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=NEVER','-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=NEVER']);
|
|
await run('compile','cmake',['--build',build,'--target','IfcParse','IfcGeom','geometry_kernel_opencascade','-j2']);
|
|
const artifacts=['ifcparse/libIfcParse.a','ifcgeom/libIfcGeom.a','ifcgeom/kernels/libgeometry_kernel_opencascade.a'].map(name=>{
|
|
const file=path.join(build,name);return {file,size:fs.statSync(file).size,sha256:createHash('sha256').update(fs.readFileSync(file)).digest('hex')};
|
|
});
|
|
fs.writeFileSync(path.join(output,'artifacts.json'),JSON.stringify(artifacts,null,2)+'\n');
|
|
await run('host-configure','cmake',['-S','freecad-source','-B',path.join(dependencies,'configure'),
|
|
`-DFREECAD_WEB_IFCOPENSHELL_SOURCE=${path.resolve(source)}`,`-DFREECAD_WEB_IFCOPENSHELL_BUILD=${build}`]);
|
|
await run('host-link','python3',['tools/build_web_module_artifacts.py','--target','FreeCADWebPartBoxProbe','--jobs','2','--timeout','600']);
|
|
console.log(output);
|