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:
ninja: error: manifest 'build.ninja' still dirty after 100 tries
Here is the minimal CMakeLists.txt file to reproduce this behavior:
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:
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:
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)?
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?
@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.
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).
@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).
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(-)
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.
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().