1. Sonoma下安装CocoaPods为什么总是翻车
1.1 系统自带Ruby的那个"坑"
2024年把Mac升级到Sonoma之后,很多iOS开发者做的第一件事就是打开终端,敲下那句看了无数遍的命令:
gem install cocoapods然后下一秒就被红色报错糊了一脸:
ERROR: While executing gem ... (Gem::FilePermissionError) You don't have write permissions for the /Library/Ruby/Gems/2.6.0 directory.这不是你操作失误,而是Sonoma系统下安装CocoaPods最典型的宿命。原因是macOS Sonoma自带的是Ruby 2.6.10版,而系统为了保护核心文件,把/usr/bin/ruby、/Library/Ruby/Gems这些目录统统划进了系统保护区域。普通用户没有写权限,默认也不建议你硬用sudo去破解——因为一旦你sudo gem install cocoapods,就会往系统Ruby目录里塞一堆依赖,看起来装上了,但下次系统升级可能直接给你重置掉,甚至你更新系统后碰到权限冲突,整个Gem环境直接坏掉。
所以,Sonoma下装CocoaPods的根本问题不是你敲错了命令,而是你在用系统Ruby做不该由它做的事。
1.2 Ruby版本冲突到底冲突在哪
社区里常说的"Ruby版本冲突",本质上有三层意思:
第一层,是系统Ruby版本太老。CocoaPods官方文档写的支持区间是Ruby 2.6+,但2024年最新版的CocoaPods(1.15.x)在安装依赖时,很多gem的最新版本已经慢慢开始要求Ruby >= 2.7或更高,系统自带的2.6.10虽然旧,但未必报错,却会经常遇到某些依赖的编译问题——因为新版activesupport等gem在Ruby 2.6下面已经不属于官方重点测试范围了。
第二层,是PATH路径错乱。很多人之前可能用Homebrew装过Ruby,或者装过RVM,导致系统里同时存在好几个Ruby环境。当你执行ruby -v时看到的是3.x,但gem install装到的却是另一个路径下的gems,然后pod命令找不到,或者找到了又加载了旧版本的库,报一堆dyld: Library not loaded之类的错。
第三层,是权限与配置互相纠缠。系统Ruby被SIP保护,Homebrew的Ruby在/usr/local/opt/ruby或/opt/homebrew/opt/ruby,如果你混着用,gem的安装路径、环境变量、PATH顺序全都会打架。
解决思路很清晰:不要碰系统Ruby,自己装一个用户级别的Ruby,并且让这个Ruby成为当前shell里的唯一默认环境。这件事,rbenv做得比RVM干净得多。
2. 安装前的环境检查:先把家底摸清楚
2.1 确认系统版本和芯片类型
动手之前,先花一分钟看清自己的环境。在终端里依次执行:
sw_vers uname -m第一条命令会显示系统版本,比如14.5之类的,确认是Sonoma系列就行。第二条命令输出arm64说明是M1/M2/M3芯片的Apple Silicon机器,输出x86_64说明是Intel芯片的老机器。
这个信息很重要,因为后续Homebrew的安装路径不一样:Apple Silicon机器的Homebrew装在/opt/homebrew,Intel机器装在/usr/local。很多报错其实都是因为自己手动改PATH时写错路径导致的。
2.2 检查Ruby、Homebrew、CommandLineTools三件套
接着检查以下几个内容:
ruby -v which ruby gem -v which gem brew -v xcode-select -p正常情况下,你大概率会看到:
ruby是/usr/bin/ruby,版本2.6.10gem是/usr/bin/gem- Homebrew可能已经装好,也可能提示
command not found xcode-select -p如果输出/Library/Developer/CommandLineTools或者/Applications/Xcode.app/Contents/Developer,说明命令行工具没问题。
如果没有装Homebrew,先装。方法很简单,官方一行命令:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"这里多说一句,国内网络环境下如果这条命令执行很慢,可以把脚本下载后改国内镜像源再跑,或者直接先配置Git的代理镜像。整体上,Homebrew安装到机器没有坑,最辛苦的是后面brew install rbenv时如果遇到网络问题,可以在下面第3节里用我给出的镜像方案解决。
如果xcode-select -p报错,先执行:
xcode-select --install弹出的窗口点安装,装完再检查。这一步不做,后面rbenv install编译Ruby时百分之百会失败,因为需要一个能用的C编译器(clang)。
2.3 验证一个关键点:当前Gem目录归属
有时候你之前折腾过,机器里已经有多个Ruby了。这时执行:
gem env home如果输出是/Library/Ruby/Gems/2.6.0,说明gem还在系统目录下,后面需要彻底切换到新环境。如果输出的是~/.rbenv/versions/xxx/lib/ruby/gems/...,说明你可能之前装过rbenv,那就直接跳到第3节检查版本即可。
这一步建议认真看,因为很多报错"看起来"是CocoaPods的问题,实际上是你把gem装到了一个自己都不知道是哪里的目录。
3. 用rbenv管理Ruby版本:一劳永逸的核心方案
3.1 为什么选rbenv而不是RVM
很多老教程会推荐RVM,但我的建议是:新项目一律用rbenv。
RVM的机制是替换shell函数,会在你cd进目录时自动切换Ruby版本,还能管理gemset,功能强大,但对新手来说太"重"了,而且它会在~/.rvm下维护一大堆逻辑,一旦和系统Ruby混用,PATH环境变量很容易乱。
rbenv的机制则很朴素:它只是把~/.rbenv/shims目录放到PATH最前面,这个目录里放了一堆"代理程序"(shims),当你输入ruby、gem、pod时,实际执行的是shims里的软链脚本,由rbenv根据你当前设定的版本,把真正执行权交给~/.rbenv/versions/<version>/bin/下的对应程序。
一句话总结:rbenv做的唯一一件事就是管理PATH,干净、透明、好排查。
3.2 安装rbenv和ruby-build
用Homebrew安装是最省事的方式:
brew update brew install rbenv ruby-buildruby-build是rbenv的插件,负责从源码编译Ruby各版本。安装完成后执行:
rbenv -v能输出版本号就说明装好了。
这里有个国内用户很容易踩的坑:后续执行rbenv install 3.2.2时,ruby-build会先从GitHub下载Ruby源码包,网络差的时候会卡在Downloading ruby-3.2.2.tar.gz...这一步。解决办法是给ruby-build设置一个镜像环境变量:
export RUBY_BUILD_MIRROR_URL='https://mirrors.ustc.edu.cn/ruby-build/'然后再执行install命令,下载速度完全不一样。这个变量只在当前终端有效,如果之后要多次安装,建议把它写进~/.zshrc。
3.3 配置zsh环境变量:最容易遗忘的一步
如果你是macOS默认的zsh,安装完rbenv后需要手动把初始化代码加进~/.zshrc。官方推荐的是这三行:
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.zshrc echo 'if command -v rbenv >/dev/null; then eval "$(rbenv init -)"; fi' >> ~/.zshrc source ~/.zshrc第一行把rbenv的命令路径加进PATH,第二行让当前shell初始化rbenv的shims,第三行让配置立即生效。
很多人装完rbenv后直接rbenv install报command not found,或者装完Ruby后gem还是指向系统Ruby,百分之九十都是因为这一步没做,或者做完了没开新终端。要验证配置是否成功,执行:
which rbenv如果输出~/.rbenv/bin/rbenv(或者/opt/homebrew/bin/rbenv),就OK了。
3.4 安装指定版本的Ruby:推荐3.2.x
先看一下有哪些版本可以装:
rbenv install -l列表会很长,建议装3.2.2或3.2.3。这个版本经过2024年大量iOS项目的验证,和最新版CocoaPods兼容性最好。不建议一上来就追最新3.3.x,虽然理论上没问题,但有些老项目里的gem原生扩展在3.3上编译容易遇到小毛病,犯不着给自己添堵。
执行安装:
rbenv install 3.2.2这条命令会花几分钟,因为是从源码编译,期间你可能会看到刷屏的编译日志,耐心等就行。如果过程中有BUILD FAILED的提示,多半是缺少CommandLineTools或者网络问题,回到第2.2节检查一下。
装完后设置全局默认版本:
rbenv global 3.2.2这一步会生成一个~/.rbenv/version文件,内容就是3.2.2,告诉rbenv:以后所有shell默认都用这个版本。
然后执行:
ruby -v which ruby正常情况下ruby -v会显示ruby 3.2.2,which ruby会指向~/.rbenv/shims/ruby。看到这个结果,环境就对了。
3.5 性能提效:gem源换不换一句话说清
Ruby的gem源默认是https://rubygems.org/,国内访问速度不稳定。建议换成清华的镜像源:
gem sources --remove https://rubygems.org/ gem sources --add https://mirrors.tuna.tsinghua.edu.cn/rubygems/执行完用:
gem sources -l确认源列表里只剩一个https://mirrors.tuna.tsinghua.edu.cn/rubygems/就行。这一步不影响后续任何操作,只是让gem install从下载到结束快很多。
4. 安装CocoaPods:从命令行到第一个项目
4.1 正式安装:不需要sudo
现在Ruby环境已经切到rbenv管理的3.2.2了,直接执行:
gem install cocoapods注意,这次前面不需要加sudo。因为rbenv把gems装到了~/.rbenv/versions/3.2.2/lib/ruby/gems/,用户目录下的写入权限完全没问题。
安装过程中会拉取一堆依赖gem,包括activesupport、xcodeproj、cocoapods-core、cocoapods-downloader等等,如果换过源的话,一两分钟就能装完。如果卡在某个原生扩展的编译上,八成是CommandLineTools的问题,回到第2.2节。
装完以后执行验证:
pod --version能看到版本号(比如1.15.2)就说明CocoaPods装好了。如果提示command not found:pod,别慌,执行一下:
rbenv rehashrehash的作用是让rbenv重新扫描所有已安装gem的可执行文件,在shims目录里生成对应的代理命令。每次你通过gem安装或卸载了任何自带命令行的gem,都习惯性执行一次就不会错。
4.2 多个Ruby版本之间切换的坑
有些老项目可能要求Ruby 2.7或3.0,如果你用rbenv切到了另一个版本,比如:
rbenv global 3.0.2那这个shell里的pod可能又找不到了。这是正常的,因为每个Ruby版本下的gems是独立的,你在3.2.2里装的CocoaPods,3.0.2里当然没有。
处理办法有两种:
- 切到对应版本后重新
gem install cocoapods - 或者在项目目录里建一个
.ruby-version文件,写上3.2.2,rbenv会在你进入这个目录时自动切换版本
我个人用后者最多,因为iOS老项目如果带了.ruby-version文件,团队协作时大家本地环境就能一致起来,少踩很多奇怪的兼容性问题。
4.3 验证并初始化一个测试项目
为了确认CocoaPods真的能用,不要省这一步。随便建个测试目录:
mkdir ~/pod-test cd ~/pod-test pod init执行完pod init后,目录里会多出一个Podfile。打开看一眼内容,默认是给iOS平台准备的:
# Uncomment the next line to define a global platform for your project # platform :ios, '11.0'然后执行:
pod install这一步如果你没有在Podfile里写任何依赖,实际会很快完成,并生成Podfile.lock。看到类似:
Pod installation complete! There are 0 dependencies from the Podfile and 0 total pods installed.就说明整个链路是通的。以后你只需要把真正的第三方库写进Podfile,执行pod install就会拉取依赖并生成.xcworkspace文件,记得打开工程时用.xcworkspace而不是.xcodeproj,CocoaPods的依赖才会被正确引用。
5. 常见错误与排错实录:你踩过的坑我基本都踩过
5.1 "You don't have write permissions" 经典权限报错
现象
ERROR: While executing gem ... (Gem::FilePermissionError) You don't have write permissions for the /Library/Ruby/Gems/2.6.0 directory.原因
你还在用系统Ruby,gem要往系统目录写文件,但没有权限。
解决
别试sudo gem install cocoapods!这个命令确实能装成功,但它会污染系统Ruby环境,后续升级系统或安装其他Ruby相关工具时很容易出问题。
正确做法是走第3节的rbenv方案。如果你已经装了rbenv但还报这个错,看ruby -v是不是3.2.2,which gem是不是~/.rbenv/shims/gem,确认rbenv global 3.2.2生效后再试。
5.2rbenv: version 'X.X.X' is not installed版本没装上
现象
执行rbenv global 3.2.2报错说3.2.2不存在。
原因
安装过程失败了但你没注意到日志,或者安装根本没开始。
解决
用rbenv versions查看当前已装的版本。如果列表里没有,就重新执行:
rbenv install 3.2.2如果卡在下载,就用第3.2节提到的RUBY_BUILD_MIRROR_URL环境变量走镜像。如果编译中途失败,看日志里有没有failed to build gem native extension或clang: error之类字样,有的话先装CommandLineTools。
还有一种情况很隐蔽:你执行rbenv install时用了sudo。rbenv不能配合sudo用,因为sudo会把当前用户环境变量重置掉,装出来的文件归属也会变成root用户,后面各种奇怪权限问题都会冒出来。
5.3pod: command not found装完却找不到命令
现象
gem install一切正常,但执行pod --version提示找不到命令。
原因
可能性很多,按顺序排查:
- 先检查
rbenv rehash是否执行过; which pod看看是不是指向~/.rbenv/shims/pod;- 如果还是找不到,
gem list cocoapods看看gem是否真的存在; - 如果gem存在但shim没有,删掉
~/.rbenv/shims下的pod再rehash一次,往往能解决。
解决
rbenv rehash pod --version我遇到过最无语的情况是:~/.zshrc里的PATH顺序不对,导致系统在rbenv的shims之前找到了另一个版本的pod。查看一下:
echo $PATH确保~/.rbenv/shims在/usr/bin之前。
5.4 卡在activesupport编译:缺少命令行工具
现象
gem install cocoapods时长时间卡在类似:
Building native extensions. This could take a while...然后报:
ERROR: Failed to build gem native extension.原因
CocoaPods的依赖链里有activesupport等gem,为了性能会编译原生扩展(比如json gem的C扩展),这个动作需要调用系统的clang编译器。如果没有Xcode CommandLineTools,或者装了Xcode但路径不对,就会失败。
解决
xcode-select --install装完后重新执行gem install cocoapods。如果已经装了Xcode但还是报错,执行:
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer手动指定开发者目录,再次尝试。
5.5 问题速查表
| 报错现象 | 根本原因 | 推荐解法 |
|---|---|---|
Gem::FilePermissionError | 使用了系统Ruby | 换rbenv安装3.2.x版本Ruby |
rbenv: version not installed | 版本未安装/安装失败 | rbenv install 3.2.2,必要时配镜像 |
pod: command not found | shims未生成或PATH顺序错误 | rbenv rehash,检查PATH |
Failed to build gem native extension | 缺少CommandLineTools | xcode-select --install |
dyld: Library not loaded | 多个Ruby环境路径污染 | 重装rbenv并清理~/.zshrc中的多余Ruby配置 |
| 下载Ruby源码卡死 | 网络问题 | 设置RUBY_BUILD_MIRROR_URL为国内镜像 |
gem install下载很慢 | gem源网络不稳定 | 换清华gem源,见第3.5节 |
6. Sonoma下的几个额外小提醒
6.1 新系统上Terminal的权限弹窗
Sonoma对终端app的权限提示比之前更严格,第一次在终端里访问~/Desktop、~/Documents、~/Downloads这些目录时会弹授权窗口,点允许就行。这个和CocoaPods本身没关系,但如果你的项目放在桌面上,pod install时偶发找不到路径,先去系统设置里给终端加上"完全磁盘访问权限",就能根治。
6.2 不要为了省事直接改系统Ruby
我见过很多人用sudo gem install cocoapods -n /usr/local/bin这种方式,把pod命令塞到/usr/local/bin,绕过权限限制。短期看能用,但系统升级时一旦Ruby版本被刷新,这些gem就会变成孤儿文件,甚至因为Gem环境不一致,pod初始化时反复崩溃。我的建议是:既然已经深入到了安装工具的层面,就一次把环境理顺,rbenv方案的成本其实只有十几分钟。
6.3 每次新开终端后确认环境
如果你配置好了rbenv,但换了个终端窗口,ruby -v又回到2.6.10了,那一定是~/.zshrc没刷新或者没写对。新开终端会自动加载~/.zshrc,正常不该出现这种情况。如果出现,检查:
cat ~/.zshrc | grep rbenv看看那三行初始化代码是不是真的在。如果之前用的是bash,后来切到了zsh,之前写入~/.bash_profile的配置不会对zsh生效,需要同步写一份。
6.4 团队协作时把Ruby版本固定下来
最后分享一个我自己的习惯:如果项目团队不只你一个人,我强烈建议在仓库根目录创建.ruby-version文件,内容写3.2.2。这样所有成员一旦用rbenv,进入目录后就会自动切到相同版本,CocoaPods的lock文件、原生扩展的编译行为都会更统一,省掉"我本地能跑你本地为啥不行"的口水战。
这块我在实际项目中试过,团队里有人用3.0.2,有人用3.2.2,最后发现某人本地安装某依赖时出现了只有新版Ruby才有的编译问题,而老版Ruby又因为某个API废弃而报warning。统一版本后,沟通成本立刻降了下来。