From 759bb4c3d23776d661fbc0fe167e935e425e2e86 Mon Sep 17 00:00:00 2001 From: Olaf <8780533+OlafRocket@users.noreply.github.com> Date: Wed, 2 Sep 2026 18:54:35 +0100 Subject: [PATCH] Set install_name and rpath at link time on macOS The bundle relied on post-build and post-install install_name_tool passes to rewrite library ids and add rpaths. Those ran after codesigning had already happened during macdeployqt, invalidating the signatures they touched. Set the properties at configure time instead, so the linker emits the right paths and no rewriting is needed: - INSTALL_NAME_DIR "@rpath" with BUILD_WITH_INSTALL_NAME_DIR makes internal libraries self-identify as @rpath/libfoo.dylib, replacing the install_name_tool -id pass. - INSTALL_RPATH plus additive BUILD_RPATH on both the libraries and the executable. BUILD_RPATH keeps CMake's linker-derived paths alongside @executable_path/../Frameworks, so build/xSTUDIO.app runs on a fresh checkout without a preceding install. macdeployqt strips the extra rpath on install, leaving the shipped bundle unchanged. Drop the now-redundant fixup_macos_bundle.cmake and the install_name_tool calls in macdeploy.cmake.in, and remove the per-target rpath block in src/global that macros.cmake now covers. Pass -always-overwrite to macdeployqt so a stale bundle from a prior install cannot leave frameworks unsigned. Also document the incremental build workflow in the macOS build guide: after an initial install, cmake --build alone relinks in seconds. Signed-off-by: Olaf <8780533+OlafRocket@users.noreply.github.com> --- cmake/macros.cmake | 3 +++ docs/reference/build_guides/macos.md | 16 ++++++++++++ src/global/src/CMakeLists.txt | 10 +------- src/launch/xstudio/src/CMakeLists.txt | 8 ++---- .../xstudio/src/fixup_macos_bundle.cmake | 15 ----------- src/launch/xstudio/src/macdeploy.cmake.in | 25 ++++--------------- 6 files changed, 27 insertions(+), 50 deletions(-) delete mode 100644 src/launch/xstudio/src/fixup_macos_bundle.cmake diff --git a/cmake/macros.cmake b/cmake/macros.cmake index 3670db8e4..e3a71b693 100644 --- a/cmake/macros.cmake +++ b/cmake/macros.cmake @@ -105,7 +105,10 @@ macro(default_options_local name) set_target_properties(${name} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/xSTUDIO.app/Contents/Frameworks" + INSTALL_NAME_DIR "@rpath" + BUILD_WITH_INSTALL_NAME_DIR TRUE INSTALL_RPATH "@executable_path/../Frameworks" + BUILD_RPATH "@executable_path/../Frameworks" INSTALL_RPATH_USE_LINK_PATH TRUE ) elseif(UNIX) diff --git a/docs/reference/build_guides/macos.md b/docs/reference/build_guides/macos.md index 17d1eb3f3..e7aecbd41 100644 --- a/docs/reference/build_guides/macos.md +++ b/docs/reference/build_guides/macos.md @@ -73,3 +73,19 @@ When this has finished, you can build xSTUDIO with: RelWithDebInfo and Debug variants are also available — see [CMakePresets.json](../../../CMakePresets.json) for the full list. If the build is successful, you should have an application bundle in the 'build' folder called 'xSTUDIO.app'. This can be drag & dropped into your applications folder, desktop and dock as for any other application. + +### Fast iteration on source changes + +The `install` target above runs `macdeployqt` and copies documentation, preferences, and Python dependencies into the bundle. On a warm bundle this takes several minutes even when nothing has changed. Once you have done it at least once, incremental rebuilds do not need to repeat it, because the compiled binaries are linked directly into `build/xSTUDIO.app/Contents/`. + +For iteration on C++ / QML source changes, use: + + cmake --build build + +and re-launch `build/xSTUDIO.app`. A single-file relink completes in seconds instead of minutes. + +You should re-run `cmake --build build --target install` when: + +- files under `share/docs`, `share/preference`, `share/snippets`, or `share/fonts` change, +- a new dynamic library or plugin is added that `macdeployqt` needs to discover, +- the Qt SDK is upgraded and the copied frameworks in the bundle need refreshing. diff --git a/src/global/src/CMakeLists.txt b/src/global/src/CMakeLists.txt index 28218db67..ebb7dd934 100644 --- a/src/global/src/CMakeLists.txt +++ b/src/global/src/CMakeLists.txt @@ -57,12 +57,4 @@ if(UNIX AND NOT APPLE) target_link_libraries(${PROJECT_NAME} PRIVATE asound) # Link against asound on Linux endif() -if(APPLE) - set_target_properties(${PROJECT_NAME} PROPERTIES - LINK_DEPENDS_NO_SHARED true - INSTALL_RPATH "@executable_path/../Frameworks" - BUILD_WITH_INSTALL_RPATH TRUE - ) -else() - set_target_properties(${PROJECT_NAME} PROPERTIES LINK_DEPENDS_NO_SHARED true) -endif() +set_target_properties(${PROJECT_NAME} PROPERTIES LINK_DEPENDS_NO_SHARED true) diff --git a/src/launch/xstudio/src/CMakeLists.txt b/src/launch/xstudio/src/CMakeLists.txt index aa460f563..c368d6d91 100644 --- a/src/launch/xstudio/src/CMakeLists.txt +++ b/src/launch/xstudio/src/CMakeLists.txt @@ -125,6 +125,8 @@ elseif(APPLE) RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/xSTUDIO.app/Contents/MacOS" OUTPUT_NAME "${PROJECT_NAME}.bin" LINK_DEPENDS_NO_SHARED true + INSTALL_RPATH "@executable_path/../Frameworks" + BUILD_RPATH "@executable_path/../Frameworks" ) add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD @@ -150,12 +152,6 @@ elseif(APPLE) configure_file(macdeploy.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/macdeploy.cmake @ONLY) install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/macdeploy.cmake) - # Add custom command to fix library paths after build - add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -DAPP_BUNDLE_DIR=${CMAKE_BINARY_DIR}/xSTUDIO.app - -P ${CMAKE_CURRENT_SOURCE_DIR}/fixup_macos_bundle.cmake - ) - else() set_target_properties(${PROJECT_NAME} diff --git a/src/launch/xstudio/src/fixup_macos_bundle.cmake b/src/launch/xstudio/src/fixup_macos_bundle.cmake deleted file mode 100644 index 4766332a6..000000000 --- a/src/launch/xstudio/src/fixup_macos_bundle.cmake +++ /dev/null @@ -1,15 +0,0 @@ -# Fix library paths in the app bundle to ensure they're relative -file(GLOB_RECURSE LIBRARIES "${APP_BUNDLE_DIR}/Contents/Frameworks/*.dylib") -foreach(LIB ${LIBRARIES}) - get_filename_component(LIB_NAME ${LIB} NAME) - execute_process(COMMAND install_name_tool -id "@rpath/${LIB_NAME}" ${LIB}) -endforeach() - -# Fix executable references to libraries -execute_process( - COMMAND - install_name_tool - -add_rpath - "@executable_path/../Frameworks" - ${APP_BUNDLE_DIR}/Contents/MacOS/xstudio.bin -) diff --git a/src/launch/xstudio/src/macdeploy.cmake.in b/src/launch/xstudio/src/macdeploy.cmake.in index 4a7b59b7e..4c6100173 100644 --- a/src/launch/xstudio/src/macdeploy.cmake.in +++ b/src/launch/xstudio/src/macdeploy.cmake.in @@ -2,25 +2,10 @@ # This command manipulates the rpath in ffmpeg so it can find the ffmpeg libs in the Frameworks # folder in the app bundle execute_process(COMMAND install_name_tool ${CMAKE_BINARY_DIR}/xSTUDIO.app/Contents/MacOS/ffmpeg -rpath @loader_path/../../lib @loader_path/../Frameworks WORKING_DIRECTORY "${CMAKE_INSTALL_PREFIX}") - + # macdeployqt finds xSTUDIO's library dependencies and adds them to the app bundle, as well as -# making necessary rpath manipulations -message("Running @macdeployqt_exe@ with args: ${CMAKE_BINARY_DIR}/xSTUDIO.app -qmldir=@CMAKE_SOURCE_DIR@/ui") -execute_process(COMMAND "@macdeployqt_exe@" ${CMAKE_BINARY_DIR}/xSTUDIO.app -qmldir=@CMAKE_SOURCE_DIR@/ui +# making necessary rpath manipulations. -always-overwrite forces a fresh deploy so that a +# stale bundle from a prior install cannot leave frameworks unsigned. +message("Running @macdeployqt_exe@ with args: ${CMAKE_BINARY_DIR}/xSTUDIO.app -qmldir=@CMAKE_SOURCE_DIR@/ui -always-overwrite") +execute_process(COMMAND "@macdeployqt_exe@" ${CMAKE_BINARY_DIR}/xSTUDIO.app -qmldir=@CMAKE_SOURCE_DIR@/ui -always-overwrite WORKING_DIRECTORY "${CMAKE_INSTALL_PREFIX}") - -# Fix library paths to ensure they're relative to the bundle -execute_process( - COMMAND - install_name_tool -id - "@rpath/libglobal.dylib" - ${CMAKE_BINARY_DIR}/xSTUDIO.app/Contents/Frameworks/libglobal.dylib -) -execute_process( - COMMAND - install_name_tool - -change - "@rpath/libglobal.dylib" - "@executable_path/../Frameworks/libglobal.dylib" - ${CMAKE_BINARY_DIR}/xSTUDIO.app/Contents/MacOS/xstudio.bin -)