title: Access classpath dependencies defined in buildscript block in applied external-script
body: <p>My original goal was to be able to use classpath dependencies defined in <code>buildscript</code> in <code>build.gradle</code>, inside a script that was imported into <code>build.gradle</code> using <code>apply from:</code>. However, the external script didn't compile since the classes could not be resolved. After researching the issue, I found out that the logic needs to be duplicated and so I thought I would extract <code>buildscript</code> into a separate file. Then I would be able to apply that inside <code>build.gradle</code> and also inside the external script. </p>
  
  <p>I didn't even get past successfully applying the external buildscript file from <code>build.gradle</code>, let alone applying it from the external script. I've tried multiple things, but it seems like I always end up with one of two problems no matter what I try: either properties from <code>gradle.properties</code> cannot be used, or the plugin cannot be found (even though the classpath dependency has been defined).</p>
  
  <p>Currently my <code>gradle/buildscript.gradle</code> file looks like this:</p>
  
  <pre><code>buildscript {
      repositories {
          maven { url "http://some.url.com" }
      }
  
      dependencies {
          classpath "my.gradle.plugin:gradle-plugin:1.0.0"
          classpath "my.library:my-library:$libraryVersion"
      }
  }
  </code></pre>
  
  <p><code>libraryVersion</code> has been defined in <code>gradle.properties</code>. My <code>build.gradle</code> is as follows:</p>
  
  <pre><code>buildscript {
      apply from: "gradle/buildscript.gradle"
  }
  
  apply plugin: 'my.gradle.plugin.PluginClass'
  </code></pre>
  
  <p>When I do this, gradle complains that it cannot find a plugin with id <code>my.gradle.plugin.PluginClass</code>. I tried removing the quotes, and I also trying <code>project.plugin.apply(...)</code> using the plugin's FQN with and without quotes; both of these caused gradle to error out with a message saying that it could not find the property <code>my</code> on the root project. </p>
  
  <p>I also tried:</p>
  
  <pre><code>buildscript {
      apply from: "gradle/buildscript.gradle", to: buildscript
  }
  
  apply plugin: 'my.gradle.PluginClass'
  </code></pre>
  
  <p>But this causes another error where gradle complains that it cannot resolve <code>libraryVersion</code> in <code>gradle/buildscript.gradle</code>. So I then tried this:</p>
  
  <pre><code>buildscript {
      ext.libraryVersion = "1.0.1"
  
      repositories {
          maven { url "http://some.url.com" }
      }
  
      dependencies {
          classpath "my.gradle.plugin:gradle-plugin:1.0.0"
          classpath "my.library:my-library:$libraryVersion"
      }
  }
  </code></pre>
  
  <p>Which causes <em>another</em> error, where gradle says that there is no such property <code>ext</code> on <code>buildscript</code>. I understand that this is because there really is no "project" to speak of yet, since <code>buildscript</code> is compiled separately. Then I changed my <code>buildscript</code> block in <code>build.gradle</code> back to:</p>
  
  <pre><code>buildscript {
      apply from: "gradle/buildscript.gradle"
  }
  </code></pre>
  
  <p>Now I don't get the <code>ext</code> error, but I still get an error saying that it cannot find the plugin with the specified id. </p>
  
  <p>I cannot hardcode <code>libraryVersion</code> inside <code>buildscript</code>, because I need it as a compile-time dependency in <code>build.gradle</code> and I'd rather not have to maintain it in two places.</p>
  
  <p>This is extremely confusing and frustrating, because the following <code>buildscript</code> block works fine by itself in <code>build.gradle</code>:</p>
  
  <pre><code>buildscript {
      ext.libraryVersion = "1.0.1"
  
      repositories {
          maven { url "http://some.url.com" }
      }
  
      dependencies {
          classpath "my.gradle.plugin:gradle-plugin:1.0.0"
          classpath "my.library:my-library:$libraryVersion"
      }
  }
  
  apply plugin: 'my-plugin-id' //No need to use FQN
  
  dependencies {
      compile "my.library:library-version:$libraryVersion"
  }
  </code></pre>
  
  <p>The reason I tried to split out the <code>buildscript</code> block is because I have a file <code>other.gradle</code> that has some custom tasks that use classes from <code>my.library</code>:</p>
  
  <pre><code>import my.library.SomeThing
  
  task customTask(type: DefaultTask) {
      //does something with SomeThing
  }
  </code></pre>
  
  <p>But when I leave the <code>buildscript</code> block in <code>build.gradle</code> and apply the other file like so:</p>
  
  <pre><code>buildscript {
      ext.libraryVersion = "1.0.1"
  
      repositories {
          maven { url "http://some.url.com" }
      }
  
      dependencies {
          classpath "my.gradle.plugin:gradle-plugin:1.0.0"
          classpath "my.library:my-library:$libraryVersion"
      }
  }
  
  apply plugin: 'my-plugin-id' //No need to use FQN
  
  dependencies {
      compile "my.library:my-library:$libraryVersion"
  }
  
  apply from: 'gradle/other.gradle'
  </code></pre>
  
  <p>I get an error from gradle saying that it cannot resolve the class <code>my.library.SomeThing</code>. I figured I could solve this and avoid duplication by having a common <code>buildscript</code> file that I could then apply in both <code>build.gradle</code> and <code>other.gradle</code>.</p>
  
  <p>I created a custom plugin inside <code>buildSrc</code> to configure the project the way I wanted it, only to end up with a more complicated way to fail with the same result. The root cause was the same: there was no way to expose classpath dependencies to external scripts.</p>
  
  <p>Is there comprehensive documentation regarding this sorts of behavior? Everything about this violates the principle of least-surprise. I would expect a <code>buildscript</code> block that is being used in <code>build.gradle</code> to "just work" when I move it to another file. </p>
  
  <p>The semantics of <code>apply</code> with respect to <code>buildscript</code> blocks is not clear. In addition, the semantics of <code>buildscript</code> itself when it appears in an external file are not clear either - there is a marked variation in behavior, especially with respect to plugins and external properties. </p>
  
  <p>What is the best way to deal with this?</p>