Very different behaviour after excising common code from build.gradle and re-including it via apply from:


I have some common configuration which is called common-configuration.gradle. It contains things like apply plugin: ‘java’, etc. This works great.

I also have a second file called common-execution.gradle which contains a bunch of methods.
I “import” it in some build.gradle files in my multi-project build via apply from: ‘…/common-execution.gradle’ . However when I execute it tells me:
“Could not find method createExecutableTasks() for arguments [[project.ProjectName]] on project ‘:desktop’.”

The funny thing is if I copy and paste the contents of common-execution.gradle to the desktop projec’ts build.gradle it works perfectly.

The sane approach for Gradle would be to just naively inline all files refereced by “apply from” and then interpret the build.gradle. But no. Gradle seems to do some super-helpful (irony) black box magic that royally srews up everything. As a bonus you have no clue what is going on or how to figure out how to fix it.

I am wasting my time with stupid problems like these. Why does Gradle remind me more and more of Maven :frowning:

apply from: 'file' doesn’t inline the files because it’s not a preprocessing trick. It compiles the file separately and executes it. It’s similar behavior to apply plugin: 'pluginId'.

That means variables and methods put in the separate file will only be visible in that file. If you want to add ad-hoc methods/properties, you have to use the ExtraPropertiesExtension.

My general rule of thumb is…

  1. Just hacking/experimenting on something – keep it in build.gradle
  2. Configuring existing plugins – separate it into different .gradle files when it’s get long
  3. Adding a big “block of configuration” – put it in a separate file using ext.
  4. Adding “helper” methods – start looking at buildSrc/separate plugins if you have a lot or multi-projects. use ext until it’s too painful.

The advantage of buildSrc is that you can also write tests for your new methods.

Since Gradle is still relatively slow (even with 2.4 rc) compared to Ant or Maven, I have a high priority for independent projects. So no allprojects/subprojects or similar magic.

I know the ext-mechanism but I was always reluctant to use it. Does it sacrifice project independence? Is there a switch that shows me which projects in my multiproject build are independent and which are not - and the reason why?

Can you post a minimal example with ext in a separate file that defines some method and task and how to access it in build.gradle?


On a side note: any idea why they allow something like “apply from” with all its wacky side effects and not a simple “verbatim include”?

Maybe I don’t see the big picture and there is always a good reason…but sometimes I really doubt the design decisions of the Gradle team.

When I started with Gradle almost a year ago the first thing that completely confused me for days was the wacky task-keyword. It’s not really Groovy. It’s some wacky hybrid keyword/method that uses some compiler magic to make it possible. And to what end? Why? Show the clever tricks developers can do? Confuse users?