Wie deklariere ich in Gradle gemeinsame Abhängigkeiten an einem einzigen Ort?

108

In Maven gibt es eine sehr nützliche Funktion, wenn Sie eine Abhängigkeit im <dependencyManagement>Abschnitt des übergeordneten POM definieren und auf diese Abhängigkeit von untergeordneten Modulen verweisen können, ohne die Version oder den Bereich oder was auch immer anzugeben.

Was sind die Alternativen in Gradle?

Stanislav Bashkyrtsev
quelle

Antworten:

179

Sie können allgemeine Abhängigkeiten in einem übergeordneten Skript deklarieren:

ext.libraries = [ // Groovy map literal
    spring_core: "org.springframework:spring-core:3.1",
    junit: "junit:junit:4.10"
]

In einem untergeordneten Skript können Sie dann die Abhängigkeitsdeklarationen wie folgt verwenden:

dependencies {
    compile libraries.spring_core
    testCompile libraries.junit
}

Um Abhängigkeitsdeklarationen für erweiterte Konfigurationsoptionen freizugeben, können Sie Folgendes verwenden DependencyHandler.create:

libraries = [
    spring_core: dependencies.create("org.springframework:spring-core:3.1") {
        exclude module: "commons-logging"
        force = true
    }
]

Mehrere Abhängigkeiten können unter demselben Namen gemeinsam genutzt werden:

libraries = [
    spring: [ // Groovy list literal
        "org.springframework:spring-core:3.1", 
        "org.springframework:spring-jdbc:3.1"
    ]
]

dependencies { compile libraries.spring } fügt dann beide Abhängigkeiten gleichzeitig hinzu.

Die einzige Information, die Sie auf diese Weise nicht teilen können, ist die Konfiguration ( Umfang in Maven-Begriffen), der eine Abhängigkeit zugewiesen werden soll. Aus meiner Erfahrung ist es jedoch besser, dies explizit zu erwähnen.

Peter Niederwieser
quelle
3
Vielen Dank, dies löst meine Frage, hat aber dennoch Bedenken. In Maven können wir die Version leer lassen. Wenn dies eine Bibliothek ist, ist dies praktisch, da Sie sie in unserer App verwenden und dependencyManagement durchführen können, um zu definieren, welche Version der Bibliothek vorhanden ist es sollte dauern. Wie würden Sie dasselbe mit Gradle machen?
Stanislav Bashkyrtsev
Ich verstehe die Frage nicht. Bitte geben Sie ein Beispiel.
Peter Niederwieser
4
Peter, was ctapobep sagt, ist, dass Sie in maven Abhängigkeiten mit Version (und Umfang) in einem übergeordneten (oder Aggregator-) POM im Abschnitt dependencyManagement deklarieren können. Dann müssen Sie im "konkreten" Pom die Version nicht erneut deklarieren. nur Artefakt und Gruppen-ID. Grundsätzlich sagt es maven "Ich brauche X: Y, aber benutze die Version, die der Elternteil konfiguriert hat."
Michael Campbell
2
Um diese Art der Duplizierung zu vermeiden, erstelle ich normalerweise ein separates dependencies.gradleSkript, in dem ich alle meine Abhängigkeiten als Eigenschaften definiere, z ext.GROOVY = 'org.codehaus.groovy:groovy-all:2.1.6'. In das Root-Projekt schließe build.gradleich ein allprojects { apply from: "$rootDir/dependencies.gradle" }. Dann werden alle Abhängigkeiten in einer Datei definiert, anstatt sie zu verteilen, und in den Abhängigkeitskonfigurationen werden "einfach zu lesende" Konstanten verwendet.
Steinar
1
Genau das habe ich oben getan. Sie müssen sich nicht bewerben, allprojectsda zusätzliche Eigenschaften auf Projektebene für Teilprojekte sichtbar sind.
Peter Niederwieser
7

Es ist eine späte Antwort, aber vielleicht möchten Sie auch einen Blick darauf werfen: http://plugins.gradle.org/plugin/io.spring.dependency-management Es bietet die Möglichkeit, einen Maven 'bom' zu importieren und die Definitionen wiederzuverwenden definiert in der 'bom'. Es ist sicherlich eine gute Hilfe bei der schrittweisen Migration von Maven zu Gradle! Genieße es jetzt.

Zimmerg
quelle
Es ist sogar ein Muss, wenn Sie dieselben Abhängigkeiten für mehrere (Mehrfach-) Projekte verwenden möchten.
Zimmer
7
Obwohl dieses Plugin praktisch ist, kann es einen erheblichen Leistungsbedarf haben. Für 30 Teilprojekte mit mehr als 200 Abhängigkeiten dauert die Phase der Abhängigkeitsauflösung bis zu 1 Minute. Für kleine Projekte funktioniert es jedoch wie ein Zauber
Jk1
Es überschreibt auch transitive Abhängigkeitsversionen, z. B. Sie haben Version 3.0.0 in der Abhängigkeitsverwaltung deklariert. Für eines der Teilprojekte müssen Sie jedoch eine ältere Version verwenden, z. B. 2.5.0. Wenn Sie ein Projekt haben, das von diesem älteren Projekt abhängig ist, ist das Die transitive Abhängigkeit wird von 2.5.0 auf das überschrieben, was im Abhängigkeitsverwaltungs-Plugin deklariert ist. 3.0.0 ist in diesem Fall ein sehr seltsames Verhalten
KameeCoding
7

Ab Gradle 4.6 werden in der Dokumentation Abhängigkeitsbeschränkungen vorgeschlagen, um dies zu erreichen. Von https://docs.gradle.org/current/userguide/declaring_dependencies.html#declaring_a_dependency_without_version :

Eine empfohlene Vorgehensweise für größere Projekte besteht darin, Abhängigkeiten ohne Versionen zu deklarieren und Abhängigkeitsbeschränkungen für die Versionsdeklaration zu verwenden. Der Vorteil besteht darin, dass Sie mit Abhängigkeitsbeschränkungen Versionen aller Abhängigkeiten, einschließlich transitiver Abhängigkeiten, an einem Ort verwalten können.

In Ihrer übergeordneten build.gradleDatei:

allprojects {
  plugins.withType(JavaPlugin).whenPluginAdded {
    dependencies {
      constraints {
        implementation("com.google.guava:guava:27.0.1-jre")
      }
    }
  }
}

Umschließen des Abhängigkeitsblocks mit einer Überprüfung des Java-Plugins (... whenPluginAdded { ) ist nicht unbedingt erforderlich, es wird jedoch das Hinzufügen eines Nicht-Java-Projekts zum selben Build behandelt.

Dann können Sie in einem Child Gradle-Projekt einfach die Version weglassen:

apply plugin: "java"

dependencies {
  implementation("com.google.guava:guava")
}

Untergeordnete Builds können weiterhin eine höhere Version angeben. Wenn eine niedrigere Version angegeben wird, wird diese automatisch auf die in der Einschränkung angegebene Version aktualisiert.

Adrian Baker
quelle
1
In Gralde 4.6 wurden Abhängigkeitsbeschränkungen hinzugefügt, sodass dies mit Gradle 4.6 oder höher funktioniert.
Jim Hurne
Ich denke, Gradle sieht vor, dass das Java Platform Plugin in einem solchen Fall verwendet wird. Die Gradle-Dokumentation ist zu diesem Zeitpunkt jedoch nicht sehr klar. Ich denke, die Verwendung von allprojectsist auch in Ordnung.
JojOatXGME
Ich möchte die Einschränkungen im Stammprojekt deklarieren, aber nur in einem meiner Teilprojekte. Ich möchte alle Abhängigkeiten laden, für die Einschränkungen definiert sind.
dtc
2

io.spring.gradle:dependency-management-pluginDas Plugin hat Probleme mit der neuen Gradle 3.x-Serie, ist jedoch für die 2.x-Serie stabil. Als Referenz siehe Fehlerbericht Drop-Unterstützung für Gradle 3 # 115

Im Falle von Spring ( Hauptförderer der Stücklistenverwendung ) können Sie mit Folgendem enden:

buildscript {
    repositories {
        mavenLocal()
        jcenter()
    }
    dependencies {
        classpath 'io.spring.gradle:dependency-management-plugin:1.0.0.RELEASE'
    }
}

repositories {
    mavenLocal()
    jcenter()
}

apply plugin: 'java'
apply plugin: 'io.spring.dependency-management'

dependencyManagement {
    imports {
        mavenBom 'io.spring.platform:platform-bom:Athens-SR3'
    }
}

dependencies {
    compile 'org.springframework.boot:spring-boot-starter-web'

    testCompile 'org.springframework.boot:spring-boot-starter-test'
}

Beachten Sie, io.spring.platform:platform-bomdass org.springframework.boot:spring-boot-starter-parentals übergeordnetes Element mit Spring Boot kompatibel ist

Sie können die tatsächliche Abhängigkeitsauflösung überprüfen über:

$ gradle dependencies
$ gradle dependencies --configuration compile
$ gradle dependencies -p $SUBPROJ

$ gradle buildEnvironment
$ gradle buildEnvironment -p $SUBPROJ

oder mit Aufgabe:

task showMeCache {
    configurations.compile.each { println it }
}

Lesen Sie den offiziellen Soring-Blogbeitrag Besseres Abhängigkeitsmanagement für Gradle , um den Grund für die Einführung zu verstehen io.spring.gradle:dependency-management-plugin.

Gavenkoa
quelle
1

In diesem Blogbeitrag wird vorgeschlagen, Abhängigkeiten und Gruppen als Konfigurationen zu verwalten: https://www.javacodegeeks.com/2016/05/manage-dependencies-gradle-multi-project-build.html

Ich habe es nicht selbst versucht, aber es sieht interessant aus.

Root-Projekt build.gradle

subprojects {
  configurations {
    commonsIo
  }

  dependencies {
    commonsIo 'commons-io:commons-io:2.5'
  }
}

Unterprojekt build.gradle

configurations {
  compile.extendsFrom commonsIo
}
tkruse
quelle
0

Sie können zentralisieren eine Abhängigkeit mithilfe des folgenden Codes :

Im gradle.properties

COMPILE_SDK_VERSION=26
BUILD_TOOLS_VERSION=26.0.1
TARGET_SDK_VERSION=26
MIN_SDK_VERSION=14

ANDROID_SUPPORT_VERSION=26.0.2

In jedem Modul hinzufügen zu build.gradle:

android {
    compileSdkVersion COMPILE_SDK_VERSION as int
    buildToolsVersion BUILD_TOOLS_VERSION as String

    defaultConfig {
        minSdkVersion MIN_SDK_VERSION as int
        targetSdkVersion TARGET_SDK_VERSION as int
        versionCode 1
        versionName "1.0"

    }

}

dependencies {
 compile "com.android.support:appcompat-v7:${ANDROID_SUPPORT_VERSION}"
 compile "com.android.support:support-v4:${ANDROID_SUPPORT_VERSION}"
 compile "com.android.support:support-annotations:${ANDROID_SUPPORT_VERSION}"
 compile "com.android.support:support-vector-drawable:${ANDROID_SUPPORT_VERSION}"
 compile "com.android.support:design:${ANDROID_SUPPORT_VERSION}"
}
Dhaval Jivani
quelle
0

Um Ihre Gradle-Datei sauber zu halten, können wir Abhängigkeiten in einem Array gruppieren und später implementieren.

  1. Fügen Sie eine Version solcher Bibliotheken in build.gradle (App-Ebene) außerhalb des Abhängigkeitsblocks hinzu :

// Versionen der Bibliothek deklarieren

final RetrofitVersion = '2.3.0'
final OkHttpVersion = '3.9.1'
  1. Erstellen Sie ein Array verwandter Abhängigkeiten, damit Sie es später leicht finden können. Fügen Sie es in build.gradle (App-Ebene) außerhalb des Abhängigkeitsblocks hinzu :

// Version in der Bibliothek verwenden und Abhängigkeit zusammen mit dem Zugriffsnamen hinzufügen (wie Nachrüstung (erste))

final networkDependencies = [
        retrofit             : "com.squareup.retrofit2:retrofit:${RetrofitVersion}",
        retrofitGsonConverter: "com.squareup.retrofit2:converter-gson:${RetrofitVersion}",
        retrofitRxJavaAdapter: "com.squareup.retrofit2:adapter-rxjava2:${RetrofitVersion}",
        okHttp3              : "com.squareup.okhttp3:okhttp:${OkHttpVersion}",
        okHttp3Logging       : "com.squareup.okhttp3:logging-interceptor:${OkHttpVersion}"
]
  1. Und im Abhängigkeitsblock :

// Implementiere alle Abhängigkeiten vom Array

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation networkDependencies.values()
}

Der endgültige Code sieht also folgendermaßen aus:

final RetrofitVersion = '2.3.0'
final OkHttpVersion = '3.9.1'

final networkDependencies = [
        retrofit             : "com.squareup.retrofit2:retrofit:${RetrofitVersion}",
        retrofitGsonConverter: "com.squareup.retrofit2:converter-gson:${RetrofitVersion}",
        retrofitRxJavaAdapter: "com.squareup.retrofit2:adapter-rxjava2:${RetrofitVersion}",
        okHttp3              : "com.squareup.okhttp3:okhttp:${OkHttpVersion}",
        okHttp3Logging       : "com.squareup.okhttp3:logging-interceptor:${OkHttpVersion}"
]

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation networkDependencies.values()
}
Suraj Vaishnav
quelle
Wie kann man einen Anmerkungsprozessor einbinden? wie im Fall von Lombok
Pritish Joshi