我必须编写一个插件来编译现有插件未涵盖的某种类型的文件。
我的最初要求仅仅是,如果输入文件被更改或输出丢失,那么任务将 not 是最新的。换句话说,我希望核心的“使用文件”范式对我有用。
我的第一个尝试是同时声明inputs
和outputs
,以查看该项目是否能够像大多数人期望的那样工作。
class TestPlugin implements Plugin<Project> {
void apply (Project project) {
project.task('compile') {
doFirst {
inputs.files.eachWithIndex { inFilename, idx ->
def inFile = project.file(inFilename)
def outFilename = outputs.files[idx]
def outFile = project.file(outFilename)
logger.info "converting ${inFile} to ${outFile}"
outFile.append "something"
}
}
}
}
}
apply plugin: TestPlugin
compile {
inputs.file "test.in"
outputs.file "test.out"
}
确实如此。至此,除了一件事情外,它已完成了我所需要的一切:我必须与outputs
相关地定义inputs
。但是定义输出非常复杂,足以保证将部分代码纳入插件的任务中。
我的下一个尝试是尝试获取定义其outputs
的任务,但是它失败了,因为执行“填充输出”代码时,inputs
为空,因此没有outputs
是添加。
class TestPlugin implements Plugin<Project> {
void apply (Project project) {
project.task('compile') {
inputs.files.each { outputs.files.add(it.replaceFirst(~/\.in$/, '.out')) }
doFirst {
inputs.files.eachWithIndex { inFilename, idx ->
def inFile = project.file(inFilename)
def outFilename = outputs.files[idx]
def outFile = project.file(outFilename)
logger.info "converting ${inFile} to ${outFile}"
outFile.append "something"
}
}
}
}
}
apply plugin: TestPlugin
compile { inputs.file "test.in" }
以上操作失败,并由于索引空的outputs
列表而导致错误“路径可能不为空...”(因为在任务的外部块遍历{{时,inputs
为空1}}。
我尝试在Project.afterEvaluate和Project.beforeEvaluate中填充inputs
,但是都没有用。 beforeEvaluate关闭从未执行。好吧,在评估项目之后,执行了afterEvaluate闭包,这意味着它是在将任务设置为最新或过期之后执行的,因此对我的需求没有用。
我也尝试了outputs
,但是那也不起作用。
然后我发现了lazy configuration,但是由于它正在孵化,我认为我应该避免使用它。我假设Java和C插件不使用孵化功能,这使我想知道这些插件如何实现与懒惰配置等效的功能。
然后我发现了Gradle plugin for custom language,但没有答案。但是,确实有一条注释使我着眼于gradle源代码的很多。再说一次,我认为我不必重新发明轮子。
最后,如果我不得不做出将其编译为Project.configure
的决定,而不必费心声明输出(从而放弃任务的最新性),那就也可以了。我只需要知道并继续前进即可。
有关更多信息,我正在从doFirst
迁移构建。我参加的两个udemy.com课程对我有很大帮助,但走得不够远,不足以使我有信心去解决所提出的问题。我向一位教师及其社区提出了类似的问题,但无济于事。