I would like to create a macOS .app containing a gui application and its command line equivalent.
This is exactly the sort of thing that the CMake.app appears to do.
How can I do this
I initially thought to build the command line version specifying it shouldn’t create a bundle and save the output directory name, then when building the gui version I thought I’d just copy the binary for the CL version into the MacOS directory alongside the gui version:
if(APPLE)
message("ls -l ${DSSCL_BINARY_DIR}")
message("ls -l ${CMAKE_CURRENT_BINARY_DIR}/DeepSkyStacker.app/Contents/MacOS")
message ("cp ${DSSCL_BINARY_DIR}/DeepSkyStackerCL ${CMAKE_CURRENT_BINARY_DIR}/DeepSkyStacker.app/Contents/MacOS/")
message ("$ENV{HOME}/.unlock_keychain")
add_custom_command(TARGET DeepSkyStacker
POST_BUILD
#
# Now we've built the DSS .app bundle, copy the DSSCL binary into the bundle
#
COMMAND "ls -l ${DSSCL_BINARY_DIR}"
COMMAND "ls -l ${CMAKE_CURRENT_BINARY_DIR}/DeepSkyStacker.app/Contents/MacOS"
COMMAND "cp ${DSSCL_BINARY_DIR}/DeepSkyStackerCL ${CMAKE_CURRENT_BINARY_DIR}/DeepSkyStacker.app/Contents/MacOS/"
COMMAND "$ENV{HOME}/.unlock_keychain"
)
Configure output said:
1> [CMake] ls -l /Users/amonra/.vs/DSS/out/build/DeepSkyStackerCL
1> [CMake] ls -l /Users/amonra/.vs/DSS/out/build/DeepSkyStacker/DeepSkyStacker.app/Contents/MacOS
1> [CMake] cp /Users/amonra/.vs/DSS/out/build/DeepSkyStackerCL/DeepSkyStackerCL /Users/amonra/.vs/DSS/out/build/DeepSkyStacker/DeepSkyStacker.app/Contents/MacOS/
1> [CMake] /Users/amonra/.unlock_keychain
Build said:
/bin/sh: ls -l /Users/amonra/.vs/DSS/out/build/DeepSkyStackerCL: No such file or directory
Don’t put quotes around the whole command. CMake would treat the whole quoted string as the executable to run, which you can see in your output where the error message lists the whole command for “No such file…”.
You’re also hard-coding locations for the built binaries (command line and GUI app), and at least one of those will be wrong because Xcode is a multi-config generator, which you haven’t accounted for. Instead of hard-codeing locations of executables, use generator expressions to let CMake provide them for you. For example (omitting all the printing and just focusing on the copy command):
Is there any way to express the dependency here - add_dependencies complains about a non-existent target. Or does the use of $<TARGET_FILE:DeepSkyStackerCL> achieve that?
I want to tell the build the DeepSkyStackerCL must have been built …
It adds the dependecy automatically. Quoting the relevant docs:
$<TARGET_FILE:tgt>
Full path to the tgt binary file.
Note that tgt is not added as a dependency of the target this expression is evaluated on, unless the expression is being used in add_custom_command() or add_custom_target().
Since you’re using it as part of an add_custom_command(), this tells us (after untangling the double negative) that a dependency on the target is added.