# Infinite re-run loop with CMake 3.5.1 and Ninja 1.10.0

**URL:** https://discourse.cmake.org/t/infinite-re-run-loop-with-cmake-3-5-1-and-ninja-1-10-0/1435
**Category:** Usage
**Tags:** os:linux, gen:ninja
**Created:** [June 23, 2020, 1:17pm UTC](https://discourse.cmake.org/t/infinite-re-run-loop-with-cmake-3-5-1-and-ninja-1-10-0/1435 "2020-06-23T13:17:40Z")
**Posts on this page:** 17
**Page:** 1

<div class="post-metadata">

### Author: ![Holger](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/h/ed8c4c/32.png) [@Holger](https://discourse.cmake.org/u/Holger)
#### Post date: [June 23, 2020, 1:17pm UTC](https://discourse.cmake.org/t/infinite-re-run-loop-with-cmake-3-5-1-and-ninja-1-10-0/1435/1 "2020-06-23T13:17:40Z")

</div>

I encounter strange behavior when running CMake (3.5.1) in tandem with  
Ninja (1.10.0): CMake is constantly re-run until Ninja finally gives up with  
the following message:

```auto
    ninja: error: manifest 'build.ninja' still dirty after 100 tries

```

Here is the minimal CMakeLists.txt file to reproduce this behavior:

```auto
    add_library(mylib main.cpp)

    # Variable containing a generator expression.
    set(mylib_LIBRARY $<TARGET_FILE_NAME:mylib>)

    # Substitue expression @VAR@ by contents of variables.
    configure_file(mylib-config.cmake.in mylib-config.cmake.tmp)

    # Create final output file, evaluating generator expression(s).
    file(GENERATE OUTPUT mylib-config.cmake INPUT mylib-config.cmake.tmp)

```

The file `mylib-config.cmake.in` is just a one-liner:

```auto
    set(mylib_LIBRARY "@mylib_LIBRARY@")

```

The reason seems to be that the temporary intermediate file  
`mylib-config.cmake.tmp` appears in the implicit dependencies controlling  
whether to re-run CMake. Ninja complains about that and re-runs CMake:

```auto
    ninja explain: output mylib-config.cmake.tmp of phony edge with no inputs doesn't exist

```

This behavior also happens with newer versions of CMake (e.g. 3.15.3).

Is this a bug in Ninja? It does not appear in earlier versions (e.g. 1.5.3).  
However the logic of Ninja seems to be right (i.e. the file does in fact not  
exists yet).

Is there a more elegant solution for the original problem (i.e. configuring a  
file containing generator expressions)?

---

<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: [June 23, 2020, 1:40pm UTC](https://discourse.cmake.org/t/infinite-re-run-loop-with-cmake-3-5-1-and-ninja-1-10-0/1435/2 "2020-06-23T13:40:40Z")

</div>

Hmm. I’ve done things like this before and hadn’t seen this behavior. What filesystem/OS are you on? I wonder if you’re only getting second-level timestamp resolution and it cycles at at least 100 Hz?

Thoughts @brad.king?

---

<div class="post-metadata">

### Author: ![Holger](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/h/ed8c4c/32.png) [@Holger](https://discourse.cmake.org/u/Holger)
#### Post date: [June 23, 2020, 1:44pm UTC](https://discourse.cmake.org/t/infinite-re-run-loop-with-cmake-3-5-1-and-ninja-1-10-0/1435/3 "2020-06-23T13:44:09Z")

</div>

I am running Ubuntu 16.04.6 on kernel 4.15.0-106.

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [June 23, 2020, 1:51pm UTC](https://discourse.cmake.org/t/infinite-re-run-loop-with-cmake-3-5-1-and-ninja-1-10-0/1435/4 "2020-06-23T13:51:00Z")

</div>

@Holger please try ninja 1.8 and 1.9 to compare the behavior. Starting in Ninja 1.9, file modification times are tracked with nanosecond resolution. That may be what exposed this problem.

---

<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: [June 23, 2020, 2:15pm UTC](https://discourse.cmake.org/t/infinite-re-run-loop-with-cmake-3-5-1-and-ninja-1-10-0/1435/5 "2020-06-23T14:15:21Z")

</div>

What filesystem is your build tree using? Any stock filesystem in Linux is going to support nanosecond timestamps. If you’re building on vfat, nfs, or cifs, timestamps may be less accurate (ntfs is probably fine these days, but unknown for sure).

---

<div class="post-metadata">

### Author: ![Holger](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/h/ed8c4c/32.png) [@Holger](https://discourse.cmake.org/u/Holger)
#### Post date: [June 23, 2020, 2:17pm UTC](https://discourse.cmake.org/t/infinite-re-run-loop-with-cmake-3-5-1-and-ninja-1-10-0/1435/6 "2020-06-23T14:17:09Z")

</div>

@brad.king The ninja versions you mention (1.8 and 1.9) exhibit the same behavior. I went backwards with the versions and found out that the problem was introduced in version 1.6.0 (version 1.5.3 is last working one).

---

<div class="post-metadata">

### Author: ![Holger](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/h/ed8c4c/32.png) [@Holger](https://discourse.cmake.org/u/Holger)
#### Post date: [June 23, 2020, 2:18pm UTC](https://discourse.cmake.org/t/infinite-re-run-loop-with-cmake-3-5-1-and-ninja-1-10-0/1435/7 "2020-06-23T14:18:33Z")

</div>

@ben.boeckel Running plain old ext4 here.

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [June 23, 2020, 2:30pm UTC](https://discourse.cmake.org/t/infinite-re-run-loop-with-cmake-3-5-1-and-ninja-1-10-0/1435/8 "2020-06-23T14:30:54Z")

</div>

> [@Holger](#):
>
> the problem was introduced in version 1.6.0

Thanks. Might you be able to build Ninja from source and `git bisect` to find the exact commit?

---

<div class="post-metadata">

### Author: ![Holger](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/h/ed8c4c/32.png) [@Holger](https://discourse.cmake.org/u/Holger)
#### Post date: [June 23, 2020, 2:47pm UTC](https://discourse.cmake.org/t/infinite-re-run-loop-with-cmake-3-5-1-and-ninja-1-10-0/1435/9 "2020-06-23T14:47:23Z")

</div>

Here is the result of git bisect:

```auto
636034b288777c9f0b7aca1072e0496de94db27c is the first bad commit
commit 636034b288777c9f0b7aca1072e0496de94db27c
Merge: 62458b6 5fbfa4b
Author: Nico Weber <nicolasweber@gmx.de>
Date: Tue Feb 3 13:01:28 2015 -0800

    Merge pull request #908 from colincross/multipass
    
    Allow manifest rebuild to loop up to 100 times

 src/ninja.cc | 27 +++++++++++++--------------
 1 file changed, 13 insertions(+), 14 deletions(-)

```

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [June 23, 2020, 2:50pm UTC](https://discourse.cmake.org/t/infinite-re-run-loop-with-cmake-3-5-1-and-ninja-1-10-0/1435/10 "2020-06-23T14:50:54Z")

</div>

Thanks. That change to Ninja both raised the number of tries from `2` to `100` and also _added the error message_. I think this was never fully working but Ninja didn’t diagnose it before.

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [June 23, 2020, 3:07pm UTC](https://discourse.cmake.org/t/infinite-re-run-loop-with-cmake-3-5-1-and-ninja-1-10-0/1435/11 "2020-06-23T15:07:49Z")

</div>

The logic in `cmGlobalNinjaGenerator::WriteTargetRebuildManifest` needs to be updated to avoid adding to `reBuild.ImplicitDeps` entries from any local generator’s `localGen->GetMakefile()->GetListFiles()` that also appear in any local generator’s `localGen->GetMakefile()->GetOutputFiles()`.

---

<div class="post-metadata">

### Author: ![Holger](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/h/ed8c4c/32.png) [@Holger](https://discourse.cmake.org/u/Holger)
#### Post date: [June 24, 2020, 11:03am UTC](https://discourse.cmake.org/t/infinite-re-run-loop-with-cmake-3-5-1-and-ninja-1-10-0/1435/12 "2020-06-24T11:03:08Z")

</div>

@brad.king Your suggested fix works! Thank you 🙂

Could you please review the patch?

```auto
Index: 3.15.3/src/Source/cmGlobalNinjaGenerator.cxx
===================================================================
--- 3.15.3.orig/src/Source/cmGlobalNinjaGenerator.cxx
+++ 3.15.3/src/Source/cmGlobalNinjaGenerator.cxx
@@ -1341,8 +1341,11 @@ void cmGlobalNinjaGenerator::WriteTarget
   reBuild.Outputs.push_back(this->NinjaOutputPath(NINJA_BUILD_FILE));
 
   for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ const auto& outputFiles = localGen->GetMakefile()->GetOutputFiles();
     for (std::string const& fi : localGen->GetMakefile()->GetListFiles()) {
- reBuild.ImplicitDeps.push_back(this->ConvertToNinjaPath(fi));
+ if (std::find(outputFiles.begin(), outputFiles.end(), fi) == outputFiles.end()) {
+ reBuild.ImplicitDeps.push_back(this->ConvertToNinjaPath(fi));
+ }
     }
   }
   reBuild.ImplicitDeps.push_back(this->CMakeCacheFile);

```

---

<div class="post-metadata">

### Author: ![Holger](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/h/ed8c4c/32.png) [@Holger](https://discourse.cmake.org/u/Holger)
#### Post date: [June 24, 2020, 11:06am UTC](https://discourse.cmake.org/t/infinite-re-run-loop-with-cmake-3-5-1-and-ninja-1-10-0/1435/13 "2020-06-24T11:06:46Z")

</div>

@brad.king Just re-read your post and found out that the above patch does not take into account multiple local generators. Will rework the patch …

---

<div class="post-metadata">

### Author: ![Holger](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/h/ed8c4c/32.png) [@Holger](https://discourse.cmake.org/u/Holger)
#### Post date: [June 24, 2020, 11:28am UTC](https://discourse.cmake.org/t/infinite-re-run-loop-with-cmake-3-5-1-and-ninja-1-10-0/1435/14 "2020-06-24T11:28:30Z")

</div>

@brad.king Next try. Is this what you have in mind?

```auto
Index: 3.15.3/src/Source/cmGlobalNinjaGenerator.cxx
===================================================================
--- 3.15.3.orig/src/Source/cmGlobalNinjaGenerator.cxx
+++ 3.15.3/src/Source/cmGlobalNinjaGenerator.cxx
@@ -1342,7 +1342,9 @@ void cmGlobalNinjaGenerator::WriteTarget
 
   for (cmLocalGenerator* localGen : this->LocalGenerators) {
     for (std::string const& fi : localGen->GetMakefile()->GetListFiles()) {
- reBuild.ImplicitDeps.push_back(this->ConvertToNinjaPath(fi));
+ if (!this->IsContainedInLocalOutput(fi)) {
+ reBuild.ImplicitDeps.push_back(this->ConvertToNinjaPath(fi));
+ }
     }
   }
   reBuild.ImplicitDeps.push_back(this->CMakeCacheFile);
@@ -1564,6 +1566,17 @@ void cmGlobalNinjaGenerator::WriteTarget
   }
 }
 
+bool cmGlobalNinjaGenerator::IsContainedInLocalOutput(const std::string& fn) const
+{
+ for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ const auto& outputFiles = localGen->GetMakefile()->GetOutputFiles();
+ if (std::find(outputFiles.begin(), outputFiles.end(), fn) != outputFiles.end()) {
+ return true;
+ }
+ }
+ return false;
+}
+
 void cmGlobalNinjaGenerator::InitOutputPathPrefix()
 {
   this->OutputPathPrefix =
Index: 3.15.3/src/Source/cmGlobalNinjaGenerator.h
===================================================================
--- 3.15.3.orig/src/Source/cmGlobalNinjaGenerator.h
+++ 3.15.3/src/Source/cmGlobalNinjaGenerator.h
@@ -382,6 +382,9 @@ private:
     cmGeneratorTarget const* target,
     std::set<cmGeneratorTarget const*>& depends);
 
+ /// Check if fn is contained in any LocalGenerator's OutputFiles.
+ bool IsContainedInLocalOutput(const std::string& fn) const;
+
   std::string CMakeCmd() const;
   std::string NinjaCmd() const;
 

```

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [June 24, 2020, 12:27pm UTC](https://discourse.cmake.org/t/infinite-re-run-loop-with-cmake-3-5-1-and-ninja-1-10-0/1435/15 "2020-06-24T12:27:59Z")

</div>

@Holger good start, thanks. Please see [CONTRIBUTING.rst](https://gitlab.kitware.com/cmake/cmake/-/blob/master/CONTRIBUTING.rst) and open a merge request for that. We can polish the details during review.

---

<div class="post-metadata">

### Author: ![Holger](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/h/ed8c4c/32.png) [@Holger](https://discourse.cmake.org/u/Holger)
#### Post date: [June 24, 2020, 3:57pm UTC](https://discourse.cmake.org/t/infinite-re-run-loop-with-cmake-3-5-1-and-ninja-1-10-0/1435/16 "2020-06-24T15:57:05Z")

</div>

@brad.king Filed a merge request ([https://gitlab.kitware.com/cmake/cmake/-/merge\_requests/4939](https://gitlab.kitware.com/cmake/cmake/-/merge_requests/4939)). Looking forward to your input!

---

<div class="post-metadata">

### Author: ![mohammad\_b\_nazari](https://discourse.cmake.org/user_avatar/discourse.cmake.org/mohammad_b_nazari/32/2460_2.png) [@mohammad\_b\_nazari](https://discourse.cmake.org/u/mohammad_b_nazari)
#### Post date: [May 27, 2022, 4:24pm UTC](https://discourse.cmake.org/t/infinite-re-run-loop-with-cmake-3-5-1-and-ninja-1-10-0/1435/17 "2022-05-27T16:24:08Z")

</div>

CMake is re-running because generate.stamp is out-of-date.  
Check the system time…
