【问题标题】:How can I make a simple gradle build script to compile a java program?如何制作一个简单的 gradle 构建脚本来编译 java 程序?
【发布时间】:2020-11-24 18:48:05
【问题描述】:

我正在尝试学习如何使用 gradle 来更轻松地编译和打包我的 java 程序。我已经有 java 编程经验,通常我只是使用 eclipse 来管理它,或者,我只是手动编译我的程序(在终端中使用 javac)。但是,我已经到了想要使用似乎最容易通过 gradle 使用和维护的库的地步。

为了更多地了解 gradle 的工作原理,我访问了 gradle 站点,他们提供了用于编写简单的 gradle 设置的教程,以便在编写 Java 应用程序时使用(this 是我找到的那个)。但是,本教程并没有真正解释其中的任何一个应该如何工作,并且似乎假设您正在遵循某些特定系统来进行项目布局。它还包括一些测试程序或在构建程序时测试程序的东西。除了这些事情之外,它从未真正解释过运行 gradle 构建函数是如何工作的,或者文件在哪里(以及什么)保存了构建程序时它正在做什么的说明。

所以本质上,我在问是否有人可以解释制作一个简单的 gradle 环境的步骤,该环境只需编译一组 .java 文件并将它们放入可执行 jar 或将它们保留为 .class 文件在单独的bin 文件夹或其他东西中。如果您解释每个部分在做什么以及如何进行更改以添加更多内容(例如基本依赖项,可能在 .jar 周围添加 .exe 包装器等),这也会有所帮助

【问题讨论】:

    标签: java gradle build-automation


    【解决方案1】:

    让我们从一个简单的问题开始:构建 Java 项目需要哪些基本步骤?好吧,只要您的项目不使用一些花哨的预处理或代码生成,第一步可能是将.java 文件编译为.class 文件。然后可以将那些.class 文件(和资源,如果提供)打包到.jar 文件中。现在对您来说似乎并不明显,但一般来说,您还应该在构建项目时运行(单元)测试。根据您的项目,可能会有更多可能的步骤(例如发布、文档编制、质量控制)。

    在 Gradle 中,这些步骤称为任务。任务基本上可以做任何可以帮助您构建软件的事情。这通常意味着一个任务需要一些输入文件并将它们转换为一些输出文件。例如,编译任务.java 文件转换为.class 文件。另一个任务可以将.class 文件转换为.jar 文件(让我们将此任务称为jar 任务)。由于需要创建.class 文件以将它们放入.jar 文件中,因此jar 任务 依赖于 编译任务。您可以使用 Gradle 来表达这种关系,因此每次 jar 任务 运行时,Gradle 都会确保 编译任务 已经预先运行。任务不需要做什么,它们可能只是用来表达这种关系(这样的任务称为生命周期任务)。您可以创建特定任务类型的任务来重用功能,例如,可以使用两个不同的任务来编译生产代码和测试代码,但两者都在内部使用编译器并且只是在不同的集合上运行输入文件。

    您可以手动创建任务,我强烈建议您创建一些任务以了解它们的关系和执行方式,但通常您不需要在构建脚本中创建任务,因为所有必要的任务都是由插件。 Gradle 插件非常强大,因为它们基本上可以完成您可以在构建脚本中手动执行的所有操作,there is a plugin for almost everything 您可能希望在构建过程中执行此操作。

    [...] 我在问是否有人可以解释制作一个简单的 gradle 环境的步骤,该环境只编译一组 .java 文件 [...]

    使用 Gradle 编译 Java 项目的最简单方法是创建一个文件build.gradle,其内容如下:

    plugins {
        id 'java'
    }
    

    就是这样! Gradle 已准备好构建您的项目(只需运行 gradle build)。这怎么可能?好吧,Java 插件创建了编译、测试和打包项目所需的所有必要任务,并将它们配置为遵循通用约定。看看documentation of the Java plugin,它甚至包含一张漂亮的图片,显示了所有任务及其依赖关系。如图所示,build 任务依赖于所有其他任务。该任务在您调用gradle build 时执行。您也可以调用gradle jargradle assemble,Gradle 将只运行构建.jar 文件所需的任务。

    [...] 它似乎假设您正在遵循某些特定系统来进行项目布局。

    是的,Gradle 遵循一种称为约定优于配置的方法。这意味着对于必须手动配置的所有内容都有一个(某种通用或有用的)约定。

    此方法的一个简单示例是源文件和资源文件的预期位置。可以看到,上面的构建脚本中没有配置这个位置。但是,有一个约定(由 Maven 建立),.java 源文件应该进入 src/main/java 用于生产代码,src/test/java 用于测试代码。当然,这些路径可能会改变,但在大多数项目中,您应该简单地遵守约定。

    如果您解释每个部分在做什么以及我如何进行更改以添加更多内容(如基本依赖项 [...])也会很有帮助

    让我们简单看一下教程中的构建文件:

    plugins {
        id 'application' 
    }
    
    repositories {
        jcenter() 
    }
    
    dependencies {
        testImplementation 'junit:junit:4.13' 
        implementation 'com.google.guava:guava:29.0-jre' 
    }
    
    application {
        mainClass = 'demo.App' 
    }
    

    第一个块与上面的示例类似,但不是使用标识符为 java 的插件,而是应用标识符为 application 的插件。但是,这不会有太大变化,因为 Application 插件在内部也应用了 Java 插件。

    现在让我们看看repositoriesdependencies 块。 dependencies 块可用于注册依赖项。您可以添加对本地 .jar 文件、其他 Gradle 项目(在多项目构建中)或外部模块的依赖项。 external 一词指的是提供您可以在项目中使用的库的远程存储库。 dependencies 块中的每一行通过定义依赖范围和模块标识符来表示特定的依赖关系,该模块标识符由组标识符、工件标识符和版本组成(使用 : 作为分隔符)。依赖范围(在 Gradle 中也称为配置)基本上定义了可以在何处以及如何使用依赖项。例如,第一个依赖项只能在测试代码中使用(由于testImplementation 范围)。现在 Gradle 知道构建项目需要 什么 库,但它不知道 从哪里 获取该库。这里 repositories 块来救援,因为它可以用来定义 Gradle 应该在哪里寻找外部模块依赖。大多数情况下,您将主要使用jcenter()mavenCentral()google(),但也可以添加可通过自定义 URL 访问的存储库。

    最后一部分应用了必要的配置,因为无法应用任何有用的约定。 Gradle 根本不知道你项目中的哪个类应该作为你应用的主类,所以你必须手动定义它。

    现在,多亏了应用程序插件,您不仅可以使用gradle build 构建您的项目,还可以使用gradle run 从 Gradle 运行您的应用程序,因为任务run 是在上面创建的任务之一Java 插件创建的任务。

    【讨论】:

    • 非常感谢这个一般性的纲要,这正是我一直在寻找的,它解释了我的大部分问题。再次感谢!
    猜你喜欢
    • 1970-01-01
    • 2014-02-28
    • 1970-01-01
    • 2011-09-12
    • 1970-01-01
    • 2011-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多