This time /tmp/fred.out has been updated. That was not what I’d expect to happen.
At the very least this is inconsistent behaviour, but which is deemed correct?
This what I’m running on a Linux setup
$ ninja --version
1.10.2
$ make --version
GNU Make 3.82
Built for x86_64-redhat-linux-gnu
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ cmake --version
cmake version 3.22.1
CMake suite maintained and supported by Kitware (kitware.com/cmake).
I guess the problem is that you assume that timestamp is the only condition for an up-to-date check, e.g.:
“Outputs implicitly depend on the command line that was used to generate them, which means that changing e.g. compilation flags will cause the outputs to rebuild.”
On first run, there is a file and unknown how it was created. Make just decides on timestamp but I guess that for ninja the command changed. That kind of makes sense to get to a known state from whatever was there before.
Thanks for that. I can understand both points of view, but the position at the moment is there is inconsistent behaviour. That is never good.
Is this behaviour down to how make & ninja work, or is it ultimately controlled by CMake ?
I did the equivalent experiment with add_executable to see if the dependency between the executable and its source file are handled in the same way. They are – ninja will rebuild the executable, while make will not.
This is causing us some pain because we need to create a file at configure time, but also have a custom target & command in place to spot any changes to the dependency to allow the output file to be regenerated.
The problem with that is is the output file will get updated twice during a ninja build - first at configure time and then at some point during the build. The side effect of that means that if we immediately invoke ninja again it will find some targets out of date.
Using an add_dependency will probably make the problem go away, but the generation of the output file is buried in a cmake function that auto-generates the target name. Setting up the add_dependency will need to be abstracted into a wrapper function that knows how to map the output filename to its custom target. More complexity!
Ninja is no make. Please see the manual for some differences.
I would consider this command line check and the restat functionality superior over make.
Every build tool supported by CMake has its pros/cons. And not all features are supported in every build tool.
About your problem:
Having two different ways to create the same file is a bad design. It just worked somehow, because make does only a very simple time stamp check.
If you create that file at the configure/generate stage, you should add the dependent files to the directory property CMAKE_CONFIGURE_DEPENDS. So any build tool will call CMake configure automatically to re-generate that file first before building the rest. There’s no need for a custom command.
If the created file depends on some files modified by the build itself, then this disqualifies it to be created during configure/generate stage. Then it must always be created during build.