subagent transcript
session 17f09f89 · workflow wf_54002329
delegated task
CONTEXT — FreeCAD is being ported to WebAssembly (emscripten). Toolchain facts you MUST assume: - Emscripten 4.0.12 (clang/LLVM 22), Binaryen v123, at
▸ Magik
CONTEXT — FreeCAD is being ported to WebAssembly (emscripten). Toolchain facts you MUST assume:
- Emscripten 4.0.12 (clang/LLVM 22), Binaryen v123, at /opt/toolchains/emsdk.
- Native wasm exceptions (exnref): compile with -fwasm-exceptions -sWASM_LEGACY_EXCEPTIONS=0. NO legacy asyncify-EH for new TUs.
- NO pthreads/std::thread (single-threaded wasm build). NO real sockets. Filesystem is emscripten MEMFS.
- No subprocess/popen/system (external solvers like ccx/calculix, gmsh are NOT available at runtime).
- The build already ships OCCT, Qt6 (widgets), Python 3.14, PySide6, and many FreeCAD Mods (Part, Mesh, Draft, BIM, CAM, Import, etc.). Mesh module was built WITHOUT SMESH (uses OCCT mesher).
- FreeCAD source root: /home/magik6k/lcad-wasm/freecad-port/FreeCAD
- GOAL: load the example file data/examples/FEMExample.FCStd in the browser. Its objects are:
Fem::FemAnalysis(3), Fem::ConstraintForce/Fixed/Displacement, Fem::FemSolverObjectPython(3),
Fem::FemMeshObjectPython(3), Fem::FemMeshShapeBaseObjectPython(3), Fem::FemResultObjectPython(3),
Fem::FemPostPipeline(3), Fem::FemPostWarpVectorFilter(3), Fem::FeaturePython(2),
App::MaterialObjectPython(3), Part::Box/Plane/Line, App::TextDocument, App::DocumentObjectGroup.
- Restore currently fails: "No module named 'Fem'" (C++ Fem module not built, BUILD_FEM=OFF) AND a security block
in src/App/PropertyPythonObject.cpp isAllowedModule() blocks 'femobjects.material_common'.
- KEY: src/Mod/Fem/CMakeLists.txt gates all VTK behind BUILD_FEM_VTK (adds -DFC_USE_VTK). FemPost*/VTKExtensions are VTK-only.
You have Read/Grep/Glob/Bash (read-only intent — do NOT modify files, do NOT run long builds; quick greps/find are fine).
Return ONLY the requested structured fields. Be concrete: cite exact files, CMake option names, #ifdef guards, class names.
YOUR AREA: What wasm-hostile patterns exist in salomesmesh + Fem/App that will break or need patching in the emscripten single-threaded, no-subprocess, native-EH build?
Investigate (grep src/3rdParty/salomesmesh and src/Mod/Fem/App):
1. Threads: std::thread, pthread, OpenMP (#pragma omp), boost::thread, vtkSMPTools, tbb. List occurrences.
2. Subprocess/external tools: system(), popen, QProcess, exec*, fork — (calculix/ccx solver invocation, gmsh). These must be guarded (solving won't run in wasm, but RESTORE must not touch them).
3. Sockets/network.
4. Exceptions: any code assuming legacy EH? throw/catch is fine with -fwasm-exceptions, but setjmp/longjmp, or -fno-exceptions TUs mixing? Note the Qt-TU legacy-vs-new EH gotcha from context — does any of this compile -fexceptions currently?
5. Boost dependency (which boost libs; header-only OK, compiled boost may be an issue).
6. File paths / temp dirs assumptions (writing to /tmp for solver input) — only matters for solving, but flag if it's in a restore path.
7. Static initializers / global registration that might not run.
Answer: a prioritized list of patches needed, separating 'blocks the BUILD' from 'blocks solving-but-not-restore' (the latter can be deferred/guarded).
Fable
thinking
I'm going to search through the salomesmesh and Fem/App codebases to identify patterns that are incompatible with WebAssembly, starting with some targeted grep searches.
Fable
I'll investigate wasm-hostile patterns across salomesmesh and Fem/App. Let me start with parallel searches.
Fable
⚙ Bash {"command": "echo \"=== THREADS: std::thread ===\" && grep -rn \"std::thread\\|pthread_\\|#include <thread>\\|#include <pthread\" src/3rdParty/salomesmesh src/Mod/Fem/App 2>/dev/null | head -60", "description": "Search for thread usage"}
Fable
⚙ Bash {"command": "echo \"=== OpenMP pragma ===\" && grep -rn \"pragma omp\\|_OPENMP\\|omp_get\\|omp_set\" src/3rdParty/salomesmesh src/Mod/Fem/App 2>/dev/null | head -60", "description": "Search for OpenMP usage"}
Fable
⚙ Bash {"command": "echo \"=== TBB / vtkSMPTools / boost::thread ===\" && grep -rn \"vtkSMPTools\\|tbb::\\|#include <tbb\\|boost::thread\\|boost/thread\" src/3rdParty/salomesmesh src/Mod/Fem/App 2>/dev/null | head -60", "description": "Search for …
Fable
⚙ Bash {"command": "echo \"=== SUBPROCESS ===\" && grep -rn \"\\bsystem(\\|popen\\|QProcess\\|::execv\\|execvp\\|execl\\|_popen\\|fork()\\|posix_spawn\" src/3rdParty/salomesmesh src/Mod/Fem/App 2>/dev/null | head -80", "description": "Search for s…
Fable
thinking
I'm trying to understand the dependency chain here — specifically whether the Fem module actually requires salomesmesh to build, or if it can work with just the OCCT mesher. The real goal is getting FEMExample.FCStd to load, which means I need the C++ Fem module compiled. Let me trace through what Fem/App actually depends on.
Fable
Let me check the build dependencies and whether salomesmesh is actually required by Fem/App.
Fable
⚙ Bash {"command": "echo \"=== SOCKETS/NETWORK ===\" && grep -rn \"socket(\\|::connect(\\|gethostby\\|<sys/socket\\|<netinet\\|WSAStartup\\|bind(\\|listen(\" src/3rdParty/salomesmesh src/Mod/Fem/App 2>/dev/null | head -40", "description": "Search …
Fable
⚙ Bash {"command": "echo \"=== setjmp/longjmp & -fexceptions ===\" && grep -rn \"setjmp\\|longjmp\\|sigsetjmp\" src/3rdParty/salomesmesh src/Mod/Fem/App 2>/dev/null | head -20; echo \"=== fno-exceptions/fexceptions in CMake ===\" && grep -rn \"fno…
Fable
⚙ Bash {"command": "echo \"=== boost usage in Fem/App ===\" && grep -rn \"boost::\\|#include <boost\\|#include \\\"boost\" src/Mod/Fem/App 2>/dev/null | head -40", "description": "Search for boost usage in Fem App"}
Fable
⚙ Bash {"command": "echo \"=== Does Fem/App depend on salomesmesh (SMESH)? ===\" && grep -rn \"SMESH\\|SMDS\\|salome\\|SMESHDS\" src/Mod/Fem/App/CMakeLists.txt 2>/dev/null; echo \"--- includes of SMESH in Fem/App source ---\"; grep -rln \"SMESH_\\…
Fable
thinking
The Fem module has a hard dependency on SMESH since FemMesh.h includes SMESH classes, which means salomesmesh needs to be built first for the C++ compilation to work. I'm digging into the specific files where this matters — checking the OpenMP usage in FemMesh.cpp to see if it's in critical paths, and looking at how salomesmesh gets invoked through system calls in the MED and SMESH implementations.
Fable
SMESH is a hard dependency of Fem/App (FemMesh.h includes SMESH). Let me examine the key patterns in detail.
Fable
⚙ Bash {"command": "echo \"=== FemMesh.cpp OpenMP context (lines 585-625) ===\"; sed -n '585,625p' /home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/Mod/Fem/App/FemMesh.cpp", "description": "Read FemMesh.cpp OpenMP context"}
Fable
⚙ Bash {"command": "echo \"=== SMESH_Mesh.cpp system() calls context (lines 1490-1540) ===\"; sed -n '1490,1540p' /home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/3rdParty/salomesmesh/src/SMESH/SMESH_Mesh.cpp", "description": "Read SMESH_Mesh.cpp …
Fable
⚙ Bash {"command": "echo \"=== SMESH_Mesh.cpp boost::thread context (lines 210-245) ===\"; sed -n '210,245p' /home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/3rdParty/salomesmesh/src/SMESH/SMESH_Mesh.cpp", "description": "Read SMESH_Mesh.cpp boost…
Fable
thinking
I'm finding a critical issue in SMESH_Mesh.cpp where `boost::thread` is being instantiated in the destructor. Since this is a compiled boost library, it creates a hard dependency on pthread at both build time and runtime, and requires linking against the compiled `libboost_thread` library.
But wait — the context says the Mesh module was built without SMESH, yet the Fem/App module has a hard requirement on SMESH since FemMesh.h includes SMESH classes directly. This means to build Fem at all, we'd need to build salomesmesh first, or FemMesh's implementation is deeply coupled to SMESH.
The `system()` calls for export functions like ExportSAUV and ExportDAT won't block the build itself — emscr …
Fable
Key finding: Fem/App hard-depends on SMESH. Let me verify the SMESH-in-restore-path concern, the tbb guard, and how salomesmesh links boost.
Fable
⚙ Bash {"command": "echo \"=== FemMesh.h SMESH includes ===\"; grep -n \"SMESH\\|SMDS\\|SMESHDS\\|#include\" /home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/Mod/Fem/App/FemMesh.h | head -40", "description": "Read FemMesh.h includes"}
Fable
⚙ Bash {"command": "echo \"=== FemMesh::Restore / read (SMESH in restore path) ===\"; grep -n \"Restore\\|::read\\|SaveDocFile\\|RestoreDocFile\\|readABAQUS\\|read(\" /home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/Mod/Fem/App/FemMesh.cpp | head …
Fable
⚙ Bash {"command": "echo \"=== tbb guard in StdMeshers_Cartesian_3D.cpp (lines 95-115) ===\"; sed -n '95,115p' /home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/3rdParty/salomesmesh/src/StdMeshers/StdMeshers_Cartesian_3D.cpp; echo \"=== guard aroun…
Fable
thinking
TBB is conditionally compiled behind a guard, so it's only a concern if WITH_TBB is explicitly enabled in the CMake configuration. Let me check whether that flag is actually set in the salomesmesh build. Now I need to locate the actual persistence methods for FemMesh — the Restore and SaveDocFile/RestoreDocFile implementations — since the read methods further down are specifically for Nastran file imports.
Fable
TBB is guarded behind `#ifdef WITH_TBB` — good. Now let me examine the FemMesh persistence (restore path) and the salomesmesh build config.
Fable
⚙ Bash {"command": "echo \"=== FemMesh persistence methods ===\"; grep -n \"FemMesh::Restore\\|FemMesh::Save\\|FemMesh::RestoreDocFile\\|FemMesh::SaveDocFile\\|getGenerator\\|_mesh_gen\\|new SMESH_Gen\\|SMESH_Gen::\" /home/magik6k/lcad-wasm/freeca…
Fable
⚙ Bash {"command": "echo \"=== salomesmesh CMakeLists: TBB/boost/pthread/MED ===\"; grep -n \"TBB\\|tbb\\|MED\\|Boost\\|boost\\|pthread\\|Threads\\|thread\\|WITH_\\|find_package\\|target_link\" /home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/3rdP…
Fable
thinking
I need to trace through the FemMesh::Restore and RestoreDocFile functions to see if SMESH is involved in the restore path, and then check the salomesmesh CMakeLists to understand what's being built — particularly whether MED_Factory.cpp with its system() call is included, what boost dependencies are linked, and if any of this is even compiled into the wasm build.
Fable
⚙ Bash {"command": "echo \"=== FemMesh::Restore + RestoreDocFile (2412-2490) ===\"; sed -n '2412,2490p' /home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/Mod/Fem/App/FemMesh.cpp", "description": "Read FemMesh Restore path"}
Fable
⚙ Bash {"command": "echo \"=== salomesmesh sources: is MED/MED_Factory/med-wrapper compiled? boost linkage ===\"; grep -n \"MED_Factory\\|MED_Wrapper\\|MEDWrapper\\|Utils_Mutex\\|SMESH_Mesh.cpp\\|Boost_LIBRARIES\\|boost_thread\\|MEDFILE\\|MEDWRAPP…
Fable
thinking
I'm realizing that FemMesh::RestoreDocFile actually invokes the SMESH library's UNVToMesh function, which means SMESH is directly involved in the restoration process. The FemMeshObjectPython instances store their mesh data in UNV format, and when restored, this goes through SMESH_Mesh and the DriverUNV layer—so SMESH is fundamentally part of the restore pipeline.
Beyond that, the FemMesh constructor calls `getGenerator()->CreateMesh()` to instantiate an SMESH_Mesh via SMESH_Gen, which happens during restore when the FemMesh property is being reconstructed. There's also a critical issue: the SMESH_Mesh destructor uses `boost::thread`, which creates a hard problem for single-threaded WebAssem …
Fable
CRITICAL: `FemMesh::RestoreDocFile` calls `myMesh->UNVToMesh(...)` and the FemMesh ctor calls `getGenerator()->CreateMesh()` — so SMESH is squarely in the restore path. Let me read the full salomesmesh CMake and check MED/boost/UNV.
Fable
⚙ Bash {"command": "echo \"=== salomesmesh CMakeLists.txt (1-130) ===\"; sed -n '1,130p' /home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/3rdParty/salomesmesh/CMakeLists.txt", "description": "Read salomesmesh CMakeLists head"}
Fable
thinking
I need to examine the rest of the CMakeLists file to understand how the non-MSVC build path works, what subdirectories are included, and how MED_Factory and MED_Wrapper get compiled, plus whether MEDFILE is a required dependency.
Fable
⚙ Bash {"command": "echo \"=== salomesmesh CMakeLists.txt (130-215) ===\"; sed -n '130,215p' /home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/3rdParty/salomesmesh/CMakeLists.txt", "description": "Read salomesmesh CMake source/lib section"}
Fable
⚙ Bash {"command": "echo \"=== Where is MED_Factory.cpp / MED_Wrapper compiled? (grep all CMake) ===\"; grep -rn \"MED_Factory\\|MED_Wrapper\\|MEDWrapper\\|MEDWrapp\\|DriverMED\\|src/MEDWrapper\\|MED_V\" /home/magik6k/lcad-wasm/freecad-port/FreeCA…
Fable
thinking
I see that MED_Factory.cpp is actually located in the src/3rdParty/salomesmesh/src/SMESH/ directory, not in a separate MED or MEDWrapper folder as I initially thought.
Now I need to trace through the actual build targets — SMESH, SMESHDS, StdMeshers, Controls, DriverUNV — to understand what gets compiled and what dependencies they pull in. The critical issue is that SMESH_Mesh.cpp uses boost::thread, which requires a compiled boost library. Since BUILD_FEM is currently OFF, salomesmesh isn't being built at all, but enabling it would require checking whether the wasm build has boost_thread available. The real question is what breaks when we turn BUILD_FEM=ON, particularly around the DriverUN …
Fable
⚙ Bash {"command": "echo \"=== salomesmesh CMakeLists.txt (215-300 / end) ===\"; sed -n '215,320p' /home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/3rdParty/salomesmesh/CMakeLists.txt; echo \"=== total lines ===\"; wc -l /home/magik6k/lcad-wasm/fr…
Fable
⚙ Bash {"command": "echo \"=== Is MED_Factory in SMESH source glob? Check its includes ===\"; sed -n '1,70p' /home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/3rdParty/salomesmesh/src/SMESH/MED_Factory.cpp | grep -n \"include\\|system\\|HAVE_MED\\|…
Fable
thinking
I'm noticing that all these SMESH targets are configured as shared libraries, but in a WebAssembly build with Emscripten and static linking, shared libraries need to be converted to static ones—likely handled by a global BUILD_SHARED_LIBS=OFF setting in the FreeCAD wasm configuration, though it's worth keeping in mind as a potential issue.
The more pressing concern is that MED_Factory.cpp unconditionally includes `<med.h>` from the external MEDFILE library, which means either MEDFILE is available as a wasm dependency or this file gets excluded from the build entirely—I need to determine which path the FreeCAD wasm build takes.
Fable
⚙ Bash {"command": "echo \"=== MED-related files in src/SMESH ===\"; ls /home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/3rdParty/salomesmesh/src/SMESH/ | grep -i \"med\\|MED\"; echo \"=== which SMESH .cpp include <med.h> (unguarded MED dep) ===\"…
Fable
⚙ Bash {"command": "echo \"=== Boost_LIBRARIES / boost thread requirement in main build ===\"; grep -rn \"Boost_LIBRARIES\\|find_package(Boost\\|COMPONENTS.*thread\\|boost_thread\\|Boost.*thread\\|WITHOUT_MED\\|MEDFILE\\|FREECAD_USE_EXTERNAL_SMESH…
Fable
thinking
I'm checking whether the MED file handling is properly guarded in the build system. The source glob pattern captures all the C and C++ files including those with MED dependencies, but if MEDFILE isn't found, this could break the build unless there's a preprocessor guard protecting the includes.
I need to verify a few critical things: whether the Fem module's CMakeLists actually requires MED or if it's optional, how the main build gates SMESH and MED compilation around lines 140-170, and whether there's a HAVE_MED-style guard protecting the salomesmesh source files since the glob doesn't seem to have one built in.
Fable
⚙ Bash {"command": "echo \"=== main CMakeLists 140-175 (SMESH/MED/boost gating) ===\"; sed -n '140,175p' /home/magik6k/lcad-wasm/freecad-port/FreeCAD/CMakeLists.txt; echo \"=== BUILD_FEM / MEDFile requirement ===\"; grep -rn \"BUILD_FEM\\b\\|MEDFi…
Fable
⚙ Bash {"command": "echo \"=== Fem/App CMakeLists MED / VTK / library decl (1-60) ===\"; sed -n '1,60p' /home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/Mod/Fem/App/CMakeLists.txt | grep -n \"MED\\|VTK\\|add_library\\|SHARED\\|generate_from_py\\|F…
Fable
⚙ Bash {"command": "echo \"=== calculix/ccx/gmsh subprocess in Fem/App (should be Python, not C++) ===\"; grep -rn \"ccx\\|calculix\\|CalculiX\\|gmsh\\|QProcess\\|subprocess\\|/tmp\\|GetTempPath\\|getTempFileName\\|getTempPath\" /home/magik6k/lcad…
Fable
thinking
The Calculix references in Fem/App are just naming conventions and mesh operations, not actual subprocess calls. The real CCX solver invocation happens in Python through femtools/ccxtools.py using subprocess, so there's no C++ subprocess handling in Fem/App itself. The subprocess concern is isolated to salomesmesh where MED_Factory.cpp uses system() calls.
Now I'm looking at the MED export path — MED_Factory.cpp's system() call only triggers during MED file read/write operations, not in the UNV restore path. But since it's in the build glob, it must compile and needs med.h. The core issue is whether building SMESH requires the external MED library. If MEDFILE isn't found, the build fails be …
Fable
Solver invocation (ccx/calculix) in Fem/App is only naming conventions and mesh queries, not subprocess. Now let me confirm pthread_create usage, the boost::thread link requirement, and how the mutex header is used.
Fable
⚙ Bash {"command": "echo \"=== pthread_create actual calls (not just types) in salomesmesh ===\"; grep -rn \"pthread_create\\|pthread_join\\|pthread_mutex_init\\|pthread_mutex_lock\" /home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/3rdParty/salome…
Fable
⚙ Bash {"command": "echo \"=== SMESH_Mesh.cpp top includes (80-95) ===\"; sed -n '80,95p' /home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/3rdParty/salomesmesh/src/SMESH/SMESH_Mesh.cpp; echo \"=== boost::thread / boost::bind ALL occurrences in sal…
Fable
⚙ Bash {"command": "echo \"=== SMESH_Mesh.cpp: does it reference DriverMED / ExportMED (MED coupling for excludability) ===\"; grep -n \"DriverMED\\|ExportMED\\|MED::\\|#include.*MED\\|MED_Factory\\|myMed\" /home/magik6k/lcad-wasm/freecad-port/Fre…
Fable
thinking
I'm seeing that SMESH_Mesh.cpp has dependencies on DriverMED through its ImportMED and ExportMED methods, so excluding MED file support would require either removing those methods or providing stubs to avoid linker failures.
The UNV restore path through DriverUNV appears to be completely independent of MED — it doesn't include med.h anywhere in the chain. So the MED coupling is isolated to just those specific import/export methods and the MED_*.cpp and DriverMED_*.cpp files themselves.
The real question is whether medfile is even available in the wasm build environment — FindMEDFile.cmake exists, but if the wasm libpack doesn't include medfile, the build would fail when trying to compile t …
Fable
Let me check whether med.h is vendored (which determines if MED is a build blocker) and confirm the UNV restore chain is fully MED-free.
Fable
⚙ Bash {"command": "echo \"=== Is med.h vendored anywhere in the tree? ===\"; find /home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/3rdParty -iname \"med.h\" 2>/dev/null; find /home/magik6k/lcad-wasm/freecad-port/FreeCAD -iname \"med.h\" -not -pat…
Fable
⚙ Bash {"command": "echo \"=== UNVToMesh definition (restore entrypoint) ===\"; grep -rn \"UNVToMesh\\|ExportUNV\" /home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/3rdParty/salomesmesh/src/SMESH/SMESH_Mesh.cpp | head; echo \"=== SetupSalomeSMESH m…
Fable
thinking
I'm checking the SetupSalomeSMESH.cmake file to see how the MEDFile dependency is gated, specifically looking at the find_package call around line 93 and what conditions control it.
Fable
⚙ Bash {"command": "echo \"=== SetupSalomeSMESH.cmake (full) ===\"; cat -n /home/magik6k/lcad-wasm/freecad-port/FreeCAD/cMake/FreeCAD_Helpers/SetupSalomeSMESH.cmake 2>/dev/null | head -130", "description": "Read SetupSalomeSMESH macro"}
Fable
thinking
The `FREECAD_USE_SMESH` flag controls the entire SMESH build process, automatically enabling VTK and requiring both MEDFile and HDF5 as dependencies for the internal SMESH build.
Since MEDFile and HDF5 aren't available in the wasm toolchain and would be prohibitively heavy to build, I'd need to patch the SMESH CMakeLists to exclude the MED-related source files and stub out the import/export methods, then modify the setup script to skip those library requirements entirely.
Let me check what boost libraries are actually built in the wasm toolchain to see if boost_thread is available, and confirm there's no HDF5 present.
Fable
Let me verify the wasm boost build (does it include boost_thread) and confirm HDF5/medfile absence.
Fable
⚙ Bash {"command": "echo \"=== boost-wasm libs available ===\"; find /opt/toolchains/boost-wasm -name \"*.a\" 2>/dev/null | xargs -n1 basename 2>/dev/null | sort -u | head -40; echo \"=== any hdf5 / medC in toolchains ===\"; find /opt/toolchains -…
Fable
thinking
So the issue is that while `libboost_thread.a` does exist for WebAssembly, actually using `boost::thread` at runtime requires pthread support through SharedArrayBuffer, but the build isn't configured with pthreads enabled. This means attempting to construct a `boost::thread` will fail because it tries to call `pthread_create` under the hood, which isn't available in this single-threaded emscripten environment.
The real problem surfaces in the SMESH_Mesh destructor during the restore path—when temporary FemMesh objects get destroyed, the destructor tries to spawn a thread to run `deleteMeshDS`, which either leaks memory (the cleanup never runs) or aborts entirely. This is a concrete runtime …
Fable
Confirmed: `libboost_thread.a` exists for wasm (so boost::thread links) but no HDF5/medC/libmed anywhere. Let me do one final check on whether SMDS itself hard-requires the VTK data model (nails the vtk_needed level for the restore path).
Fable
⚙ Bash {"command": "echo \"=== SMDS uses vtkUnstructuredGrid? (data-model dep of restore) ===\"; grep -rln \"vtkUnstructuredGrid\\|vtkCellArray\\|#include <vtk\\|#include \\\"vtk\" /home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/3rdParty/salomesm…
Fable
thinking
So SMDS is fundamentally built on VTK's vtkUnstructuredGrid through SMDS_UnstructuredGrid, with the mesh elements (edges, faces, volumes) wrapping VTK objects, and when restoring a FemMesh from UNV format, the data flows through SMDS into that underlying VTK grid structure.
The restore path requires at minimum the VTK data model components—vtkCommonCore and vtkCommonDataModel—which confirms what I need to specify for the dependency configuration.
Fable
I now have a complete picture. Let me compile the structured findings.
Fable
⚙ StructuredOutput {"area": "salomesmesh + Fem/App wasm-hostile patterns (single-threaded, no-subprocess, native-EH build)", "verdict": "Turning on BUILD_FEM drags in the internal salomesmesh SMESH library, which is a genuine restore-path dependency (FemMesh …