【发布时间】:2020-11-17 11:42:37
【问题描述】:
背景:我正在尝试将我自己的特定领域语言的编译器挂接到 Gradle 中。 DSL 被编译为 Java 源代码,所以我构建了一个在 Java 编译器之前运行的任务。编译器目前无法处理具有依赖关系的多个项目,所以我正在尝试添加它。
我的 DSL 有像 Java 这样的包,它们被映射到相同的 Java 包。项目也应该如此。在这种情况下,对于每个项目,DSL 源都被编译为 Java 源代码以及元数据(每个编译类的 JSON 文件,包含来自 DSL 类型系统的信息,这些信息无法映射到 Java 类型)。当项目 A 依赖于 B 时,A 的 DSL 编译过程需要来自 B 的元数据文件。该元数据应作为资源与生成和编译的 Java 代码一起打包到 JAR 文件中,可能还需要手动打包。编写和编译的 Java 代码。
FoobarPlugin.groovy:
class FoobarPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
// create the compileFoobar task
CompileFoobarTask task = project.getTasks().create('compileFoobar', CompileFoobarTask.class);
task.group = 'build';
task.setDescription('Compiles Foobar to Java code.');
task.sourceDirectory = new File(project.projectDir, "src/main/foobar");
task.outputDirectory = new File(project.getBuildDir(), "foobar-java");
// compileFoobar must run before compiling Java code
project.tasks.compileJava.dependsOn(task);
// add the task's output folders as Java source folders
project.sourceSets.main.java.srcDirs += task.outputDirectory;
project.sourceSets.main.resources.srcDirs += task.outputDirectory;
project.sourceSets.test.java.srcDirs += task.outputDirectory;
project.sourceSets.test.resources.srcDirs += task.outputDirectory;
// Turn project dependencies into task dependencies. We have to delay this until the end of the configuration
// phase because project dependencies are not fully known until then.
project.gradle.addBuildListener(new BuildAdapter() {
@Override
void projectsEvaluated(Gradle gradle) {
project.configurations.compile.each {
task.dependencyOutputs += it
}
}
});
}
}
编译FoobarTask.groovy:
class CompileFoobarTask extends DefaultTask {
@InputDirectory
File sourceDirectory;
@InputFiles
List<File> dependencyOutputs = new ArrayList<>();
@OutputDirectory
File outputDirectory;
@TaskAction
void run() {
FileUtils.write(new File(outputDirectory, "timestamp"), "" + System.currentTimeMillis(), StandardCharsets.UTF_8);
}
}
来自项目 A 的 build.gradle:
apply plugin: 'java'
apply plugin: foobar.gradle.FoobarPlugin
repositories {
mavenCentral()
}
dependencies {
compile project(':b')
}
来自项目 B 的 build.gradle:
apply plugin: 'java'
apply plugin: foobar.gradle.FoobarPlugin
repositories {
mavenCentral()
}
dependencies {
compile 'org.apache.commons:commons-lang3:3.0'
}
测试运行和输出:
martin@xyz:~/git-repos/gradle-test$ ./gradlew clean a:compileFoobar
adding dependency /home/martin/git-repos/gradle-test/b/build/libs/b.jar to task task ':a:compileFoobar'
> Task :a:compileFoobar
running task ':a:compileFoobar'
BUILD SUCCESSFUL in 1s
4 actionable tasks: 2 executed, 2 up-to-date
martin@xyz:~/git-repos/gradle-test$ ./gradlew clean b:compileFoobar
adding dependency /home/martin/git-repos/gradle-test/b/build/libs/b.jar to task task ':a:compileFoobar'
> Task :b:compileFoobar
running task ':b:compileFoobar'
BUILD SUCCESSFUL in 469ms
4 actionable tasks: 2 executed, 2 up-to-date
martin@xyz:~/git-repos/gradle-test$ ./gradlew clean a:compileJava
adding dependency /home/martin/git-repos/gradle-test/b/build/libs/b.jar to task task ':a:compileFoobar'
> Task :a:compileFoobar
running task ':a:compileFoobar'
> Task :b:compileFoobar
running task ':b:compileFoobar'
BUILD SUCCESSFUL in 487ms
7 actionable tasks: 5 executed, 2 up-to-date
martin@xyz:~/git-repos/gradle-test$ ./gradlew clean b:compileJava
adding dependency /home/martin/git-repos/gradle-test/b/build/libs/b.jar to task task ':a:compileFoobar'
> Task :b:compileFoobar
running task ':b:compileFoobar'
BUILD SUCCESSFUL in 471ms
4 actionable tasks: 3 executed, 1 up-to-date
如您所见,即使我将 b.jar 作为依赖项添加到 a:compileFoobar,Gradle 也不会在运行 a:compileFoobar 之前构建该 JAR。 Java 插件似乎做了一些不同的事情,因为运行 a:compileJava 将首先构建 b.jar。为了完成我的任务,我必须做些什么?
【问题讨论】:
标签: gradle plugins dependencies