mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-11 18:16:40 +00:00
bonsaiviewer: stage all IfcOpenShell dylibs (core + plug-ins) on macOS
The .app bundle's Frameworks/ staging rule was only globbing ifcopenshell.*.dylib (the dlopen-only plug-ins) on the assumption that macdeployqt would follow BonsaiViewer's link-time @rpath deps for the lib-prefixed core shared libs. In practice it doesn't — non-Qt @rpath deps whose source path is outside the standard system / Qt prefixes get skipped silently. In a static build this didn't matter: libifcopenshell.geometry, libIfcParse, libIfcViewer, etc. were statically embedded in BonsaiViewer.exe, so there was no runtime dep. With --shared (added inddee88bedfor the bundle-size win) they're separate dylibs that must physically live in Frameworks/, or the binary won't even start: dyld: Library not loaded: @rpath/libifcopenshell.geometry.dylib Reason: tried '…/BonsaiViewer.app/Contents/Frameworks/ libifcopenshell.geometry.dylib' (no such file) Broaden the install(CODE) glob to *.dylib so both flavours land: * lib-prefixed linked core libs (libifcopenshell.geometry.dylib, libIfcParse.dylib, libIfcViewer.dylib, lib<mapping/kernel>.dylib) * non-prefixed plug-ins (ifcopenshell.parse.schema.ifcXxX.dylib, ifcopenshell.geometry.mapping.ifcXxX.dylib, etc.) <prefix>/lib/ is IfcOpenShell-exclusive (Qt / boost / eigen live in their own brew / build prefixes), so the broad glob doesn't risk sweeping in unrelated dylibs. The geometry-writer EXCLUDE regex is preserved so the size win from the writer-skip side ofddee88bedstays in place. In a static build the lib/ directory simply has no *.dylib files that match, so the rule no-ops cleanly — same code path is safe for both --shared and the (unused but possible) default static config. Linux didn't need a counterpart: build_rocky.yml already does the equivalent in workflow bash (`patchelf --set-rpath '$ORIGIN'` + `stage_runtime_payload`), and local Linux dev uses CMake's BUILD_RPATH which auto-resolves to the build subdirectories. macOS .app bundles are treated as opaque by the packaging step (no stage_runtime_payload against Contents/), so the staging has to happen at CMake install time when the bundle is being assembled. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -156,21 +156,37 @@ install(TARGETS BonsaiViewer
|
||||
)
|
||||
ifcopenshell_deploy_qt_runtime(BonsaiViewer)
|
||||
|
||||
# Stage IfcOpenShell plug-ins (schemas, kernels, mappings, serializers —
|
||||
# anything named ifcopenshell.*.dylib) into the .app bundle's
|
||||
# Frameworks/ directory on macOS. These are dlopen-only deps so
|
||||
# macdeployqt does not follow them automatically. The upstream
|
||||
# install(TARGETS …) rules place them at <prefix>/lib/ (outside the
|
||||
# bundle).
|
||||
# Stage IfcOpenShell dylibs into the .app bundle's Frameworks/ directory.
|
||||
#
|
||||
# Frameworks/ is the standard macOS app-bundle location for shared
|
||||
# libraries the app pulls in at runtime — it's where macdeployqt
|
||||
# already deposited libIfcParse/libIfcGeom/etc. as linked deps, and
|
||||
# the BonsaiViewer exe's INSTALL_RPATH (@executable_path/../Frameworks)
|
||||
# points there. With the plug-in loader's primary search path being
|
||||
# dirname(libIfcParse) (= Frameworks/ inside the bundle), placing the
|
||||
# plug-ins alongside libIfcParse means they're found on the first
|
||||
# probe — no fallback search needed.
|
||||
# Two flavours sit alongside each other in <prefix>/lib/ after install:
|
||||
#
|
||||
# 1. Linked core libs (lib*.dylib) — IfcParse, IfcGeom (output-named
|
||||
# libifcopenshell.geometry.dylib), IfcViewer, plug-in / mapping /
|
||||
# kernel shared libs. With --shared these are runtime @rpath deps
|
||||
# of BonsaiViewer.exe. macdeployqt is *supposed* to follow them
|
||||
# but in practice misses non-Qt @rpath deps when the source lib
|
||||
# lives outside the standard system / Qt prefixes, so we stage
|
||||
# them explicitly. (In a static build these are absent from lib/
|
||||
# and the glob just no-ops, so this rule is safe in both modes.)
|
||||
#
|
||||
# 2. Plug-ins (ifcopenshell.*.dylib, no `lib` prefix) — dlopen-only
|
||||
# deps the plug-in loader resolves at runtime. macdeployqt has
|
||||
# no way to know about these.
|
||||
#
|
||||
# Both kinds get a flat copy into Contents/Frameworks/. The plug-in
|
||||
# loader's primary search path is dirname(libIfcParse) (= Frameworks/
|
||||
# inside the bundle), so plug-ins and core libs both find each other
|
||||
# on the first probe.
|
||||
#
|
||||
# The geometry-writer filter drops ifcopenshell.geometry.writer.*.dylib
|
||||
# (the per-schema OBJ / glTF / DAE / STP / IGS / SVG / TTL export
|
||||
# converters — heavy, viewer-irrelevant). Mirrors the Rocky workflow's
|
||||
# filter in `stage_runtime_payload` (see 27249770e).
|
||||
#
|
||||
# <prefix>/lib/ is IfcOpenShell-exclusive — Qt / boost / eigen live in
|
||||
# their own brew / build prefixes — so a broad *.dylib glob is safe
|
||||
# here and automatically picks up any future shared libs without
|
||||
# needing to maintain an explicit name list.
|
||||
#
|
||||
# Subdirectory order in cmake/CMakeLists.txt guarantees that ifcparse/
|
||||
# / ifcgeom/ / serializers/ are add_subdirectory'd before bonsaiviewer/,
|
||||
@@ -178,21 +194,14 @@ ifcopenshell_deploy_qt_runtime(BonsaiViewer)
|
||||
# on disk under <prefix>/lib/.
|
||||
if(APPLE)
|
||||
install(CODE [[
|
||||
file(GLOB _ifc_plugins
|
||||
"${CMAKE_INSTALL_PREFIX}/lib/ifcopenshell.*.dylib")
|
||||
# Skip ifcopenshell.geometry.writer.*.dylib — those are heavy
|
||||
# schema-specific OBJ / glTF / DAE / STP / IGS / SVG / TTL export
|
||||
# converters. BonsaiViewer is a viewer; it never writes geometry
|
||||
# out, so they're pure deadweight. Mirrors the Rocky workflow's
|
||||
# filter in `stage_runtime_payload` (see 27249770e). Cuts the
|
||||
# macOS .app by ~100-150 MB.
|
||||
list(FILTER _ifc_plugins EXCLUDE REGEX "ifcopenshell\\.geometry\\.writer\\.")
|
||||
if(_ifc_plugins)
|
||||
message(STATUS "Staging IfcOpenShell plug-ins into BonsaiViewer.app/Contents/Frameworks")
|
||||
file(COPY ${_ifc_plugins}
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/BonsaiViewer.app/Contents/Frameworks")
|
||||
set(_fw "${CMAKE_INSTALL_PREFIX}/BonsaiViewer.app/Contents/Frameworks")
|
||||
file(GLOB _ifc_dylibs "${CMAKE_INSTALL_PREFIX}/lib/*.dylib")
|
||||
list(FILTER _ifc_dylibs EXCLUDE REGEX "ifcopenshell\\.geometry\\.writer\\.")
|
||||
if(_ifc_dylibs)
|
||||
message(STATUS "Staging IfcOpenShell dylibs (linked core + plug-ins) into BonsaiViewer.app/Contents/Frameworks")
|
||||
file(COPY ${_ifc_dylibs} DESTINATION "${_fw}")
|
||||
else()
|
||||
message(WARNING "No ifcopenshell.*.dylib plug-ins found in lib/ — BonsaiViewer.app will fail at the first IFC load")
|
||||
message(WARNING "No IfcOpenShell *.dylib found in lib/ — BonsaiViewer.app will fail to launch (missing @rpath linked deps) or at IFC load time (missing plug-ins)")
|
||||
endif()
|
||||
]])
|
||||
endif()
|
||||
|
||||
Reference in New Issue
Block a user