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从开发到分发的完整链路。你看,每个阶段都有对应的工具和规范。少了任何一个环节,后面都会出问题。
我个人习惯在项目启动时就搭好这套流程。虽然前期会多花一两天时间,但后面省下的时间绝对值得。你想想看,如果每次发布都要手动操作,那得浪费多少精力?
一个小建议:
刚开始做包管理时,别追求大而全。先把「版本号规范」和「发布流程自动化」这两件事做好。其他的,比如多架构产物管理、依赖冲突自动检测,可以慢慢完善。一口吃不成胖子,对吧?
好了,这一章的内容就到这里。包管理这件事,说难不难,说简单也不简单。关键是要有规范、有工具、有流程。后面几章我会具体讲每个环节的实践细节,包括怎么搭私有仓库、怎么自动化发布、怎么处理依赖冲突……
可可精品资料库