No Gradle, como declaro dependências comuns em um único lugar?

109

No Maven, há um recurso muito útil quando você pode definir uma dependência na <dependencyManagement>seção do POM pai e fazer referência a essa dependência dos módulos filhos sem especificar a versão ou escopo ou qualquer outra coisa.

Quais são as alternativas no Gradle?

Stanislav Bashkyrtsev
fonte

Respostas:

179

Você pode declarar dependências comuns em um script pai:

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

Em um script filho, você pode usar as declarações de dependência da seguinte forma:

dependencies {
    compile libraries.spring_core
    testCompile libraries.junit
}

Para compartilhar declarações de dependência com opções de configuração avançada, você pode usar DependencyHandler.create:

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

Várias dependências podem ser compartilhadas com o mesmo nome:

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

dependencies { compile libraries.spring } irá então adicionar ambas as dependências de uma vez.

A única informação que você não pode compartilhar dessa maneira é a qual configuração ( escopo nos termos do Maven) uma dependência deve ser atribuída. No entanto, pela minha experiência, é melhor ser explícito sobre isso de qualquer maneira.

Peter Niederwieser
fonte
3
Obrigado, isso resolve minha dúvida, mas ainda tenho uma preocupação. No Maven podemos deixar a versão vazia e se for uma lib, é conveniente porque você pode usá-lo em nosso aplicativo e fazer dependencyManagement para definir qual versão da lib deve demorar. Como você faria o mesmo com o Gradle?
Stanislav Bashkyrtsev
Eu não entendo a pergunta. Forneça um exemplo.
Peter Niederwieser
4
Peter, o que ctapobep está dizendo é que no maven você pode declarar dependências com versão (e escopo) em um pom pai (ou agregador) na seção dependencyManagement. Então, no pom "concreto", você não precisa declarar novamente a versão; apenas artefato e groupId. Basicamente, ele diz ao maven "Eu preciso de X: Y, mas use qualquer versão que o pai tenha configurado."
Michael Campbell
2
Para evitar este tipo de duplicação, que tendem a criar um separado dependencies.gradlescript onde eu definir todas as minhas dependências como propriedades, por exemplo: ext.GROOVY = 'org.codehaus.groovy:groovy-all:2.1.6'. No projeto raiz build.gradle, eu incluo allprojects { apply from: "$rootDir/dependencies.gradle" }. Então, todas as dependências são definidas em um arquivo em vez de distribuí-las, e mais constantes "fáceis de ler" são usadas nas configurações de dependência.
Steinar,
1
Isso é exatamente o que fiz acima. Você não precisa se inscrever allprojectsporque as propriedades extras no nível do projeto são visíveis para os subprojetos.
Peter Niederwieser,
7

É uma resposta tardia, mas você também pode querer dar uma olhada em: http://plugins.gradle.org/plugin/io.spring.dependency-management Oferece a possibilidade de importar um maven 'bom' e reutilizar as definições definido no 'bom'. Certamente é uma boa ajuda ao migrar gradualmente de maven para gradle! Aproveitando agora.

quartosg
fonte
é até obrigatório quando você deseja compartilhar as mesmas dependências entre vários (vários) projetos.
quartos de
7
Embora conveniente, este plug-in pode ter uma pegada de desempenho significativa. Para 30 subprojetos com mais de 200 dependências, adiciona até 1 minuto à fase de resolução de dependência. Para pequenos projetos, funciona
perfeitamente
ele também substitui as versões de dependência transitiva, digamos que você tenha declarado a versão 3.0.0 no gerenciamento de dependência, mas para um dos subprojetos você precisa usar uma versão mais antiga, por exemplo, 2.5.0, então se você tiver um projeto dependente deste projeto mais antigo, a dependência transitiva será sobrescrita de 2.5.0 para o que está declarado no plugin de gerenciamento de dependência, então 3.0.0, neste caso, um comportamento muito estranho
KameeCoding
7

A partir do Gradle 4.6, as restrições de dependência são sugeridas na documentação como a maneira de fazer isso. De https://docs.gradle.org/current/userguide/declaring_dependencies.html#declaring_a_dependency_without_version :

Uma prática recomendada para projetos maiores é declarar dependências sem versões e usar restrições de dependência para declaração de versão. A vantagem é que as restrições de dependência permitem que você gerencie versões de todas as dependências, incluindo as transitivas, em um só lugar.

Em seu build.gradlearquivo principal :

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

Encapsular o bloco de dependências com uma verificação do plug-in Java (... whenPluginAdded {) não é estritamente necessário, mas então tratará da adição de um projeto não-Java à mesma construção.

Então, em um projeto gradle filho, você pode simplesmente omitir a versão:

apply plugin: "java"

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

Os builds filhos ainda podem escolher especificar uma versão superior. Se uma versão inferior for especificada, ela será automaticamente atualizada para a versão na restrição.

Adrian Baker
fonte
1
As restrições de dependência foram adicionadas no Gralde 4.6, portanto, funcionará com o Gradle 4.6 ou superior.
Jim Hurne
Acho que o Gradle prevê que o Java Platform Plugin seja usado nesse caso. No entanto, a documentação do Gradle não é muito clara neste momento. Acho que o uso de também allprojectsestá bom.
JojOatXGME
Quero declarar as restrições no projeto raiz, mas apenas em um dos meus subprojetos, quero carregar todas as dependências que têm restrições definidas.
dtc
2

io.spring.gradle:dependency-management-pluginO plugin tem problemas com a nova série Gradle 3.x, mas estável para a série 2.x. Para referência, veja o relatório de bug - Suporte para o Gradle 3 # 115

No caso do Spring ( principal promotor do uso do BOM ) você pode terminar com:

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

Observe que io.spring.platform:platform-bomtem org.springframework.boot:spring-boot-starter-parentcomo pai, por isso é compatível com Spring Boot

Você pode verificar a resolução real da dependência por meio de:

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

$ gradle buildEnvironment
$ gradle buildEnvironment -p $SUBPROJ

ou com tarefa:

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

Leia a postagem oficial do blog Soring Melhor gerenciamento de dependências para o Gradle para entender o motivo da introdução io.spring.gradle:dependency-management-plugin.

Gavenkoa
fonte
1

Você pode centralizar uma dependência usando o código abaixo:

No 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

Em cada módulo, adicione a 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
fonte
1

Esta postagem do blog sugere o gerenciamento de dependências e grupos como configurações: https://www.javacodegeeks.com/2016/05/manage-dependencies-gradle-multi-project-build.html

Eu mesmo não tentei, mas parece interessante.

Projeto raiz build.gradle

subprojects {
  configurations {
    commonsIo
  }

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

Subprojeto build.gradle

configurations {
  compile.extendsFrom commonsIo
}
tkruse
fonte
0

Para manter seu arquivo gradle limpo, podemos agrupar as dependências em um array e implementá-las posteriormente.

  1. Adicione uma versão de bibliotecas como esta em build.gradle (nível de aplicativo) fora do bloco de dependência :

// declara versões da biblioteca

final RetrofitVersion = '2.3.0'
final OkHttpVersion = '3.9.1'
  1. Crie uma matriz de dependências relacionadas, para que possa localizá-la facilmente mais tarde. Adicione-o em build.gradle (nível de aplicativo) fora do bloco de dependência :

// Usar a versão na biblioteca e adicionar dependência junto com o nome de acesso (como retrofit (primeiro))

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. E no bloco de dependência :

// Implementar todas as dependências do array

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

    implementation networkDependencies.values()
}

Portanto, o código final ficará assim:

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
fonte
como incluir processador de anotação por este ?? como no caso de lombok
Pritish Joshi