草庐IT

java - 用于构建 'debug' 和 'release' JAR 文件的惯用 Gradle 脚本

coder 2024-03-11 原文

我正在尝试创建一个 Gradle 构建脚本来构建 Java .jar文件处于“发布”或“调试”模式,并且无法参数化脚本。

问题是:使用 Java 插件在 Gradle 脚本中执行此操作的惯用方法是什么?
(或者,如果没有惯用的方法,那么实际有效的hacky解决方案是什么?)

我不介意参数化的方法,只要命令行和 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 build lifecycle ),而我只想运行一个。所以我想我想在执行时运行它们?

添加一些 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-release,这是因为顶级的“默认”。如果我将其注释掉,则不会生成版本化的 jar,而是默认值 TestGradleModule.jar制作。似乎 doLast 块的内容对 compileJava 任务的影响完全没有用(但没有关于这一点的警告?)。我猜这些修改在执行时为时已晚,或者需要做其他事情以便 compileJava 任务以不同的方式“配置”?

使用配置?

我注意到 the Java plugin 的手册包含对 buildConfigName 的引用和 uploadConfigName ,并声称它们依赖于“在配置 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 的输出,正如我所料。但我可以运行这些任务。
  • 它似乎只是让 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 插件的意义并且非常垃圾?

    最佳答案

    经过几个小时的搜索......

    “构建脚本基础”的“通过 DAG 配置”部分 Gradle教程描述了一种方法,即

    https://docs.gradle.org/current/userguide/tutorial_using_tasks.html#configure-by-dag

    引自教程

    "Gradle has a configuration phase and an execution phase. After the configuration phase, Gradle knows all tasks that should be executed. Gradle offers you a hook to make use of this information. A use-case for this would be to check if the release task is among the tasks to be executed. Depending on this, you can assign different values to some variables."


    以下是应用 gradle.taskGraph.whenReady{} 的示例使用 buildRelease()buildDebug()任务...
    gradle.taskGraph.whenReady { taskGraph ->
        if (taskGraph.hasTask(buildRelease)) {
            compileJava.options.debug = false
            project.version = '1.0-release'
        } else if (taskGraph.hasTask(buildDebug)) {
            compileJava.options.debug = true
            project.version = '1.0-debug'
        }
    }
    
    task buildRelease(type: GradleBuild, dependsOn: build) {
    }
    
    task buildDebug(type: GradleBuild, dependsOn: build) {
    }
    

    IMO,Gradle 是一个完全需要学习的人。我确实很想念好 ol' make。

    关于java - 用于构建 'debug' 和 'release' JAR 文件的惯用 Gradle 脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47390481/

    有关java - 用于构建 'debug' 和 'release' JAR 文件的惯用 Gradle 脚本的更多相关文章

    1. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

      我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

    2. ruby - 其他文件中的 Rake 任务 - 2

      我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

    3. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

      我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

    4. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

      我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

    5. ruby-on-rails - Rails 3 中的多个路由文件 - 2

      Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

    6. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

      我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

    7. ruby - 将差异补丁应用于字符串/文件 - 2

      对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

    8. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

      大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

    9. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

      我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

    10. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

      使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

    随机推荐