Gradle 6: Verbesserte Abhängigkeitsverwaltung

Diesen Monat wurde Gradle 6 veröffentlicht, und es stellt sich die übliche Frage, was gibt es Neues?

Eines der größeren Ziele von Gradle 6 ist es, den Umgang mit großen und komplexen Abhängigkeiten zu verbessern. Dies soll einige übliche Probleme reduzieren:

  • Eine Abhängigkeit wird in zwei verschiedenen Versionen, welche nicht kompatibel sind, angefordert.
  • Mehrere Abhängigkeiten bieten dasselbe Feature an (z. B. Logback und Log4J)
  • Inkompatible Runtimes (z. B. Update von Groovy über eine Abhängigkeit verursacht Fehler in älterem Groovy-Code)

In den einfacheren Fällen sind diese Fehler noch recht gut erkennbar, da direkt zur Compilezeit Fehler auftreten, jedoch ist dies nur bei einer relativ kleinen Menge aller Fehlerquellen der Fall.

Als Lösungsansatz führt Gradle 6 das Konzept von Module Metadata ein, welches Probleme durch zu ungenaue Abhängigkeiten reduzieren soll. Dieses Feature ermöglicht es, deutlich mehr Informationen zu den notwendigen und optionalen Abhängigkeiten anzugeben. Hierdurch ist es möglich, automatisch eine Version der Abhängigkeit zu wählen, mit der alle Bedingungen eingehalten werden. Hier eine grobe Übersicht über die Möglichkeiten:

KeywordBedeutung
require(“1.5”)Mindestens Version 1.5 wird benötigt, neuere Versionen dürfen ohne Einschränkungen verwendet werden
require(“[1.0, 2.0[“)Version zwischen 1.0 und 2.0 (exklusive) sollte verwendet werden, Upgrade auf Versionen über 2.0 sind gestattet
strictly(“1.0, 2.0[“)Version zwischen 1.0 und 2.0 (exklusive) muss verwendet werden, transitive Abhängigkeiten werden überschrieben
reject(“1.4”)Version 1.4 darf nicht verwendet werden (z. B. wegen einem bekannten Bug oder Sicherheitsproblem)
prefer(“1.5”)Version 1.5 wird bevorzugt, wenn möglich, keinerlei weitere Einschränkungen
prefer(“latest.release”)Die aktuellste Version zur Build-Zeit wird bevorzugt, keinerlei weitere Einschränkungen
strictly(“1.5”)Version 1.5 muss benutzt werden
strictly(“[1.5,1.6[“)Der aktuellste Patch von 1.5.x  wird verwendet

Verwenden kann man diese Einschränkungen jetzt in der Definition von Abhängigkeiten im Build-Skript:

dependencies {
    implementation("org.sample:sample") {
        version {
            strictly("[1.0, 2.0[")
            prefer("1.5")
            reject("1.6")
        }
    }
}

Zum Beispiel wird mit der obigen Definition ausgedrückt, dass Version 1.5 verwendet werden soll, wenn die genaue Version nicht an einer anderen Stelle im Build überschrieben wird. Versionen zwischen 1.0 (inklusive) und 2.0 (exklusive) sind erlaubt. Version 1.6 darf nicht verwendet werden.

Dies ermöglicht es, einen Build fehlschlagen zu lassen, wenn eine andere Abhängigkeit eine Version 2.0+ anfordert, oder exakt die Version 1.6 verwenden will. Existiert jetzt noch eine Abhängigkeit mit

dependencies {
    implementation("org.sample:sample") {
        version {
            strictly("[1.7, 2.6]")
            prefer("2.1")
        }
    }
}

… kann Gradle feststellen, dass Versionen von 1.7 bis 2.0 (exklusive) eine gültige Lösung darstellen, da hiermit alle strict und reject-Regeln eingehalten werden. Da dieses mehrere Lösungen hat, die von zum Bauzeitpunkt verfügbaren Abhängigkeiten beeinflusst werden, empfiehlt es sich, wie auch zuvor ein Locking der Versionen zu betreiben. Hierbei wird dokumentiert, welche genauen Versionen verwendet wurden. Somit wird zu einem späteren Zeitpunkt die Erstellung eines identischen Builds ermöglicht. Dies ist hilfreich, um z. B. einen Fehler, der nur in bestimmten Versionen auftritt, nachzustellen.

Wie bislang ist es möglich, die Abhängigkeiten ohne Version zu definieren, um diese dann zentral innerhalb des Builds zu pflegen. Dies ist gerade bei MultiModule-Builds deutlich übersichtlicher, wie folgendes Beispiel am Ende zeigt:

//Innerhalb der Module
dependencies {
    implementation 'org.springframework:spring-web'
}

//Im Root-Projekt von Gradle
dependencies {
    constraints {
        implementation('org.springframework:spring-web') {
            version {
                prefer '4.2.9.RELEASE'
                reject '4.3.16.RELEASE'
            }
        }
    }
}

Short URL for this post: https://wp.me/p4nxik-3yO
This entry was posted in Build, config and deploy. Bookmark the permalink.

Leave a Reply