enable incremental compilation and compile your project
recompile it; notice that nothing is compiled at all, since it is incremental
execute “echo ’ ’ >> build/classes/main/some/of/your/Classes.class” to simulate instrumentation
recompile project; notice that everything gets recompiled now.
In other words, if you instrument at least one class after compilation, setting incremental is useless, because either way everything will get recompiled.
If you do instrumentation in a different task (or completely outside Gradle as in your example), then you already run into up-to-date check problems, even without incremental compilation.
Can you try doing instrumentation in a doLast {} - block added to the compileJava task? Does that break incremental compilation too?
You are modifying a tasks output which means it is no longer UP-TO-DATE. This is why it is recommended never to alter the outputs of a task. Like Stefan recommended, your instrumentation should be done by a separate task, which puts the instrumented classes in a separate output directory.
If you do instrumentation in a different task (or completely outside
Gradle as in your example), then you already run into up-to-date check
problems, even without incremental compilation.
I know, but speed of compilation is much more important for me than correctness — I know when it might produce incorrect result and in those specific cases I would do clean + build. This is what I did with Ant. It is annoying when you work on one class internals, but Gradle insists on recompiling everything anyway.
Like Stefan recommended, your instrumentation should be done by a
separate task, which puts the instrumented classes in a separate output
directory.
But then I would get two copies of the same class, as instrumentation is modification of existing, not generation of new classes. How would I then combine them when packaging and ensure that classpaths are right (I also run some code from built, but not package state)?
My suggestion would be to copy the classes to another directory and run the instrumentation on those files. You’ll then need to update the Jar task (and possibly others) to package the new output.
The other option might be to do the instrumentation from a doLast() on the compileJava task. In this case Gradle would snapshot the outputs after instrumentation was done which wouldn’t cause the outputs to be continually out of date.
Oh, that other option sounds interesting. Currently instrumentation is done in a separate task, not like you suggested. I’ll look into it in the next days, thanks.
Instrumenting in doLast rather than a separate task seems to work fine. Sometimes it deems that full recompilation is necessary, but only if I modify really widely used interfaces. Probably could do without a full recompilation, but they do influent like 50% of the code.