如何找到当前Gradle脚本的路径?

14

我们在一个中心点使用一些基于Gradle的脚本。这些脚本是通过"apply from:"从大量脚本中包含的。这些基础脚本需要访问相对于脚本的文件。如何找到基础脚本的位置?

一个 build.gradle 的示例:

apply from: "../../gradlebase/base1.gradle"

base1.gradle的示例

println getScriptLocation()

5
你需要获取base1.gradlebase1.gradle中的完整路径吗?你可以直接从buildscript.sourceFile获取。或者你需要调用脚本使用的相对路径?如果你知道调用方是一个build.gradle文件,你可以从buildFile获取。请问能否在你的问题中添加样例输出? - Aarjav
是的,这就是正确答案。 - Horcrux7
还有在这个问题/答案中:https://dev59.com/MH_aa4cB1Zd3GeqP3XV0#41446643 - djKianoosh
8个回答

11

我不确定这是否属于内部接口,但是DefaultScriptHandler有一个getSourceFile()方法,而当前实例可以通过buildscript属性访问,因此您可以使用buildscript.sourceFile。它是指向当前脚本的File实例。


它在API中,网址为https://docs.gradle.org/current/javadoc/org/gradle/api/initialization/dsl/ScriptHandler.html#getSourceFile-- ,因此我认为可以安全依赖它。 - Adrian Baker

5
我不确定我是否理解了问题,但是您可以使用以下代码找到当前gradle脚本的路径:
println project.buildscript.sourceFile

它提供了当前运行的脚本的完整路径。这是您正在寻找的吗?


1
这将返回项目构建脚本的位置。在build.gradle示例中也可以在base1.gradle中调用它。但我需要base1.gradle的位置。这也是预期的。它是项目的构建脚本,而不是当前脚本。 - Horcrux7
你需要在build.gradle中知道base1.gradle的位置,是吗? - Opal
不,我需要在base1.gradle中找到base1.gradle的位置。build.gradle当然知道base1.gradle的位置。请参见我的解决方法。 - Horcrux7
不好意思,这是不可能的。Gradle为每个应用的脚本设置了workingDir,等同于被调用的那个。除非你自己想出一个解决方法,否则这是不可能的。 - Opal
6
正确答案是不带“project”的。只有“buildscript.sourceFile”返回正确的路径。 - Horcrux7

2
我正在从堆栈中取出它。
buildscript {
    def root = file('.').toString();
    // We have to seek through, since groovy/gradle introduces
    // a lot of abstraction that we see in the trace as extra frames.
    // Fortunately, the first frame in the build dir is always going
    // to be this script.
    buildscript.metaClass.__script__ = file(
        Thread.currentThread().stackTrace.find { ste -> 
            ste.fileName?.startsWith root 
        }.fileName
    )

    // later, still in buildscript

    def libDir = "${buildscript.__script__.parent}/lib"


    classpath files("${libDir}/custom-plugin.jar")
}
// This is important to do if you intend to use this path outside of 
//   buildscript{}, since everything else is pretty asynchronous, and
//   they all share the buildscript object.
def __buildscripts__ = buildscript.__script__.parent;

对于不喜欢杂乱无章的人,可以使用精简版:

    String r = file('.').toString();
buildscript.metaClass.__script__ = file(Thread.currentThread().stackTrace*.fileName?.find { it.startsWith r })

我用".endsWith '.gradle'"替换了".startsWith root",然后它就可以工作了。非常酷的技巧! :-) - Horcrux7

1

我的当前解决方法是从调用脚本注入路径。这是丑陋的hack。

调用脚本必须知道基础脚本的位置。在调用之前,我将此路径保存在属性中:

ext.scriptPath = '../../gradlebase'
apply from: "${scriptPath}/base1.gradle"

在base1.gradle中,我也可以访问属性${scriptPath}。

你还有其他的解决方案吗?我可以尝试,但我感觉自己没有很好地理解这个问题。能否提供一个最小可行示例? - Opal
1
这个答案是我目前的解决方法。问题是如何检测当前脚本的位置/路径?该脚本在存储库中进行了检查,并且在任何开发人员系统上具有不同的位置。 - Horcrux7
您有任何最小工作示例吗?只是想知道您需要实现什么? - Opal
我已经添加了一个最小示例。 - Horcrux7

1

另一种解决方案是在全局gradle设置中为A.gradle的位置设置一个属性,路径为:{userhome}/.gradle/gradle.properties


如果脚本只存在一个,则这可能是一种解决方案。如果我为不同的分支多次检出工作区,则此方法将无法正常工作。 - Horcrux7

0

这个解决方案尚未使用“apply from”进行测试,但已经在settings.gradle中进行了测试。

Gradle有一个Script.file(String path)函数。我通过以下方式解决了我的问题

def outDir = file("out")
def releaseDir = new File(outDir, "release")

而“out”目录始终位于调用此行的build.gradle旁边。


是的,它与主要的build.gradle有关,而不是内联的gradle文件。 - Horcrux7
抱歉,我没有意识到你正在使用“apply from”。 - Nathan

0

你可以在相对路径中搜索这些脚本,例如:

if(new File(rootDir,'../path/A.gradle').exists ()){
    apply from: '../path/A.gradle'
}

我不理解你的回答。从你的示例中,我应该如何在脚本中找到A.gradle的路径。这是我需要加载A.gradle.properties所必需的。 - Horcrux7
你必须知道 A.gradle 的可能位置才能使用它。 - Bill Lin

0
我正在寻找Gradle Kotlin DSL文件的位置,就像我们为shell脚本做的那样。
export LNX_SPI_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接