build.gradle - Gradle Distribution plugin: how to make the tasks "opt-in?" - Stack Overflow

Gradle 8.12, using Groovy syntax.I want to include the distribution plugin in my build but I don'

Gradle 8.12, using Groovy syntax.

I want to include the distribution plugin in my build but I don't want its tasks automatically placed in the build dependency tree. In other words, I want to "opt-in" to running distZip only when needed, not whenever build task is run.

Right now, if I run gradlew build, distZip is included. When I want to use distZip I want to explicitly request it (ie, with gradlew distZip). I do not want to totally disable distZip, just make it an explicit choice.

What's the cleanest/simplest way to accomplish that?

Gradle 8.12, using Groovy syntax.

I want to include the distribution plugin in my build but I don't want its tasks automatically placed in the build dependency tree. In other words, I want to "opt-in" to running distZip only when needed, not whenever build task is run.

Right now, if I run gradlew build, distZip is included. When I want to use distZip I want to explicitly request it (ie, with gradlew distZip). I do not want to totally disable distZip, just make it an explicit choice.

What's the cleanest/simplest way to accomplish that?

Share Improve this question asked Mar 6 at 17:46 E-RizE-Riz 33.1k14 gold badges105 silver badges152 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 1

You can use onlyIf to run only if some condition is met. For example, the someProperty value must be set in order for the task to run:

tasks {
    distZip {
        onlyIf("property present") {
            hasProperty("someProperty")
        }
    }
}

The distZip will only run when someProperty is set, so ./gradlew build would not execute distZip.

But ./gradlew build -PsomeProperty will since someProperty is specified.

Discussion

If you inspect the code of the Distribution plugin1, you'll see that the dependency of the build task on distZip arises because assemble is given a dependency on distZip (and build by default depends on assemble).

That suggests three possible approaches:

  1. Remove the the dependency of assemble on distZip

    This the most obvious and desirable. However it turns out this is not straightforward to do.2

  2. Write your own version of the build task

    This is maybe do-able, but it dodges the original question and could be hard to maintain as the build grows. Still, it the most Gradle-esque approach.

  3. Call the parts of the Distribution plugin you want manually

    It turns out the Distribution plugin is pretty simple and you can fairly easily call the bits of code you want. To do this, probably against my better judgement I've pulled together a plugin to call the essential bits of the Distribution plugin and omit assemble's dependency. It was necessary to write a plugin as getting hold of the dependencies of the Distribution Plugin requires accessing Gradle's internal dependency injection mechanisms, which I don't believe is possible within a build script.

    I've included the code for this below. To make it work, put it in the file buildSrc/main/java/AlteredDistributionPlugin.java and also add the supplied buildSrc build file at buildSrc/build.gradle (or make similar amendements to an existing one). You can then apply the plugin instead of the Distribution plugin with the id alteredDistribution in the plugins block. You can check that task dependency has been removed with the command ./gradlew build --dry-run.

    Please note the arrangement, but not the functionality, of the Distribution Plugin code changed in Gradle 8.13, with most moving to a Distribution Base Plugin. The supplied code will thus need to be amended to be compatible with Gradle 8.13 as it depends on the plugin's implementation details.

Code

// buildSrc/main/java/AlteredDistributionPlugin.java

import .gradle.api.Plugin;
import .gradle.api.Project;
import .gradle.api.distribution.DistributionContainer;
import .gradle.api.distribution.internal.DefaultDistributionContainer;
import .gradle.api.distribution.Distribution;
import .gradle.api.distribution.plugins.DistributionPlugin;
import .gradle.api.internal.CollectionCallbackActionDecorator;
import .gradle.api.internal.file.FileOperations;
import .gradle.api.tasks.bundling.AbstractArchiveTask;
import .gradle.api.tasks.bundling.Zip;
import .gradle.internal.reflect.Instantiator;

import javax.inject.Inject;
import java.lang.reflect.Method;

public class AlteredDistributionPlugin implements Plugin<Project> {

    private final Instantiator instantiator;
    private final FileOperations fileOperations;
    private final CollectionCallbackActionDecorator callbackActionDecorator;

    @Inject
    public AlteredDistributionPlugin(
        Instantiator instantiator,
        FileOperations fileOperations,
        CollectionCallbackActionDecorator callbackActionDecorator
    ) {
        this.instantiator = instantiator;
        this.fileOperations = fileOperations;
        this.callbackActionDecorator = callbackActionDecorator;
    }

    @Override
    public void apply(final Project project) {
        DistributionContainer distributions = project.getExtensions().create(DistributionContainer.class, "distributionsAltered", DefaultDistributionContainer.class, Distribution.class, instantiator, project.getObjects(), fileOperations, callbackActionDecorator);
        distributions.all(dist -> {
            dist.getContents().from("src/" + dist.getName() + "/dist");
            addArchiveTaskByReflection(project, "distZip", Zip.class, dist);
        });
        distributions.create(DistributionPlugin.MAIN_DISTRIBUTION_NAME);
    }

    @SuppressWarnings("SameParameterValue")
    private void addArchiveTaskByReflection(final Project project, String taskName, Class<? extends AbstractArchiveTask> type, final Distribution distribution) {
        DistributionPlugin distributionPlugin = new DistributionPlugin(instantiator, fileOperations, callbackActionDecorator) {};
        try {
            Method addArchiveTask;
            addArchiveTask = DistributionPlugin.class.getDeclaredMethod("addArchiveTask", Project.class, String.class, Class.class, Distribution.class);
            addArchiveTask.setAccessible(true);
            addArchiveTask.invoke(distributionPlugin, project, taskName, type, distribution);
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}
// buildSrc/build.gradle

plugins {
    id 'java'
    id 'java-gradle-plugin'
}

gradlePlugin {
    plugins {
        register('alteredDistribution') {
            id = 'alteredDistribution'
            implementationClass = "AlteredDistributionPlugin"
        }
    }
}

1 Code at version 8.12

2 Eg you can try and work with the dependsOn property of assemble, but this returns a collection of AbstractTaskDependencys, an internal Gradle class loaded by a different class loader, so you are fighting Gradle fairly hard by that route.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744958215a4603326.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信