Getting macdeployqt to handle multiple binaries in the bundle
-
I build a Command Line version of DeepSkyStacker called DeepSkyStackerCL in its own directory as a loose binary (i.e. not in a bundle). I, when I build DeepSkyStacker, I copy it into the bundle at the end of the build:
if(APPLE) add_custom_command(TARGET DeepSkyStacker POST_BUILD # # Now we've built the DSS .app bundle, copy the DSSCL binary into the bundle # The use of $<TARGET_FILE:DeepSkyStackerCL> in add_custom_command also adds # a dependency on the target, so that the DSSCL binary is built before this. # COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:DeepSkyStackerCL> $<TARGET_BUNDLE_CONTENT_DIR:DeepSkyStacker>/MacOS/ COMMAND "$ENV{HOME}/.unlock_keychain" ) endif() if(NOT LINUX) set (deploy_tool_options_arg "-verbose=1") if(APPLE) set(deploy_tool_options_arg "${deploy_tool_options_arg} -hardened-runtime -timestamp -no-strip") set(deploy_tool_options_arg "${deploy_tool_options_arg} \"-codesign=Developer ID Application: David Partridge (VH8AYT3C7Y)\"") elseif(WIN32) set(deploy_tool_options_arg "${deploy_tool_options_arg} --pdb") endif() # Generate a deployment script to be executed at install time # App bundles on macOS have an .app suffix if(APPLE) set(executable_path "${CMAKE_CURRENT_BINARY_DIR}/$<TARGET_FILE_NAME:DeepSkyStacker>.app") else() message ("Target filename:" $<TARGET_FILE_NAME:DeepSkyStacker>) set(executable_path "${CMAKE_CURRENT_BINARY_DIR}/$<TARGET_FILE_NAME:DeepSkyStacker>") endif() message ("executable_path: " ${executable_path}) message ("deploy tools options arg: " ${deploy_tool_options_arg}) qt_generate_deploy_script( TARGET DeepSkyStacker OUTPUT_SCRIPT deploy_script CONTENT " qt_deploy_runtime_dependencies( EXECUTABLE \"${executable_path}\" DEPLOY_TOOL_OPTIONS ${deploy_tool_options_arg} )" ) else() qt_generate_deploy_app_script( TARGET ${PROJECT_NAME} OUTPUT_SCRIPT deploy_script DEPLOY_TOOL_OPTIONS ${deploy_tool_options_arg} ) endif() install (SCRIPT ${deploy_script}) install(TARGETS ${PROJECT_NAME} BUNDLE DESTINATION .)Which is fine except that DeepSkyStackerCL doesn't get updated to point to the libraries in the bundle, so when I try to run it I get:
amonra@Saturn Debug % DSSCL dyld[54749]: Library not loaded: @rpath/QtWidgets.framework/Versions/A/QtWidgets Referenced from: <6DE065A6-9F76-3296-9667-682886AB7282> /Applications/DeepSkyStacker.app/Contents/MacOS/DeepSkyStackerCL Reason: tried: '/usr/local/lib/QtWidgets.framework/Versions/A/QtWidgets' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/usr/local/lib/QtWidgets.framework/Versions/A/QtWidgets' (no such file), '/opt/Qt/6.8.2/macos/lib/QtWidgets.framework/Versions/A/QtWidgets' (code signature in <B16538D5-4C8E-357D-B89A-72F6F81A918D> '/opt/Qt/6.8.2/macos/lib/QtWidgets.framework/Versions/A/QtWidgets' not valid for use in process: mapping process and mapped file (non-platform) have different Team IDs), '/System/Volumes/Preboot/Cryptexes/OS/opt/Qt/6.8.2/macos/lib/QtWidgets.framework/Versions/A/QtWidgets' (no such file), '/usr/local/lib/QtWidgets.framework/Versions/A/QtWidgets' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/usr/local/lib/QtWidgets.framework/Versions/A/QtWidgets' (no such file), '/opt/Qt/6.8.2/macos/lib/QtWidgets.framework/Versions/A/QtWidgets' (code signature in <B16538D5-4C8E-357D-B89A-72F6F81A918D> '/opt/Qt/6.8.2/macos/lib/QtWidgets.framework/Versions/A/QtWidgets' not valid for use in process: mapping process and mapped file (non-platform) have different Team IDs), '/System/Volumes/Preboot/Cryptexes/OS/opt/Qt/6.8.2/macos/lib/QtWidgets.framework/Versions/A/QtWidgets' (no such file) zsh: abort DSSCLHow can I persuade macdeployqt to process all the binaries in the Contents/MacOS directory of the bundle?
Is it as simple as adding:
set(deploy_tool_options_arg "${deploy_tool_options_arg} \"-executable=$<TARGET_BUNDLE_CONTENT_DIR:DeepSkyStacker>/MacOS/DeepSkyStackerCL\"")to the above code?
Thanks
David -
Hi @Perdrix,
The
qt_deploy_runtime_dependencies()command has anADDITIONAL_EXECUTABLESparameter that likely does what you're after?Cheers.
-
Hi @Perdrix,
I should stop using macdeployqt and windeployqt and use
qt_deploy_runtime_dependenciesin all cases?If I'm reading your original post correctly, it looks like you're already using
qt_deploy_runtime_dependencies()for both macOS and Windows.You can use
macdeployqtandwindeployqtdirectly, butqt_deploy_runtime_dependencies()wraps them for you. From the docs:... when executed on macOS or Windows, the command will use either
macdeployqtorwindeployqt, ...If that's now the official position I'll go with it.
I'm not sure either is considered "the official position" - both seem to be supported, and in my mind, both are good options. Though
qt_deploy_runtime_dependencies()was only added in Qt 6.3, so if you want to support older Qt's, then executing{mac,win}deployqtdirectly is the way to go, otherwise I'd stick withqt_deploy_runtime_dependencies()if/while it meets your needs.Either way,
- if you stick with
qt_deploy_runtime_dependencies(), then try adding anADDITIONAL_EXECUTABLESparameter; or - if you want to use
{mac,win}deployqtdirectly, then just copy all of your executables to a staging area, and run{mac,win}deployqton all of them.
Cheers.
- if you stick with