Trích xuất các phương thức phổ biến từ tập lệnh xây dựng Gradle


85

Tôi có một tập lệnh xây dựng Gradle ( build.gradle), trong đó tôi đã tạo một số tác vụ. Các tác vụ này chủ yếu bao gồm các cuộc gọi phương thức. Các phương thức được gọi cũng nằm trong tập lệnh xây dựng.

Bây giờ, đây là tình huống:

Tôi đang tạo ra một lượng lớn các tập lệnh xây dựng, chứa các tác vụ khác nhau, nhưng sử dụng các phương pháp giống nhau từ tập lệnh gốc. Vì vậy, tôi muốn trích xuất các "phương thức chung" này theo một cách nào đó, để tôi có thể dễ dàng sử dụng lại chúng thay vì sao chép chúng cho mỗi tập lệnh mới mà tôi tạo.

Nếu Gradle là PHP, một cái gì đó như sau sẽ là lý tưởng:

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

Nhưng tất nhiên, điều đó là không thể. Hoặc là nó?

Dù sao, làm thế nào tôi có thể đạt được kết quả này? Phương pháp tốt nhất có thể để làm điều này là gì? Tôi đã đọc qua tài liệu Gradle rồi, nhưng dường như tôi không thể xác định phương pháp nào sẽ dễ nhất và phù hợp nhất cho việc này.

Cảm ơn trước!


CẬP NHẬT:

Tôi đã quản lý để giải nén các phương thức trong một tệp khác

(đang sử dụng apply from: 'common-methods.gradle'),

vì vậy cấu trúc như sau:

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

Sau khi thực hiện một tác vụ từ build.gradle, tôi đã gặp phải một vấn đề mới: rõ ràng, các phương thức không được nhận dạng khi chúng ở trong common-methods.gradle.

Bất kỳ ý tưởng về cách khắc phục điều đó?


Bạn có chắc chắn cần viết các phương pháp này không? Bạn sẽ bỏ lỡ một số tính năng tốt của Gradle nếu bạn viết kịch bản xây dựng của mình về mặt phương pháp, quan trọng nhất là bạn sẽ mất thêm công sức để bản dựng tăng dần hoạt động chính xác. Mục đích trừu tượng là sử dụng và sử dụng lại Task s. Bạn cũng có thể tạo các tác vụ tùy chỉnh . Có lẽ bạn nên xem xét việc đưa các triển khai mà bạn có trong các phương thức vào các nhiệm vụ.
Alpar

@Alpar và những người khác ; mục đích nào được phục vụ tạo ra một cái gì đó như a timestamp()hoặc currentWorkingDirectory()các phương thức dưới dạng task-s (ví dụ:). Các chức năng tiện ích và những thứ tương tự về danh nghĩa là vô hướng - Chúng sẽ không phải là nhiệm vụ ngoại trừ việc có những hạn chế trong việc tái sử dụng mã được tích hợp sẵn với Gradle và hầu hết các hệ thống xây dựng. Tôi thích thế giới KHÔ nơi tôi có thể tạo ra một thứ MỘT lần và sử dụng lại nó. Trên thực tế, mở rộng ví dụ của @Pieter VDE, tôi cũng sử dụng root.gradlemẫu "" cho dự án mẹ của mình - Tệp build.gradle thường xác định một số chi tiết cụ thể của dự án và sau đó chỉ apply ${ROOT}...
sẽ

Nếu bạn cần một cách tập trung để làm việc với các thuộc tính, có thể câu hỏi này có thể giúp bạn: stackoverflow.com/questions/60251228/…
GarouDan

Câu trả lời:


76

Không thể chia sẻ các phương thức, nhưng bạn có thể chia sẻ các thuộc tính bổ sung có chứa một bao đóng, tổng hợp các thuộc tính giống nhau. Ví dụ, khai báo ext.foo = { ... }trong common-methods.gradle, sử dụng apply from:để áp dụng tập lệnh, và sau đó gọi bao đóng với foo().


1
Nó thực sự lừa! Nhưng tôi có một câu hỏi về điều này: Làm thế nào về các phương thức trả về một cái gì đó? Fe File foo(String f)sẽ trở thành ext.foo = { f -> ... }, sau đó tôi có thể làm điều gì đó như File f = foo(...):?
Pieter VDE

2
Rõ ràng, câu hỏi trong bình luận trước của tôi là có thể. Vì vậy, cảm ơn bạn Peter, đã trả lời câu hỏi này!
Pieter VDE

1
@PeterNiederwieser Tại sao không thể? Gradle.org lại nghĩ khác: docs.gradle.org/current/userguide/...
IgorGanapolsky

1
@IgorGanapolsky cảm ơn vì liên kết. Tôi tự hỏi làm thế nào tôi có thể sử dụng một giá trị được tạo ra trong riêng biệt tập xây dựng trong gradle.build - cách này nó sẽ rất hữu ích :)
kiedysktos

@IgorGanapolsky Làm thế nào để liên kết bạn đã chia sẻ trợ giúp trong bối cảnh câu hỏi Peter VDEs?
t0r0X

157

Dựa trên câu trả lời của Peter , đây là cách tôi xuất các phương pháp của mình:

Nội dung của 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
}

Và đây là cách tôi sử dụng các phương pháp đó trong một tập lệnh khác:

// 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)
}

Dưới đây là thông tin thêm về chuyển đổi phương thức thành bao đóng trong Groovy.


có bất kỳ lý do cụ thể nào để sử dụng tên đóng làm máy lẻ không?
Anoop

1
@AnoopSS Chúng tôi thêm hai đóng vào các thuộc tính bổ sung của Gradle . Các thuộc tính bổ sung này được đóng gói trong một đối tượng được gọi ext.
Matthias Braun

Bằng cách nào đó, chúng ta có thể truyền giá trị dưới dạng một lớp của chúng ta, được định nghĩa trong tệp bao gồm không?
GarouDan

Có lẽ bạn nên đăng một câu hỏi riêng với mã ví dụ về điều này, @GarouDan.
Matthias Braun

7

Sử dụng dsl Kotlin nó hoạt động như thế này:

build.gradle.kts :

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

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

external.gradle.kts :

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

tuyệt vời có cách nào để chia sẻ kiểu actuall không? về cơ bản, bạn đang mất an toàn kiểu và trợ giúp của trình biên dịch ... nếu bạn có thể chia sẻ lớp chứa các phương thức của mình thì bạn có thể sử dụng trình biên dịch.
vach

0

Một cách tiếp cận khác cho Kotlin DSL có thể là:

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))
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.