Transcoder代码学习-项目构建

244 阅读6分钟

Transcoder代码学习-核心代码

Transcoder项目构建分析

一、项目架构

1. 模块结构

Transcoder项目采用多模块架构,包含三个主要模块:

  • lib: 核心库模块

    • Maven坐标:io.deepmedia.community:transcoder-android
    • 包名:io.deepmedia.transcoder
    • 核心功能实现
    • 构建产物:
      • transcoder-android-0.11.2.aar
      • transcoder-android-0.11.2-sources.jar
      • transcoder-android-0.11.2-javadoc.jar
      • transcoder-android-0.11.2.pom
  • lib-legacy: 遗留兼容模块

    • Maven坐标:com.otaliastudios:transcoder
    • 包名:com.otaliastudios.transcoder
    • 兼容层实现
    • 构建产物:
      • transcoder-0.11.2.aar
      • transcoder-0.11.2-sources.jar
      • transcoder-0.11.2-javadoc.jar
      • transcoder-0.11.2.pom
  • demo: 示例应用模块

    • 展示库的使用方法
    • 测试和验证功能
    • 构建产物:demo-debug.apk, demo-release.apk

2. 依赖关系

demo
  ├── :lib
  │    ├── com.otaliastudios.opengl:egloo:0.6.1
  │    └── androidx.annotation:annotation:1.8.2
  ├── com.google.android.material:material:1.12.0
  └── androidx.appcompat:appcompat:1.7.0

lib-legacy
  └── :lib (api)

lib
  ├── com.otaliastudios.opengl:egloo:0.6.1
  └── androidx.annotation:annotation:1.8.2

3. 兼容性设计

lib-legacy模块通过巧妙的设计实现向后兼容:

  1. 无源码设计:仅包含构建配置,所有功能委托给lib模块
  2. API透明转发:使用api依赖确保完整暴露lib模块的API
  3. 包名保持:维护原有的包名空间
  4. Maven坐标兼容:保留原始的groupId和artifactId

二、构建系统设计

1. 插件体系

1.1 Android Gradle Plugin (AGP)
  • 完整名称:com.android.library
  • 版本:8.2.2
  • 配置位置:build.gradle.kts
  • 主要任务:
    • assembleDebug: 构建调试版本
    • assembleRelease: 构建发布版本
    • bundleDebugAar: 打包调试AAR
    • bundleReleaseAar: 打包发布AAR
    • generateDebugBuildConfig: 生成调试构建配置
    • generateReleaseBuildConfig: 生成发布构建配置
  • 配置示例:
plugins {
    id("com.android.library") version "8.2.2"
    id("org.jetbrains.kotlin.android") version "1.9.0"
}

android {
    namespace = "io.deepmedia.transcoder"
    compileSdk = 34
    
    defaultConfig {
        minSdk = 21
        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }
    
    buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"))
        }
    }
}
1.2 Deployer插件
  • 完整名称:io.deepmedia.tools.deployer
  • 版本:0.8.0
  • 配置位置:build.gradle.kts
  • 主要任务:
    • publishToMavenLocal: 发布到本地Maven仓库
    • publishToSonatype: 发布到Maven Central
    • publishToGitHub: 发布到GitHub Packages
    • signReleasePublication: 对发布构件进行签名
  • 配置示例:
plugins {
    id("io.deepmedia.tools.deployer") version "0.8.0"
}

projectInfo {
    groupId = "io.deepmedia.community"
    artifactId = "transcoder-android"
    release.version = "0.11.2"
    description = "Android video transcoder"
    url = "https://github.com/natario1/Transcoder"
    
    developer {
        id = "natario1"
        name = "Mattia Iavarone"
        email = "mat.iavarone@gmail.com"
    }
}

content {
    component {
        fromSoftwareComponent("release")
        docs(javadocs)
        kotlinSources()
    }
}

deployer {
    nexusSpec("release") {
        repository = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/"
        auth.user = secret("SONATYPE_USER")
        auth.password = secret("SONATYPE_PASSWORD")
    }
    
    githubSpec {
        auth.token = secret("GITHUB_TOKEN")
        owner = "natario1"
        repository = "Transcoder"
    }
    
    signing {
        key = secret("SIGNING_KEY")
        password = secret("SIGNING_PASSWORD")
    }
}
1.3 Dokka插件
  • 完整名称:org.jetbrains.dokka
  • 版本:1.9.20
  • 配置位置:lib/build.gradle.kts
  • 主要任务:
    • dokkaJavadoc: 生成Javadoc格式文档
    • dokkaJavadocJar: 打包Javadoc为JAR文件
  • 配置示例:
plugins {
    id("org.jetbrains.dokka") version "1.9.20"
}

dependencies {
    dokkaPlugin("org.jetbrains.dokka:android-documentation-plugin:1.9.20")
}

val javadocs = tasks.register<Jar>("dokkaJavadocJar") {
    dependsOn(tasks.dokkaJavadoc)
    from(tasks.dokkaJavadoc.flatMap { it.outputDirectory })
    archiveClassifier.set("javadoc")
}

2. 构建流程

2.1 基础构建阶段 (AGP)
  1. 编译源代码
    • 输入:src/main/java, src/main/kotlin
    • 输出:build/intermediates/javac, build/tmp/kotlin-classes
  2. 处理资源文件
    • 输入:src/main/res, src/main/assets
    • 输出:build/intermediates/compiled_local_resources
  3. 生成AAR文件
    • 输入:编译后的类文件和处理后的资源
    • 输出:build/outputs/aar/lib-release.aar
2.2 文档生成阶段 (Dokka)
  1. 解析源代码注释
    • 输入:src/main/java, src/main/kotlin
    • 输出:build/dokka/html
  2. 生成API文档
    • 输入:解析后的文档数据
    • 输出:build/dokka/javadoc
  3. 打包为javadoc.jar
    • 输入:build/dokka/javadoc
    • 输出:build/libs/lib-javadoc.jar
2.3 发布准备阶段 (Deployer)
  1. 配置Maven POM信息
    • 输入:projectInfo配置
    • 输出:build/publications/release/pom-default.xml
  2. 整合构建产物
    • 输入:
      • AAR:build/outputs/aar/lib-release.aar
      • 源码:build/libs/lib-sources.jar
      • 文档:build/libs/lib-javadoc.jar
    • 输出:build/publications/release
  3. 生成元数据文件
    • 输入:整合后的构建产物
    • 输出:
      • MD5:*.md5
      • SHA1:*.sha1
      • SHA256:*.sha256
      • 签名:*.asc
2.4 部署阶段 (Deployer)
  1. 验证构件完整性
    • 检查所有必需文件是否存在
    • 验证校验和
    • 验证签名
  2. 处理认证信息
    • 读取环境变量中的密钥
    • 配置仓库认证信息
  3. 执行上传操作
    • 上传所有构件和元数据
    • 验证上传结果

3. 关键编译命令

3.1 完整构建命令
# 清理构建目录
./gradlew clean

# 构建所有模块
./gradlew build

# 构建并发布到本地Maven仓库
./gradlew publishToMavenLocal

# 构建并发布到Maven Central
./gradlew publishToSonatype

# 构建并发布到GitHub Packages
./gradlew publishToGitHub
3.2 单模块构建命令
# 构建lib模块
./gradlew :lib:build

# 构建lib-legacy模块
./gradlew :lib-legacy:build

# 构建demo模块
./gradlew :demo:build
3.3 文档生成命令
# 生成HTML文档
./gradlew dokkaHtml

# 生成Javadoc
./gradlew dokkaJavadoc

# 生成Markdown文档
./gradlew dokkaGfm

4. 关键任务分析

4.1 AGP核心任务
assembleDebug
├── compileDebugKotlin
├── compileDebugJavaWithJavac
├── processDebugManifest
├── processDebugResources
└── packageDebugAssets

assembleRelease
├── compileReleaseKotlin
├── compileReleaseJavaWithJavac
├── processReleaseManifest
├── processReleaseResources
└── packageReleaseAssets

bundleReleaseAar
├── assembleRelease
├── bundleLibRuntimeToJar
└── copyDebugJniLibsProjectAndLocalJars
4.2 Dokka任务链
dokkaHtmlJar
├── dokkaHtml
│   └── koltinSourcesJar
└── jarHtml

dokkaJavadocJar
├── dokkaJavadoc
│   └── koltinSourcesJar
└── jarJavadoc

dokkaGfmJar
├── dokkaGfm
│   └── koltinSourcesJar
└── jarGfm
4.3 Deployer任务链
deployLocal
├── generatePomFileForReleasePublication
├── publishReleasePublicationToLocalRepository
└── signReleasePublication

deployToSonatype
├── generatePomFileForReleasePublication
├── publishReleasePublicationToSonatypeRepository
└── signReleasePublication

deployToGitHub
├── generatePomFileForReleasePublication
├── publishReleasePublicationToGitHubPackagesRepository
└── signReleasePublication
4.4 发布相关任务
publish
├── publishToMavenLocal
│   └── deployLocal
├── publishToSonatype
│   └── deployToSonatype
└── publishToGitHub
    └── deployToGitHub

signReleasePublication
├── generatePomFileForReleasePublication
└── signAllReleasePublications

generatePomFileForReleasePublication
├── bundleReleaseAar
└── dokkaJavadocJar
4.5 任务输入输出
assembleRelease任务
  • 输入:
    • src/main/java/
    • src/main/kotlin/
    • src/main/res/
    • src/main/assets/
    • AndroidManifest.xml
  • 输出:
    • build/intermediates/aar_main_jar/release/classes.jar
    • build/intermediates/compile_library_classes_jar/release/classes.jar
    • build/intermediates/runtime_library_classes_jar/release/classes.jar
    • build/intermediates/packaged_res/release/
    • build/intermediates/library_manifest/release/
dokkaJavadocJar任务
  • 输入:
    • src/main/java/
    • src/main/kotlin/
    • build/tmp/kapt3/stubs/
  • 输出:
    • build/dokka/javadoc/
    • build/libs/lib-javadoc.jar
deployLocal任务
  • 输入:
    • build/outputs/aar/lib-release.aar
    • build/libs/lib-javadoc.jar
    • build/libs/lib-sources.jar
    • build/publications/release/pom-default.xml
  • 输出:
    • build/inspect/[group]/[artifact]/[version]/
      • transcoder-android-0.11.2.aar (lib模块)
      • transcoder-android-0.11.2.pom
      • transcoder-android-0.11.2-javadoc.jar
      • transcoder-android-0.11.2-sources.jar
      • transcoder-0.11.2.aar (lib-legacy模块)
      • transcoder-0.11.2.pom
      • transcoder-0.11.2-javadoc.jar
      • transcoder-0.11.2-sources.jar
      • *.md5
      • *.sha1
      • *.sha256
      • *.asc

注意:输出路径是通过Deployer插件的localSpec配置指定的:

localSpec {
    directory.set(rootProject.layout.buildDirectory.get().dir("inspect"))
    signing {
        key = absent()
        password = absent()
    }
}
4.6 任务配置示例
Dokka任务配置
tasks.named<org.jetbrains.dokka.gradle.DokkaTask>("dokkaHtml") {
    outputDirectory.set(buildDir.resolve("dokka/html"))
    dokkaSourceSets {
        configureEach {
            includeNonPublic.set(false)
            skipDeprecated.set(false)
            reportUndocumented.set(true)
            skipEmptyPackages.set(true)
        }
    }
}

tasks.register<Jar>("dokkaJavadocJar") {
    dependsOn(tasks.dokkaJavadoc)
    from(tasks.dokkaJavadoc.flatMap { it.outputDirectory })
    archiveClassifier.set("javadoc")
}
Deployer任务说明

Deployer插件会根据配置自动生成以下发布任务:

  • deployLocal: 发布到本地Maven仓库

    • 自动依赖:generatePomFileForReleasePublication
    • 自动依赖:publishReleasePublicationToLocalRepository
    • 自动依赖:signReleasePublication
    • 执行命令:./gradlew deployLocal
  • deployToSonatype: 发布到Maven Central

    • 自动依赖:generatePomFileForReleasePublication
    • 自动依赖:publishReleasePublicationToSonatypeRepository
    • 自动依赖:signReleasePublication
    • 执行命令:./gradlew deployToSonatype
  • signReleasePublication: 对发布构件进行签名

    • 自动依赖:generatePomFileForReleasePublication
    • 自动配置:在生成POM文件后执行

这些任务都是由Deployer插件根据projectInfodeployer配置块自动生成的,不需要手动注册。只需要在build.gradle.kts中配置好相关信息,插件就会自动创建和配置这些任务。

三、插件协作机制

1. AGP与Dokka协作

  • 共享源代码目录结构
  • 支持Android构建变体
  • 处理Android资源引用

2. Dokka与Deployer协作

  • 文档生成任务集成
  • 构件打包协调
  • 发布流程整合

3. AGP与Deployer协作

  • 软件组件共享
  • 构建变体处理
  • 构件生成同步

四、发布策略

1. 多仓库支持

  • 本地Maven仓库
  • Maven Central
  • GitHub Packages

2. 构件管理

  • AAR文件
  • 源代码JAR
  • 文档JAR
  • POM文件
  • 元数据文件

3. 版本控制

  • 版本号管理
  • 版本号应用
  • 版本更新流程

总结

1. 架构设计优势

  • 清晰的模块结构,职责分明
  • 优雅的兼容性解决方案
  • 合理的依赖管理策略

2. 构建系统特点

  • 三大核心插件协同工作
  • 完善的任务依赖链
  • 清晰的执行流程

3. 发布流程亮点

  • 多仓库支持
  • 完整的构件集
  • 安全的认证机制

4. 最佳实践启示

  • 模块化设计促进代码复用
  • 自动化构建提高效率
  • 标准化发布流程保证质量
  • 完善的文档支持易于维护

这些特点使得Transcoder项目不仅具有良好的可维护性和可扩展性,也为其他Android库项目提供了值得借鉴的最佳实践。