From f66ad22f1dcab9ac08263cc2bce4ca22557c10fd Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Tue, 2 Jun 2026 17:05:41 +1000 Subject: [PATCH] macOS: ship libwgpu_native.dylib into the bundle and set the rpath MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BonsaiViewer.app crashed at launch on a fresh macOS arm64 mac with: Library not loaded: @rpath/libwgpu_native.dylib Referenced from: /Applications/BonsaiViewer.app/Contents/MacOS/BonsaiViewer Reason: no LC_RPATH's found The exe had \`LC_LOAD_DYLIB @rpath/libwgpu_native.dylib\` (CMake baked that in from the upstream dylib's install_name), but zero \`LC_RPATH\` entries, so dyld had nowhere to look — and macdeployqt hadn't pulled the dylib in either, since it sat at \`/lib/\` rather than inside the .app. Two changes: - \`src/ifcviewer-wgpu/CMakeLists.txt\`: on macOS, when BUILD_BONSAIVIEWER is on, install libwgpu_native.dylib straight into \`BonsaiViewer.app/Contents/Frameworks/\` instead of \`/lib/\`. That matches the standard macOS bundle layout. - \`src/bonsaiviewer/CMakeLists.txt\`: set \`INSTALL_RPATH "@executable_path/../Frameworks"\` on the BonsaiViewer target on Apple. That's where dyld looks at launch, and where the dylib now lives. Together the @rpath load resolves at launch without depending on macdeployqt to follow non-Qt @rpath references (it usually only chases Qt frameworks). Co-Authored-By: Claude Opus 4.7 --- src/bonsaiviewer/CMakeLists.txt | 13 +++++++++++++ src/ifcviewer-wgpu/CMakeLists.txt | 16 +++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/bonsaiviewer/CMakeLists.txt b/src/bonsaiviewer/CMakeLists.txt index 69f07fd804..29ed79e00c 100644 --- a/src/bonsaiviewer/CMakeLists.txt +++ b/src/bonsaiviewer/CMakeLists.txt @@ -120,6 +120,19 @@ set_target_properties(BonsaiViewer PROPERTIES MACOSX_BUNDLE ON ) +# macOS bundle runtime layout. BonsaiViewer's exe has +# `LC_LOAD_DYLIB @rpath/libwgpu_native.dylib` (CMake bakes that in from +# the dylib's own install_name). Without an LC_RPATH entry pointing at +# the bundle's Frameworks/ dir, dyld aborts at launch with +# "no LC_RPATH's found". Set the standard macOS app-bundle rpath so +# the load resolves; the wgpu CMakeLists installs the dylib straight +# into BonsaiViewer.app/Contents/Frameworks for us. +if(APPLE) + set_target_properties(BonsaiViewer PROPERTIES + INSTALL_RPATH "@executable_path/../Frameworks" + ) +endif() + target_link_libraries(BonsaiViewer PRIVATE # IfcViewer still ships SceneLoader / Federation / GeometryStreamer / # SidecarBuilder until the GL ViewportWindow is deleted. IfcViewerWgpu diff --git a/src/ifcviewer-wgpu/CMakeLists.txt b/src/ifcviewer-wgpu/CMakeLists.txt index 322417bd5e..d304a9d5b7 100644 --- a/src/ifcviewer-wgpu/CMakeLists.txt +++ b/src/ifcviewer-wgpu/CMakeLists.txt @@ -173,10 +173,20 @@ install(FILES ${IFCVIEWER_WGPU_H_FILES} # Install the wgpu_native shared library so the deployed runtime can find it. # At build/run-from-build-tree time CMake adds wgpu_native_SOURCE_DIR to the # binary's rpath automatically (IMPORTED_LOCATION dirname). -if(NOT WIN32) - install(FILES "${wgpu_native_SOURCE_DIR}/lib/${_wgpu_lib}" DESTINATION lib) -else() +# +# macOS: drop libwgpu_native.dylib straight into BonsaiViewer.app's +# Frameworks/. The exe has `LC_LOAD_DYLIB @rpath/libwgpu_native.dylib` +# (baked from the dylib's install_name), and BonsaiViewer's +# INSTALL_RPATH is set to @executable_path/../Frameworks — together +# they resolve at launch without depending on macdeployqt to follow +# non-Qt @rpath references. +if(WIN32) install(FILES "${wgpu_native_SOURCE_DIR}/lib/${_wgpu_runtime}" DESTINATION bin) +elseif(APPLE AND BUILD_BONSAIVIEWER) + install(FILES "${wgpu_native_SOURCE_DIR}/lib/${_wgpu_lib}" + DESTINATION "BonsaiViewer.app/Contents/Frameworks") +else() + install(FILES "${wgpu_native_SOURCE_DIR}/lib/${_wgpu_lib}" DESTINATION lib) endif() if(BUILD_BONSAIVIEWER_TESTS)