如何在build.gradle中定义和调用自定义方法


Answers:


106

下面给出一种方法:

ext.myMethod = { param1, param2 ->
    // Method body here
}

注意,这是为项目范围创建的,即。全局可用于该项目,可以在构建脚本中的任何位置按以下方式调用,使用myMethod(p1, p2)等效于project.myMethod(p1, p2)

该方法也可以在不同范围内定义,例如在任务内:

task myTask {
    ext.myMethod = { param1, param2 ->
        // Method body here
    }

    doLast {
        myMethod(p1, p2) // This will resolve 'myMethod' defined in task
    }
}

另一个疑问。我可以在任务本地标记一个方法吗?ext.myMethod将其标记为全局。
Tomin 2015年

3
当我们使用时ext,作用域仅限于定义它的地方。如果是在任务下定义的,则它是任务本地的。它的工作方式是通过实现ExtensionAware的实体(如项目,任务等)进行。这将添加一个通过指令配置的ExtraPropertiesExtensionext
看不见的箭

因此,这意味着我可以在不同任务中使用相同的方法名称而不会发生任何冲突。即 ext.myMethod在两个或多个任务中应该可以工作。
托明2015年

1
从子项目访问时,可以作为rootProject.ext.myMethod(p1,p2)访问
Philippe

30

如果您在任何其他文件* .gradle中定义了任何方法,则ext.method()使其可在整个项目范围内访问。例如,这是一个

versioning.gradle

// ext makes method callable project wide
ext.getVersionName = { ->
    try {
        def branchout = new ByteArrayOutputStream()
        exec {
            commandLine 'git', 'rev-parse', '--abbrev-ref', 'HEAD'
            standardOutput = branchout
        }
        def branch = branchout.toString().trim()

        if (branch.equals("master")) {
            def stdout = new ByteArrayOutputStream()
            exec {
                commandLine 'git', 'describe', '--tags'
                standardOutput = stdout
            }
            return stdout.toString().trim()
        } else {
            return branch;
        }
    }
    catch (ignored) {
        return null;
    }
}

build.gradle

task showVersion << {
    // Use inherited method
    println 'VersionName: ' + getVersionName()
}

如果没有ext.method()格式,则该方法仅在声明的* .gradle文件中可用。属性也是一样。


26

您可以通过以下方式定义方法:

// Define an extra property
ext.srcDirName = 'src/java'

// Define a method
def getSrcDir(project) {
    return project.file(srcDirName)
}

您可以在gradle文档第62章中找到更多详细信息。组织构建逻辑


1
我尝试了这个,但是我正在创建的方法在我正在运行的每个任务上都执行,例如,在尝试运行./gradlew clean时-我看到该方法正在执行,这不是我想要的-您知道可能会发生什么是问题吗?
user1002065

@ user1002065很难告诉您,而无需查看您的设置,如果您可以分享(即要点),那么我可以尝试提供帮助
Ivan Marinov

11

具有包含方法的根对象的示例。

hg.gradle文件:

ext.hg = [

    cloneOrPull: { source, dest, branch ->
        if (!dest.isDirectory())
            hg.clone(source, dest, branch)
        else
            hg.pull(dest)
        hg.update(dest, branch)
    },

    clone: { source, dest, branch ->
        dest.mkdirs()
        exec {
            commandLine 'hg', 'clone', '--noupdate', source, dest.absolutePath
        }
    },

    pull: { dest ->
        exec {
            workingDir dest.absolutePath
            commandLine 'hg', 'pull'
        }
    },

]

build.gradle文件

apply from: 'hg.gradle'

hg.clone('path/to/repo')

3

不知何故,也许是因为距OP已有5年了,但没有

ext.someMethod = { foo ->
   methodBody
}

方法对我有用。相反,一个简单的函数定义似乎可以在我的gradle文件中完成工作:

def retrieveEnvvar(String envvar_name) {
    if ( System.getenv(envvar_name) == "" ) {
        throw new InvalidUserDataException("\n\n\nPlease specify environment variable ${envvar_name}\n")
    } else {
        return System.getenv(envvar_name)
    }       
}

我在脚本的其他地方调用它,没有前缀,即 retrieveEnvvar("APP_PASSWORD")

这是2020年,所以我正在使用Gradle 6.1.1。


我也在gradle 6.1.1上,例如ex.someMethod = {}可以正常工作。只是我在调用lambda时无法使用参数名称。
rpattabi

0

@ether_joe上面@InvisibleArrow投票最多的答案确实有效,但是您必须在调用之前定义调用的方法-即build.gradle文件中的较早位置。

您可以在此处查看示例。我在Gradle 6.5中使用了这种方法,并且可以正常工作。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.