If you are depending on a big project, let say Boost, you get a big
performance hit. Please correct me if I'm wrong.

Story: Better input selection for AbstractNativeCompileTask
The AbstractNativeCompileTask specified @InputFiles on FileCollection
includes. The up-to-date check would then hash every files in all include
path. In practice, this doesn't work. You may only be using a couple header
files directly and because of the header dependencies, this may only gets
to a handful of files. Boost has about 10k of header files which is the
perfect example for showing this problem.

Implementation
The proposed solution is to have a list of include directory as the Input
for this task. Probably a List<File> and annotate with @Input. We would
keep the power of having File object but remove the hashing of every single
files within the include directory.

Story: Improve incremental compilation
Since we will only rely on header parsing for header dependencies, it would
be a good idea to improve the current processing. I don't take credit this
next improvement. For the full explanation, see
http://martine.github.io/ninja/manual.html#ref_headers. Basically, instead
of parsing all files in order to find the #include which is the current
Gradle way, we can use the initial compiler run with specific compiler
option to output the dependency graph as the compiler sees it. In gcc and
clang it's the -MMD and -MF flags and msvc it's the /showIncludes flag.

Implementation:
For msvc, a new option is needed on the toolchain for telling Gradle what
is the prefix String for each header dependency output line from cl.exe.
This option is needed for non-english Visual Studio installation. This can
be auto-detected by Gradle but just in case Microsoft decide to port Visual
Studio in English pirate. For gcc and clang, -MF would point to a file in
the build/tmp/<taskName> directory.

For improved speed - and I assume that Gradle cache is extremely fast and
efficient - Gradle would save the header dependency information in it's
cache. This means Gradle would parse the gcc and clang dependency file as
soon as it's generated.

The rest of the incremental compile stays the same.

Story: Even better incremental compilation
I don't think Gradle does any distinction between prebuilt libraries and
project libraries. A really good optimisation is to automatically mark
prebuilt libraries includes as up-to-date.

Implementation:
This can be quickly win by removing the header dependencies of prebuilt
library directly when the cache is generated. This way Gradle has no
knowledge of the prebuilt library which prevent unnecessary parsing.

Open Issues:
If a project is up-to-date and you decide to upgrade only the prebuilt
libraries to a newer version, the compile task will stay up-to-date. This
may not be the expected behaviour.

-- 
Daniel

Reply via email to