编写自定义构建任务以在每个构建上自动生成构建依赖项

问题描述 投票:0回答:2

我正在尝试弄清楚如何使用 Gradle。我遇到了这个问题,在 Makefiles、CMake 等中解决这个问题很简单,但我不知道如何在 Gradle 中做到这一点。

假设我有一个应用程序,其中包含一些资源文件。这些资源文件是从一组输入文件生成的,并以编译的形式放入应用程序中。

我想指示 Gradle 在需要时通过将其指向资源输入文件来自动生成这些资源。所以,实际上我想做这样的事情:

all: out1 out2
    @echo done

out1: in1
    cat in1 | xxd > out1

out2: temp1
    cat temp1 | xxd > out2

temp1: in1
    cat in2 | tr '[:lower:]' '[:upper:]' > temp1

(让我们跳过这个不幸的影响,如果

xxd
失败,则会生成无效的
out1

假设

out1
out2
是我想要嵌入到应用程序中的资源文件。这些文件是由不同的规则生成的:

  • out1
    是通过
    in1
    处理
    xxd
    生成的(这只是一个例子),
  • out2
    是从
    in2
    生成的,首先将其大写,然后通过管道将其通过
    xxd
    。同时正在创建一个临时文件
    temp1
    ,但这只是一个临时文件,根本不重要。

所以我想在 Gradle 中实现的基本上相当于上面粘贴的 Makefile 脚本及其所有功能;我主要是说,如果

out1
out2
没有改变,则不应该生成
in1
in2
(因为资源生成阶段可能既昂贵又耗时,所以我想避免必须在每个构建上运行它),并且构建系统可以自动确定如何并行运行构建,以便同时生成
out1
out2

我正在尝试挖掘 Gradle 的文档和一些示例,但我发现的 95% 都是一些使用某些特定插件的不透明脚本,没有人解释它的内部工作原理。文档说 Gradle 是一个“自动化工具”,所以它应该完全可行,我想要实现的目标,但事实真的如此吗?尝试使用 Gradle 作为本文描述的用例的工具是否有意义?

gradle makefile
2个回答
0
投票

可行。只需要一点想象力。 Gradle 任务可以在运行时创建,据我所知,它需要在调用 gradle 时准备好生成任务所需的输入(不确定一旦一项任务已经启动,是否仍然可以创建任务,我还没有亲自尝试过)。

对于您的用例,一旦输入准备好,您可能只需要执行单独的 gradle 命令(单独的构建文件)。 Gradle 允许您调用任何 shell 命令,因此只需生成另一个 gradle 调用即可。

以下是有关如何动态创建新任务的示例(多个任务从数组中生成,您可以只从文件中读取任务):https://github.com/HCL-TECH-SOFTWARE/DX-Modules -and-ScriptApps/blob/main/06ThemeComponentInApp/DxModule/build.gradle


0
投票

此处介绍了最小示例代码生成 Gradle 任务:

https://github.com/gradle/native-samples/blob/master/cpp/source- Generation/build.gradle

plugins {
    id 'cpp-application'
    id 'xcode'
    id 'visual-studio'
}

def codeGeneration = tasks.register("codeGeneration", CodeGenerator) {
    cppDir = project.layout.buildDirectory.dir("generated/cpp")
    headersDir = project.layout.buildDirectory.dir("generated/headers")
}

application {
    source.from codeGeneration.flatMap { it.cppDir }
    privateHeaders.from codeGeneration.flatMap { it.headersDir }
}


// Code generation implementation could be in another plugin or buildSrc
class CodeGenerator extends DefaultTask {
    @OutputDirectory
    DirectoryProperty cppDir = project.objects.directoryProperty()
    
    @OutputDirectory
    DirectoryProperty headersDir = project.objects.directoryProperty()

    @TaskAction
    public void generate() {
        generateSources(cppDir.getAsFile().get())
        generateHeaders(headersDir.getAsFile().get())
    }

    private void generateSources(File generatedDir) {
        new File(generatedDir, "main.cpp").text = """
#include <iostream>
#include "header.h"

int main() {
    std::cout << MESSAGE << std::endl;
    return 0;
}
        """
    }
    private void generateHeaders(File generatedDir) {
        new File(generatedDir, "header.h").text = """
#pragma once

#define MESSAGE "Hello, World!"
        """
    }
}```
© www.soinside.com 2019 - 2024. All rights reserved.