Gradle 빌드 스크립트에서 일반적인 메서드 추출


86

build.gradle몇 가지 작업을 만든 Gradle 빌드 스크립트 ( )가 있습니다. 이러한 작업은 대부분 메서드 호출로 구성됩니다. 호출 된 메서드는 빌드 스크립트에도 있습니다.

이제 상황은 다음과 같습니다.

나는 다른 작업을 포함하지만 원본 스크립트와 동일한 방법을 사용하는 상당한 양의 빌드 스크립트를 만들고 있습니다. 따라서 이러한 "일반적인 방법"을 어떤 식 으로든 추출하여 새로 만드는 스크립트마다 복사하는 대신 쉽게 재사용 할 수 있습니다.

Gradle이 PHP라면 다음과 같은 것이 이상적입니다.

//script content
...
require("common-methods.gradle");
...
//more script content

하지만 물론 불가능합니다. 아니면?

어쨌든이 결과를 어떻게 얻을 수 있습니까? 이를 수행하는 가장 좋은 방법은 무엇입니까? 이미 Gradle 문서를 읽었지만 어떤 방법이 가장 쉽고 가장 적합한 지 결정할 수없는 것 같습니다.

미리 감사드립니다!


최신 정보:

다른 파일에서 메서드를 추출했습니다.

(사용 apply from: 'common-methods.gradle'),

따라서 구조는 다음과 같습니다.

parent/
      /build.gradle              // The original build script
      /common-methods.gradle     // The extracted methods
      /gradle.properties         // Properties used by the build script

에서 작업을 실행 한 후 build.gradle새로운 문제에 부딪 혔습니다. 분명히 메서드가 .NET에있을 때 인식되지 않습니다 common-methods.gradle.

그것을 고치는 방법에 대한 아이디어가 있습니까?


메서드를 작성해야하나요? 메서드 측면에서 빌드 스크립트를 작성하면 Gradle의 장점 중 일부를 놓칠 수 있습니다. 가장 중요한 점은 증분 빌드가 올바르게 작동하려면 추가 작업이 필요하다는 것입니다. 의도 된 추상화는 Task 를 사용하고 재사용하는 것 입니다. 사용자 정의 작업을 생성 할 수도 있습니다 . 아마도 현재 메서드에있는 구현을 작업에 넣는 것을 고려해야합니다.
Alpar

@Alpar 및 기타 ; a timestamp()또는 currentWorkingDirectory()메소드와 같은 것을 task-s (예 :) 로 만드는 목적은 무엇입니까 ? 유틸리티 함수 및 이와 유사한 것은 명목상 스칼라입니다. Gradle 및 대부분의 빌드 시스템에 내장 된 코드 재사용에 대한 제한이 있다는 점을 제외하고는 작업이 아닙니다. 한 번만 만들어 재사용 할 수있는 DRY 세상을 좋아합니다 . 사실, @Pieter VDE의 예를 확장 나는 또한 "를 사용하여 root.gradle내 부모 프로젝트 '패턴 - build.gradle 파일은 일반적으로 어떤 프로젝트의 세부 사항을 정의하고 단지 apply ${ROOT}...
것이다

속성 작업을위한 중앙 집중식 방법이 필요한 경우이 질문이 도움이 될 수 있습니다. stackoverflow.com/questions/60251228/…
GarouDan

답변:


76

메서드를 공유하는 것은 불가능하지만 클로저를 포함하는 추가 속성을 공유 할 수 있습니다. 예를 들어, 선언 ext.foo = { ... }common-methods.gradle사용 apply from:스크립트를 적용하고 다음에 폐쇄를 호출 foo().


1
참으로 트릭입니다! 그러나 이것에 대해 질문이 있습니다. 메소드가 무언가를 반환하는 것은 어떻습니까? Fe File foo(String f)가 될 것입니다. ext.foo = { f -> ... }그러면 다음과 같이 할 수 File f = foo(...)있습니까?
Pieter VDE 2013 년

2
분명히 이전 의견의 질문이 가능합니다. 이 질문에 답 해주신 Peter에게 감사드립니다!
피터 VDE

1
@PeterNiederwieser 왜 가능하지 않습니까? Gradle.org 그렇지 않으면 생각 : docs.gradle.org/current/userguide/...
IgorGanapolsky

1
@IgorGanapolsky 링크 주셔서 감사합니다. gradle.build의 별도 빌드 파일에서 생성 된 값을 어떻게 사용할 수 있는지 궁금합니다.이 방법은 매우 유용합니다. :)
kiedysktos

@IgorGanapolsky Peter VDE 질문의 맥락에서 공유 한 링크는 어떻게해야합니까?
t0r0X

161

베드로의 대답을 바탕으로 과 같이 방법을 내 보냅니다.

내용 helpers/common-methods.gradle:

// Define methods as usual
def commonMethod1(param) {
    return true
}
def commonMethod2(param) {
    return true
}

// Export methods by turning them into closures
ext {
    commonMethod1 = this.&commonMethod1
    otherNameForMethod2 = this.&commonMethod2
}

그리고 이것은 다른 스크립트에서 이러한 방법을 사용하는 방법입니다.

// Use double-quotes, otherwise $ won't work
apply from: "$rootDir/helpers/common-methods.gradle"

// You can also use URLs
//apply from: "https://bitbucket.org/mb/build_scripts/raw/master/common-methods.gradle"

task myBuildTask {
    def myVar = commonMethod1("parameter1")
    otherNameForMethod2(myVar)
}

Groovy에서 메서드를 클로저로 변환하는 방법에 대한 자세한 내용다음과 같습니다 .


클로저 이름을 내선으로 사용하는 특별한 이유가 있습니까?
Anoop dec.

1
@AnoopSS Gradle의 추가 속성에 두 개의 클로저를 추가합니다 . 이러한 추가 속성은라는 개체에 번들로 제공됩니다 ext.
Matthias Braun

어떻게 든 값을 포함 된 파일에 정의 된 우리 클래스로 캐스팅 할 수 있습니까?
GarouDan

@GarouDan에 대한 예제 코드와 함께 별도의 질문을 게시하는 것이 좋습니다.
Matthias Braun

7

Kotlin dsl을 사용하면 다음 과 같이 작동합니다.

build.gradle.kts :

apply {
  from("external.gradle.kts")
}

val foo = extra["foo"] as () -> Unit
foo()

external.gradle.kts :

extra["foo"] = fun() {
  println("Hello world!")
}

1
실제 유형을 공유하는 방법이 있습니까? 기본적으로 타입 안전성을 잃어 버리고 컴파일러의 도움이됩니다. 메소드가 포함 된 클래스를 공유 할 수 있다면 컴파일러를 사용할 수 있습니다.
vach

0

Kotlin DSL의 또 다른 접근 방식은 다음과 같습니다.

my-plugin.gradle.kts

extra["sum"] = { x: Int, y: Int -> x + y }

settings.gradle.kts

@Suppress("unchecked_cast", "nothing_to_inline")
inline fun <T> uncheckedCast(target: Any?): T = target as T

apply("my-plugin.gradle.kts")

val sum = uncheckedCast<(Int, Int) -> Int>(extra["sum"])

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