42

There are two methods of creating, i.e. tasks, in Gradle (5.0+):

tasks {
    val javadocJar by creating(Jar::class) {
        val javadoc by tasks

        from(javadoc)
        classifier = "javadoc"
    }
}

and

tasks {
    val javadocJar by registering(Jar::class) {
        val javadoc by tasks

        from(javadoc)
        classifier = "javadoc"
    }
}

Basically the same API, so what's the difference?

madhead
  • 31,729
  • 16
  • 153
  • 201

2 Answers2

36

See using the container API:

tasks.named("check")
tasks.register("myTask1")
tasks.named<JavaCompile>("compileJava")
tasks.register<Copy>("myCopy1")

The above sample relies on the configuration avoidance APIs. If you need or want to eagerly configure or register container elements, simply replace named() with getByName() and register() with create().

Difference between creating and registering (or create and register in Gradle versions prior to 5.0) is related to Task Configuration Avoidance new API, which is explained in details here (see this section):

How do I defer task creation?

Effective task configuration avoidance requires build authors to change instances of TaskContainer.create(java.lang.String) to TaskContainer.register(java.lang.String).

…. The create(…​) API eagerly creates and configures tasks when it is called and should be avoided.

Using register(…​) alone may not be enough to avoid all task configuration completely. You may need to change other code that configures tasks by name or by type, as explained in the following sections.

EDIT: Also note that using withType<T> { } will immediately create and configure the task, and must be avoided using withType<T>().configureEach {} instead (source).

How do I defer task configuration?

Eager APIs like DomainObjectCollection.all(org.gradle.api.Action) and DomainObjectCollection.withType(java.lang.Class, org.gradle.api.Action) will immediately create and configure any registered tasks. To defer task configuration, you will need to migrate to a configuration avoidance API equivalent. See the table below to identify the alternative.

bric3
  • 40,072
  • 9
  • 91
  • 111
M.Ricciuti
  • 11,070
  • 2
  • 34
  • 54
  • 14
    In summary, `register is more efficient & will defer creation and configuration until required`. reference here: https://github.com/gradle/gradle/blob/master/subprojects/core-api/src/main/java/org/gradle/api/NamedDomainObjectContainer.java#L88 – mochadwi Dec 07 '19 at 04:46
  • 1
    And what is the difference between `registering` and `register` (or `creating` and `create`)? – sschuberth Sep 17 '21 at 16:49
  • 1
    @sschuberth there were a mistake in my initial answer; `registering` and `creating` as Kotlin DSL specific features explained here in details : https://docs.gradle.org/current/userguide/kotlin_dsl.html#using_kotlin_delegated_properties – M.Ricciuti Sep 17 '21 at 20:22
9

The accepted answer is great, but I want to add that if you want to actually use the reference created by created / registering call later, then there will be a difference in API. Compare

create<MavenPublication>("main") {
    …

    val sourcesJar by tasks.creating(Jar::class) {
        val sourceSets: SourceSetContainer by project
        from(sourceSets["main"].allJava)
        classifier = "sources"
    }

    artifact(sourcesJar)
}

and

create<MavenPublication>("main") {
    …

    val sourcesJar by tasks.registering(Jar::class) {
        val sourceSets: SourceSetContainer by project
        from(sourceSets["main"].allJava)
        classifier = "sources"
    }

    artifact(sourcesJar.get())
}

In case of registering, because it is lazy, you'll need an additional .get() call, or you'll get an exception:

* What went wrong:
Cannot convert the provided notation to an object of type MavenArtifact: task ':experiments:sourcesJar'.
The following types/formats are supported:
  - Instances of MavenArtifact.
  - Instances of AbstractArchiveTask, for example jar.
  - Instances of PublishArtifact
  - Maps containing a 'source' entry, for example [source: '/path/to/file', extension: 'zip'].
  - Anything that can be converted to a file, as per Project.file()
madhead
  • 31,729
  • 16
  • 153
  • 201