Currently if you have AUTOMOC turned on for a target then it means that always the moc files are being rebuild. This is counter productive as you don't want to rebuild them if non of the sources gets modified.
AUTOMOC is supposed to always rebuild because it checks files that are not listed in the sources (like extra "_p.h" headers) and which may change outside the visibility of the generator. I'm not sure if the behavior can be changed for AUTOMOC without breaking existing projects.
There should be an escape hatch for people who are nicely declaring all relevant sources to the generator and are not relying on the glob-like way of obtaining all possible inputs.
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Child items ...
Show closed items
Linked items 0
Link issues together to show that they're related.
Learn more.
It checks timestamps and file contents. But it doesn't run moc unless necessary.
There should be an escape hatch for people who are nicely declaring all relevant sources to the generator and are not relying on the glob-like way of obtaining all possible inputs.
I like the idea but I'm too busy too work on this right now.
I looked into this and the rule is done because it is a utility command with a declared output of dir/CMakeFiles/tgt_autogen which never actually gets created. This essentially means that autogen rules are "always" run. Can we declare that it depends on the source files directly? This means making it an add_custom_command rather than a utility target. The issue stated in the description might be fixable with depfile support from the autogen tool so that there is no need for saying "all sources are explicit". I don't know if moc and related tools offer that functionality.
@cristianadam There's currently no way to not run AUTOMOC and AUTOUIC, even when the build succeeded. It doesn't build anything though, just checks timestamps of discovered files. This isn't ideal of course, it shouldn't run when nothing changed.
Can you provide more information?
CMake version
Used generator? "Unix Makefiles", "Ninja", Visual Studio?
I can confirm that the same happens for me. Latest CMake (master), Ninja, macOS.
When I say the same, I mean that "cmake -E cmake_autogen foo/bar/AutogenInfo.cmake" is executed always on null builds.
Can you clarify what you mean by it's not possible not to run it?
Is it not possible to encode the information about which files the generated moc file depends on at configure time, and create ninja rules that would run cmake -E cmake_autogen only when those files were touched?
Can you clarify what you mean by it's not possible not to run it?
That means in released CMake versions. The "cmake -E ..." call is called as the command of a custom target that is always considered out of date.
We could use a custom command instead (we do in AUTORCC). But that requires to have all dependency information at configure time. We don't have that in the general case. Some dependencies are discovered at build time (e.g. .json files from Q_PLUGIN_METADATA). Adding depfile generation to the _autogen target, as mentioned by @ben.boeckel, might be a solution.
Why is parsing and reading the json file from Q_PLUGIN_METADATA not possible at configure time? Is there some limitation to run the Q_PLUGIN_METADATA detection at configure time?
Ok, I see the issue. You could mark the json file with CMAKE_CONFIGURE_DEPENDS to force a reconfiguration, but if the macro is added after the first configuration, that would imply that you'd need to make the cpp file a configure time file dependency as well, and we don't want to reconfigure every time a cpp file is changed.
Would you be willing to describe how the mentioned depfile generation would help in this case?
I said might help because I'm not exactly sure how depfiles work.
AFAIK they are make scripts with additional dependencies that are imported by the main Makefile.
At configure time an empty/noop depfile is generated, which is what the first build sees.
At build time, a new valid depfile is generated by the _autogen target.
The new file is used to override the dummy depfile from configure time. So at the second build, a valid depfile is evaluated (and possibly re-generated again).
Right, but after reading about it a bit, it seems to only give additional information when to rerun some command. And if I'm not mistaken, for this issue, we are interested in cases when we should not rerun -E cmake_autogen.
Even if moc were to generate a depfile that contains all the files it uses as sources, that gives us zero information about adding a new Q_PLUGIN_METADATA into some source file that moc didn't process.
So from my perspective, we would always be stuck running cmake_autogen at build time to search for existing files that have a new Q_PLUGIN_METADATA.
If the source file is changed (by adding Q_PLUGIN_METADATA), AUTOMOC is triggered, because the source has changed. It parses the source, finds the Q_PLUGIN_METADATA and updates the depfile with the .json entry.
(The depfile contains additional dependencies for AUTOMOC, which already depends on all the target sources.)
We need to determine when to run AUTOMOC and when not. Right now we play it safe by always calling AUTOMOC, so that we don't miss a .json change. If we had full and updated dependency information (in the Makefile/depfile), we wouldn't have to call AUTOMOC everytime, but only when one of the dependencies changed.
Qt Creator has 64 plugins. The json files are modified at configure time. I don't think they are getting any modifications after configure time.
I am testing on Windows, with latest CMake, MinGW, and ninja. It takes like 4 seconds to automoc to handle all the targets. On other colleague's machines it takes like 1 second.
It would be great if we can have an option for not having to pay for something we don't really have to.
Let's say I create foo.h , it has no Q_PLUGIN_METADATA, and a foo.cpp. Both sources are added to a target, and AUTOMOC is enabled for the target.
I configure the first time. The generated ninja file would have a rule that says: if either foo.h or foo.cpp changes, run AUTOMOC.
I build once. I build another time without changing anything, AUTOMOC is not executed the second time because the sources haven't changed.
I modify foo.h and add Q_PLUGIN_METADATA. I run ninja. foo.h has changed, AUTOMOC is executed, it scans the header file, sees the macro, generates a new mocs_compilation.cpp file.
Doesn't seem that we need a depfile for this case. Am I missing something here?