build.gradle에서 사용자 지정 메서드를 정의하고 호출하는 방법


79

내 프로젝트의 일부로 디렉토리에서 파일을 읽고 빌드 스크립트에서이 모든 작업을 수행해야합니다. 각 파일에 대해 작업은 동일합니다 (일부 SQL 쿼리를 읽고 실행). 반복적 인 작업이고 메서드 내부에 작성하는 것이 좋습니다. 나는 gradle을 처음 사용하기 때문에 그것이 어떻게되어야하는지 모르겠습니다. 도와주세요.


답변:


109

다음은 한 가지 접근 방식입니다.

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는이를 글로벌로 표시합니다.
도민

3
를 사용할 때 ext범위는 정의 된 위치로 제한됩니다. 작업 아래에 정의 된 경우 작업에 로컬입니다. 작동 방식은 ExtensionAware 를 구현하는 엔터티 (프로젝트, 작업 등)를 통하는 것 입니다. 이렇게 하면 지시문을 통해 구성된 ExtraPropertiesExtension 이 추가 ext됩니다.
Invisible Arrow

따라서 충돌없이 다른 작업에서 동일한 메서드 이름을 사용할 수 있습니다. 즉; 두 개 이상의 작업에서 ext.myMethod가 작동해야합니다.
Tomin 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 파일 내에서만 사용할 수 있습니다. 이것은 속성과 동일합니다.


27

다음과 같은 방법으로 메소드를 정의 할 수 있습니다.

// 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 당신이 (요지로 예) 주를 기쁘게 할 수 있다면 그때 도움말을 시도 할 수, 당신의 설정을 보지 않고 말할 하드
이반 마리 놉

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 = {}가 잘 작동합니다. 람다를 호출하는 동안 매개 변수 이름을 사용할 수 없다는 것입니다.
rpattabi

0

@ether_joe 위의 @InvisibleArrow가 가장 많이 뽑은 답변 작동하지만 호출 하기 전에 호출하는 메서드를 정의해야합니다 ( 예 : build.gradle파일의 앞부분) .

여기 에서 예를 볼 수 있습니다 . 이 접근 방식을 Gradle 6.5와 함께 사용했으며 작동합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.