gradle 脚本,直接 dsl 和通过自定义函数“apply from:”调用有什么区别?
gradle script, What’s difference between direct dsl and called by a custom function of “apply from:”
首先,私有maven repo中部署了一些常用脚本:
http://domain/repo/com/d/build/script/java-project/1.0/java-project-1.0.gradle
http://domain/repo/com/d/build/script/maven/1.0/maven-1.0.gradle
在目标项目中,build.gradle
subprojects {
apply from: 'http://domain/repo/com/d/build/script/java-project/1.0/java-project-1.0.gradle'
apply from: 'http://domain/repo/com/d/build/script/maven/1.0/maven-1.0.gradle'
}
还可以!
但是,
ext.applyScript = { script, version ->
apply from: "http://domain/repo/com/d/build/script/${script}/${version}/${script}-${version}.gradle"
}
subprojects {
applyScript('java-project', '1.0')
applyScript('maven', '1.0')
}
它将失败,消息:
"Error:Cannot add task ':javadocJar' as a task with that name already exists."
任务“:javadocJar”在脚本中定义 'java-project-1.0.gradle'
我们有几个子项目。
为什么?
顺便说一句:谁能告诉我 "apply from:" 的源位置?
自己很难定位。
问题是,在 latte 的情况下,您将脚本多次应用到同一个根项目。
这怎么可能?这很有趣,也有点棘手:
- 您正在将
applyScript
定义为当前 Gradle 项目的扩展容器 ext
上的闭包,
- 通常,
apply from: ...
作为 org.gradle.api.plugins.PluginAware
接口上的方法调用 apply(Map)
处理,该接口是 org.gradle.api.Project
接口的超级接口之一
- 这意味着每次您编写
apply ...
时,您都会在当前 Gradle 项目(指定 apply ...
的项目)上调用 apply
方法
- 因为您将
apply ...
定义为闭包的一部分,所以标准委托适用
- 它在语义上与
this.apply ...
相同
this
默认指向封闭的 class/object 这是根项目(这里不能是其他任何东西)
因此,即使看起来您正在将 2 个脚本应用到所有子项目,但实际上您将这 2 个脚本应用 N 次到根项目(N 是子项目的数量)。
您需要做的是将委托更改为正确的 Project
实例。:
您可以通过向闭包添加一个额外的参数并显式调用该参数的 apply 方法来非常轻松地做到这一点:
ext.applyScript = { project, script, version ->
project.apply from: "..."
}
subprojects {
applyScript(it, 'java-project', '1.0')
applyScript(it, 'maven', '1.0')
}
或者您可以显式设置委托:
ext.applyScript = { script, version ->
apply from: "..."
}
subprojects {
applyScript.resolveStrategy = Closure.DELEGATE_FIRST
applyScript.delegate = it
applyScript('java-project', '1.0')
applyScript('maven', '1.0')
}
首先,私有maven repo中部署了一些常用脚本:
http://domain/repo/com/d/build/script/java-project/1.0/java-project-1.0.gradle
http://domain/repo/com/d/build/script/maven/1.0/maven-1.0.gradle
在目标项目中,build.gradle
subprojects {
apply from: 'http://domain/repo/com/d/build/script/java-project/1.0/java-project-1.0.gradle'
apply from: 'http://domain/repo/com/d/build/script/maven/1.0/maven-1.0.gradle'
}
还可以!
但是,
ext.applyScript = { script, version ->
apply from: "http://domain/repo/com/d/build/script/${script}/${version}/${script}-${version}.gradle"
}
subprojects {
applyScript('java-project', '1.0')
applyScript('maven', '1.0')
}
它将失败,消息:
"Error:Cannot add task ':javadocJar' as a task with that name already exists."
任务“:javadocJar”在脚本中定义 'java-project-1.0.gradle' 我们有几个子项目。
为什么?
顺便说一句:谁能告诉我 "apply from:" 的源位置?
自己很难定位。
问题是,在 latte 的情况下,您将脚本多次应用到同一个根项目。
这怎么可能?这很有趣,也有点棘手:
- 您正在将
applyScript
定义为当前 Gradle 项目的扩展容器ext
上的闭包, - 通常,
apply from: ...
作为org.gradle.api.plugins.PluginAware
接口上的方法调用apply(Map)
处理,该接口是org.gradle.api.Project
接口的超级接口之一- 这意味着每次您编写
apply ...
时,您都会在当前 Gradle 项目(指定apply ...
的项目)上调用apply
方法
- 这意味着每次您编写
- 因为您将
apply ...
定义为闭包的一部分,所以标准委托适用- 它在语义上与
this.apply ...
相同
this
默认指向封闭的 class/object 这是根项目(这里不能是其他任何东西)
- 它在语义上与
因此,即使看起来您正在将 2 个脚本应用到所有子项目,但实际上您将这 2 个脚本应用 N 次到根项目(N 是子项目的数量)。
您需要做的是将委托更改为正确的 Project
实例。:
您可以通过向闭包添加一个额外的参数并显式调用该参数的 apply 方法来非常轻松地做到这一点:
ext.applyScript = { project, script, version -> project.apply from: "..." } subprojects { applyScript(it, 'java-project', '1.0') applyScript(it, 'maven', '1.0') }
或者您可以显式设置委托:
ext.applyScript = { script, version -> apply from: "..." } subprojects { applyScript.resolveStrategy = Closure.DELEGATE_FIRST applyScript.delegate = it applyScript('java-project', '1.0') applyScript('maven', '1.0') }