# Building a MAC .app with more than one executable

**URL:** <https://discourse.cmake.org/t/building-a-mac-app-with-more-than-one-executable/13997>\
**Category:** Code\
**Created:** [April 28, 2025, 11:04am UTC](https://discourse.cmake.org/t/building-a-mac-app-with-more-than-one-executable/13997 "2025-04-28T11:04:00Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![perdrix](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/p/a8b319/32.png) [@perdrix](https://discourse.cmake.org/u/perdrix)\
**Post date:** [April 28, 2025, 11:04am UTC](https://discourse.cmake.org/t/building-a-mac-app-with-more-than-one-executable/13997/1 "2025-04-28T11:04:01Z")

</div>

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:

```auto
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:

```auto
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:

```auto
/bin/sh: ls -l /Users/amonra/.vs/DSS/out/build/DeepSkyStackerCL: No such file or directory

```

But copy paste that to terminal on MAC says:

```auto
amonra@Saturn ~ % ls -l /Users/amonra/.vs/DSS/out/build/DeepSkyStackerCL
total 36144
-rw-r--r--@ 1 amonra staff 1501 28 Apr 09:12 cmake_install.cmake
drwxr-xr-x@ 4 amonra staff 128 28 Apr 09:12 CMakeFiles
-rwxr-xr-x@ 1 amonra staff 18435112 28 Apr 09:13 DeepSkyStackerCL
 ...etc

```

Questions:

1. Is this the correct approach?
2. If yes, what is going wrong above?
3. If not, what should I be doing please?

Thanks  
David

---

<div class="post-metadata">

**Author:** ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)\
**Post date:** [April 28, 2025, 9:41pm UTC](https://discourse.cmake.org/t/building-a-mac-app-with-more-than-one-executable/13997/2 "2025-04-28T21:41:39Z")

</div>

> [@perdrix](#):
>
> ```auto
> 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"
> )
> 
> ```

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):

```cmake
    add_custom_command(TARGET DeepSkyStacker
        POST_BUILD
        COMMAND cp $<TARGET_FILE:DeepSkyStackerCL> $<TARGET_BUNDLE_CONTENT_DIR:DeepSkyStacker>/MacOS/
   )

```

EDIT: Typo fixed in the above example.

---

<div class="post-metadata">

**Author:** ![perdrix](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/p/a8b319/32.png) [@perdrix](https://discourse.cmake.org/u/perdrix)\
**Post date:** [April 29, 2025, 8:31am UTC](https://discourse.cmake.org/t/building-a-mac-app-with-more-than-one-executable/13997/3 "2025-04-29T08:31:41Z")

</div>

Wow! Thank you lots, but there seems to be a problem:

```auto
1> [CMake] COMMAND ${CMAKE_COMMAND} -E copy ${<TARGET_FILE:DeepSkyStackerCL> $<TARGET_BUNDLE_CONTENT_DIR:DeepSkyStacker>/MacOS/
1> [CMake] 
1> [CMake] Invalid character ('<') in a variable name: ''

```

---

<div class="post-metadata">

**Author:** ![Angew](https://discourse.cmake.org/user_avatar/discourse.cmake.org/angew/32/229_2.png) [@Angew](https://discourse.cmake.org/u/Angew)\
**Post date:** [April 29, 2025, 8:40am UTC](https://discourse.cmake.org/t/building-a-mac-app-with-more-than-one-executable/13997/4 "2025-04-29T08:40:19Z")

</div>

The `{` is a typo, remove it. The generator expression should be just `$<TARGET_FILE:DeepSkyStackerCL>`.

---

<div class="post-metadata">

**Author:** ![perdrix](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/p/a8b319/32.png) [@perdrix](https://discourse.cmake.org/u/perdrix)\
**Post date:** [April 29, 2025, 8:50am UTC](https://discourse.cmake.org/t/building-a-mac-app-with-more-than-one-executable/13997/5 "2025-04-29T08:50:19Z")

</div>

🙂 Thanks

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 …

Thanks  
David

---

<div class="post-metadata">

**Author:** ![Angew](https://discourse.cmake.org/user_avatar/discourse.cmake.org/angew/32/229_2.png) [@Angew](https://discourse.cmake.org/u/Angew)\
**Post date:** [April 29, 2025, 8:53am UTC](https://discourse.cmake.org/t/building-a-mac-app-with-more-than-one-executable/13997/6 "2025-04-29T08:53:50Z")

</div>

It adds the dependecy automatically. Quoting the relevant [docs](https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html#genex:TARGET_FILE):

> **`$<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()`](https://cmake.org/cmake/help/latest/command/add_custom_command.html#command:add_custom_command) or [`add_custom_target()`](https://cmake.org/cmake/help/latest/command/add_custom_target.html#command: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.

---

<div class="post-metadata">

**Author:** ![perdrix](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/p/a8b319/32.png) [@perdrix](https://discourse.cmake.org/u/perdrix)\
**Post date:** [April 29, 2025, 10:27am UTC](https://discourse.cmake.org/t/building-a-mac-app-with-more-than-one-executable/13997/7 "2025-04-29T10:27:35Z")

</div>

Excellent, thanks for the explanation - exactly what I’d hoped for!!!

Many thanks again  
David
