探索 uploadArchives 产生pom文件时packaging节点生成

1,647 阅读2分钟

最近发现在我们项目中使用implementation "cn.soul.android.lib:cpnt-login:1.0.9" 依赖下来的是cpnt-login:1.0.9@jar,而不是cpnt-login:1.0.9@aar,下面分析下原因

一:理解pom的packaging节点

先看一个gradle中典型的uploadArchives配置

uploadArchives {
    repositories {
        mavenDeployer {
            repository(url: uri("../repo/"))
            pom.project {
                version '1.0.9'
                artifactId 'cpnt-login'
                groupId 'cn.soul.android.app'
                packaging 'aar'
                description 'DESCRIPTION'
            }
        }
    }
}

执行./gradlew cpnt-login:uploadComponent(声明下,我们项目中uploadComponent其实就是uploadArchives的扩展,继承自Upload,做了一点额外配置,而且会上传jar)后得到pom文件内容:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.soul.android.app</groupId>
<artifactId>cpnt-login</artifactId>
<version>1.0.9</version>
<description>DESCRIPTION</description>
<dependencies>
...
</dependencies>
</project>

可以看到packaging节点没了...看了看maven上一些别的aar包对应的pom文件都有<packaging>aar</packaging>节点,那为什么cpnt-login的pom文件没有这个节点呢? 看一眼cpnt-login包的内容

markdown

可见cpnt包中多了一个jar,这个jar是我们故意加入的,其中包含了此aar组件向外暴露的接口。

参考: maven.apache.org/pom.html 中一段介绍:“When no packaging is declared, Maven assumes the packaging is the default: jar”, 可以得出结论:

1 执行uploadArchives上传jar包时,若没有特殊配置(由下文可知指没有配置Classifier),产生的pom文件不加packaging节点。

2 maven依赖的时候若发现pom文件没有packaging节点,默认就会认为pom文件最终指向的是个jar包。

二:分析pom的packaging节点产生过程

ok,现在maven的packaging节点已经理解了,那么对于我们这个cpnt-login组件里面既有aar文件也有jar文件,uploadArchives产生的pom文件为啥偏偏选择了jar没选择aar呢,分析这个就得调试uploadArchives这个task了,对应Upload这个类 全局搜索下uploadArchives,断点DefaultArtifactPom-addArtifact()方法

 public void addArtifact(Artifact artifact, File src) {
        throwExceptionIfArtifactOrSrcIsNull(artifact, src);
        PublishArtifact publishArtifact = new MavenArtifact(artifact, src);
        ArtifactKey artifactKey = new ArtifactKey(publishArtifact);
        if (this.artifacts.containsKey(artifactKey)) {
            throw new InvalidUserDataException(String.format("A POM cannot have multiple artifacts with the same type and classifier. Already have %s, trying to add %s.", this.artifacts.get(
                    artifactKey), publishArtifact));
        }

        if (publishArtifact.getClassifier() != null) {
            addArtifact(publishArtifact);
            assignArtifactValuesToPom(artifact, pom, false);
            return;
        }

        if (this.artifact != null) {
            // Choose the 'main' artifact based on its type.
            if (!PACKAGING_TYPES.contains(artifact.getType())) {
                addArtifact(publishArtifact);
                return;
            }
            if (PACKAGING_TYPES.contains(this.artifact.getType())) {
                throw new InvalidUserDataException("A POM can not have multiple main artifacts. " + "Already have " + this.artifact + ", trying to add " + publishArtifact);
            }
            addArtifact(this.artifact);
        }

        this.artifact = publishArtifact;
        this.artifacts.put(artifactKey, publishArtifact);
        assignArtifactValuesToPom(artifact, pom, true);
    }

我们没有配置Classifier,这里只会走最后一行的assignArtifactValuesToPom方法

private void assignArtifactValuesToPom(Artifact artifact, MavenPom pom, boolean setType) {
    if (pom.getGroupId().equals(MavenProject.EMPTY_PROJECT_GROUP_ID)) {
        pom.setGroupId(artifact.getModuleRevisionId().getOrganisation());
    }
    if (pom.getArtifactId().equals(MavenProject.EMPTY_PROJECT_ARTIFACT_ID)) {
        pom.setArtifactId(artifact.getName());
    }
    if (pom.getVersion().equals(MavenProject.EMPTY_PROJECT_VERSION)) {
        pom.setVersion(artifact.getModuleRevisionId().getRevision());
    }
    if (setType) {
        pom.setPackaging(artifact.getType());
    }
}

调试发现这个方法走了两遍,artifact参数第一步指向的是cpnt-login.aar,第二步指向的是cpnt-login.jar,第二步覆盖了第一步的结果,导致了最终packaging选择了jar类型,(外面有个for循环,列表的顺序是jar产物在aar产物后面,要理解列表添加顺序,让aar在后面可以解决此问题,这涉及到控制产物目录添加顺序问题),且因为外面没有配置Classifier,外面写的packaging 'aar'其实被artifact.getType()覆盖了。。。

简单粗暴,使用pom.withXml方法直接在pom中编辑packaging节点

uploadArchives {
    repositories {
        mavenDeployer {
            repository(url: uri("../repo/"))
            pom.project {
                version '1.0.15'
                artifactId 'cpnt-login'
                groupId 'cn.soul.android.app'
                packaging 'aar'
                description 'DESCRIPTION'
            }
	    pom.withXml {
                asNode().appendNode('packaging', 'aar')
          }
        }
    }
}

解决~