习惯性Gradle脚本构建'debug'和'release'JAR文件

我试图创建一个Gradle构建脚本,它将在'release'或'debug'模式下构建一个Java .jar文件,并且无法参数化脚本。

问题是: 在使用Java插件的Gradle脚本中,通过何种惯用方式来实现这一点? (或者,如果没有惯用的方法,那么实际上有效的黑客解决方案是什么?)

我不介意参数化方法,只要命令行和IDE调用可以在两个输出选项之间轻松选择即可。 该jar文件将在其他项目中用作库,例如Android应用程序和JavaFX应用程序,所以我希望参数化方法可以从他们自己的Gradle脚本中调用/依赖。

理想情况下,我想“模拟”Android Gradle插件的每个任务的调试/发布版本的能力,即

$ ./gradlew build    
$ ./gradlew assembleRelease
$ ./gradlew checkDebug

但如果失败了,即使是顶级的buildDebug和buildRelease也是合适的。


我试过的东西

本节与问题无关。

初始点

我有以下gradle文件/项目:

group 'TestGradleProjectGroup'
apply plugin: 'java'
sourceCompatibility = 1.8

version '1.0-release'
compileJava {
    options.debug = false
}

repositories {
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.11'
}

这工作正常,并生成jar文件:

$ ls TestGradleModule/build/libs/
TestGradleModule-1.0-release.jar

当用javap检查提取的类时,它不包含任何调试信息。 欢呼。 不,我们需要一种方法来制作调试版本。

添加调试和发布任务

version '1.0-release'
compileJava {
    options.debug = false
}

task buildRelease(type: GradleBuild, dependsOn: build) {
    project.version = '1.0-release'
    compileJava {
        options.debug = false
    }
}

task buildDebug(type: GradleBuild, dependsOn: build) {
    project.version = '1.0-debug'
    compileJava {
        options.debug = true
    }
}

这不起作用,因为调试项目总是被构建,即使buildRelease是命令行上给出的任务。 我想这是因为两个任务的代码都是在配置时(Gradle构建生命周期)运行的,而我只想运行一个。 所以我想我想在执行时间运行它们?

添加一些doLast任务

version '1.0-release'
compileJava {
    options.debug = false
}

task buildRelease(type: GradleBuild, dependsOn: build) {
    doLast {
        project.version = '1.0-release'
        compileJava {
            options.debug = false

        }
    }
}

task buildDebug(type: GradleBuild, dependsOn: build) {
    doLast {
        project.version = '1.0-debug'
        compileJava {
            options.debug = true
        }
    }
}

这更糟糕。 输出文件始终是1.0版本,这是因为顶层的“默认”。 如果我发表评论,那么不会创建一个版本化的jar,而是TestGradleModule.jar的默认值。 似乎doLast块的内容对compileJava任务的影响完全没有用处(但对此没有任何警告)。 我猜这些修改已经太迟了,不能在执行时完成,或者需要做其他事情,以便compileJava任务的“配置”不同。

使用配置?

我注意到Java插件的手册中包含对buildConfigNameuploadConfigName的引用,并声称它们依赖于“配置ConfigName中产生工件的任务”。 鉴于我在配置时没有参数化,插件能够做到这一点看起来很有希望:

group 'TestGradleProjectGroup'
apply plugin: 'java'
sourceCompatibility = 1.8

configurations {
    debug
    release
}

version '1.0-release'
compileJava {
    options.debug = false
}

repositories {
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.11'
}

但:

  • 这并没有将buildReleasebuildDebug添加到./gradlew tasks --all的输出中 - ./gradlew tasks --all ,正如我预期的那样。 但我可以运行这些任务。
  • 它似乎只使buildReleasebuildDebug ,而不是例如assembleRelease
  • buildRelease在运行时似乎不依赖于任何东西,因此没有任何有用的效果。
  • 迭代任务?

    作为最后的尝试,我试图创建所有适当的任务并链接所有事物的依赖关系。 我试着迭代任务并添加依赖关系:

    gradle.taskGraph.whenReady { taskGraph ->
    
        taskGraph.allTasks.each { taskIter ->
    
            println("iterating" + taskIter)
    
            def releaseTask = project.task(taskIter.name + "Release")
            def debugTask = project.task(taskIter.name + "Debug")
    
            taskIter.dependsOn += [releaseTask, debugTask].toSet()
            println("new taskIter.dependsOn:" + taskIter.dependsOn)
    
            /*
                set debug mode here,
                copy over effects of task to debug/release
                disable effects of task
            */
        }
    }
    

  • 这似乎没有正确地创建任务,它们不能从命令行访问,并且运行“build”没有运行“buildRelease”等。
  • 我还必须将所有“行动”从当前的现有任务“移动”到调试和发布任务中,以避免重复每个行为的影响。 我不知道该怎么做。
  • 总之,我不知道我在做什么。 作为最后的手段,我可​​以手动创建所有的任务,但这似乎打败了使用Java插件的重点,并且非常垃圾?


    你是否需要用一次gradle创建两个罐子? 如果不是这样,它可以像使用一些额外的参数到gradle一样简单,比如

    compileJava {
        options.debug = project.hasProperty('debugBuild')
    }
    
    gradle assemble -PdebugBuild=true # or false
    

    有关文档,请参阅此处:https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_properties_and_system_properties

    也不是说你可能会在Gradle论坛中获得更好的帮助。


    不知道,但也许我的gradle-java-flavors插件可以在这里帮助。 例如:

    plugins {
        id "com.lazan.javaflavours" version "1.2"
    }
    javaFlavours {
        flavour 'debug'
        flavour 'release'
    }
    debugJar {
        version = "${project.version}-debug"
    }
    releaseJar {
        version = "${project.version}-release"
    }
    

    每种风格都有它自己的JarJavaCompile任务等,您可以指定自定义源,资源,测试,每种风味的依赖关系。

    请参阅这里了解有关可用的任务,目录和配置的更多概述,以及用于涵盖功能的测试。

    这种方法与GradleBuild风格不同,因为“风味”可以愉快地生活在一个项目中,这个项目可以构建多个构件,而不是使用两个不同的参数运行两次项目。


    由于您对问题进行了深入分析,因此您的问题很详细。 尽管我相信如果你想以更简单的方式思考,这个问题就可以解决。
    因此,如果我们认为简单,那么针对您的案例可能的解决方案是在发布完成后运行调试任务。 看下面的例子:

    compileJava {
        options.debug = false
    }
    
    task buildRelease(type: GradleBuild, dependsOn: build) {
        doLast {
            project.version = '1.0-release'
            compileJava {
                options.debug = false
    
            }
        }
    }
    
    task buildDebug(type: GradleBuild, dependsOn: build) {
        doLast {
            project.version = '1.0-debug'
            compileJava {
                options.debug = true
            }
        }
    }
    
    // Here you are telling the buildDebug task to be executed right after the 
    // buildRelease task is finalized.
    buildDebug.mustRunAfter buildRelease
    

    以上述方式控制任务执行的顺序,而不会在它们之间引入明确的依赖关系。

    链接地址: http://www.djcxy.com/p/40887.html

    上一篇: Idiomatic Gradle script to build 'debug' and 'release' JAR files

    下一篇: Keep Background Image from Resizing During CSS Animation and Remove Flicker