如何在编译前修改我的 Gradle 项目中的 Java 源代码而不修改磁盘上的文件?
How can I modify Java source code in my Gradle project prior to compilation without modifying the files on disk?
我有一个 Gradle 项目。在我的源代码中,我有一些注释(除其他外)采用相同的字符串。然而,这个相同的字符串存在于一个配置文件中,我只想引用那个文件,所以我只需要在一个地方更改这个字符串以更改它的所有实例。因此,我必须从文件中读取字符串,这意味着该字符串不是编译时常量。因此我不能使用从文件中读取的字符串作为注释参数。
// I have this.
@Annotation("some_string")
Object a;
@Annotation("some_string")
Object b;
// This doesn't work
String ss = // read a file, fetch the string from the file.
@Annotation(ss)
Object a;
@Annotation(ss)
Object b;
我想知道 Gradle 中是否有一种方法可以在编译之前修改源代码,使我可以用一个变量控制所有注释参数。
即,在源代码中我可以 @Annotation("%%some_string%%")
并将所有出现的 %%some_string%%
替换为 Gradle 任务中的变量。用
之类的东西简单地修改每个源文件就足够容易了
def annotation_variable = // read a file, fetch the string from the file.
for ( f in srcFileTree ) {
def text = file(f).text
file(f).text = text.replaceAll("%%some_string%%", annotation_variable)
}
但是,这将永久修改源文件。所以,我正在寻找一种方法来修改管道中的文件,而不实际修改磁盘上的文件。有办法吗?
您可以修改输出文件而不是源文件。 War 任务和 replaceTokens 过滤器示例(使用您最喜欢的任务和过滤器):
tasks.withType(War) { warTask ->
...
from('src/main/java/YOUR_PACKAGE') {
include YOUR_FILE(s)
filter ReplaceTokens, beginToken: '@', endToken: '@', tokens: [
'YOUR_TOKEN_NAME': YOUR_VALUE
]
}
}
将您的 java 模板放在与正常 java 来源不同的目录中(例如 src/template/java
)。这将减少 Gradle 所需的 "work",也意味着您的 IDE 不会尝试编译模板。
然后添加一个任务来替换模板中的标记并将它们复制到 $buildDir
下的目录(因此它们通过 "clean" 删除并且也从未提交到 git)
task generateJava(type: Copy) {
from 'src/template/java'
into "$buildDir/generated/java"
filter(ReplaceTokens, tokens: [someToken: 'someReplacement'])
}
现在将生成的目录添加到 "main" java sourceSet 并将任务连接到 DAG
sourceSets.main.java.srcDir "$buildDir/generated/java"
compileJava.dependsOn 'generateJava'
假设您的 IDE 具有 Gradle 集成,您的 IDE 现在也应该编译生成的源代码
请参阅 working with files 文档中的 "Filtering files as they are copied"
我有一个 Gradle 项目。在我的源代码中,我有一些注释(除其他外)采用相同的字符串。然而,这个相同的字符串存在于一个配置文件中,我只想引用那个文件,所以我只需要在一个地方更改这个字符串以更改它的所有实例。因此,我必须从文件中读取字符串,这意味着该字符串不是编译时常量。因此我不能使用从文件中读取的字符串作为注释参数。
// I have this.
@Annotation("some_string")
Object a;
@Annotation("some_string")
Object b;
// This doesn't work
String ss = // read a file, fetch the string from the file.
@Annotation(ss)
Object a;
@Annotation(ss)
Object b;
我想知道 Gradle 中是否有一种方法可以在编译之前修改源代码,使我可以用一个变量控制所有注释参数。
即,在源代码中我可以 @Annotation("%%some_string%%")
并将所有出现的 %%some_string%%
替换为 Gradle 任务中的变量。用
def annotation_variable = // read a file, fetch the string from the file.
for ( f in srcFileTree ) {
def text = file(f).text
file(f).text = text.replaceAll("%%some_string%%", annotation_variable)
}
但是,这将永久修改源文件。所以,我正在寻找一种方法来修改管道中的文件,而不实际修改磁盘上的文件。有办法吗?
您可以修改输出文件而不是源文件。 War 任务和 replaceTokens 过滤器示例(使用您最喜欢的任务和过滤器):
tasks.withType(War) { warTask ->
...
from('src/main/java/YOUR_PACKAGE') {
include YOUR_FILE(s)
filter ReplaceTokens, beginToken: '@', endToken: '@', tokens: [
'YOUR_TOKEN_NAME': YOUR_VALUE
]
}
}
将您的 java 模板放在与正常 java 来源不同的目录中(例如 src/template/java
)。这将减少 Gradle 所需的 "work",也意味着您的 IDE 不会尝试编译模板。
然后添加一个任务来替换模板中的标记并将它们复制到 $buildDir
下的目录(因此它们通过 "clean" 删除并且也从未提交到 git)
task generateJava(type: Copy) {
from 'src/template/java'
into "$buildDir/generated/java"
filter(ReplaceTokens, tokens: [someToken: 'someReplacement'])
}
现在将生成的目录添加到 "main" java sourceSet 并将任务连接到 DAG
sourceSets.main.java.srcDir "$buildDir/generated/java"
compileJava.dependsOn 'generateJava'
假设您的 IDE 具有 Gradle 集成,您的 IDE 现在也应该编译生成的源代码
请参阅 working with files 文档中的 "Filtering files as they are copied"