Android AAR取决于AAR失败,Javadoc Generation

发布于 2025-01-21 22:54:32 字数 6117 浏览 2 评论 0 原文

我有一个Android Gradle项目结构,看起来像该

  • Module1-AAR
  • 2-AAR
  • TESTAPP-APK

关键事实

  • -AAR取决于Module1-AAR
  • TESTAPP-APK取决于Module2-AAR
  • JDK11 jdk11
  • gradle
  • 7.4.4.4.4.2

Module2 Javadocs,GPG,签名或出版,一切都很好。应用程序运行,一切都很棒。

当我开始添加以生成Javadocs的任务时,这就是所有事情都发生的时候。 Module1-aar将毫无问题地构建和生成Javadocs。但是,在Javadoc任务期间,Module2-aar总是失败。

任务在下面。其中大部分是从这里借来的

project.task("javadoc", type: Javadoc) {
    afterEvaluate {
        configurations.all
                .each {item ->
                    item.setCanBeResolved(true)
                }

        classpath += configurations.api
        classpath += configurations.implementation
        // Wait after evaluation to add the android classpath
        // to avoid "buildToolsVersion is not specified" error
        classpath += files(android.getBootClasspath())

        // Process AAR dependencies
        def aarDependencies = classpath.filter { it.name.endsWith('.aar') }
        classpath -= aarDependencies
        //fails here when an AAR depends on an AAR
        aarDependencies.each { aar ->
            // Extract classes.jar from the AAR dependency, and add it to the javadoc classpath
            def outputPath = "$buildDir/tmp/aarJar/${aar.name.replace('.aar', '.jar')}"
            classpath += files(outputPath)

            // Use a task so the actual extraction only happens before the javadoc task is run
            dependsOn task(name: "extract ${aar.name}").doLast {
                extractEntry(aar, 'classes.jar', outputPath)
            }
        }

    }

    source = android.sourceSets.main.java.srcDirs
    classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
    classpath += project.files(android.getBootClasspath())
    classpath += configurations.implementation
    classpath += fileTree(dir: project.buildDir.absolutePath + "/tmp/aarsToJars/")
    classpath += files(project.buildDir.absolutePath + "/intermediates/compile_r_class_jar/release/R.jar")
    classpath += files(project.buildDir.absolutePath + "/generated/source/buildConfig/release/release")
    classpath += files(project.buildDir.absolutePath + "/generated/source/r/buildConfig/release/release")
    destinationDir = file( project.buildDir.absolutePath + "/outputs/javadoc/")
     failOnError true
    options.charSet 'UTF-8'
    options.docEncoding 'UTF-8'
    options.encoding 'UTF-8'
    options.addBooleanOption 'Xdoclint:none', true
    exclude '**/BuildConfig.java'
    exclude '**/R.java'
    exclude '**/doc-files/*'
}


// Utility method to extract only one entry in a zip file
private def extractEntry(archive, entryPath, outputPath) {
    if (!archive.exists()) {
        throw new GradleException("archive $archive not found")
    }

    def zip = new java.util.zip.ZipFile(archive)

    zip.entries().each {
        if (it.name == entryPath) {
            def path = new File(outputPath)

            if (!path.exists()) {
                path.getParentFile().mkdirs()

                // Surely there's a simpler is->os utility except
                // the one in java.nio.Files? Ah well...
                def buf = new byte[1024]
                def is = zip.getInputStream(it)
                def os = new FileOutputStream(path)
                def len

                while ((len = is.read(buf)) != -1) {
                    os.write(buf, 0, len)
                }
                os.close()
            }
        }
    }
    zip.close()
}

//wires in the javadoc task to the normal build
tasks.named("build") { finalizedBy("generateJavadocJar") }

我收到的错误消息是

* What went wrong:
A problem occurred configuring project ':module2-aar'.
> Could not resolve all files for configuration ':module2-aar:implementation'.
   > Could not resolve project :module1-aar.
     Required by:
         project :module2-aar
      > Cannot choose between the following variants of project :module1-aar:
          - debugRuntimeElements
          - releaseRuntimeElements
        All of them match the consumer attributes:
          - Variant 'debugRuntimeElements' capability com.github.test:module1-aar:6.1.11-SNAPSHOT:
              - Unmatched attributes:
                  - Provides com.android.build.api.attributes.AgpVersionAttr '7.1.3' but the consumer didn't ask for it
                  - Provides com.android.build.api.attributes.BuildTypeAttr 'debug' but the consumer didn't ask for it
                  - Provides com.android.build.gradle.internal.attributes.VariantAttr 'debug' but the consumer didn't ask for it
                  - Provides org.gradle.usage 'java-runtime' but the consumer didn't ask for it
          - Variant 'releaseRuntimeElements' capability com.github.test:module1-aar:6.1.11-SNAPSHOT:
              - Unmatched attributes:
                  - Provides com.android.build.api.attributes.AgpVersionAttr '7.1.3' but the consumer didn't ask for it
                  - Provides com.android.build.api.attributes.BuildTypeAttr 'release' but the consumer didn't ask for it
                  - Provides com.android.build.gradle.internal.attributes.VariantAttr 'release' but the consumer didn't ask for it
                  - Provides org.gradle.usage 'java-runtime' but the consumer didn't ask for it

我一直在处理Gradle任务的以下内容,似乎我尝试在Module2-aar的类Path上迭代时,就会生成错误消息。

我还尝试了许多其他建议,例如将Module2-aar的依赖性声明从

api  project(':module2-aar')

TO

api  project(path:':module2-aar')

更改,但是我也没有

尝试过任何事情:

api project(path: ':module1-aar', configuration: 'default')

虽然以上解决了报告的问题,但它会导致编译问题,使Module2-AAR不可能在编译期间,似乎在类路径中具有模块1-aar,并且似乎在Module1-aar之前进行了编译。

不幸的是,配置的文档表示在引用Android项目时有点薄,或者我在错误的位置上寻找。我不确定还有哪些有效值可用。

无论如何,除了在这方面花费太多时间,我不确定这里有什么问题。

I have an android gradle project structure that looks like this

  • module1-aar
  • module2-aar
  • testapp-apk

Key facts

  • module2-aar depends on module1-aar
  • testapp-apk depends on module2-aar
  • JDK11
  • Gradle 7.4.2
  • Android gradle plugin 7.1.3

Without javadocs, gpg, signing, or publishing, everything builds just fine. App runs, everything is great.

When i started adding in tasks to generate javadocs, that's when everything went haywire. module1-aar will build and generate javadocs with no problem. module2-aar however always fails during the javadoc task.

Task is below. Most of it was borrowed from here How to generate javadoc for android library when it has dependencies which are also aar libraries?

project.task("javadoc", type: Javadoc) {
    afterEvaluate {
        configurations.all
                .each {item ->
                    item.setCanBeResolved(true)
                }

        classpath += configurations.api
        classpath += configurations.implementation
        // Wait after evaluation to add the android classpath
        // to avoid "buildToolsVersion is not specified" error
        classpath += files(android.getBootClasspath())

        // Process AAR dependencies
        def aarDependencies = classpath.filter { it.name.endsWith('.aar') }
        classpath -= aarDependencies
        //fails here when an AAR depends on an AAR
        aarDependencies.each { aar ->
            // Extract classes.jar from the AAR dependency, and add it to the javadoc classpath
            def outputPath = "$buildDir/tmp/aarJar/${aar.name.replace('.aar', '.jar')}"
            classpath += files(outputPath)

            // Use a task so the actual extraction only happens before the javadoc task is run
            dependsOn task(name: "extract ${aar.name}").doLast {
                extractEntry(aar, 'classes.jar', outputPath)
            }
        }

    }

    source = android.sourceSets.main.java.srcDirs
    classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
    classpath += project.files(android.getBootClasspath())
    classpath += configurations.implementation
    classpath += fileTree(dir: project.buildDir.absolutePath + "/tmp/aarsToJars/")
    classpath += files(project.buildDir.absolutePath + "/intermediates/compile_r_class_jar/release/R.jar")
    classpath += files(project.buildDir.absolutePath + "/generated/source/buildConfig/release/release")
    classpath += files(project.buildDir.absolutePath + "/generated/source/r/buildConfig/release/release")
    destinationDir = file( project.buildDir.absolutePath + "/outputs/javadoc/")
     failOnError true
    options.charSet 'UTF-8'
    options.docEncoding 'UTF-8'
    options.encoding 'UTF-8'
    options.addBooleanOption 'Xdoclint:none', true
    exclude '**/BuildConfig.java'
    exclude '**/R.java'
    exclude '**/doc-files/*'
}


// Utility method to extract only one entry in a zip file
private def extractEntry(archive, entryPath, outputPath) {
    if (!archive.exists()) {
        throw new GradleException("archive $archive not found")
    }

    def zip = new java.util.zip.ZipFile(archive)

    zip.entries().each {
        if (it.name == entryPath) {
            def path = new File(outputPath)

            if (!path.exists()) {
                path.getParentFile().mkdirs()

                // Surely there's a simpler is->os utility except
                // the one in java.nio.Files? Ah well...
                def buf = new byte[1024]
                def is = zip.getInputStream(it)
                def os = new FileOutputStream(path)
                def len

                while ((len = is.read(buf)) != -1) {
                    os.write(buf, 0, len)
                }
                os.close()
            }
        }
    }
    zip.close()
}

//wires in the javadoc task to the normal build
tasks.named("build") { finalizedBy("generateJavadocJar") }

The error message i'm getting is the following

* What went wrong:
A problem occurred configuring project ':module2-aar'.
> Could not resolve all files for configuration ':module2-aar:implementation'.
   > Could not resolve project :module1-aar.
     Required by:
         project :module2-aar
      > Cannot choose between the following variants of project :module1-aar:
          - debugRuntimeElements
          - releaseRuntimeElements
        All of them match the consumer attributes:
          - Variant 'debugRuntimeElements' capability com.github.test:module1-aar:6.1.11-SNAPSHOT:
              - Unmatched attributes:
                  - Provides com.android.build.api.attributes.AgpVersionAttr '7.1.3' but the consumer didn't ask for it
                  - Provides com.android.build.api.attributes.BuildTypeAttr 'debug' but the consumer didn't ask for it
                  - Provides com.android.build.gradle.internal.attributes.VariantAttr 'debug' but the consumer didn't ask for it
                  - Provides org.gradle.usage 'java-runtime' but the consumer didn't ask for it
          - Variant 'releaseRuntimeElements' capability com.github.test:module1-aar:6.1.11-SNAPSHOT:
              - Unmatched attributes:
                  - Provides com.android.build.api.attributes.AgpVersionAttr '7.1.3' but the consumer didn't ask for it
                  - Provides com.android.build.api.attributes.BuildTypeAttr 'release' but the consumer didn't ask for it
                  - Provides com.android.build.gradle.internal.attributes.VariantAttr 'release' but the consumer didn't ask for it
                  - Provides org.gradle.usage 'java-runtime' but the consumer didn't ask for it

I've been playing around with the gradle task a bit and it seems that the error message is generated anytime i attempt to iterate over the classpath of the module2-aar.

I have tried a number of other suggestions, like changing module2-aar's dependency declaration from

api  project(':module2-aar')

to

api  project(path:':module2-aar')

However that doesn't do anything

I also tried this:

api project(path: ':module1-aar', configuration: 'default')

While the above resolves the reported issue, it causes a compile issue whereby module2-aar doesn't appear to have module1-aar in the classpath during compile...and it seems to compile before module1-aar.

Unfortunately, the documentation for what configuration means when referencing an android project is a bit thin, or perhaps I'm looking in the wrong place. I'm not sure what other valid values are available.

Anyhow, I'm not sure what's wrong here other than I've spent way too much time on this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

睫毛溺水了 2025-01-28 22:54:32

我将发布我的解决方案,以解决Javadoc中使用“ AAR”文件的问题。在试图解决问题的过程中,我也遇到了与间谍所指的相同错误。实际上,错误意味着它可以区分它应该使用发布还是调试库。在我看来,尝试纠正该问题是太徒劳的,因此,我采用了另一种方法来解决我认为本质上的问题。

就我而言,我有一个包含多个子项目的项目,当我制作Javadoc文档时,我想制作一个合并的Javadoc文档,其中仅包括一些子项目(不是所有的子项目)。据我所知,这不是Android Studio内置的功能。当前版本的Android Studio(2021.2.1)似乎在为Android库模块生成Javadoc文档时遇到了问题。有两个问题:

1。)Javadoc Class Path没有添加Android引导类。您会发现引用任何Android SDK方法(例如“上下文”,“字体”等)的错误

。2。2.)Javadoc Class Path不会在其中添加任何Androidx库。许多Androidx库是“ AAR”文件。使用Javadoc时,Android Studio(2021.2.1)无法正确处理AAR文件。

我的环境类似于间谍,除了我使用的是Android Gradle插件7.2.0。我已经在“应用”模块的build.gradle.kts脚本中创建了一个自定义的Javadoc任务。我的“应用程序”模块是一个Android应用程序模块。该代码需要放置在包含插件“ com.android.application”或“ com.android.library”插件的任何模块中。我生产合并的Javadoc的一些模块是Java库,这没关系。

 // create a custom configuration  
 val javadocDeps = configurations.create("javadocDeps")

 // add javadoc dependencies that you need.
 dependencies {
     javadocDeps(project(":OsgiFramework"))
     // note: I'm using a libs version catalog for the dependencies
     // you can add hardwired dependencies if you prefer
     javadocDeps (libs.androidx.appcompat)
     javadocDeps (libs.androidx.fragment)
     javadocDeps (libs.androidx.navigation.fragment)
     javadocDeps (libs.androidx.navigation.ui)
     javadocDeps (libs.androidx.constraint.layout)
 }

 // register the createCoreJavadoc task
 // in my case, "gradlew app:createCoreJavadoc" creates the merged javadoc 
 tasks {
    register<Javadoc>("createCoreJavadoc") {
        setFailOnError(true)
        val docDir: File = File(project.projectDir.parentFile.parentFile, "Doc/Core")
        println("javadoc destination dir: " + docDir.absolutePath)
        // set the location where the documentation is produced in
        setDestinationDir(docDir)

        // select the projects to produce merged javadoc for
        var sourcepaths: FileCollection = project(":CoreInterfaces").files("src/main/java")
        sourcepaths =
            sourcepaths.plus(project(":CoreInternalInterfaces").files("src/main/java"))
        sourcepaths = sourcepaths.plus(project(":CoreAndroidInterfaces").files("src/main/java"))
        sourcepaths =
            sourcepaths.plus(project(":CoreAndroidInternalInterfaces").files("src/main/java"))
        sourcepaths = sourcepaths.plus(project(":OsgiInterface").files("src/main/java"))
        sourcepaths =
            sourcepaths.plus(project(":InstallPlanInterfaces_1_0_0").files("src/main/java"))
        setSource(sourcepaths.asFileTree)


        // fix the problem with the missing android bootclasses
        android.bootClasspath.forEach{
            classpath += fileTree(it)
        }

        // create a temporary directory for storing the "classes.jar" file contained in the *.aar files
        val tmpDir:File = File(project.buildDir, "\\tmpAar\\")
        if (tmpDir.exists()) tmpDir.delete()
        tmpDir.mkdirs()
        // add the javadoc dependencies
        javadocDeps.forEach {
            // I've got a custom class that allows me to treat jar or zip files and a file system
            // you could replace this using spy's zip file extraction method
            val zipFileSystem: com.phinneyridge.ZipFileSystem = ZipFileSystem(it.absolutePath,null)
            if (it.name.endsWith(".aar")) {
                // extract the classes.jar file from the aar file to the tmpDir
                // renaming it to name of the aar file, but change the extension to jar
                val tmpFile:File = File(tmpDir, it.name.replace(".aar", ".jar"))
                zipFileSystem.extractEntry("classes.jar", tmpFile)
            } else {
                // for jar files, we just add it to the path
                classpath += fileTree(it)
            }
        }
        // now add the tmpDir files to the javadoc classpath
        classpath += fileTree(tmpDir)
        // for diagnosis purposes, we'll print the classpath.
        // Notice that you have a lot more path entries then you have javadocDeps
        println("classpath: " + classpath.asPath)

    }
}

I going to publish my solution to the problem of using "aar" files in javadoc. In the course of trying to solve the problem, I too, had been getting the same error that spy was referring to. That actually error means it can differentiate whether it should be using release or debug libraries. It seemed to me to be too futile to try and correct that issue, so instead, I took a different approach to solving what I think is essentially the same problem.

In my case, I have a project that contains multiple subprojects, and when I produce my javadoc documentation I wanted to produce a merged javadoc document, that consisted of just some of the subprojects (not all of the subprojects). As far as I know, this is not a capability, built into Android Studio. The current version of Android Studio(2021.2.1) seems to have problems producing javadoc documentation for android library modules. There are two issues:

1.) the javadoc classpath doesn't have the android bootclasses added. You get errors for referencing any android SDK method such as "Context", "Typeface", etc.

2.) the javadoc classpath doesn't get any AndroidX libraries added to it. Many of the AndroidX libraries are "aar" files. Android Studio(2021.2.1) does not handle aar files correctly when using javadoc.

My environment is similar to spy, except that I'm using android gradle plugin 7.2.0. I've created a custom javadoc task in the "app" module's build.gradle.kts script. My "app" module is an android application module. The code needs to be place in any module that contains either the plugin "com.android.application" or "com.android.library". Some of the modules that I produce the merged javadoc for are java libraries, and that's okay.

 // create a custom configuration  
 val javadocDeps = configurations.create("javadocDeps")

 // add javadoc dependencies that you need.
 dependencies {
     javadocDeps(project(":OsgiFramework"))
     // note: I'm using a libs version catalog for the dependencies
     // you can add hardwired dependencies if you prefer
     javadocDeps (libs.androidx.appcompat)
     javadocDeps (libs.androidx.fragment)
     javadocDeps (libs.androidx.navigation.fragment)
     javadocDeps (libs.androidx.navigation.ui)
     javadocDeps (libs.androidx.constraint.layout)
 }

 // register the createCoreJavadoc task
 // in my case, "gradlew app:createCoreJavadoc" creates the merged javadoc 
 tasks {
    register<Javadoc>("createCoreJavadoc") {
        setFailOnError(true)
        val docDir: File = File(project.projectDir.parentFile.parentFile, "Doc/Core")
        println("javadoc destination dir: " + docDir.absolutePath)
        // set the location where the documentation is produced in
        setDestinationDir(docDir)

        // select the projects to produce merged javadoc for
        var sourcepaths: FileCollection = project(":CoreInterfaces").files("src/main/java")
        sourcepaths =
            sourcepaths.plus(project(":CoreInternalInterfaces").files("src/main/java"))
        sourcepaths = sourcepaths.plus(project(":CoreAndroidInterfaces").files("src/main/java"))
        sourcepaths =
            sourcepaths.plus(project(":CoreAndroidInternalInterfaces").files("src/main/java"))
        sourcepaths = sourcepaths.plus(project(":OsgiInterface").files("src/main/java"))
        sourcepaths =
            sourcepaths.plus(project(":InstallPlanInterfaces_1_0_0").files("src/main/java"))
        setSource(sourcepaths.asFileTree)


        // fix the problem with the missing android bootclasses
        android.bootClasspath.forEach{
            classpath += fileTree(it)
        }

        // create a temporary directory for storing the "classes.jar" file contained in the *.aar files
        val tmpDir:File = File(project.buildDir, "\\tmpAar\\")
        if (tmpDir.exists()) tmpDir.delete()
        tmpDir.mkdirs()
        // add the javadoc dependencies
        javadocDeps.forEach {
            // I've got a custom class that allows me to treat jar or zip files and a file system
            // you could replace this using spy's zip file extraction method
            val zipFileSystem: com.phinneyridge.ZipFileSystem = ZipFileSystem(it.absolutePath,null)
            if (it.name.endsWith(".aar")) {
                // extract the classes.jar file from the aar file to the tmpDir
                // renaming it to name of the aar file, but change the extension to jar
                val tmpFile:File = File(tmpDir, it.name.replace(".aar", ".jar"))
                zipFileSystem.extractEntry("classes.jar", tmpFile)
            } else {
                // for jar files, we just add it to the path
                classpath += fileTree(it)
            }
        }
        // now add the tmpDir files to the javadoc classpath
        classpath += fileTree(tmpDir)
        // for diagnosis purposes, we'll print the classpath.
        // Notice that you have a lot more path entries then you have javadocDeps
        println("classpath: " + classpath.asPath)

    }
}
刘备忘录 2025-01-28 22:54:32

我了解您有这样的项目结构:app - &gt; module2 - &gt; module1。

其中 - &gt; 表示依赖关系流。因此,我部署了一个具有相同依赖性流量的项目,但是使用Gradle 7.0.2(因为这是我当前正在使用的),并且没有问题为Module2和Module1生成Javadoc,

基本上可以归结为在每个级别中实现它模块: https://stackoverflow.com/a/a/a/a/a/73096187/9902249

我希望它为您服务。

I understand that you have a project structure like this: app -> module2 -> module1.

Where -> means the dependency stream. So I deployed a project with that same dependency flow, but using gradle 7.0.2 (because that's what I'm currently using), and had no problem generating javadoc for module2 and module1

Basically it boils down to implementing this in every gradle of every module: https://stackoverflow.com/a/73096187/9902249

I hope it works for you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文