03|环境准备:把工具链装得服服帖帖

做SDK集成,说白了就是给不同平台搭积木。但积木之间的插口对不上,神仙也救不了。所以环境准备这步,我每次都不敢马虎。你想想看,一个依赖版本不对,编译花半小时才发现,心态直接崩掉。

3.1 开发工具的选择

我个人的习惯是:每个平台用官方推荐的主力工具,别整花活。三大平台的最低配置清单如下:

平台必装工具版本要求我踩过的坑
AndroidAndroid Studio + JDKJDK 11+ / AGP 7.x+JDK 8 编译新AGP直接报错
iOSXcode + CocoaPods / SPMXcode 14+ / iOS 13+Xcode-beta 发布时记得切stable
WebVS Code + Node.jsNode.js 18+ / npm 9+低版本npm lockfile冲突频繁

嗯,这里要注意:Android SDK 路径别带空格,我曾经项目路径里有个空格,Gradle 解析文件死活找不到本地仓库,折腾了两小时。

我的小建议:装好工具后,先跑官方 demo 验证环境。
如果 demo 都编译不过,一定是工具链的问题,不是你的代码问题。

3.2 依赖管理:Gradle

Android 用 Gradle + Maven 仓库。说白了就是把 SDK 的 aar/jar 包地址写在 build.gradle 里。但这里门道不少。

// app/build.gradle
dependencies {
    implementation 'com.example:sdk-core:2.1.0'
    // 如果你要调试本地版本
    // implementation files('libs/sdk-core-2.1.0.aar')
}

我在项目中遇到过最头疼的事:transitive dependencies 自动拉进来的库和宿主冲突。比如你 SDK 依赖了 okhttp 4.10,而宿主项目用了 okhttp 3.12,运行期直接 NoSuchMethodError。解决方案?

  • 在发布 SDK 时尽量用 compileOnly 或 provided 声明可选依赖
  • 在接入方的 gradle 里显式排除:exclude group: 'com.squareup.okhttp3'
  • 或者干脆让宿主统一管理版本——用 BOM 或 version catalog 都行

曾经有个教训:我发布 SDK 时用了 implementation 依赖了一个内部库,结果宿主引了两个冲突的版本,Android 打包时直接 duplicate class。后来我全部改成 api + transitive = false,才稳住。

3.3 依赖管理:CocoaPods

iOS 我最常用 CocoaPods。其实 Swift Package Manager 也不错,但很多旧版三方库还没完全适配,所以我个人还是优先 CocoaPods。

# Podfile
platform :ios, '13.0'
target 'YourApp' do
  pod 'YourSDK', '~> 3.0'
end

你可能会问:为什么不直接用 Swift Package?我的看法是:如果你的接入方还在用 CocoaPods,你也必须提供 Podspec。另外,CocoaPods 的 use_frameworks! 开关要注意:

  • use_frameworks!:生成动态 framework,支持 Swift 混编
  • 不写:默认静态库,包体积小但 Objective-C 只能用
  • 如果 SDK 内用了 Swift,必须开 use_frameworks!

嗯,这里有个坑:如果宿主项目同时用了 use_frameworks! 和静态库形式的其他 Pod,链接时可能报错 duplicate symbol。我曾经被迫把整个 SDK 改成只支持动态 framework 来规避。

3.4 依赖管理:npm

Web 端最简单,也最容易翻车。npm 的 package.json 里声明依赖,但经常被忽略的细节是:peerDependencies 和 bundleDependencies。

// package.json
{
  "name": "your-sdk",
  "version": "2.0.0",
  "peerDependencies": {
    "react": ">=17.0.0",
    "react-dom": ">=17.0.0"
  },
  "optionalDependencies": {
    "canvas": "^2.9.0"
  }
}

为什么要用 peerDependencies?因为你的 SDK 如果锁死了 react 版本,宿主那边用 18 就不兼容了。peerDependencies 可以告诉 npm:「我的宿主自己装 react,版本别低于 17 就行」。

避坑指南:npm 7+ 会自动安装 peerDependencies,如果版本冲突会报错。
我曾经在 CI 上遇到 npm 7 自动装了 react 18,而我的 SDK 需要 react 17,结果 Hook 报错。后来我在 .npmrc 里加了 legacy-peer-deps=true 才跳过。

3.5 构建系统配置速查

这里我把三个平台的构建配置关键差异整理成了表格,方便你以后查阅:

项目Android (Gradle)iOS (CocoaPods)Web (npm)
配置文件build.gradle.kts / .gradlePodfile + .podspecpackage.json
仓库声明repositories { mavenCentral() }source 'https://cdn.cocoapods.org/'"registry": "https://registry.npmjs.org"
版本约束implementation('1.+') 不推荐pod 'SDK', '~> 2.0'"^2.0.0" (semver)
本地调试implementation files('...')pod 'SDK', :path => '../local'npm link 或 file:../
构建缓存.gradle/ 目录~/Library/Caches/CocoaPodsnode_modules/

你看,每个平台的配置思路都差不多,但细节不同。比如版本约束:Gradle 用 + 太危险,npm 用 ^ 相对安全,CocoaPods 的 ~> 则只允许最后一段浮动。不建议混着用思维。

3.6 跨平台开发者的「通用工具箱」

如果你同时维护 Android、iOS、Web 三端的 SDK,我建议你准备以下东西:

  • 统一的文档站点:每个平台写一页集成指南,方便自己查
  • CI 上的构建验证脚本:每次发版前自动编译各大平台的 demo app
  • 本地代理仓库:比如用 Artifactory 或 Nexus 缓存远程依赖,避免重复下载

我个人还有一个习惯:在每个项目的根目录下放一个 env-check.sh,自动检测 JDK、Xcode、Node 版本,确保所有开发者用的环境一致。这东西花十分钟写一次,能救你无数个小时的 debug 时间。

▸ 环境准备 · 知识体系 SDK多平台环境准备 Android (Gradle) iOS (CocoaPods) Web (npm) JDK 11+ / AGP 7.x+ mavenCentral / jitpack implementation / api / compileOnly Xcode 14+ / iOS 13+ Podfile + .podspec :path / :git 本地调试 Node.js 18+ / npm 9+ package.json / .npmrc peerDependencies / npm link 避坑共性:版本冲突、缓存清理、本地调试路径、CI一致性