繁体   English   中英

当它具有也是 aar 库的依赖项时,如何为 android 库生成 javadoc?

[英]How to generate javadoc for android library when it has dependencies which are also aar libraries?

我有依赖于其他 android 库项目的 android 库项目。 我需要为库生成 javadoc,但它失败了,因为 gradle 将 javadoc 类路径放入 .aar 位置,但 javadoc 需要 .jar 文件。

简化的gradle文件:

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    configurations {
        javadocDeps
    }

    defaultConfig {
        minSdkVersion 7
        targetSdkVersion 23
        versionCode 1
        versionName "0.1.0"
    }
}

dependencies {
    compile 'com.android.support:support-v4:23.2.0'
    compile 'com.android.support:appcompat-v7:23.2.0'
    compile 'com.nineoldandroids:library:2.4.0'
    compile 'com.annimon:stream:1.0.7'
    javadocDeps 'com.android.support:support-annotations:23.2.0'
    javadocDeps 'com.nineoldandroids:library:2.4.0'
    javadocDeps 'com.android.support:support-v4:23.2.0'
}

task sourcesJar(type: Jar) {
    from android.sourceSets.main.java.srcDirs
    classifier = 'sources'
}    

task javadoc(type: Javadoc, dependsOn: explodeAars) {
    source = android.sourceSets.main.java.srcDirs
    classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
    classpath += configurations.javadocDeps
}

task javadocJar(type: Jar, dependsOn: javadoc) {
    classifier = 'javadoc'
    from javadoc.destinationDir
}

artifacts {
    archives javadocJar
    archives sourcesJar
}

3种可能的解决方案:

1)以某种方式从它依赖的每个aar库中添加到类路径路径classes.jar build/intermidiates/exploded-aar/library/version/jars/classes.jar 我不知道如何在javadoc任务中包含这些路径。

2)从aar文件中手动解压classes.jar并将它们添加到javadoc任务的类路径中

3)非常肮脏的黑客 - 库的硬编码路径 - 但我认为这是非常错误的。

如何使用 gradle dsl 实现 1 或 2?

我设法通过提取每个 AAR 文件中包含的classes.jar并将其添加到 javadoc 任务的类路径来自动化Guillaume Perrot的解决方案。

它似乎适用于 Android Studio 2.3 和 Gradle 3.3 上的 AAR 依赖项和 AAR 模块

import java.nio.file.Files
import java.nio.file.Paths
import java.io.FileOutputStream
import java.util.zip.ZipFile

task javadoc(type: Javadoc) {
    source = android.sourceSets.main.java.srcDirs
    classpath += configurations.compile
    classpath += configurations.provided

    afterEvaluate {
        // 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
        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)
            }
        }
    }
}

// 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 ZipFile(archive)
    zip.entries().each {
        if (it.name == entryPath) {
            def path = Paths.get(outputPath)
            if (!Files.exists(path)) {
                Files.createDirectories(path.getParent())
                Files.copy(zip.getInputStream(it), path)
            }
        }
    }
    zip.close()
}

这仅适用于早于 2.3 的 Android Studio 和/或早于 3.3 的 Gradle

要从 AAR 添加 JAR,您可以将以下doFirst添加到 javadoc 任务:

task javadoc(type: Javadoc) {
    source = android.sourceSets.main.java.srcDirs
}
.doFirst {
    classpath += fileTree(dir: "$buildDir/intermediates/exploded-aar/", include:"**/classes.jar")
}

它将所有 AAR 中的所有.jar文件添加到 javadoc 类路径。 (您提出的解决方案中的选项1)

@rve 的解决方案现在在 Android Studio 2.3 / Gradle 3.3 上被破坏,因为exploded-aar不再存在(在构建目录中没有替代方案)。

如果您依赖的 aar 不是项目中的模块,则需要先提取 classes.jar,然后在类路径中引用它(基本上手动重新创建intermediates/exploded-aar )。

如果您依赖的 aar 只是项目中的另一个模块,您还可以使您的 javadoc 任务依赖于该模块的编译任务并引用该模块的intermediates/classes/release (如果您使 javadoc 依赖于 assembleRelease 例如) . 该解决方法的一个示例: https ://github.com/Microsoft/mobile-center-sdk-android/pull/345/files

我真的希望有人提出更好的解决方案。

我正在运行新的 Android Studio 3.0-beta7,并尝试使用@nicopico 的答案,但它因许多不同的错误而失败,所以这里有一个不依赖于不存在的java.nio实用程序的改编版。

task javadoc(type: Javadoc) {
    failOnError false
    source = android.sourceSets.main.java.srcDirs
    // Also add the generated R class to avoid errors...
    // TODO: debug is hard-coded
    source += "$buildDir/generated/source/r/debug/"
    // ... but exclude the R classes from the docs
    excludes += "**/R.java"

    // TODO: "compile" is deprecated in Gradle 4.1, 
    // but "implementation" and "api" are not resolvable :(
    classpath += configurations.compile

    afterEvaluate {
        // 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
        aarDependencies.each { aar ->
            System.out.println("Adding classpath for aar: " + aar.name)
            // Extract classes.jar from the AAR dependency, and add it to the javadoc classpath
            def outputPath = "$buildDir/tmp/exploded-aar/${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)
            }
        }
    }
}

// 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()
}

困扰我的是,我们需要所有这些代码来为库生成一个可怕的 javadoc,但至少我得到了这个工作。 但是,我确实需要为 configuration.api 和 configuration.implementation 无法解决找到解决方法。

这就是我使用zipTree解决这个问题的方法。 配置:Gradle 4.10,Gradle 插件:3.3.2,Android Studio:3.4。

task javadoc(type: Javadoc) {

    doFirst {
        configurations.implementation
                .filter { it.name.endsWith('.aar') }
        .each { aar ->
            copy {
                from zipTree(aar)
                include "**/classes.jar"
                into "$buildDir/tmp/aarsToJars/${aar.name.replace('.aar', '')}/"
            }
        }
    }

    configurations.implementation.setCanBeResolved(true)
    source = android.sourceSets.main.java.srcDirs
    classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
    classpath += configurations.implementation
    classpath += fileTree(dir: "$buildDir/tmp/aarsToJars/")
    destinationDir = file("${project.buildDir}/outputs/javadoc/")
    failOnError false
    exclude '**/BuildConfig.java'
    exclude '**/R.java'
}

如果您正在使用 Kotlin 开发 Android 应用程序/库,则此处列出的所有解决方案都已过时。 要生成 javadocs 以及其他几种格式的文档,请使用 KDoc 和 Dokka:

https://kotlinlang.org/docs/kotlin-doc.html

https://kotlin.github.io/dokka/1.5.0/

https://github.com/Kotlin/dokka

我在Android AAR 上发布了针对此问题的解决方案,具体取决于 AAR failed with javadoc generation 我认为 Johann 评论列出的解决方案已过时可能是正确的,但 mike192 解决方案看起来相当不错,尽管我认为它在处理 androidx 依赖项时可能存在问题。 我还没有尝试过 KDoc 和 Dokka,但是在查看文档时,这看起来很有希望。 希望它适用于android java库。 android studio 的内置 javadoc 工具 (2021.2.1) 在处理该模块类型时存在问题; 因此需要构建一个自定义的 javadoc 任务来解决这些问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM