Native incremental build lacks -MMD support or some analogue

Hey guys!

I’m trying to make my c++ files to get incrementally recompiled on header files changes. I’ve got a plenty of those - headers from 3rd-party libs, headers from autogeneration tools (like javah) and so on.

First, I tried to avoid to manually add them to source sets by **/ *.h mask, and was wondering if gradle could use some .d files generated by gcc-like compilers if run with -MMD flag (like all build systems do - make, cmake, ninja, etc…). But it seems like it can not. Found an old topic,
[cpp-plugin] Header file change didn't cause recompile
people said there that gradle will have a better incremental compilation support implemented later, and that was 2 years ago, but it seems it still relies on manual header including to source sets.

Adding them manually has a number of problems:

  1. It’s not scalable for big projects, you should add dozens of possible headers locations to source sets, it’s easy to miss something.
  2. According to build logs, gradle makes a compiler call to every header that is explicitly added to source set. I.e. with config like this,
main(NativeExecutableSpec) {
  sources.cpp {
    source {
      srcDir "src"
    source {
      srcDir "build/generated/jni"
      include "*.h"

gradle calls

g++ @opts.txt header.h

for every header in there. Needless to say, this makes a huge build time overhead.
3. It actually… doesn’t recompile all the .cpp files that these headers are included to! :frowning:

Actually, I think I’m doing something wrong here. What is the best way to get my sources recompiled on auto-generated files change, without performing a clean task?

My environment: gradle 2.9, linux host. Main goal is really to get android-experimental ndk plugin make all this stuff, but since it’s based on cpp plugin, just decided to start over here.

Best regards,

Guys? If my question seems vague and unclear, please ask me questions so I can clarify things. I don’t think that javah code generation is something rare or uncommon among gradle projects, there must be a standard way to support incremental compilation on headers change?

Yes, incremental compilation is fully supported for changes to header files. There are a few ways that you can specify the header files for a set of C++ sources, but adding the headers as a “srcDir” is not one of them.

For headers that are specific to a set of sources, you should declare them as exportedHeaders in the source set. I’d suggest reading the user guide chapter to learn more.

For headers that are sourced from outside your project (like 3rd-party libs), I’d suggest declaring a prebuiltLibrary: see the ‘prebuilt’ sample in the gradle release.

For headers generated by Javah, I’d probably model them as a generated source set. See the ‘idl’ sample to get an idea of how this would work.

Gradle 2.10 (now in RC) has made some major improvements to header file processing, so that it’s now more performant for very large projects. See the release notes.

Thanks, Daz, that really helped!

However, I had a hard time trying to find an analogue of CSourceSet.generatedBy and linkage: ‘api’ with PrebuiltLibraries in android experimental plugin - seems like these things are not implemented out there.

ExportedHeaders work just fine, though.

Changes in 2.10 look very promising, I’d definitely try it out as soon as android plugins support it (right now it doesn’t compile)