Optional Gradle dependencies for Maven libraries
Asked Answered
S

3

14

I'm working on an Android library and would like to use a dependency only if the project using my library includes that dependency as well. Similar to what Picasso does with OkHttp.

I already took care of this on the main code by checking for ClassNotFoundExceptions but it still includes the dependencies upon deploying it to Maven Central. How do I generate something such as Maven's <optional>true</optional> tag?

I'm using gradle-mvn-push to deploy my artifacts via Gradle.

Superfluity answered 17/8, 2014 at 2:27 Comment(0)
R
17

Vote for GRADLE-1749.

In the mean time you can use pom.withXml approach to modify the generated pom file, for example to add <optional> tags or change <scope>values:

apply plugin: 'java'
apply plugin: 'maven-publish'

configurations {
  optional
  compile.extendsFrom optional
}

dependencies {
  compile 'com.some.group:artifact:1.0';
  optional 'com.another.group:optional-artifact:1.0'
}

publishing {
  publications {
    maven( MavenPublication ) {
      from components.java

      pom.withXml {
        asNode().dependencies.dependency.findAll { xmlDep ->
          // mark optional dependencies
          if ( project.configurations.optional.allDependencies.findAll { dep ->
            xmlDep.groupId.text() == dep.group && xmlDep.artifactId.text() == dep.name
          } ) {
            def xmlOptional = xmlDep.optional[ 0 ];
            if ( !xmlOptional ) {
              xmlOptional = xmlDep.appendNode( 'optional' )
            }
            xmlOptional.value = 'true';
          }

          // fix maven-publish issue when all maven dependencies are placed into runtime scope
          if ( project.configurations.compile.allDependencies.findAll { dep ->
            xmlDep.groupId.text() == dep.group && xmlDep.artifactId.text() == dep.name
          } ) {
            def xmlScope = xmlDep.scope[ 0 ];
            if ( !xmlScope ) {
              xmlScope = xmlDep.appendNode( 'scope' )
            }
            xmlScope.value = 'compile';
          }
        }
      }
    }
  }
}
Rosannarosanne answered 24/9, 2014 at 12:31 Comment(1)
Small update: Gradle issue has been moved to Github: github.com/gradle/gradle/issues/867. Apparently, nothing merged though. And pom.withXml works really fine.Malinda
C
5

The Nebula Extra Configurations Gradle plugin seems to be providing optional.

You would use it like this:

apply plugin: 'java'
apply plugin: 'nebula.optional-base'

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.apache.commons:commons-lang3:3.3.2', optional
    compile group: 'log4j', name: 'log4j', version: '1.2.17', optional
}
Cudweed answered 14/7, 2016 at 9:33 Comment(1)
Plugin with id 'nebula.optional-base' not found.Compendious
K
3

According to this blog, Compile-only dependencies address a number of use cases, including:

  • Dependencies required at compile time but required at runtime only when using certain features, a.k.a. optional dependencies;
  • Dependencies required at compile time but never required at runtime, such as source-only annotations or annotation processors;
  • Dependencies whose API is required at compile time but whose implementation is to be provided by a consuming library, application or runtime environment.

So just using compileOnly to declare an optional dependency.

Koski answered 18/3, 2021 at 18:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.