So definieren und rufen Sie benutzerdefinierte Methoden in build.gradle auf

79

Als Teil meines Projekts muss ich Dateien aus einem Verzeichnis lesen und einige dieser Vorgänge im Build-Skript ausführen. Für jede Datei ist der Vorgang derselbe (einige SQL-Abfragen lesen und ausführen). Ich denke, es ist eine sich wiederholende Aufgabe und besser, innerhalb einer Methode zu schreiben. Da ich neu im Gradle bin, weiß ich nicht, wie es sein soll. Bitte helfen Sie.

Tomin
quelle

Antworten:

106

Ein Ansatz unten angegeben:

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

Beachten Sie, dass dies für den Projektbereich erstellt wird, d. H. global für das Projekt zur Verfügung, die aufgerufen werden kann , wie überall in dem Build - Skript folgt mit myMethod(p1, p2)dem entsprichtproject.myMethod(p1, p2)

Die Methode kann auch in verschiedenen Bereichen definiert werden, z. B. innerhalb von Aufgaben:

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

    doLast {
        myMethod(p1, p2) // This will resolve 'myMethod' defined in task
    }
}
Unsichtbarer Pfeil
quelle
Noch ein Zweifel. Kann ich eine lokale Methode für die Aufgabe markieren? ext.myMethod markiert es als global.
Tomin
3
Wenn wir verwenden ext, ist der Bereich auf den definierten Bereich beschränkt, d. H. Wenn es unter einer Aufgabe definiert ist, ist es lokal für die Aufgabe. Die Funktionsweise erfolgt über Entitäten (wie Projekte, Aufgaben usw.), die ExtensionAware implementieren . Dadurch wird eine ExtraPropertiesExtension hinzugefügt, die über die extDirektive konfiguriert wird .
Unsichtbarer Pfeil
Das bedeutet, dass ich denselben Methodennamen ohne Konflikte in verschiedenen Aufgaben verwenden kann. dh; ext.myMethod in zwei oder mehr Aufgaben sollte funktionieren.
Tomin
1
Beim Zugriff von einem Unterprojekt aus kann als rootProject.ext.myMethod (p1, p2)
Philippe
30

Wenn Sie Methoden in einer anderen Datei definiert haben * .gradle - ext.method () macht sie projektweit zugänglich. Zum Beispiel ist hier ein

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

Ohne das Format ext.method () ist die Methode nur in der deklarierten * .gradle-Datei verfügbar. Dies gilt auch für Eigenschaften.

Rowland Mtetezi
quelle
26

Sie können Methoden folgendermaßen definieren:

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

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

Weitere Informationen finden Sie in der Gradle-Dokumentation in Kapitel 62. Organisieren der Build-Logik

Ivan Marinov
quelle
1
Ich habe dies versucht, aber die Methode, die ich erstelle, wird für jede von mir ausgeführte Aufgabe ausgeführt, z. B. beim Versuch, ./gradlew clean auszuführen. Ich sehe, dass die Methode ausgeführt wird und dies nicht das ist, was ich möchte. Wissen Sie, was möglicherweise der Fall ist? das Problem sein?
user1002065
@ user1002065 schwer zu sagen, ohne Ihr Setup zu sehen, wenn Sie bitte teilen könnten (dh als Kern), dann könnte ich versuchen zu helfen
Ivan Marinov
11

Ein Beispiel mit einem Stammobjekt, das Methoden enthält.

hg.gradle Datei:

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-Datei

apply from: 'hg.gradle'

hg.clone('path/to/repo')
Kevin Struillou
quelle
3

Irgendwie, vielleicht weil es fünf Jahre her ist, seit dem OP, aber keiner von den

ext.someMethod = { foo ->
   methodBody
}

Ansätze arbeiten für mich. Stattdessen scheint eine einfache Funktionsdefinition die Aufgabe in meiner Gradle-Datei zu erledigen:

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

Und ich nenne es an anderer Stelle in meinem Skript ohne Präfix, dh retrieveEnvvar("APP_PASSWORD")

Dies ist 2020, also verwende ich Gradle 6.1.1.

ether_joe
quelle
Ich bin auch auf Gradle 6.1.1, ex.someMethod = {} funktioniert gut. Nur dass ich beim Aufrufen des Lambda keine Parameternamen verwenden konnte.
rpattabi
0

@ether_joe Die Antwort von @InvisibleArrow oben funktioniert am besten. Sie müssen jedoch die Methode definieren, die Sie aufrufen, bevor Sie sie aufrufen - dh früher in der build.gradleDatei.

Sie können ein Beispiel siehe hier . Ich habe diesen Ansatz mit Gradle 6.5 verwendet und es funktioniert.

Marrakuen
quelle