I am using maven-publish plugin in gradle to publish artifacts. I need to generate a POM file that contains dependencies so that my consumers can fetch the needed dependencies.
Since maven-publish does not by default contains dependencies onto POM file, I had to use
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
configurations.compile.allDependencies.each {
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.group)
dependencyNode.appendNode('artifactId', it.name)
dependencyNode.appendNode('version', it.version)
dependencyNode.appendNode('scope', 'compile')
}
}
It was all working fine to me until I swapped keyword compile to api or Implementation.
the published POM does not contain any dependencies uses keyword api or Implementation. I had to use compile to make it included in POM file, am I missing anything here?
After couple of hours searching online, I just realized that the property you include POM file is changed as well.
It now become
//for implementation dependencies
configurations.implementation.allDependencies.each { ... }
//for api dependencies
configurations.api.allDependencies.each { ... }
However,
configurations.implementation.allDependencies.each { ... }
seems includes api dependencies in the POM file already.
you can simply skip the scope part, you hardly come across maven dependencies with scopes. ':D
Related
I've just migrated my Android lib from JCenter to MavenCentral. The process completed successfully and I can find my lib through Sonatype Repo Search.
However, when I try to use the lib in my sample application, I get the following error:
Execution failed for task ':sample:checkDebugAarMetadata'.
> Could not resolve all files for configuration ':sample:debugRuntimeClasspath'.
> Could not find :unspecified:.
Required by:
project :sample > com.techyourchance:threadposter:1.0.0
Possible solution:
- Declare repository providing the artifact, see the documentation at https://docs.gradle.org/current/userguide/declaring_repositories.html
It looks like Gradle finds my lib (because if I change to a non-existent version, say 2.0.0, then I get completely different error), but there is some problem with the artifact.
All the source code (both the lib and the sample app) can be found here. Specifically, here is build.gradle of the lib and that's the additional Gradle script that handles publication to Sonatype.
I've already spent two hours searching for each of the above error messages on the internet, but couldn't solve this issue so far.
Skip dependencies with name 'unspecified' in your publish-maven.gradle.
withXml {
def dependenciesNode = asNode().appendNode('dependencies')
project.configurations.implementation.allDependencies.each {
if (it.name != 'unspecified') {
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.group)
dependencyNode.appendNode('artifactId', it.name)
dependencyNode.appendNode('version', it.version)
}
}
}
I have a library that uses Kotlin Coroutines and uses the CoroutineScope as
private val coroutineScope by lazy(mode = LazyThreadSafetyMode.NONE) {
CoroutineScope(Dispatchers.Main)
}
When I use the library in other projects I am getting error:
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: java.lang.ClassNotFoundException: Didn't find class "kotlinx.coroutines.Dispatchers" on path: DexPathList[[zip file "/data/app/com.ssss.ssss-X44QPiLhKdl-D6eyVAYkOA==/base.apk"],nativeLibraryDirectories=[/data/app/com.ssss.testauthenticater-X44QPiLhKdl-D6eyVAYkOA==/lib/x86, /system/lib, /system/product/lib]]
I have added -keepnames class kotlinx.** { *; }
in my consumer pro guard file as well.
Does anyone have similar issue? I am using coroutine 1.3.3 in android.
Can you please use this version and try again:
kotlin_coroutinesVersion = "1.2.1"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutinesVersion"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutinesVersion"
ClassNotFoundException can appears due to wrong generation of pox.xml file, which contains dependencies graph of the library, here is a script for publishing library to local maven repo and generating pom.xml file:
https://gist.github.com/Robyer/a6578e60127418b380ca133a1291f017
For applying it to library need to add publishMavenLocal.gradle to library project and put this line at the bottom of library build.gradle: apply from: 'publishMavenLocal.gradle'.
Also for testing it from local maven repo there should be additional identificator in test app gradle file - transitive = true, like this:
implementation ('com.example.android:library:0.0.1-library#aar') { transitive = true }
After sometime with help of link posted by #orest-herdil above, I figured out the issue was the dependency of my library module were not added in the POM file generated while bundling the AAR file. So I updated my maven publish code as:
publishing {
publications {
aar(MavenPublication) {
groupId "com.mylibrary"
version "1.1.1"
artifactId "awesome"
artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
configurations.implementation.allDependencies.each { dependency ->
final dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', dependency.group)
dependencyNode.appendNode('artifactId', dependency.name)
dependencyNode.appendNode('version', dependency.version)
}
}
}
}
}
The part pom.withXml { .... } will go through all the dependency in my library module and add them in generating POM file one by one. As of now the compile is already deprecated, I am going through implementation dependency only.
When I build an app with a *.aar file instead of the module with Gradle 4.x and following the docu concerning implements and api, I expect using api the included aar file has all dependencies included, but it hasn't.
When you do
git clone https://github.com/hannesa2/aar_dependency
./gradlew clean assembleDebug
means
dependencies {
api project(':mylibrary')
it works properly.
But when I use insted of lib-module the previous generated *.aar file as dependency
dependencies {
api 'com.example.my.mylibrary:mylibrary-debug#aar'
(in demo app just do)
git checkout with_aar
./gradlew clean assembleDebug
I run into this
Task :app:transformClassesWithDesugarForDebug
Exception in thread "main" java.lang.TypeNotPresentException: Type io.reactivex.ObservableTransformer not present
at sun.invoke.util.BytecodeDescriptor.parseSig(BytecodeDescriptor.java:85)
at sun.invoke.util.BytecodeDescriptor.parseMethod(BytecodeDescriptor.java:63)
at sun.invoke.util.BytecodeDescriptor.parseMethod(BytecodeDescriptor.java:41)
at java.lang.invoke.MethodType.fromMethodDescriptorString(MethodType.java:1067)
at com.google.devtools.build.android.desugar.LambdaDesugaring$InvokedynamicRewriter.visitInvokeDynamicInsn(LambdaDesugaring.java:399)
at org.objectweb.asm.MethodVisitor.visitInvokeDynamicInsn(Unknown Source)
at org.objectweb.asm.MethodVisitor.visitInvokeDynamicInsn(Unknown Source)
Because I ordinary run into this with uploading the aar artifacts into our company Maven Nexus, I created this demo-repo to show exactly what's wrong. In demo app or using Maven I see the same issue.
Does someone knows what I did wrong ?
I was able to solve it. The main issue was Android O with Gradle 4.x using api
dependencies {
api 'com.squareup.okhttp3:logging-interceptor:3.4.1'
api "io.reactivex.rxjava2:rxandroid:$versions.libs.rxAndroid"
Most answers are concerning something like this
publishing {
publications {
mipartner(MavenPublication) {
groupId '...'
artifactId '..'
version 1.0
artifact "$buildDir/outputs/aar/myLib-release.aar"
//generate pom nodes for dependencies
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
configurations.compile.allDependencies.each { dependency ->
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', dependency.group)
dependencyNode.appendNode('artifactId', dependency.name)
dependencyNode.appendNode('version', dependency.version)
}
}
}
}
repositories{
maven {
url "https://some.url.com"
}
}
}
but here in the resulting *.pom there are no dependencies included, after change this line to api the dependencies are included in deployed pom !
configurations.api.allDependencies.each { dependency ->
after this you can easily consume the aar file
dependencies {
api "com.mylib.net:mylib:1.0"
When I build an app with a *.aar file instead of the module with Gradle 4.x and following the docu concerning implements and api, I expect using api the included aar file has all dependencies included, but it hasn't.
When you do
git clone https://github.com/hannesa2/aar_dependency
./gradlew clean assembleDebug
means
dependencies {
api project(':mylibrary')
it works properly.
But when I use insted of lib-module the previous generated *.aar file as dependency
dependencies {
api 'com.example.my.mylibrary:mylibrary-debug#aar'
(in demo app just do)
git checkout with_aar
./gradlew clean assembleDebug
I run into this
Task :app:transformClassesWithDesugarForDebug
Exception in thread "main" java.lang.TypeNotPresentException: Type io.reactivex.ObservableTransformer not present
at sun.invoke.util.BytecodeDescriptor.parseSig(BytecodeDescriptor.java:85)
at sun.invoke.util.BytecodeDescriptor.parseMethod(BytecodeDescriptor.java:63)
at sun.invoke.util.BytecodeDescriptor.parseMethod(BytecodeDescriptor.java:41)
at java.lang.invoke.MethodType.fromMethodDescriptorString(MethodType.java:1067)
at com.google.devtools.build.android.desugar.LambdaDesugaring$InvokedynamicRewriter.visitInvokeDynamicInsn(LambdaDesugaring.java:399)
at org.objectweb.asm.MethodVisitor.visitInvokeDynamicInsn(Unknown Source)
at org.objectweb.asm.MethodVisitor.visitInvokeDynamicInsn(Unknown Source)
Because I ordinary run into this with uploading the aar artifacts into our company Maven Nexus, I created this demo-repo to show exactly what's wrong. In demo app or using Maven I see the same issue.
Does someone knows what I did wrong ?
I was able to solve it. The main issue was Android O with Gradle 4.x using api
dependencies {
api 'com.squareup.okhttp3:logging-interceptor:3.4.1'
api "io.reactivex.rxjava2:rxandroid:$versions.libs.rxAndroid"
Most answers are concerning something like this
publishing {
publications {
mipartner(MavenPublication) {
groupId '...'
artifactId '..'
version 1.0
artifact "$buildDir/outputs/aar/myLib-release.aar"
//generate pom nodes for dependencies
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
configurations.compile.allDependencies.each { dependency ->
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', dependency.group)
dependencyNode.appendNode('artifactId', dependency.name)
dependencyNode.appendNode('version', dependency.version)
}
}
}
}
repositories{
maven {
url "https://some.url.com"
}
}
}
but here in the resulting *.pom there are no dependencies included, after change this line to api the dependencies are included in deployed pom !
configurations.api.allDependencies.each { dependency ->
after this you can easily consume the aar file
dependencies {
api "com.mylib.net:mylib:1.0"
Since I cannot use a private maven in order to share my library, I was thinking in sharing the aar and importing into another project.
The problem comes when the aar and jar files does not contain any dependency. So once I manually import the aar in android studio (using Import .JAR/.AA Package) there is no dependency, and I have to manually add all dependencies again.
I already generated a pom file through a gradle task, although I cannot find any way to manually import it on the project.
On the build.gradle file automatically generated by the "Import .JAR/.AA Package" is:
configurations.maybeCreate("default")
artifacts.add("default", file('TestSample_1.0.0.aar'))
Is there a way to add the pom/iml file too? something like:
artifacts.add("default", file('pomDependencies.xml'))
1. Publishing
In your aar project, add maven-publish plugin and add necessary plugin configuration.
apply plugin: 'com.android.library'
apply plugin: 'maven-publish'
...
dependencies {
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.novoda:bintray-release:0.2.7'
}
...
publishing {
publications {
maven(MavenPublication) {
groupId 'com.example' //You can either define these here or get them from project conf elsewhere
artifactId 'example'
version '0.0.1-SNAPSHOT'
artifact "$buildDir/outputs/aar/app-release.aar" //aar artifact you want to publish
//generate pom nodes for dependencies
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
configurations.compile.allDependencies.each { dependency ->
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', dependency.group)
dependencyNode.appendNode('artifactId', dependency.name)
dependencyNode.appendNode('version', dependency.version)
}
}
}
}
//publish to filesystem repo
repositories{
maven {
url "$buildDir/repo"
}
}
}
Few things to note:
We're using a custom maven publication, so you have to define what is being published with the artifact clause
We have to generate the pom ourselves, in the code above I'm using all compile config dependencies, you may want to make sure all the configs you care about are covered.
Running gradle publish will publish to a maven repo structure to the repo folder, which you can then consume from a different project.
2. Using published .aar
In a different android project, to use the aar published in #1:
In top level build.gradle:
allprojects {
repositories {
jcenter()
maven {
url "D:/full/path/to/repo"
}
}
}
add the path to earlier repo as a maven repository. Note that you may have to use the full path, because $buildDir has a different value for this project. In your app build.gradle:
dependencies {
...
other dependencies
...
implementation ('com.example:example:0.0.1-SNAPSHOT#aar'){transitive=true}
}
transitive=true is required for to fetch the transitive dependencies from the pom file.
Things have changed a little, here's how you do it with the latest versions of gradle
Create the package localy (aar and pom)
Modify your library build.gradle file to include
apply plugin: 'maven-publish'
android {
...
...
}
dependencies {
...
...
}
publishing {
publications {
maven(MavenPublication) {
groupId 'com.domain' //You can either define these here or get them from project conf elsewhere
artifactId 'name'
version '1.0.0'
artifact "$buildDir/outputs/aar/sdk-release.aar" //aar artifact you want to publish
//generate pom nodes for dependencies
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
configurations.implementation.allDependencies.each { dependency ->
if (dependency.name != 'unspecified') {
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', dependency.group)
dependencyNode.appendNode('artifactId', dependency.name)
dependencyNode.appendNode('version', dependency.version)
}
}
}
}
//publish to filesystem repo
repositories{
maven {
url "$buildDir/repo"
}
}
}
Run from terminal
./gradlew clean
./gradlew build
./gradlew --console=verbose publishToMavenLocal
The aar and pom files have been created at $HOME/.m2/repository/
How to load the library from a different project
Modify the projects's build.gradle in the following way:
allprojects {
repositories {
maven {
url "/Users/username/.m2/repository/"
}
google()
jcenter()
}
You can use $rootDir and set a relative path.
Add the library as a dependency in your app module build.gradle
implementation 'com.domain:name:1.0.0'