Як визначити та викликати власні методи в build.gradle


79

Як частина мого проекту, мені потрібно читати файли з каталогу та виконувати деякі операції у сценарії збірки. Для кожного файлу операція однакова (читання деяких запитів sql та його виконання). Я думаю, це повторюване завдання, і краще писати всередині методу. Оскільки я новачок у градації, я не знаю, як це повинно бути. Будь ласка, допоможіть.


Відповіді:


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 у двох або більше завданнях повинен працювати.
Томін

1
При доступі з підпроекту можна отримати доступ як rootProject.ext.myMethod (p1, p2)
Філіпп

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

Якось, можливо, тому, що минуло п’ять років з часу проведення ОП, але жодного з них

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, напр. SomeMethod = {} чудово працює. Тільки те, що я не міг використовувати імена параметрів під час виклику лямбди.
rpattabi

0

@ether_joe зверху проголосували відповідь на @InvisibleArrow вище робить роботу , однак ви повинні визначити метод ви називаєте , перш ніж ви це називаєте - тобто на початку build.gradleфайлу.

Ви можете побачити приклад тут . Я використав цей підхід з Gradle 6.5, і він працює.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.