# What can I replace "INSTALL" with?

**URL:** <https://discourse.cmake.org/t/what-can-i-replace-install-with/13050>\
**Category:** Code\
**Created:** [November 24, 2024, 10:25pm UTC](https://discourse.cmake.org/t/what-can-i-replace-install-with/13050 "2024-11-24T22:25:23Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![mzlink](https://discourse.cmake.org/user_avatar/discourse.cmake.org/mzlink/32/5147_2.png) [@mzlink](https://discourse.cmake.org/u/mzlink)\
**Post date:** [November 24, 2024, 10:25pm UTC](https://discourse.cmake.org/t/what-can-i-replace-install-with/13050/1 "2024-11-24T22:25:23Z")

</div>

Hello, I have a CMakeLists.txt that I’m not entirely happy with as a user of Visual Studio 2022.

Basically, I haven’t found a solution to the catch-22 that is: if i do build ALL\_BUILD the INSTALL step happens and the application is successfully built, but this configuration cannot be debugged directly.

If I instead change to build MyApp, the INSTALL step will never execute and thus the debugger cannot find the files.

I do not like having to first do the ALL\_BUILD, switch to MyApp and then run the debugger.  
What are some options to patch the CMakeLists.txt file?

Relevant code:

```auto

# Set the correct debugger working directory in case Visual Studio is to be used
set_property(TARGET ${PROJECT_NAME} PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")

# Without the trailing / after assets, it would copy the directory instead of its contents
install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_SOURCE_DIR}/bin) #executable

install(DIRECTORY "$<TARGET_FILE:tgui>" DESTINATION ${CMAKE_SOURCE_DIR}/bin) # libtgui.a

install(DIRECTORY ${PROJECT_SOURCE_DIR}/src/assets/ DESTINATION ${CMAKE_SOURCE_DIR}/bin) # logo.png and other assets

install(DIRECTORY ../build/_deps/tgui-src/themes/ DESTINATION ${CMAKE_SOURCE_DIR}/bin/themes) # black.txt and etc theme-specific files

```

---

<div class="post-metadata">

**Author:** ![ferdnyc](https://discourse.cmake.org/user_avatar/discourse.cmake.org/ferdnyc/32/267_2.png) [@ferdnyc](https://discourse.cmake.org/u/ferdnyc)\
**Post date:** [November 25, 2024, 4:33am UTC](https://discourse.cmake.org/t/what-can-i-replace-install-with/13050/2 "2024-11-25T04:33:35Z")

</div>

If you just want to create a runnable/debuggable copy of your application after it’s compiled, I definitely wouldn’t recommend using `install()` for that.

I also wouldn’t recommend writing any destination paths relative to `${CMAKE_SOURCE_DIR}`, under any circumstances. Install paths are meant to be relative to the `${CMAKE_INSTALL_PREFIX}` (but that’s implicit, you don’t have to write it), and I think that defaults to `C:\Program Files\` on Windows — but it can be changed at install time. And any other paths you write to during the build process should be relative to the `${CMAKE_BINARY_DIR}`, instead of polluting your source tree.

It’s common to consolidate application files, necessary DLLs, etc. into a directory inside the build directory, when running on Windows, because those are often necessary prerequisites for running the program uninstalled. (Or running tests on the compiled programs/DLLs.)

The way that’s typically done is by using CMake’s `-E` mode to run common filesystem commands (you can run `cmake -E help` to get a list of them); you’d execute those commands inside an `execute_process()` (for static files that are available at configure time), or as an `add_custom_command(TARGET <name> POST_BUILD)` step that will run after the target’s build step is complete.

So, you might do something like this:

```cmake
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
  COMMAND
    ${CMAKE_COMMAND} -E make_directory
      "${CMAKE_BINARY_DIR}/bin"
  COMMAND 
    ${CMAKE_COMMAND} -E copy
      "$<TARGET_FILE:${PROJECT_NAME}>"
      "${CMAKE_BINARY_DIR}/bin/"
)

execute_process(
  COMMAND
    ${CMAKE_COMMAND} -E make_directory
      "${CMAKE_BINARY_DIR}/bin"
  COMMAND
    ${CMAKE_COMMAND} -E copy_directory
      "${PROJECT_SOURCE_DIR}/src/assets"
      "${CMAKE_BINARY_DIR}/bin/"
)

```

And so on for anything else. The `make_directory` will silently succeed if the dir already exists, so it’s safest to do it redundantly.

Any `execute_process()` commands will execute _during the configure step_, so the files they’re accessing have to already exist. For files that only exist _after_ certain targets are built, use `add_custom_command()` to set the copy up as a `POST_BUILD` step.

(That includes anything that comes from `tgui-src`, as that won’t exist when cmake is setting up the initial config. Tho presuming that’s a `FetchContent` package, you should use the variable `${tgui_SOURCE_DIR}` to reference paths in that location. `FetchContent_Populate()` will create that variable when it’s run.)

**Edit:** Note that all of these commands should ideally be used _in addition to_ a set of `install()` commands that make your program actually installable. But like I said, _those_ commands should use paths that are implicitly relative to the `${CMAKE_INSTALL_PREFIX}`, which on Windows often means installing everything to a directory named after the project, or maybe `"${PROJECT_NAME}-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"`:

```cmake
set(PROJECT_INSTALL_DIR
 "${PROJECT_NAME}-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
install(TARGETS ${PROJECT_NAME}
  RUNTIME DESTINATION ${PROJECT_INSTALL_DIR}
  LIBRARY DESTINATION ${PROJECT_INSTALL_DIR}
  ARCHIVE DESTINATION ${PROJECT_INSTALL_DIR}
)
install(DIRECTORY
  "${CMAKE_SOURCE_DIR}/src/assets/"
  DESTINATION ${PROJECT_INSTALL_DIR}
)
install(DIRECTORY
  "${tgui_SOURCE_DIR}/themes"
  DESTINATION ${PROJECT_INSTALL_DIR}
)

```

I _believe_ it’s safe to use `${tgui_SOURCE_DIR}` in the `install()` command, as long as that variable has already been set, because the `install()` command just generates commands to a `cmake_install.cmake` script that gets executed to perform the install. And at install time, you know the `tgui` source will already have been downloaded.

---

<div class="post-metadata">

**Author:** ![mzlink](https://discourse.cmake.org/user_avatar/discourse.cmake.org/mzlink/32/5147_2.png) [@mzlink](https://discourse.cmake.org/u/mzlink)\
**Post date:** [November 25, 2024, 8:55am UTC](https://discourse.cmake.org/t/what-can-i-replace-install-with/13050/3 "2024-11-25T08:55:22Z")

</div>

> [@ferdnyc](#):
>
> I also wouldn’t recommend writing any destination paths relative to `${CMAKE_SOURCE_DIR}`, under any circumstances

It technically isn’t doing that “pollution” afaik. Because i have a root directory with CMakeLists.txt which calls CMakeLists.txt inside “src” folder (this one holds the actual build process, including fetching deps)  
Reference: [GitHub - Snowblaze/sdl2-cmake-starter](https://github.com/Snowblaze/sdl2-cmake-starter) (which i have edited a fair bit)

**Edit:** I recall messing around with the `${CMAKE_BINARY_DIR}` but never actually getting it to “stick” with Visual Studio, it always ended up in a weird path after a while. This makes the built application annoying to package, especially since it would leave me with random duplicates.

---

<div class="post-metadata">

**Author:** ![ferdnyc](https://discourse.cmake.org/user_avatar/discourse.cmake.org/ferdnyc/32/267_2.png) [@ferdnyc](https://discourse.cmake.org/u/ferdnyc)\
**Post date:** [November 25, 2024, 11:05am UTC](https://discourse.cmake.org/t/what-can-i-replace-install-with/13050/4 "2024-11-25T11:05:22Z")

</div>

> [@mzlink](#):
>
> It technically isn’t doing that “pollution” afaik.

It absolutely is. `${CMAKE_SOURCE_DIR}` is the source directory of your project, the place your top-level `CMakeLists.txt` is located. `${CMAKE_CURRENT_SOURCE_DIRECTORY}` is the directory of the **current** `CMakeLists.txt` file being processed. But they’re all source directories. If you create anything during the build, it should be somewhere inside `${CMAKE_BINARY_DIR}` or `${CMAKE_CURRENT_BINARY_DIR}`.

> [@mzlink](#):
>
> Because i have a root directory with CMakeLists.txt which calls CMakeLists.txt inside “src” folder (this one holds the actual build process, including fetching deps)

I know you’re using Visual Studio, which probably has its own weird ideas about where to store build artifacts (Qt Creator does as well), but that’s a tool issue. If you were to go into a terminal session and run this:

```console
$ cd c:\path\to\your\toplevel\source\directory
$ cmake -B build -S . -G "Visual Studio 17 2022"

```

What would happen is that CMake would set up a directory `C:\path\to\your\toplevel\source\directory\build` where all of the generated configuration and build artifacts live.

When it processes the top-level `CMakeLists.txt`, _both_ `${CMAKE_BINARY_DIR}` and `${CMAKE_CURRENT_BINARY_DIR}` are set to `C:\path\to\your\toplevel\source\directory\build`. Both `${CMAKE_SOURCE_DIR}` and `${CMAKE_CURRENT_SOURCE_DIR}` are set to `C:\path\to\your\toplevel\source\directory`.

Then, when it descends into the `src` directory due to the `add_directory(src)` in the toplevel `CMakeLists.txt`, `${CMAKE_SOURCE_DIR}` and `${CMAKE_BINARY_DIR}` stay the same, but `${CMAKE_CURRENT_SOURCE_DIR}` becomes `C:\path\to\your\toplevel\source\directory\src`, and `${CMAKE_CURRENT_BINARY_DIR}` becomes `C:\path\to\your\toplevel\source\directory\build\src`.

But if you write anything into any `_SOURCE_DIR` path, you’re storing it somewhere in the _source_ of your project.

### Install destinations

Writing into the source dir can be _valid_, for **install** artifacts — you may _want_ to install your program to `C:\path\to\your\toplevel\source\directory\bin` (a path outside the build directory). But you should do that by setting the `CMAKE_INSTALL_PREFIX` to `C:\path\to\your\toplevel\source\directory\bin` (by adding `--install-prefix C:\path\to\your\toplevel\source\directory\bin` or `-DCMAKE_INSTALL_PREFIX=C:\path\to\your\toplevel\source\directory\bin` to the `cmake` command / VS CMake configuration, not by hardcoding it in your `CMakeLists.txt` file), then installing the artifacts right in the install directory:

```cmake
install(TARGETS ${PROJECT_NAME}
  RUNTIME DESTINATION "."
  LIBRARY DESTINATION "."
  ARCHIVE DESTINATION "."
)
install(DIRECTORY
  "${CMAKE_SOURCE_DIR}/src/assets/"
  DESTINATION "."
)
# This will create "${CMAKE_INSTALL_PREFIX}/themes"
# with the contents of the directory
install(DIRECTORY
  "${tgui_SOURCE_DIR}/themes" DESTINATION "."
)

```

But the uninstalled, debuggable files that CMake creates during the build should be inside the build directory, so that they can be _deleted_ with the build directory, and so that they’ll be _recreated_ with each build, not persist outside the space where it’s unclear which build they’re from or how they were compiled. (In fact, if you add a `BYPRODUCTS` argument to `add_custom_command()` listing the files created, they’ll be marked as additional build artifacts and deleted when you clean the build directory.)

```cmake
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
  COMMAND
    ${CMAKE_COMMAND} -E make_directory
      "${CMAKE_BINARY_DIR}/bin"
  COMMAND 
    ${CMAKE_COMMAND} -E copy
      "$<TARGET_FILE:${PROJECT_NAME}>"
      "${CMAKE_BINARY_DIR}/bin/"
  BYPRODUCTS
    "${CMAKE_BINARY_DIR}/bin/$<TARGET_FILE_NAME:${PROJECT_NAME}>"
)

```

There’s probably no real reason to do that for the files created with `execute_process()`, because they’re static and don’t need to be recreated. But if you think you might be editing those and _want_ them to be recreated during the build, you can do that copying in `add_custom_command()` calls with `BYPRODUCTS` as well.

### Taking a step back

I should’ve mentioned that if your goal is simply to make the `${PROJECT_NAME}` target output debuggable, and it needs additional files in its directory to do so, it might be better/simpler _not_ to copy that file itself, and instead just copy the _other_ files needed into the same directory where it’s built.

In the same `CMakeLists.txt` where you create the `${PROJECT_NAME}` target with `add_library()` / `add_executable()`, you can copy in all of the required files _to that same directory_ as a post-build step:

```cmake
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
  COMMAND 
    ${CMAKE_COMMAND} -E copy_directory
      "${CMAKE_CURRENT_SOURCE_DIR/assets/"
      "${CMAKE_CURRENT_BINARY_DIR}"
  COMMAND
    ${CMAKE_COMMAND} -E copy_directory
      "${tgui_SOURCE_DIR}/src/themes"
      "${CMAKE_CURRENT_BINARY_DIR}/themes"
  BYPRODUCTS
    # (List the files copied from 
    # "${CMAKE_CURRENT_SOURCE_DIR}/assets/")
    "${CMAKE_CURRENT_BINARY_DIR}/themes"
)

```

…If those files are all that’s required, that should make `$<TARGET_FILE:${PROJECT_NAME}>` (aka `${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.exe` probably) executable directly from its build location, which is the simplest way to make it debuggable, and avoids making a redundant extra copy of the executable.

---

<div class="post-metadata">

**Author:** ![mzlink](https://discourse.cmake.org/user_avatar/discourse.cmake.org/mzlink/32/5147_2.png) [@mzlink](https://discourse.cmake.org/u/mzlink)\
**Post date:** [November 25, 2024, 11:58am UTC](https://discourse.cmake.org/t/what-can-i-replace-install-with/13050/5 "2024-11-25T11:58:06Z")

</div>

> [@ferdnyc](#):
>
> It absolutely is.

I thought the structure of the reference project was to make this “not the case”, but okay.

Moving on:  
I cannot trust the `BINARY_DIR` due to inconsistent behavior in VS2022 - that’s why i want to consolidate everything into a separate directory. (This helps setting up the debugger as well as packaging)

Because I have tried to redirect where VS puts the built files and it is extremely “moody” for a lack of a better word. Sometimes it follows the directions given, sometimes it just ignores it. (this is the duplicates I meant)

---

<div class="post-metadata">

**Author:** ![hsattler](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/h/59ef9b/32.png) [@hsattler](https://discourse.cmake.org/u/hsattler)\
**Post date:** [November 25, 2024, 2:44pm UTC](https://discourse.cmake.org/t/what-can-i-replace-install-with/13050/6 "2024-11-25T14:44:37Z")

</div>

Can you elaborate on the issues you have with VS regarding build directory?

From my experience, it is working just fine.

---

<div class="post-metadata">

**Author:** ![mzlink](https://discourse.cmake.org/user_avatar/discourse.cmake.org/mzlink/32/5147_2.png) [@mzlink](https://discourse.cmake.org/u/mzlink)\
**Post date:** [November 25, 2024, 3:50pm UTC](https://discourse.cmake.org/t/what-can-i-replace-install-with/13050/7 "2024-11-25T15:50:52Z")

</div>

It reverted to building in weird paths, despite not changing anything but rewriting a couple of .hpp files and nothing I did would convince it to reliably use the supplied redirect anymore

I wasted 2 weeks off and on getting nowhere back in March/April, then got tired of the problem and so I changed from trying to make VS2022 “behave” to “let it do it’s thing” and just consolidate files elsewhere, which has been working fine, apart from the issues described in the post at the top.

Something about redirecting `CMAKE_BINARY_OUTPUT_PATH` is wonky when it comes to VS2022 and I haven’t found a pattern to this. `CMAKE_CURRENT_BINARY_DIR` may also be affected, at this point, I don’t know more.

When the redirect is not respected, the executable ends up in like: `MyApp/build/src/<cpu architecture>/<build type>/`

Now i’m not opposed to building release/debug in different folders, but it is not necessary for this project i’m working on. (also that output path is weird, it shouldn’t have `src` in it, but rather `${PROJECT_NAME}` i believe? )
