1. 包管理概述

1.1 为什么我们需要包管理

做SDK开发这些年,我越来越觉得包管理是个被低估的环节。很多人觉得不就是把代码打个包嘛,有什么好讲的?

其实不然。你想想看,一个SDK从开发到交付,中间要经历多少环节:依赖管理、版本控制、构建产物、文档、示例代码……如果没有一套规范的包管理流程,这些环节很快就会变成一团乱麻。

我个人习惯把包管理比作「厨房里的调料架」。你做饭的时候,盐、糖、酱油各归其位,拿起来顺手。但如果所有调料都堆在一个袋子里,你炒菜时就得翻半天——这就是没有包管理的下场。

包管理的核心价值:

  • 依赖解析——自动处理SDK与第三方库的版本关系
  • 版本控制——确保每次发布的内容可追溯、可回滚
  • 构建标准化——不同环境、不同平台产出一致的产物
  • 分发效率——让用户能快速集成,而不是手动下载一堆文件

我在项目中遇到过最典型的例子:有个团队做Android SDK,每次发布都是手动打AAR包,然后上传到内部FTP。结果有一次,开发A上传了v2.0.1,开发B也上传了v2.0.1,两个包内容不一样……用户那边集成时直接崩溃。你说这锅该谁背?

1.2 SDK包管理的痛点

做SDK包管理,和做普通应用开发完全是两码事。我踩过的坑,随便数数就有好几个。

痛点一:依赖冲突

这是最头疼的。你的SDK依赖了OkHttp 3.12,用户的App里也依赖了OkHttp,但版本是4.0。两个版本不兼容,用户一跑就报ClassNotFoundException。

更麻烦的是,有些依赖是「传递性」的。你依赖了库A,库A又依赖了库B,库B又依赖了库C……这链条一长,版本冲突的概率就指数级上升。

我曾经踩过的坑:

有一次发布iOS SDK,我依赖了一个第三方加密库。结果用户反馈说他们的App里也有这个库,但版本不同。两个库的符号冲突,链接阶段直接报duplicate symbol。最后我不得不把那个加密库的源码直接嵌入到SDK里,并做了符号重命名——折腾了两天。

痛点二:产物碎片化

一个SDK往往要支持多个平台、多个架构。Android有armeabi-v7a、arm64-v8a、x86、x86_64;iOS有armv7、arm64、模拟器架构。再加上不同的构建配置(Debug/Release)、不同的API版本……

产物一多,管理就乱。我见过有人把不同架构的.so文件放在同一个目录下,结果用户集成时不知道该用哪个。还有人把Debug版和Release版搞混,用户拿到的SDK里全是调试日志。

痛点三:版本号管理混乱

版本号怎么定?语义化版本(SemVer)大家都懂,但真正执行起来,很多人就放飞自我了。

我见过最离谱的版本号:v2.0.0-final-3-fix-hotfix-20211231。你告诉我这是哪个版本?

问题类型 典型表现 后果
版本号不规范 随意加后缀、不遵循SemVer 用户无法判断兼容性
版本号重复 不同构建打出相同版本号 缓存混乱、无法追溯
版本号跳跃 从v1.0直接跳到v3.0 用户不敢升级

痛点四:文档与产物脱节

SDK发布了,但文档没更新。用户拿着新版本的SDK,看着旧版本的文档,API都对不上。这种问题我遇到太多次了。

说白了,包管理不只是管「包」,还要管「包」相关的所有元信息——文档、变更日志、示例代码、许可证……这些信息如果和包本身分离,用户用起来就特别痛苦。

1.3 现代包管理工具生态概览

好在现在工具链已经成熟了很多。我按平台给大家梳理一下。

Android / Java 生态

  • Maven Central——老牌仓库,Java生态的基石。但发布流程比较繁琐,审核也慢。
  • JitPack——直接从GitHub构建,省事。适合小团队快速发布。
  • GitHub Packages——和GitHub深度集成,权限管理方便。我最近在用它。
  • 本地Maven仓库——适合内部SDK,不对外公开。

我的建议:

如果是商业SDK,建议用Maven Central + 私有仓库的组合。Maven Central做公开分发,私有仓库做内部测试版。这样既保证了公信力,又控制了发布节奏。

iOS / macOS 生态

  • CocoaPods——最主流,生态最丰富。但依赖解析速度慢,大型项目容易卡。
  • Carthage——轻量级,去中心化。适合对构建速度有要求的团队。
  • Swift Package Manager (SPM)——苹果官方出品,集成度最高。我建议新项目优先考虑SPM。

嗯,这里要注意:SPM虽然好,但有些老旧的第三方库还不支持。如果你的SDK依赖了这些库,可能还得用CocoaPods做过渡。

跨平台 / 其他生态

  • npm——JavaScript生态的王者。现在很多跨平台SDK(比如React Native、Flutter的插件)都用它。
  • NuGet——.NET生态的标准。做Unity SDK的应该很熟悉。
  • Conan——C/C++生态的包管理器。虽然小众,但做底层SDK的团队可以考虑。

1.4 包管理核心流程

说了这么多,我画了一张图来总结包管理的核心流程。这张图我每次做培训都会用,算是我的「压箱底」了。

SDK包管理核心流程 阶段1:开发 代码编写 依赖声明 阶段2:构建 编译打包 依赖解析 阶段3:发布 版本标记 上传仓库 分发 关键活动 依赖管理 解析传递依赖 处理版本冲突 版本管理 语义化版本 变更日志维护 产物管理 多架构产物 产物签名校验 主流工具生态 Maven / Gradle CocoaPods / SPM npm / NuGet Conan / vcpkg

这张图展示了一个SDK从开发到分发的完整链路。你看,每个阶段都有对应的工具和规范。少了任何一个环节,后面都会出问题。

我个人习惯在项目启动时就搭好这套流程。虽然前期会多花一两天时间,但后面省下的时间绝对值得。你想想看,如果每次发布都要手动操作,那得浪费多少精力?

一个小建议:

刚开始做包管理时,别追求大而全。先把「版本号规范」和「发布流程自动化」这两件事做好。其他的,比如多架构产物管理、依赖冲突自动检测,可以慢慢完善。一口吃不成胖子,对吧?

好了,这一章的内容就到这里。包管理这件事,说难不难,说简单也不简单。关键是要有规范、有工具、有流程。后面几章我会具体讲每个环节的实践细节,包括怎么搭私有仓库、怎么自动化发布、怎么处理依赖冲突……

可可精品资料库