如何将一个 Gradle 脚本导入另一个?

Posted

技术标签:

【中文标题】如何将一个 Gradle 脚本导入另一个?【英文标题】:How can I import one Gradle script into another? 【发布时间】:2011-01-16 22:35:51 【问题描述】:

我有一个复杂的 Gradle 脚本,其中包含围绕构建大量 NetBeans 项目并将其部署到多个环境的大量功能。

该脚本运行良好,但本质上它都是通过包含项目和环境信息的六张地图配置的。

我想将任务抽象到另一个文件中,这样我就可以在一个简单的构建文件中简单地定义我的地图,并从另一个文件中导入任务。通过这种方式,我可以为多个项目使用相同的核心任务,并使用一组简单的地图配置这些项目。

谁能告诉我如何以类似于 Ant 任务的方式将一个 Gradle 文件导入另一个文件?到目前为止,我已经搜索了 Gradle 的文档,但无济于事。

其他信息

在汤姆在下面的回复之后,我想我会尝试澄清我的意思。

基本上我有一个运行多个子项目的 Gradle 脚本。但是,子项目都是 NetBeans 项目,并带有自己的 ant 构建脚本,所以我在 Gradle 中有任务来调用它们。

我的问题是文件顶部有一些配置,比如:

projects = [
    [name:"MySubproject1", shortname: "sub1", env:"mainEnv", cvs_module="mod1"],
    [name:"MySubproject2", shortname: "sub2", env:"altEnv", cvs_module="mod2"]
]

然后我生成如下任务:

projects.each(
    task "checkout_$it.shortname" << 
         // Code to for example check module out from cvs using config from 'it'.
    
)

我有很多这样的任务生成 sn-ps,它们都是通用的——它们完全依赖于项目列表中的配置。

所以我想要的是一种将其放在单独的脚本中并以以下方式导入的方法:

projects = [
    [name:"MySubproject1", shortname: "sub1", env:"mainEnv", cvs_module="mod1"],
    [name:"MySubproject2", shortname: "sub2", env:"altEnv", cvs_module="mod2"]
]

import("tasks.gradle") // This will import and run the script so that all tasks are generated for the projects given above.

因此,在此示例中,tasks.gradle 将包含所有通用任务生成代码,并将针对主 build.gradle 文件中定义的项目运行。这样一来,tasks.gradle 是一个可供所有大型项目使用的文件,这些大型项目由许多具有 NetBeans ant 构建文件的子项目组成。

【问题讨论】:

考虑“应用自:'other.gradle'”结构来导入外部声明。 (参见“12.4. 使用外部构建脚本配置项目”gradle.org/0.9-preview-1/docs/userguide/…) @PetrGladkikh apply from 立即执行外部任务。这在执行逻辑中可能不太可取(即,我想在我想要的时候执行任务,而不是立即执行)。 上面评论中的这句话不正确apply from 立即执行外部任务。不要被误导。外部任务已配置,未执行。 Is there a way to split/factor out common parts of Gradle build的可能重复 【参考方案1】:

0.9 中有一个新功能。您可以使用apply from: 'other.gradle' 命令。

阅读我关于同一件事的问题:Is there a way to split/factor out common parts of Gradle build

【讨论】:

【参考方案2】:

问题的答案原来是在插件系统中,您可以在插件系统中添加所需的功能,这些插件可以是位于目录buildSrc/src/main/groovy 中的常规文件。插件也可以打包成 Jar,虽然我没试过。

详情请看:Custom Plugins

【讨论】:

只是让您知道链接已损坏 - 这是更新gradle.org/docs/current/userguide/… 插件链接:gradle.org/docs/current/userguide/…【参考方案3】:

好吧,如果不实际查看您的构建文件,很难判断什么最适合您。

我可以假设将您的环境设置为多项目构建应该为您提供您正在寻找的抽象。

在您的项目根build.gradle 中,您可以定义所有特定于域的内容以及适用于所有子项目的内容:

repositories 
    add(new org.apache.ivy.plugins.resolver.FileSystemResolver()) 
        name = 'destRepo'
        addIvyPattern( file( project.properties['repo.dest.dir']).absolutePath + '/[organisation]/[module]/ivys/ivy(-[revision]).xml')
        addArtifactPattern( file( project.properties['repo.dest.dir']).absolutePath + '/[organisation]/[module]/[type]s/[artifact](-[revision]).[ext]')
        descriptor = 'optional'
        checkmodified = true
    
    ...

...
subprojects 
    sourceCompatibility = 1.5
    targetCompatibility = 1.5
    group = 'my.group'
    version = '1.0'
    uploadArchives 
        uploadDescriptor = true
        repositories 
            add rootProject.repositories.destRepo
        
    
    apply type my.group.gradle.api.plugins.MyPlugin 
    ...


dependsOnChildren()

项目根目录还可能包含一个gradle.properties 文件,您可以在其中定义项目使用的属性:

buildDirName=staging
repo.dest.dir=/var/repo
...

然后在您的项目根目录中名为settings.gradle 的附加文件中,您实际上指向您的子项目:

include 'my-first-component',
        'my-second-component'
...
project(':my-first-component').projectDir = new File(rootDir, 'path/to/first/component')
project(':my-second-component').projectDir = new File(rootDir, 'path/to/second/component')
...

每个子项目目录都包含一个build.gradle 文件,其中仅包含子项目特定的内容。

无论您是从项目根目录还是子项目目录调用gradle,gradle 都会自动考虑您在各个文件中完成的所有定义。

另外请注意,只要您没有在根级别加载任何超出默认插件的插件,就不会为您的项目根执行任何编译任务。

【讨论】:

感谢您花时间回答。这不是我遇到麻烦的子项目,而是创建一个常见任务的“库”。我用更多信息和代码 sn-ps 编辑了我的原始问题,以使事情更清楚。 因此,您可以使用 subprojects 部分指定所有子项目使用的通用任务生成代码,而不是从示例中执行 import("tasks.gradle")。这应该提供您正在寻找的相同抽象!? 这里真的需要Ivy插件吗? Gradle不能单独使用吗?【参考方案4】:

这是 Kotlin DSL (build.gradle.kts) 的示例。

apply(from = "scripts/my-script.gradle.kts")

脚本/my-script.gradle.kts

println(
    """
    I am defined at the top level of the script and
    executed at the configuration phase of build process
    """
)

tasks.create("MyTask") 
    println(
        """
        I am defined in a task and
        run at the configration phase of build process"""
    )
    doLast 
        // ...
    

请参阅 this answer 和 this answer,了解如何从 Kotlin DSL 中的另一个脚本导入函数。

【讨论】:

以上是关于如何将一个 Gradle 脚本导入另一个?的主要内容,如果未能解决你的问题,请参考以下文章

检测离线的gradle脚本功能

Gradle 项目同步在导入另一个模块时失败

AS将一个项目导入到另一个项目中

如何向Android Studio里导入从Github上面下载的Project?

将 Spring Boot Gradle 项目导入 Eclipse 时遇到问题

gradle 教程学习笔记