# Target-dependent linker output location

**URL:** https://discourse.cmake.org/t/target-dependent-linker-output-location/9923
**Category:** Code
**Created:** [January 24, 2024, 6:25pm UTC](https://discourse.cmake.org/t/target-dependent-linker-output-location/9923 "2024-01-24T18:25:21Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![gpanders](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/g/e19adc/32.png) [@gpanders](https://discourse.cmake.org/u/gpanders)
#### Post date: [January 24, 2024, 6:25pm UTC](https://discourse.cmake.org/t/target-dependent-linker-output-location/9923/1 "2024-01-24T18:25:21Z")

</div>

We use `-Wl,-Map,output.map` in `add_link_options` to output a map file in the link stage for all executable targets. This works when using the Makefile generator because Make first changes to the target build directory before compiling and linking, so the `output.map` file is created in each target’s build directory.

However, with the Ninja generator this is not the case. Ninja does not change its directory and thus outputs an `output.map` file in the top level build directory for each target, so they end up clobbering each other.

We could manually use `target_link_options` for every single executable in our source tree, but this is not a desirable solution because it requires quite a bit of new CMake code (`add_link_options` is nice precisely because it applies to all targets “automatically”).

Is there a way to either:

1. Instruct Ninja to behave like Make and have it change to the target’s build directory before compiling & linking?
2. Use the target’s build directory in `add_link_options` so that the map file location is unique for each target (something like `-Wl,-Map,${CMAKE_CURRENT_BINARY_DIR}/output.map`)?

Thanks!

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [January 26, 2024, 2:06pm UTC](https://discourse.cmake.org/t/target-dependent-linker-output-location/9923/2 "2024-01-26T14:06:21Z")

</div>

Does using `$<TARGET_PROPERTY:RUNTIME_OUTPUT_DIRECTORY>` help at all? This might be able to be wrapped up in an `INTERFACE` target that gives it to executables (need to wrap up in a test of the target type as well).

---

<div class="post-metadata">

### Author: ![gpanders](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/g/e19adc/32.png) [@gpanders](https://discourse.cmake.org/u/gpanders)
#### Post date: [January 26, 2024, 2:47pm UTC](https://discourse.cmake.org/t/target-dependent-linker-output-location/9923/3 "2024-01-26T14:47:24Z")

</div>

Thanks for your reply.

I tried changing the line in `add_link_options` to `-Wl,-Map,$<TARGET_PROPERTY:RUNTIME_OUTPUT_DIRECTORY>/output.map`, but this resolves to `/output.map` which fails during linking because the linker cannot write to `/output.map`.

I then tried adding an INTERFACE target, as you suggested:

```auto
    add_library(link-interface INTERFACE)
    target_link_options(link-interface INTERFACE
        # Generate map file for symbol/address information
        -Wl,-Map,$<TARGET_PROPERTY:RUNTIME_OUTPUT_DIRECTORY>/output.map
    )
    link_libraries(link-interface)

```

But the result was the same (the linker tries to write to `/output.map`). And just to be sure, I also tried linking `link-interface` explicitly to a target using `target_link_libraries`, but that did not behave any differently either.

Did I misunderstand your suggestion?

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [January 26, 2024, 5:32pm UTC](https://discourse.cmake.org/t/target-dependent-linker-output-location/9923/4 "2024-01-26T17:32:05Z")

</div>

No; it seems that the property is just unset. If you do something like:

```cmake
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")

```

near the start of your CMake (before any executable is made), does this help? Might still be busted for multi-config generators though.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [January 26, 2024, 5:33pm UTC](https://discourse.cmake.org/t/target-dependent-linker-output-location/9923/5 "2024-01-26T17:33:15Z")

</div>

A possible solution would be to support [`$<TARGET_FILE_DIR>`](https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html#genex:TARGET_FILE_DIR) without an argument where the “head target” is used. @brad.king Thoughts? I suspect that this family of genexes having this behavior would help other, similar, use cases.

---

<div class="post-metadata">

### Author: ![gpanders](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/g/e19adc/32.png) [@gpanders](https://discourse.cmake.org/u/gpanders)
#### Post date: [January 26, 2024, 5:40pm UTC](https://discourse.cmake.org/t/target-dependent-linker-output-location/9923/6 "2024-01-26T17:40:34Z")

</div>

Setting `CMAKE_RUNTIME_OUTPUT_DIRECTORY` causes all executables to be placed in the same directory, but there is still just a single map file (with the same original problem: each executable is clobbering `output.map` when it is linked).

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [January 26, 2024, 8:09pm UTC](https://discourse.cmake.org/t/target-dependent-linker-output-location/9923/7 "2024-01-26T20:09:12Z")

</div>

Hrm, true. This is not something CMake gives good control over now, sorry. You can set `RUNTIME_OUTPUT_DIRECTORY` on each target explicitly in the meantime (it is initialized from the `CMAKE_RUNTIME_OUTPUT_DIRECTORY` variable).
