首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >用于构建“debug”和“release”JAR文件的惯用Gradle脚本

用于构建“debug”和“release”JAR文件的惯用Gradle脚本
EN

Stack Overflow用户
提问于 2017-11-20 19:02:08
回答 3查看 6.7K关注 0票数 11

我正在尝试创建一个Gradle构建脚本,该脚本将在“发布”或“调试”模式下构建一个Java .jar文件,但在参数化该脚本时遇到问题。

问题是:在Gradle script中使用Java做这件事的惯用方法是什么?(或者,如果没有惯用的方法,什么是真正有效的hacky解决方案?)

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

理想情况下,我想“模仿”Android gradle插件的能力,即每个任务都有一个Debug/Release版本。

代码语言:javascript
复制
$ ./gradlew build    
$ ./gradlew assembleRelease
$ ./gradlew checkDebug

但如果做不到这一点,即使是顶级的buildDebug和buildRelease也是合适的。

我试过的东西

这一部分与问题并不真正相关。

起点

我有以下gradle文件/项目:

代码语言:javascript
复制
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文件:

代码语言:javascript
复制
$ ls TestGradleModule/build/libs/
TestGradleModule-1.0-release.jar

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

添加调试和发布任务

代码语言:javascript
复制
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 build lifecycle)运行的,而我只想让其中一个任务运行。所以我想我想在执行时运行它们?

添加一些doLast任务

代码语言:javascript
复制
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-release,这是因为顶层的'default‘。如果我将其注释掉,则不会生成版本化的jar,而是默认设置为TestGradleModule.jar。似乎doLast块的内容对compileJava任务的影响是完全无用的(但是没有关于这方面的警告吗?)。我猜这些修改太晚了,不能在执行时完成,或者还有其他事情需要做,以便以不同的方式“配置”compileJava任务?

使用配置?

我注意到the Java plugin的手册中包含了对buildConfigNameuploadConfigName的引用,并声称它们依赖于“在configuration ConfigName中产生工件的任务”。考虑到我在配置时未能参数化东西,这个插件的能力看起来很有希望:

代码语言:javascript
复制
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'
}

但是:

  1. 没有像我预期的那样将buildReleasebuildDebug添加到./gradlew tasks --all的输出中。但我可以运行这些任务。
  2. It似乎只生成buildReleasebuildDebug,而不是例如,assembleRelease tasks在运行时似乎不依赖于任何东西,因此没有任何有用的效果。

迭代任务?

作为最后一次尝试,我尝试创建所有合适的任务,并将所有内容的依赖关系链接起来。我尝试迭代任务并添加依赖项:

代码语言:javascript
复制
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
        */
    }
}

  1. 这似乎没有正确地创建任务,它们不能从命令行访问,并且运行"build“没有运行"buildRelease”等。
  2. 我还必须将所有“操作”从当前的现有任务“移动”到调试和发布任务中,以避免重复每个任务的效果。我不知道该怎么做。

简而言之,我不知道我在做什么。作为最后的手段,我可以手动创建所有的任务,但这似乎违背了使用java插件的意义,而且非常垃圾?

EN

回答 3

Stack Overflow用户

发布于 2017-11-29 09:53:23

您是否需要使用单次运行gradle来创建两个jars?如果不是,那么只需对gradle使用一些额外的参数,例如

代码语言:javascript
复制
compileJava {
    options.debug = project.hasProperty('debugBuild')
}

gradle assemble -PdebugBuild

请查看此处的文档:https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_properties_and_system_properties

也不是说你可以在gradle论坛上得到更好的帮助。

票数 4
EN

Stack Overflow用户

发布于 2017-12-05 17:15:11

你的问题很详细,因为你对问题进行了深入的分析。虽然我相信如果你能以更简单的方式思考,这个问题是可以解决的。

因此,如果我们认为简单,对您的情况一个可能的解决方案是在发布完成后运行调试任务。如下例所示:

代码语言:javascript
复制
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

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

票数 1
EN

Stack Overflow用户

发布于 2017-12-05 18:11:17

不确定,但也许我的gradle-java-flavours插件可以在这里提供帮助。例如:

代码语言:javascript
复制
plugins {
    id "com.lazan.javaflavours" version "1.2"
}
javaFlavours {
    flavour 'debug'
    flavour 'release'
}
debugJar {
    version = "${project.version}-debug"
}
releaseJar {
    version = "${project.version}-release"
}

每种风格都有自己的JarJavaCompile任务等,你也可以为每种风格指定定制的源代码、资源、测试和依赖关系。

有关可用任务、目录和配置的更多概述,请参见here;有关涵盖该功能的测试,请参阅here

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47390481

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档