mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-28 07:49:59 +00:00
35f261b3a6
`geom.tree().select()` silently returns zero results (or raises SWIG's "An unknown error occurred") in the Linux release packages, while the same commit built from source returns correct answers. `select_box()` agrees between both, and geometry conversion is bit-identical -- only operations that touch a stored TopoDS_Shape diverge. Cause is linkage, not code.8bdaa8c7cnarrowed the Rocky builds from `--shared` to `--ifcopenshell-shared`, which shares IfcOpenShell's own libraries but leaves every dependency static. OCCT is then compiled privately into each plug-in that uses it -- 15 of them, verified by their own copies of the BRepClass3d/BRepExtrema/Standard_Failure strings. That contradicts what the binaries already declare. tree.h:1748 casts a `conversion_result_shape*` to `open_cascade_shape*`, moves the TopoDS_Shape out of it and frees it; `open_cascade_shape` is defined once in ifcopenshell_geometry_kernel_opencascade.so and left undefined in ifcopenshell_geometry_tree_opencascade_brep.so for the loader to resolve. So the two plug-ins are designed to share one OCCT-based type system, yet static linking gives each its own Standard_Type registry and allocator. Shapes get read and released by a different OCCT instance than made them. Add `--opencascade-shared`, mirroring the existing `--ifcopenshell-shared` precedent, and use it on both Rocky workflows. It cannot be spelled `--occt-shared`: build-all.py parses any `occt-*` flag as a version override. BUILD_STATIC drives three things at once -- dependency link type, -fvisibility=hidden, and BUILD_SHARED_LIBS -- so making one dependency shared means overriding all three for it. Visibility is the subtle one: OCCT's Standard_EXPORT expands to nothing on Unix, so it relies on default visibility to export its API. Built shared under -fvisibility=hidden it exports almost nothing and its own libraries cannot resolve against each other (libTKMath.so fails to find NCollection_BaseAllocator::CommonBaseAllocator in libTKernel.so). Static archives are immune, which is why this surfaces only once OCCT goes shared. Compile OCCT with the pre-visibility flag set instead. Put the shared OCCT on LD_LIBRARY_PATH for the build itself. Nothing else points at it -- IfcOpenShell's libraries get INSTALL_RPATH=$ORIGIN and OCCT sits in its own dependency prefix -- so the post-build `import ifcopenshell` check fails with "libTKernel.so.7.8: cannot open shared object file". This is build-time only; the shipped packages get libTK*.so* staged beside the payload with an $ORIGIN RUNPATH instead. Suffix OCCT's install directory with `-shared` when it applies. Static and shared installs are not interchangeable, but `build_dependency` skips any dependency whose install dir already exists and cache_dependencies.py keys its tarballs purely on that directory name -- so the static `cache-occt-7.8.1.tar.gz` restored from the build-outputs repo silently satisfied the build and BUILD_LIBRARY_TYPE was never applied. This is the same cache stickiness8bdaa8c7cdescribed, pointing the other way. The suffix makes the key configuration-aware, so it self-invalidates and the static tarball stays valid for builds that still want static. Packaging is the other half, and is why8bdaa8c7cbacked the flag out -- `stage_runtime_payload` only copies from install/ifcopenshell, so OCCT in install/occt-* was never staged and `--shared` "worked by accident" off cached static outputs. Stage libTK*.so* alongside, then give every staged library an $ORIGIN RUNPATH: the core libs currently carry dead build-machine RPATHs and the plug-ins carry none, resolving only because the Python wrapper pulls them in by SONAME first. Shared OCCT has no such first loader, since it is reached through the dlopen'd plug-ins. This shrinks the packages. Duplicated OCCT is 113 MB of the 287 MB unpacked python payload (the eight geometry_writer_ifc* plug-ins alone are 4.6 MB each); one shared copy of the 29 linked libTK is around 67 MB, and the plug-ins collapse to source-build sizes -- kernel_opencascade 15.4 MB -> 1.2 MB, tree_opencascade_brep 9.6 MB -> 248 KB. Same argument asa91b1da28("Reduce Rocky package size") and402591e71. macOS and Windows are affected too but are not fixed here. Their packaging resolves via @loader_path install names and would need install_name_tool rewriting, which cannot be verified from Linux; adding the flag without that would ship a package that fails to load. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>