10 x apply plugin: $x works but list.each { apply plugin: it } doesn't ?!

Hey,

I just ran into a problem that I don’t really understand. We do have a multi project build (main project: oscs, subprojects: dwh, web) and the main build file is applying a bunch of different plugins with a lot of “apply plugin”-statements in the allprojects closure:

apply plugin: 'base'
    apply plugin: 'maven'
    apply plugin: 'java'
    apply plugin: 'war'
    apply plugin: 'tomcat'
    apply plugin: 'idea'
    apply plugin: 'eclipse'

As this looked a little messy to me, I changed it into

['base', 'maven', 'java', 'war', 'tomcat', 'idea', 'eclipse'].each {
        apply plugin: it
    }

From my point of view, both solutions should be equivalent but the latter produces an error:

FAILURE: Build failed with an exception.
  * Where:
Build file '/Users/moritzprinz/Documents/git/oscs/build.gradle' line: 40
  * What went wrong:
A problem occurred evaluating root project 'oscs'.
> Could not find property 'compile' on configuration container.
  * Try:
Run with --info or --debug option to get more log output.

The whole allprojects closure looks like this:

allprojects {
    group = projectGroup
    version = projectVersion
      sourceCompatibility = 1.6
    targetCompatibility = 1.6
      apply plugin: 'base'
    apply plugin: 'maven'
    apply plugin: 'java'
    apply plugin: 'war'
    apply plugin: 'tomcat'
    apply plugin: 'idea'
    apply plugin: 'eclipse'
          repositories {
        maven {
            name 'nexus'
            url "http://some/nexus"
        }
    }
      configurations.compile.transitive = true
      archivesBaseName = project.projectName
      [compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
      dependencies {
        tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}",
               "org.apache.tomcat.embed:tomcat-embed-logging-log4j:${tomcatVersion}"
        tomcat("org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}") {
            exclude group: 'org.eclipse.jdt.core.compiler', module: 'ecj'
        }
    }
      // some Java classes inside the project actually depend on the buildDir being 'target'. Watch out!
    buildDir = 'target'
      sourceSets {
        main.output.resourcesDir = sourceSets.main.output.classesDir
        test.output.resourcesDir = sourceSets.test.output.classesDir
    }
}

Why does this happen?

Cheers,

Moritz

Check that you aren’t introducing another change, as I can’t reproduce this. I took your code, made some adjustments for missing variables (e.g. 'projectVersion), ran it both ways and got the same result. I ran it with Gradle 1.0.

You’re right. If I’m not including the sub projects in the settings.gradle, it gives the same result. As soon as I include them it breaks. Looks like there’s something wrong with the subproject configuration.

Okay, looks like I finally found the problem. By using

['base', 'maven', 'java', 'war', 'tomcat', 'idea', 'eclipse'].each {
        apply plugin: plugin
    }

in the main build file, the settings are just applied on the main project (allprojects closure!) and not on the subprojects. Instead using

['base', 'maven', 'java', 'war', 'tomcat', 'idea', 'eclipse'].each { plugin ->
        it.apply plugin: plugin
    }

works for me.

Glad you got it working.

That actually makes sense if you understand how Groovy resolves symbols in closures. I’ll think on if we can ease this awkwardness for Gradle users.