I have project which builds a compiler plugin (target plugin) and in another directory try to use the plugin (target simple).
Therefore I need the plugin (which is basically just a shared object) to be compiled and linked before the object files of simple are compiled.
Now I’mhaving some trouble communicating this to CMake:
My first attempt was to add add_dependencies(simple plugin). This doesn’t help at all with Ninja, but does build correctly with UNIX Makefiles.
Then I tried to set the OBJECT_DEPENDS source file property for all source files to plugin. This worked great in Ninja, but failed with “No rule to make target ‘plugin’” with Makefiles. This seems fair since “OBJECT_DEPENDS” is documented to contain full-paths. But I couldn’t figure out how to specify the path to the shared object (since generator expressions don’t work here)
I don’t think so; CMake generally assumes that the compiler is complete and ready-to-use before the build starts. You might be able to leverage FetchContent to ensure the plugin is built at the right time though. @craig.scott Thoughts?
I don’t think FetchContent will help here. It would still add content to the main build and there’s no need to fetch anything in this scenario, so it wouldn’t be giving you anything different to the regular build situation.
Since CMake 3.9.0, there is an optimisation specific to the Ninja generator where even though simple has plugin as a dependency, sources for simple are allowed to be compiled as long as CMake thinks nothing about the compilation of those sources could depend on plugin. Only linking requires plugin to be fully built. See issue 15555 for more details on the reasoning behind the optimisation.
My recollection is that if there is a custom command on one of the two targets (I don’t recall which one), CMake can’t assume that compilation isn’t dependent on plugin and won’t apply that optimisation.
As a potential workaround for Ninja, in addition to using add_dependencies(), do you get the behavior you want if you add a custom command to one of the two targets? I don’t think it actually matters what that custom command does, so you can potentially test this with something like the following:
I’m not sure which target it needs to be added to, so you will need to try out both and see which one (if either) works. @ben.boeckel it looks like you wrote that optimisation, perhaps you can clarify the above?
Thanks for looking into this. Sadly adding the add_custom_command(TARGET command didn’t seem to have any effect (beside printing the message of course), no matter if it’s added to simple, plugin or both.
I left out POST_BUILD, not sure if that matters. I think it should be on the plugin target too, not the simple target. I updated my example accordingly.
Another thing to try is to make that custom command produce an output that the simple target depends on. That would be the add_custom_command(OUTPUT somefile ...) form. Or maybe try BYPRODUCTS with my earlier example. I’m shooting in the dark a bit here, I don’t recall the exact condition that blocks the optimisation, but I’m pretty sure it relates to custom commands somehow. I wasn’t able to find the posts about it when I went looking before, sorry.
I tested both versions and couldn’t see any difference.
I tried that but it only executed the custom command early, but it still didn’t link the plugin early enough. But I found a variant of your suggestion which did work:
I used add_custom_target(plugin_dummy) and then used add_dependencies to make simple depend on plugin_dummy and plugin_dummy depend on plugin. Now the objects from simpleare compiled after plugin is fully build