-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ninja scans dependencies before order-only dependencies are run #760
Comments
It seems given example is kind of invalid, why are you setting out as phony if it is not. Why are you expecting Ninja to restat Putting |
I agree that adding I am wondering whether this is intended behavior or something that needed changing (hence the question at the end of the initial report). If it is working as intended, then there needs to be some update on CMake's docs about how to do |
Ninja in fact documentaries this clearly in manual (hence
If you want
|
I think the case where the docs are unclear is that it states "the output is not rebuilt until they are built" does not convey that Ninja may have already decided that the output does not need to be rerun before the order-only dependency has been run and it never looks twice. This is in contrast with make which doesn't consider a recipe's state before all of its dependencies are complete (including order-only). How is this:
for a clarification in the docs? I know that there are solutions to this, but unfortunately the information is not always known. In this case, the tool writing the ninja file does not (and, in general, cannot) know that |
For reference, there is also discussion on the CMake side of this issue here: http://www.cmake.org/Bug/view.php?id=14963 It suggests a way CMake could be given more information to enable it to generate valid Ninja files for such cases. However, if Ninja were to have a way to request this behavior (e.g. "restat-dependencies-after-order-only = 1") then the problem would be solved for all existing CMake projects with no changes. |
Actually Ninja re-stats all outputs of rules being executed. Problem here it that you expect Ninja to re-stat some file after executing a rule that has NOT specified that file as its output. It is pure coincidence it works in Therefore IMHO it is not Ninja bug or flaw and it has to be either fixed in CMake (if it is a fault of generator) by defining properly output of some rule (if it isn't already there) or fixed by developer in |
What I explain in this CMake issue: http://www.cmake.org/Bug/view.php?id=14963 is exactly what you state. Ninja does not need to be changed for this to be made to work. Consider this Ninja issue as a feature request. If Ninja were to offer a way to ask that dependencies of a rule be stat-ed after the order-only dependencies are satisfied then CMake could be taught to use this feature and all existing projects using CMake will work unmodified. |
@bradking Now I understand, you want somehow make Ninja behave as The question to you is this feature needed to make some of So if I understand correctly the reason of Kitware/CMake@539356f12 is the same as above, compatibility with If it is so then I am eager to support this, unless if isn't enforced by default, but triggered either by some As I complained in http://www.cmake.org/Bug/view.php?id=14972 forcing this by default leads to some other harmful side effects (phony rules for all source files for in-source build). Also note that putting |
@nanoant Okay. Let me explain the history of why CMake works this way. Build systems prior to ninja do not have a feature like "restat = 1". CMake needs to support side-effect outputs that are not always updated. Consider this example:
The idea is that
So far so good. Now let's update the timestamp of
Now ninja needs to run the output rule every time because A common convention in the CMake world that works with all other supported build systems is to leave off the explicit specification of Since CMake evolved when no build tools supported restat, it never considered needing enough information to produce the above example with the explicitly listed output. Therefore the |
After thinking about this further, we do not actually need a re-stat after order-only dependencies. We just need Ninja to delay its initial stat until after order-only dependencies. I think this should just be the way Ninja works and should not need any option. IIUC, Ninja stats everything up front so it can start as many initial tasks as possible. Furthermore, one of Ninja's design goals is to do as little work as possible prior to starting the first task evaluation. Since rules with an order-only dependency cannot possibly be the first to be evaluated, why do their dependencies need to be stat-ed up front? Just consider each rule for evaluation after its order-only dependencies are satisfied and at that time stat any dependencies that have not yet been stat-ed or known to have been updated as the output of an already-evaluated rule. For rules without order-only dependencies this approach is equivalent to the current approach. For rules with order-only dependencies this is a sensible behavior. It reduces the amount of disk access that ninja has to do before starting task evaluations. If a rule fails prior to an order-only dependency being satisfied, ninja will have done less total work and failure will be known sooner. |
@bradking Wow, these are amazing insights. Indeed such behavior would fix all the issues w/o any need to do some extra work on CMake side. Looking at Ninja code however I can see this would require massive changes as nodes are stated fist time they appear in build graph and this is done top (target) to bottom (source files) in This looks like smaller change. Would be great to get some opinion on this subject from @martine |
I'm not too familiar with ninja's internals, but when building the graph of things to do, would it be possible to have a |
scan_sources.py should always emit the original source files passed as input, even if it cannot find them. This is necessary to create a proper dependency arc from the build rule "mojo_nacl" to the generated source "libmojo.cc" from the "monacl_codegen" build rule.. It's not sufficient to convey this source dependency through ninja depfiles. This is because the emitted dependency in the mojo_nacl.ninja from "mojo_nacl" to "monacl_codegen" is order-only and depenencies are scanned before order-only dependencies are run (ninja-build/ninja#760). BUG=https://code.google.com/p/chromium/issues/detail?id=440451 TEST=manually modified libmojo.cc.tmpl and rebuilt mojo_nacl. R=bradnelson@google.com, ncbray@chromium.org Review URL: https://codereview.chromium.org/798733002 git-svn-id: svn://svn.chromium.org/native_client/trunk/src/native_client@14212 fcba33aa-ac0c-11dd-b9e7-8d5594d729c2
Is anybody still interested in implementing Brad's suggestion? |
I think this bug should be given more attention, as builds can very easily be incorrect without the user knowing it.
This is an oversimplified example, leaving out the GENERATED property for the version.h file for example. |
FYI, the better way to do that is |
That would not have the same effect, as version.h is not generated if it already exists. The point of the generate_version command is to run always and check for reasons to bump the version, but only trigger a new build if something actually did change. |
Oh, right. Add |
In the time since this issue was reported I've become very familiar with Ninja internals while implementing features needed for Fortran support. It is pretty clear that what is requested in this issue cannot be implemented without a major re-implementation of Ninja internals. It just does not fit in Ninja's model. Furthermore, deferred stat prevents a monolithic build plan from being computed ahead of time, so progress information cannot be generated reliably. The feature's I've implemented to support Fortran (not yet integrated upstream) do allow build-time dependency discovery in the rare cases that really need it. Since CMake 3.2 both the add_custom_command and add_custom_target commands support a |
I have been able to create a sample which shows how this solution does not work for RC files. If you run if you do the same with NMake removing the byproducts and instead adding them as outputs for a custom target make the sample work as expected on NMake. Not that you can check the validity of the build by comparing the contents of version.cpp, the output of the generate_test executable and the version info ( on windows ) of the executable, for example through sigcheck.exe |
@arjanhouben you're missing a dependency: add_dependencies(generate_test generate_version_files) |
@bradking you are right, that will fix the first time missing file dependency.
so far so good, now I run (only) Ninja again
Now it is clear that the RC file was NOT used in the binary ( same string as before ) while the version.cpp WAS updated ( new string in executable ) |
@arjanhouben I can't reproduce that. It works for me. Either way, this discussion is outside the scope of this issue so if you still have trouble please ask over in CMake land. |
Oh sorry, looks like the earlier parts of the issue are still valid. |
@nico technically yes, but as I noted here solving this will require a fundamental shift in Ninja's model. Unless that is ever a realistic option I don't think there is a reason to keep this open. We now have a mature solution on the CMake side for the original problem that motivated this issue. |
I've created a CMake issue for the out of date RC file here: https://gitlab.kitware.com/cmake/cmake/issues/16417 |
Using the BUILD_BYPRODUCTS directive we tell ninja that those libs will be created and it is ok to use them as dependencies. Further info: * ninja-build/ninja#760 * https://cmake.org/Bug/view.php?id=14963 * https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=557aef0b
Using the BUILD_BYPRODUCTS directive we tell ninja that those libs will be created and it is ok to use them as dependencies. Further info: * ninja-build/ninja#760 * https://cmake.org/Bug/view.php?id=14963 * https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=557aef0b
Using the BUILD_BYPRODUCTS directive we tell ninja that those libs will be created and it is ok to use them as dependencies. Further info: * ninja-build/ninja#760 * https://cmake.org/Bug/view.php?id=14963 * https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=557aef0b
Using the BUILD_BYPRODUCTS directive we tell ninja that those libs will be created and it is ok to use them as dependencies. Further info: * ninja-build/ninja#760 * https://cmake.org/Bug/view.php?id=14963 * https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=557aef0b
Using the BUILD_BYPRODUCTS directive we tell ninja that those libs will be created and it is ok to use them as dependencies. Further info: * ninja-build/ninja#760 * https://cmake.org/Bug/view.php?id=14963 * https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=557aef0b
Simply saying "every .pcm.o depends on the .pcm" in an -fmodules-codegen build doesn't suffice. Ninja would need to check .pcm timestamps just before it starts working on libAllModules, since clang rewrites them as a side effect of compiling order-only dependencies of libAllModules. But in fact Ninja is designed to only check timestamps at the very start of the build (ninja-build/ninja#760). So instead pipe proper -MD -MT etc. depfile generation support through the pcm -> .o compilation path, so that Ninja can learn exactly which headers foo.pcm.o depends on, the same way it learns it for foo.cpp.o. LLVM already has convenient infra for this, since it needs to be able to produce depfiles when loading modules for .cpp -> .o compilation too. We just do the same steps in the .pcm -> .o path now. In particular: DependencyFileGenerator is the normal depfile code, and the ASTReader that both paths use to load modules from disk has a ASTReaderListener::visitInputFile into which it hooks. Each module file stores refs to its constituent headers, textual includes, and imported modules in a header, and ASTReader recurses into imported modules. So visitInputFile gets the full set of transitive includes. Also, clang wasn't actually forwarding -MMD etc to the -cc1 invocation when doing .pcm -> .o compilation (the design is: `clang` rephrases your gcc-compatible invocation into an internal `clang -cc1` invocation), since those are considered "preprocessor options" but there's no preprocessing happening. The design bug is that these aren't really preprocessor options now, but I just chase fix it in Clang.cpp and pass down all preprocessor options.
There is a CMake bug about ninja not running this properly:
Basically, ninja is scanning the dependencies of
out-copy
beforealways
is run and therefore skips the fact thatout
has changed. Is it intended that dependency scanning is only guaranteed to be done after direct dependencies, not order-only dependencies or a bug? If the former, documentation that this is the case would be nice.The text was updated successfully, but these errors were encountered: