我正在尝试弄清楚如何使用 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 任务可以在运行时创建,据我所知,它需要在调用 gradle 时准备好生成任务所需的输入(不确定一旦一项任务已经启动,是否仍然可以创建任务,我还没有亲自尝试过)。
对于您的用例,一旦输入准备好,您可能只需要执行单独的 gradle 命令(单独的构建文件)。 Gradle 允许您调用任何 shell 命令,因此只需生成另一个 gradle 调用即可。
以下是有关如何动态创建新任务的示例(多个任务从数组中生成,您可以只从文件中读取任务):https://github.com/HCL-TECH-SOFTWARE/DX-Modules -and-ScriptApps/blob/main/06ThemeComponentInApp/DxModule/build.gradle
此处介绍了最小示例代码生成 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!"
"""
}
}```