306

I am new to Gradle and I am reading the documentation but I don't understand some parts of it. One of these parts is connected with buildscript block. What is its purpose?

If your build script needs to use external libraries, you can add them to the script's classpath in the build script itself. You do this using the buildscript() method, passing in a closure which declares the build script classpath.

buildscript {
  repositories {
    mavenCentral()
  }
  dependencies {
    classpath group: 'commons-codec', name: 'commons-codec', version: '1.2'
  }
}

Ok but what is the difference with:

repositories {
  mavenCentral()
}
dependencies {
  compile group: 'commons-codec', name: 'commons-codec', version: '1.2'
}

For example, why it is necessary to use buildscript?

mkobit
  • 43,979
  • 12
  • 156
  • 150
Xelian
  • 16,680
  • 25
  • 99
  • 152
  • 2
    possible duplicate of [Gradle buildscript dependencies](http://stackoverflow.com/questions/13923766/gradle-buildscript-dependencies) – fejese Aug 17 '15 at 11:40

9 Answers9

223

The buildScript block determines which plugins, task classes, and other classes are available for use in the rest of the build script. Without a buildScript block, you can use everything that ships with Gradle out-of-the-box. If you additionally want to use third-party plugins, task classes, or other classes (in the build script!), you have to specify the corresponding dependencies in the buildScript block.

Peter Niederwieser
  • 121,412
  • 21
  • 324
  • 259
  • 2
    I can't understand Em. I wrote a task class with _group: `sample.infotask', name: 'infotask', version: '1.0'` And use _uploadArchives_ task to upload it to local repo _../lib'_ In the another project if I use my task I must write: `buildscript { repositories { maven {url 'file:../lib' } } dependencies { classpath group: 'sample.infotask', name: 'infotask', version: '1.0' } } Am I right? Why we must use _buildScript_ block? When I upload artifact local I have the jar on my machine. And just have to tell Gradle from where and what to put in my classpath nothing else what is the special here? – Xelian Jul 21 '13 at 16:19
  • 50
    You must use a `buildScript` block because Gradle needs this information in order to *understand the rest of the build script*. That's why you have to provide this information in a separate channel (the `buildScript` block). Technically speaking, Gradle needs this information in order to *compile and evaluate* the rest of the build script. What happens under the hood is that Gradle separates the build script into two scripts (the `buildScript` block and everything else) so that it can process them separately. – Peter Niederwieser Jul 21 '13 at 19:04
  • 3
    If you read this ans after reading other answers, you can understand what Peter wants to say(and is pretty correct). But the second line -"Without a buildScript block, you can use everything that ships with Gradle out-of-the-box"- is what makes the ans ambiguous. – Dexter Apr 04 '19 at 09:45
  • just a quick note that made me understand the whole thing. when using "buildscript", you are saying that whatever dependencies within buildscript { ... } are used not by the Java/Kotlin code/program (or whatever you're using) . But instead, they are ONLY meant to be used by gradle scripts. So for instance you need to use some plugins that are not provided by default, then you add it in buildscript {...} and you'll be able to use it on gradle scripts only. hope it helps – cesarmax Jun 04 '20 at 17:42
192
  • The global level dependencies and repositories sections list dependencies that required for building your source and running your source etc.
  • The buildscript is for the build.gradle file itself. So, this would contain dependencies for say creating RPMs, Dockerfile, and any other dependencies for running the tasks in all the dependent build.gradle
Ashish
  • 2,041
  • 1
  • 12
  • 3
  • 7
    All extensions to gradle itself are found through buildscript-> dependencies, which in turn are downloaded from buildscript-> repositories section. buildscript block, is run first (build system preparation phase) before starting the execution of build task such as source compile etc. – Raja Nagendra Kumar Apr 05 '17 at 12:13
  • 7
    `buildscript` is simply dependency for your build script – slier May 19 '18 at 09:28
  • 5
    buildscript is devDependencies in node.js, top-level = dependencies. – sfy May 19 '18 at 10:12
83

I appreciate Peter's answer... but it was not immediately obvious to me what the rest of the build script meant as emphasized in the answer and in the documentation.

Usually bringing in dependent functionality is for use in the Java program or whatever other program you might be writing. Bringing in Spring say, is not to be used in the build script, but in the Java program. Putting it in the buildscript closure ensures that the dependencies are available for use within the gradle build itself. Not the output program.

Alex
  • 8,093
  • 6
  • 49
  • 79
Daniel Gerson
  • 2,159
  • 1
  • 19
  • 29
13

A bit more explanation by demonstrating Android top-level gradle file.

buildscript {
    // this is where we are going to find the libraries defined in "dependencies block" at below
    repositories {
        google()
        jcenter()
        maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
    }

    // everything listed in the dependencies is actually a plugin, which we'll do "apply plugin" in our module level gradle file.
    dependencies {
        classpath 'com.android.tools.build:gradle:3.4.2' // this is android gradle plugin
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // kotlin gradle plugin
    }
}

module level gradle file

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

What is "plugin"? They are just java classes, which implement Plugin interface. Under the interface, it has a method "apply" to add multiple task objects with different names. Task is a class where we can implement the workflow. For instance, the build task consists of the flow of building the app.

So, what does buildscript do? It defines where to find the plugins. What does plugin do? It encompasses multiple tasks. What does task do? It provides us with the build, install, lint, etc.

My understanding might be wrong. Please don't hesitate to correct me if you find anything is misleading.

KunYu Tsai
  • 632
  • 1
  • 10
  • 15
9

The "buildscript" configuration section is for gradle itself (i.e. changes to how gradle is able to perform the build). So this section will usually include the Android Gradle plugin.

Maulik Baraiya
  • 203
  • 3
  • 9
3

It's a bit high level but hope helps.

For me, clear distinction started to shape once I start to understand what is a building block, method, and task. How the syntax looks like, how you can configure them etc. So I suggest you go through all these. After that, you can begin to make sense out of this syntax.

Then it's very important to know what's the type of the object build.gradle (an instance of Project class) so to know what can you have inside a build.gradle file. That would answer where that 'buildScript' and others come from. And to extend your capabilities/features (let's say android), see how plugins can help.

Last but not least, there's a very good tutorial here that talks about closures, delegates which are the concepts essential to understand the script.

stdout
  • 2,471
  • 2
  • 31
  • 40
2

buildscript block is used for the build script, NOT for the gradle build output (for example, an Android app apk). In the following code example, the encoding code is used in build script, not in the gradle build output program; so the dependecies should be added to buildscript block.

https://docs.gradle.org/current/userguide/tutorial_using_tasks.html#sec:build_script_external_dependencies

External dependencies for the build script

Instead of manipulating the script classpath directly, it is recommended to apply plugins that come with their own classpath. For custom build logic, the recommendation is to use a custom plugin. If your build script needs to use external libraries, you can add them to the script’s classpath in the build script itself. You do this using the buildscript() method, passing in a block which declares the build script classpath.

The block passed to the buildscript() method configures a ScriptHandler instance. You declare the build script classpath by adding dependencies to the classpath configuration. This is the same way you declare, for example, the Java compilation classpath. You can use any of the dependency types except project dependencies.

Having declared the build script classpath, you can use the classes in your build script as you would any other classes on the classpath. The following example adds to the previous example, and uses classes from the build script classpath.

import org.apache.commons.codec.binary.Base64

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath group: 'commons-codec', name: 'commons-codec', version: '1.2'
    }
}

tasks.register('encode') {
    doLast {
        def byte[] encodedString = new Base64().encode('hello world\n'.getBytes())
        println new String(encodedString)
    }
}
situee
  • 2,710
  • 2
  • 22
  • 27
1

I believe that everything in the buildscript {} will be available for the current build script itself and then the all its subprojects.

And for the properties declared in the file itself outside of the buildscript {} it will not become immediately available to for buildscript of the given project itself, but to all its subprojects.

  • So if you want to declare something and use it for the buildscript itself right away (current buildscript and not just subproject's buildscript), declare them in the buildscript {} for the current project and it also has the side effect to let subproject use it later on.

  • If you just want to declare something globally (for sub-projects's buildscripts) you can declare them directly as ext {} in parent project. The parent project won't be able to use them for itself's buildscript but it will be available all the subproject to use, in or out of the buildscript clause.

For example in parent project:

ext {
    kotlin_version_XX = '1.7.10' 
}

buildscript {
    ext {
      kotlin_version = '1.7.10' 
    }
    // kotlin_version will be available here since declared in buildscript{}
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 

    // will NOT be available here -- error due to kotlin_version_XX declared in project 
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version_XX" 
}

And if you have a subproject:


dependencies {
   
    // both kotlin_version and kotlin_version_XX can be used here, since it was declared in parent project
    implementation "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    implementation "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version_XX"
}

buildscript {
    
    // both kotlin_version and kotlin_version_XX can even be used here for subproject's script's use, since it was already declared in parent project
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version_XX"
}
Haomin
  • 1,265
  • 13
  • 12
0

You can imagine the buildScript block as contents from the Gradle core, like plugins{} block that already goes into Gradle internally. So all plugins from buildScript of parent build.gradle will be available in all nested build.gradle modules.

Ivan
  • 2,316
  • 2
  • 24
  • 22