# Dependency not being respected - executable not being relinked when necessary

**URL:** https://discourse.cmake.org/t/dependency-not-being-respected-executable-not-being-relinked-when-necessary/8906
**Category:** Usage
**Tags:** os:linux
**Created:** [September 8, 2023, 3:33am UTC](https://discourse.cmake.org/t/dependency-not-being-respected-executable-not-being-relinked-when-necessary/8906 "2023-09-08T03:33:33Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![Barry\_Revzin](https://discourse.cmake.org/user_avatar/discourse.cmake.org/barry_revzin/32/1283_2.png) [@Barry\_Revzin](https://discourse.cmake.org/u/Barry_Revzin)
#### Post date: [September 8, 2023, 3:33am UTC](https://discourse.cmake.org/t/dependency-not-being-respected-executable-not-being-relinked-when-necessary/8906/1 "2023-09-08T03:33:34Z")

</div>

Consider the following reduced and seemingly silly example. We require four files:

```auto
.
├── CMakeLists.txt
├── ex1.cxx
├── ex2.cxx
└── gen_linker.py

```

CMakeLists.txt:

```cmake
cmake_minimum_required(VERSION 3.24)
project(linking)

add_library(ex1-compiled OBJECT ex1.cxx)
add_library(ex2-compiled OBJECT ex2.cxx)

add_custom_command(
    OUTPUT
        linker.ld
    COMMAND
        python3 ${CMAKE_CURRENT_SOURCE_DIR}/gen_linker.py --dir ${CMAKE_CURRENT_SOURCE_DIR} > linker.ld
    DEPENDS
        ex1-compiled $<TARGET_OBJECTS:ex1-compiled>
        ex2-compiled $<TARGET_OBJECTS:ex2-compiled>
)
add_custom_target(linker.ld-target DEPENDS linker.ld)

add_executable(ex1 $<TARGET_OBJECTS:ex1-compiled> linker.ld)
add_dependencies(ex1 linker.ld-target)
target_link_options(ex1 PRIVATE "-g" "LINKER:@linker.ld")

add_executable(ex2 $<TARGET_OBJECTS:ex2-compiled> linker.ld)
add_dependencies(ex2 linker.ld-target)
target_link_options(ex2 PRIVATE "-g" "LINKER:@linker.ld")

```

The python `gen_linker.py` simply counts the number of lines in `ex1.cxx` and `ex2.cxx` and outputs them:

```python
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--dir")
args = parser.parse_args()

def num_lines(filename):
    return open(f"{args.dir}/{filename}").read().count('\n')

lines1 = num_lines("ex1.cxx")
lines2 = num_lines("ex2.cxx")
print(f"--defsym=lines1={lines1} --defsym=lines2={lines2}")

```

And `ex1.cxx` and `ex2.cxx` are both initially:

```cpp
#include <cstdio>
#include <cstdint>

extern int lines1;
extern int lines2;

int main(int, char** argv) {
    printf("%s] lines1=%ld lines2=%ld\n", argv[0], (intptr_t)&lines1, (intptr_t)&lines2);
}

```

If we try to compile this (same behavior with both Ninja and Unix Makefiles):

```auto
$ mkdir build && cd build
$ cmake -G Ninja ..
$ ninja ex1 ex2
$ ./ex1
./ex1] lines1=9 lines2=9
$ ./ex2
./ex2] lines1=9 lines2=9

```

Now, if we change `ex2.cxx` to just add another `printf`:

```diff
#include <cstdio>
#include <cstdint>

extern int lines1;
extern int lines2;

int main(int, char** argv) {
    printf("%s] lines1=%ld lines2=%ld\n", argv[0], (intptr_t)&lines1, (intptr_t)&lines2);
+ printf("ex2 rocks\n");
}

```

Then:

```auto
$ ninja ex1 ex2
$ ./ex1
./ex1] lines1=9 lines2=9
$ ./ex2
./ex2] lines1=9 lines2=10
ex2 rocks

```

`ex1` should print that `lines2=10` though, same as `ex2`, since `ex2.cxx` was updated which caused `linker.ld` to be updated updated (it does correctly read `--defsym=lines2=10`), but it doesn’t. `ex1` was not re-linked.

What needs to change in order to get this to work? That is: how do I convinced CMake to actually relink both `ex1` and `ex2` when `linker.ld` is regenerated?

---

<div class="post-metadata">

### Author: ![Barry\_Revzin](https://discourse.cmake.org/user_avatar/discourse.cmake.org/barry_revzin/32/1283_2.png) [@Barry\_Revzin](https://discourse.cmake.org/u/Barry_Revzin)
#### Post date: [September 8, 2023, 1:58pm UTC](https://discourse.cmake.org/t/dependency-not-being-respected-executable-not-being-relinked-when-necessary/8906/3 "2023-09-08T13:58:24Z")

</div>

In case it’s useful, this is the intended dependency diagram here:

 ![image](https://discourse.cmake.org/uploads/default/original/2X/9/92169057eefada05be1278708e091e7d3c61ab55.png)

In this case, mutating `ex2.cxx` does modify `ex2.o`, which leads to modifying `linker.ld`, which modifies `ex2`. But `ex1` is not updated.

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [September 8, 2023, 7:11pm UTC](https://discourse.cmake.org/t/dependency-not-being-respected-executable-not-being-relinked-when-necessary/8906/4 "2023-09-08T19:11:34Z")

</div>

I do not understand you intention to work in this way?

But with small modification to make it portable, it works for me:

```bash
Claus-iMac:build clausklein$ ninja -nv -d explain
ninja: no work to do.
Claus-iMac:build clausklein$ ninja -nv -d explain
ninja explain: output CMakeFiles/ex1-compiled.dir/ex1.cxx.o older than most recent input /Users/clausklein/Workspace/cmake/tmp/ex1.cxx (1694199831302477561 vs 1694199853806158000)
ninja explain: CMakeFiles/ex1-compiled.dir/ex1.cxx.o is dirty
ninja explain: ex1-compiled is dirty
ninja explain: CMakeFiles/ex1-compiled.dir/ex1.cxx.o is dirty
ninja explain: CMakeFiles/ex1-compiled.dir/ex1.cxx.o is dirty
ninja explain: /Users/clausklein/Workspace/cmake/tmp/build/linker.cxx is dirty
ninja explain: /Users/clausklein/Workspace/cmake/tmp/build/linker.cxx is dirty
ninja explain: CMakeFiles/ex1.dir/linker.cxx.o is dirty
ninja explain: ex1 is dirty
ninja explain: /Users/clausklein/Workspace/cmake/tmp/build/linker.cxx is dirty
ninja explain: /Users/clausklein/Workspace/cmake/tmp/build/linker.cxx is dirty
ninja explain: CMakeFiles/ex2.dir/linker.cxx.o is dirty
ninja explain: ex2 is dirty
[1/6] /usr/local/bin/g++-13 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk -MD -MT CMakeFiles/ex1-compiled.dir/ex1.cxx.o -MF CMakeFiles/ex1-compiled.dir/ex1.cxx.o.d -o CMakeFiles/ex1-compiled.dir/ex1.cxx.o -c /Users/clausklein/Workspace/cmake/tmp/ex1.cxx
[2/6] cd /Users/clausklein/Workspace/cmake/tmp/build && python3 /Users/clausklein/Workspace/cmake/tmp/gen_linker.py --dir /Users/clausklein/Workspace/cmake/tmp > linker.cxx
[3/6] /usr/local/bin/g++-13 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk -MD -MT CMakeFiles/ex1.dir/linker.cxx.o -MF CMakeFiles/ex1.dir/linker.cxx.o.d -o CMakeFiles/ex1.dir/linker.cxx.o -c /Users/clausklein/Workspace/cmake/tmp/build/linker.cxx
[4/6] /usr/local/bin/g++-13 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk -MD -MT CMakeFiles/ex2.dir/linker.cxx.o -MF CMakeFiles/ex2.dir/linker.cxx.o.d -o CMakeFiles/ex2.dir/linker.cxx.o -c /Users/clausklein/Workspace/cmake/tmp/build/linker.cxx
[5/6] : && /usr/local/bin/g++-13 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/ex1-compiled.dir/ex1.cxx.o CMakeFiles/ex1.dir/linker.cxx.o -o ex1 && :
[6/6] : && /usr/local/bin/g++-13 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/ex2-compiled.dir/ex2.cxx.o CMakeFiles/ex2.dir/linker.cxx.o -o ex2 && :
Claus-iMac:build clausklein$ 

```

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [September 8, 2023, 7:14pm UTC](https://discourse.cmake.org/t/dependency-not-being-respected-executable-not-being-relinked-when-necessary/8906/5 "2023-09-08T19:14:30Z")

</div>

CMakeLists.txt

```cmake
cmake_minimum_required(VERSION 3.24...3.27)

project(linking LANGUAGES CXX)

add_library(ex1-compiled OBJECT ex1.cxx)
add_library(ex2-compiled OBJECT ex2.cxx)

add_custom_command(
  OUTPUT linker.cxx
  COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/gen_linker.py --dir ${CMAKE_CURRENT_SOURCE_DIR} >
          linker.cxx
  DEPENDS ex1-compiled $<TARGET_OBJECTS:ex1-compiled> ex2-compiled $<TARGET_OBJECTS:ex2-compiled>
)

add_executable(ex1 $<TARGET_OBJECTS:ex1-compiled> linker.cxx)
add_executable(ex2 $<TARGET_OBJECTS:ex2-compiled> linker.cxx)

```

gen\_linker.py

```python
#! /usr/bin/env python3

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--dir")
args = parser.parse_args()

def num_lines(filename):
    return open(f"{args.dir}/{filename}").read().count("\n")

lines1 = num_lines("ex1.cxx")
lines2 = num_lines("ex2.cxx")
print(f"int lines1={lines1};\nint lines2={lines2};\n")

```

---

<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: [September 8, 2023, 9:35pm UTC](https://discourse.cmake.org/t/dependency-not-being-respected-executable-not-being-relinked-when-necessary/8906/7 "2023-09-08T21:35:06Z")

</div>

There are some subtle things going on in your original example. They might or might not be the cause of the behavior you’re seeing, but it is easy enough to find out.

- In `add_custom_command()`, if you list a relative path after `OUTPUT`, that is treated as relative to the current build directory (`${CMAKE_CURRENT_BINARY_DIR}`).
- In your call to `add_custom_target()`, you list a relative path to `linker.ld` after `DEPENDS`. The CMake docs for `add_custom_target()` are silent on how that is interpreted. After a quick look at the CMake code, I think it is treated the same as for `add_custom_command()`, which has a detailed explanation. Based on the explanation there, the bare `linker.ld` should get treated as a path relative to `${CMAKE_CURRENT_BINARY_DIR}`. It’s the last fallback when all other possibilities don’t apply.
- In both calls to `add_executable()`, `linker.ld` is once again listed without any path. In such cases, the file must exist in either the source or build directory, but I don’t recall the order in which CMake checks. This behavior is not documented, as far as I can tell. Note that it will do this check at CMake generation time, not at build time.

Now, based on the above, the final result of all the dependencies _should_ be well-defined, but I’ve long had suspicions that there may be some subtle bugs or unexpected behaviours lurking amongst all that. To remove all doubt, personally I don’t rely on those rules and always specify absolute paths when I expect a file to be in the build directory. It would be good if we could eliminate this from your example, if nothing else but to confirm that there isn’t something funky going on with all that. Here’s a modified version with paths expressed explicitly:

```cmake
cmake_minimum_required(VERSION 3.24)
project(linking)

add_library(ex1-compiled OBJECT ex1.cxx)
add_library(ex2-compiled OBJECT ex2.cxx)

set(linker_ld_file ${CMAKE_CURRENT_BINARY_DIR}/linker.ld)

add_custom_command(
    OUTPUT
        ${linker_ld_file}
    COMMAND
        python3 ${CMAKE_CURRENT_SOURCE_DIR}/gen_linker.py --dir ${CMAKE_CURRENT_SOURCE_DIR} > ${linker_ld_file}
    DEPENDS
        ex1-compiled $<TARGET_OBJECTS:ex1-compiled>
        ex2-compiled $<TARGET_OBJECTS:ex2-compiled>
)
add_custom_target(linker.ld-target DEPENDS ${linker_ld_file})

add_executable(ex1 $<TARGET_OBJECTS:ex1-compiled> ${linker_ld_file})
add_dependencies(ex1 linker.ld-target)
target_link_options(ex1 PRIVATE "-g" "LINKER:@${linker_ld_file}")

add_executable(ex2 $<TARGET_OBJECTS:ex2-compiled> ${linker_ld_file})
add_dependencies(ex2 linker.ld-target)
target_link_options(ex2 PRIVATE "-g" "LINKER:@${linker_ld_file}")

```

There’s a few other things in your example that I wouldn’t do that way or that I think are unnecessary, but those are unlikely to be related to your problem, so I’ll refrain from commenting on those so we can keep discussion focused on your problem.

---

<div class="post-metadata">

### Author: ![Barry\_Revzin](https://discourse.cmake.org/user_avatar/discourse.cmake.org/barry_revzin/32/1283_2.png) [@Barry\_Revzin](https://discourse.cmake.org/u/Barry_Revzin)
#### Post date: [September 8, 2023, 9:44pm UTC](https://discourse.cmake.org/t/dependency-not-being-respected-executable-not-being-relinked-when-necessary/8906/8 "2023-09-08T21:44:22Z")

</div>

> [@ClausKlein](#):
>
> IMHO: the CXX code is ugly?

This is quite rude. I do not care about your opinion about the quality of the C++ code that exists in this question solely to be a minimal reproduced example of the _build_ issue that I am trying to get resolved.

The comments you have added to this post are not even an attempt to answer my question. They have not been helpful.

---

<div class="post-metadata">

### Author: ![Barry\_Revzin](https://discourse.cmake.org/user_avatar/discourse.cmake.org/barry_revzin/32/1283_2.png) [@Barry\_Revzin](https://discourse.cmake.org/u/Barry_Revzin)
#### Post date: [September 8, 2023, 9:47pm UTC](https://discourse.cmake.org/t/dependency-not-being-respected-executable-not-being-relinked-when-necessary/8906/9 "2023-09-08T21:47:45Z")

</div>

Hi Craig! Thanks for the response.

I changed the CMakeLists.txt as you suggested - using absolute paths everywhere. In my real example, I was doing that already - this was a poor reproduction on my part. But doing so doesn’t resolve the issue. Even with absolute paths, `ex1` isn’t being updated when a change to `ex2.cxx` triggers a change to `linker.ld`.

---

<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: [September 9, 2023, 12:35am UTC](https://discourse.cmake.org/t/dependency-not-being-respected-executable-not-being-relinked-when-necessary/8906/10 "2023-09-09T00:35:10Z")

</div>

I did some digging into this example with Ninja, and from what I can tell, the crux of the problem is that the executable targets end up with an order-only dependency on the `linker.ld-target` custom target. I think that explains why the first build works (no targets are up to date yet), but the second build after modifying ex2.cpp doesn’t cause ex1 to be relinked. That’s a bit of a guess on my part, but I couldn’t see any else immediately obvious which may explain the behavior.

This is getting a bit beyond my understanding of the nitty gritty details of the way dependencies are defined. We may need input from @brad.king on this one. I would have expected your example to work, but maybe there’s some subtle aspect of this I’m overlooking.

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [September 9, 2023, 10:08am UTC](https://discourse.cmake.org/t/dependency-not-being-respected-executable-not-being-relinked-when-necessary/8906/11 "2023-09-09T10:08:27Z")

</div>

> [@Barry\_Revzin](#):
>
> The comments you have added to this post are not even an attempt to answer my question. They have not been helpful.

## You didn’t explain your task you want to solve with your prototype.

Q: do you really need a linker `ld` file?  
Q: does it has something to do with c++?  
Q: should your solution only work on Linux?  
Q: do you really need to count the lines in your main?

## My Example works on every build host with every c/c++ compiler, yours not!

I will try to explain my prototype:

You need a clear, simple dependency DAG.  
If you really want to create a linker ld file, that depends on every source file in your project, then my example is also not right!

## But if you only want to link all your mains, if the ld file was updated, it works fine.

Simply touch an empty source file that will be linked to your mains.

```cmake
cmake_minimum_required(VERSION 3.24...3.27)

project(linking LANGUAGES CXX)

add_library(ex1-compiled OBJECT ex1.cxx)
add_library(ex2-compiled OBJECT ex2.cxx)

set(linker_ld_file ${CMAKE_CURRENT_BINARY_DIR}/linker.ld)

add_custom_command(
  OUTPUT linker_generated.cxx ${linker_ld_file}
  COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/gen_linker.py --dir ${CMAKE_CURRENT_SOURCE_DIR} >
          linker_generated.cxx
  COMMAND touch ${linker_ld_file}
  DEPENDS ex1-compiled $<TARGET_OBJECTS:ex1-compiled> ex2-compiled $<TARGET_OBJECTS:ex2-compiled>
)

add_executable(ex1 $<TARGET_OBJECTS:ex1-compiled> linker_generated.cxx)
target_link_options(ex1 PRIVATE "-g" "LINKER:@${linker_ld_file}")

add_executable(ex2 $<TARGET_OBJECTS:ex2-compiled> linker_generated.cxx)
target_link_options(ex2 PRIVATE "-g" "LINKER:@${linker_ld_file}")

```

---

<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: [September 10, 2023, 7:40am UTC](https://discourse.cmake.org/t/dependency-not-being-respected-executable-not-being-relinked-when-necessary/8906/12 "2023-09-10T07:40:30Z")

</div>

Let’s focus on the problem raised in the original post. That post does highlight that the example given was a “reduced and seemingly silly example”. We should expect that what has been presented isn’t meant to be the best way to achieve something, only that it is somehow representative of a problem in a larger, more complex project.

@Barry_Revzin So that we can refocus discussions here, can you please confirm that the main problem you’re asking about is that you expected the `gen_linker.py` script to be re-executed and both `ex1` and `ex2` to be re-linked if either `ex1.cxx` or `ex2.cxx` is modified, but you’re not seeing that occur and you’d like to understand why?

---

<div class="post-metadata">

### Author: ![Barry\_Revzin](https://discourse.cmake.org/user_avatar/discourse.cmake.org/barry_revzin/32/1283_2.png) [@Barry\_Revzin](https://discourse.cmake.org/u/Barry_Revzin)
#### Post date: [September 11, 2023, 1:34pm UTC](https://discourse.cmake.org/t/dependency-not-being-respected-executable-not-being-relinked-when-necessary/8906/13 "2023-09-11T13:34:42Z")

</div>

> [@craig.scott](#):
>
> Let’s focus on the problem raised in the original post. That post does highlight that the example given was a “reduced and seemingly silly example”. We should expect that what has been presented isn’t meant to be the best way to achieve something, only that it is somehow representative of a problem in a larger, more complex project.

Yes, exactly. Thank you.

> [@craig.scott](#):
>
> @Barry_Revzin So that we can refocus discussions here, can you please confirm that the main problem you’re asking about is that you expected the `gen_linker.py` script to be re-executed and both `ex1` and `ex2` to be re-linked if either `ex1.cxx` or `ex2.cxx` is modified, but you’re not seeing that occur and you’d like to understand why?

Yeah, that’s right. I made a cute mermaid diagram of the dependencies that I posted up top. Basically when `ex2.cxx` is updated, `ex2.o` needs to get rebuilt (this happens), and then `linker.ld` needs to get regenerated (this happens), and then `ex2` needs to get relinked with the new object file and the new linker file (this also happens) but `ex1` doesn’t get relinked even though `linker.ld` was updated.

A colleague pointed me to `LINK_DEPENDS` and this is where it gets a little weirder. Here’s a slightly longer version of the CMakeLists.txt file. I added two options, `ADD_DEP` and `SET_PROP`. `ADD_DEP=On SET_PROP=Off` is what my original example was doing:

```cmake
cmake_minimum_required(VERSION 3.24)
project(linking)

add_library(ex1-compiled OBJECT ex1.cxx)
add_library(ex2-compiled OBJECT ex2.cxx)

set(linker_ld_file ${CMAKE_CURRENT_BINARY_DIR}/linker.ld)

add_custom_command(
    OUTPUT
        ${linker_ld_file}
    COMMAND
        python3 ${CMAKE_CURRENT_SOURCE_DIR}/gen_linker.py --dir ${CMAKE_CURRENT_SOURCE_DIR} > ${linker_ld_file}
    DEPENDS
        ex1-compiled $<TARGET_OBJECTS:ex1-compiled>
        ex2-compiled $<TARGET_OBJECTS:ex2-compiled>
)
add_custom_target(linker.ld-target DEPENDS ${linker_ld_file})

add_executable(ex1 $<TARGET_OBJECTS:ex1-compiled> ${linker_ld_file})
target_link_options(ex1 PRIVATE "-g" "LINKER:@${linker_ld_file}")

add_executable(ex2 $<TARGET_OBJECTS:ex2-compiled> ${linker_ld_file})
target_link_options(ex2 PRIVATE "-g" "LINKER:@${linker_ld_file}")

option(SET_PROP OFF)
if(SET_PROP)
    message(STATUS "Calling set_target_properties")
    set_target_properties(ex1 PROPERTIES LINK_DEPENDS linker.ld-target)
    set_target_properties(ex2 PROPERTIES LINK_DEPENDS linker.ld-target)
endif()

option(ADD_DEP OFF)
if(ADD_DEP)
    message(STATUS "Calling add_dependencies")
    add_dependencies(ex1 linker.ld-target)
    add_dependencies(ex2 linker.ld-target)
endif()

```

Now, here is the behavior I see.

| Ninja | `ADD_DEP=Off` | `ADD_DEP=On` |
| --- | --- | --- |
| `SET_PROP=Off` | doesn’t compile (won’t build linker.ld) ❌ | builds but doesn’t relink ❌ |
| `SET_PROP=On` | works! ✔ | works! ✔ |

That setting both options to `Off` (top left) causes the initial build to fail makes sense - there’s no expressed dependency on `linker.ld` so it isn’t generated.

| Unix Makefiles | `ADD_DEP=Off` | `ADD_DEP=On` |
| --- | --- | --- |
| `SET_PROP=Off` | builds but doesn’t relink (???) ❌ | builds but doesn’t relink ❌ |
| `SET_PROP=On` | doesn’t build\* ❌ | doesn’t build\* ❌ |

I don’t understand this table. Setting both options to off still has the build succeed, despite not expressing the dependency on `linker.ld` anywhere. But if you add `set_target_properties`, _that’s_ when I get this failure:

```auto
make[2]: *** No rule to make target 'linker.ld-target', needed by 'ex1'. Stop.
make[1]: *** [CMakeFiles/Makefile2:171: CMakeFiles/ex1.dir/all] Error 2
make: *** [Makefile:91: all] Error 2

```

And that’s regardless if you also add `add_dependencies()` or not.

---

<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: [September 13, 2023, 7:27pm UTC](https://discourse.cmake.org/t/dependency-not-being-respected-executable-not-being-relinked-when-necessary/8906/14 "2023-09-13T19:27:11Z")

</div>

I suspect that’s due to the split view the Makefiles have of the whole build graph. FWIW, until we have a global graph for Makefiles as well (needed for reliable C++ modules support), I think it’d be OK to just say “use the Ninja generator” for now.

---

<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: [September 13, 2023, 9:56pm UTC](https://discourse.cmake.org/t/dependency-not-being-respected-executable-not-being-relinked-when-necessary/8906/15 "2023-09-13T21:56:53Z")

</div>

> [@ben.boeckel](#):
>
> …I think it’d be OK to just say “use the Ninja generator” for now.

Note that I was [seeing problems](https://discourse.cmake.org/t/dependency-not-being-respected-executable-not-being-relinked-when-necessary/8906/10) even with the Ninja generator.
