15

I am using Gradle to build an Android library project and deploy it to maven repository as an aar.

The library has some dependencies, which should be included in the POM

With apply plugin: 'maven' no POM file is present, just the artifact

With apply plugin: 'maven-publish' a POM file is generated, but it does not include any dependencies

Any ideas? Is this just not supported?

Gradle 2.2 and Android Gradle Plugin 1.1.0

First approach:

configurations {
    archives {
        extendsFrom configurations.default
    }
}

afterEvaluate { project ->
    uploadArchives {

        configuration = configurations.archives

        repositories {
            mavenDeployer {
                repository(url: "http://nexus-url") {
                    authentication(userName: nexusUsername, password: nexusPassword)

                pom.groupId = 'com.example'
                pom.version = '123-SNAPSHOT'
                pom.artifactId = 'foo'
                pom.packaging = 'aar'

                pom.project {
                    artifactId = 'bar'
                    packaging 'aar'
                    description 'baz'
            }
        }
    }
}

Also tried it without wrapping it in afterEvaluate

Second approach:

publishing {
    publications {
        sdk(MavenPublication) {
            groupId 'com.example'
            artifactId 'foo'
            version = "0.123-SNAPSHOT"
            artifact("$buildDir/outputs/aar/app-sdk-debug.aar")
        }
    }
    repositories {
        maven {
            url "http://nexus-url"
            credentials {
                username 'foo'
                password 'bar'
            }
        }
    }
}

Update

The root cause of the problem is that this project uses flavors. Without flavors the pom is generated properly when using apply plugin: 'maven'

Philipp E.
  • 3,296
  • 3
  • 34
  • 52

2 Answers2

19

This is the solution that worked for me in the end:

publishing {
    publications {
        sdk(MavenPublication) {
            artifactId libName
            artifact "${project.buildDir}/outputs/aar/${libName}-${project.version}.aar"

            //The publication doesn't know about our dependencies, so we have to manually add them to the pom
            pom.withXml {
                // for dependencies and exclusions
                def dependenciesNode = asNode().appendNode('dependencies')
                configurations.implementation.allDependencies.withType(ModuleDepend‌​ency) { ModuleDependency dp ->
                    def dependencyNode = dependenciesNode.appendNode('dependency')
                    dependencyNode.appendNode('groupId', dp.group)
                    dependencyNode.appendNode('artifactId', dp.name)
                    dependencyNode.appendNode('version', dp.version)

                    // for exclusions
                    if (dp.excludeRules.size() > 0) {
                        def exclusions = dependencyNode.appendNode('exclusions')
                        dp.excludeRules.each { ExcludeRule ex ->
                            def exclusion = exclusions.appendNode('exclusion')
                            exclusion.appendNode('groupId', ex.group)
                            exclusion.appendNode('artifactId', ex.module)
                        }
                    }
                }
            }
        }
    }

    repositories {
        maven {
            name 'myrepo'
            url 'https://maven.foo.com'

            credentials {
                username mavenUsername
                password mavenPassword
            }      
        }
    }
}
Syzygy
  • 578
  • 7
  • 27
Philipp E.
  • 3,296
  • 3
  • 34
  • 52
  • 1
    It's better to replace `configurations.compile.allDependencies.each` with `configurations.compile.allDependencies.withType(ModuleDependency)` in order to avoid exceptions when you use `compile fileTree(dir: 'libs', include: ['*.jar'])` – Denys Vasylenko Oct 26 '17 at 14:25
  • Note that configurations.compile.allDependencies. is outdated. With the current version of gradle it should be configurations.implementation.allDependencies or a variant of that (e.g. api instead of implementation) – Syzygy Jan 30 '19 at 12:54
  • @Syzygy The code above has an error, becasue ModuleDependency in with method and before dp -> is not the same word, is it spelling mistakes ? – peerless2012 Jul 01 '20 at 05:57
  • And what should i do when i have many flavor in one module? I don't want to write the pox.withXml in each flavor publish. – peerless2012 Jul 01 '20 at 06:06
  • Not sure, but maybe `matchingFallbacks` can help? https://developer.android.com/studio/build/dependencies#resolve_matching_errors – Philipp E. Jul 01 '20 at 06:12
  • > Could not apply withXml() to generated POM > Could not get unknown property 'implementation' for configuration container of type org.gradle.api.internal.artifacts.configurations.DefaultConfigurationContainer. – desgraci May 03 '22 at 15:13
  • this can be resolved applying the `java`plugin but the dependencies are still missing – desgraci May 03 '22 at 15:18
0

try mavenDeployer: http://gradle.org/docs/current/userguide/maven_plugin.html

uploadArchives {
    repositories {
        mavenDeployer {
            repository(url: "file://localhost/tmp/myRepo/")
            pom.version = '1.0Maven'
            pom.artifactId = 'myMavenName'
        }
    }
}

here you could set the pom details. You'll get a new goal called uploadArchives. When executed, it deploys to a given repo.

sschrass
  • 7,014
  • 6
  • 43
  • 62
  • Beware of SNAPSHOT-Dependencies, Gradle doesn't follow this maven concept, meaning if you deploy SNAPSHOT-dependencies, gradle will not update them if it already got the same version (AFAIK) – sschrass Mar 03 '15 at 10:07
  • thanks, but thats actually what I meant when I mentioned `apply plugin: 'maven'` I'll post some code for both variants – Philipp E. Mar 03 '15 at 13:18
  • Needed to read that again -> you dont want dependencies in this pom. There is no reason for it, because your dependencies are baked into the artifact. Thats what compiling does. This pom is just a description of your artifact. – sschrass Mar 03 '15 at 13:31
  • Only jar dependencies are baked in. aar dependencies are transitive and need to be referenced in the POM or explicitly included in the build file of the host app. Take otto for example: http://central.maven.org/maven2/com/squareup/otto/1.3.6/otto-1.3.6.pom – Philipp E. Mar 03 '15 at 13:55
  • those dependencies are either provided (provided by something else than your aar), or test (only needed when running tests). And aar are not transitive because they are aars. Transitive means dependencies of dependencies. – sschrass Mar 03 '15 at 14:07
  • Exactly, they are provided by someone else, thats why they have to be referenced. Look at the link I provided. Or at any aar library on jcenter that depend on other libraries. – Philipp E. Mar 03 '15 at 14:12
  • If I include the artificat in a host application without explicitly referencing all of its dependencies, I get a NoClassDefFoundError – Philipp E. Mar 03 '15 at 14:15
  • 1
    Seems I never had this issue, nonetheless las suggestion: have a look here https://github.com/spring-projects/gradle-plugins/tree/master/propdeps-plugin – sschrass Mar 03 '15 at 14:58