故事要从一个使用
Cocoapods
的iOS App
的打包失败说起。[15:26:05] PhaseScriptExecution [CP]\ Copy\ Pods\ Resources /Users/xxx/workspace/xxx/a_long_long_long_long_long_long_name_branch/build/DerivedData/Build/Intermediates.noindex/ArchiveIntermediates/xxx/IntermediateBuildFilesPath/xxx.build/Distribute-iphoneos/xxx.build/Script-0302CB0D9AE3A46FDE5C4AE2.sh (in target 'xxx' from project 'xxx') [15:26:05] cd /Users/xxx/workspace/xxx/a_long_long_long_long_long_long_name_branch [15:26:05] /bin/sh -c /Users/xxx/workspace/xxx/a_long_long_long_long_long_long_name_branch/build/DerivedData/Build/Intermediates.noindex/ArchiveIntermediates/xxx/IntermediateBuildFilesPath/xxx.build/Distribute-iphoneos/xxx.build/Script-0302CB0D9AE3A46FDE5C4AE2.sh [15:26:05] error: unable to spawn process '/bin/sh' (Argument list too long) (in target 'xxx' from project 'xxx')
大概几个月前,当构建机打包报这个错误时,我是懵逼的,但既来之则安之,既然是
too long
,那就将分支名改短一点再试试吧。因为构建的工作目录带了分支名,改短之后,立竿见影,构建通过,暂告一段落。
后来有同事也遇到同样报错,我就果断表示,改短分支名,问题解决。这是构建机的环境问题,暂时也不容易推动完美解决,甩锅完毕。
再后来,越来越频繁有同事遇到同样报错,甚至这分支名也不算很长,看来事情没这么简单。
Google+Stackoverflow
之前在有空的时候,去看一下,这个
Copy Pods Resources
是我们熟悉的Cocoapods
的脚本,顾名思义,其实就是将Pods
里的资源复制到app
的生成目录。日志里的
xxx.build/Script-0302CB0D9AE3A46FDE5C4AE2.sh
其实就长这个样子。#!/bin/sh "${PODS_ROOT}/Target Support Files/Pods-xxx/Pods-xxx-resources.sh"
实际执行的脚本是
Pods-xxx-resources.sh
,大概流程就是将所有资源文件的路径逐个写入一个RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt
的文本文件中,然后执行rsync
进行批量复制。rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
这时候怀疑这个批量复制引起的
Argument list too long
,毕竟工程中这个资源列表近150个,的确不少。然而实际上,在复制之前,
install_resource
里的一个echo
都没打在日志里就已经报错了。echo "$RESOURCE_PATH" || true echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY"
那就说明脚本基本没怎么开始执行就报错。
好家伙,难道这个
unable to spawn process '/bin/sh'
跟这个Pods-xxx-resources.sh
没有关系?这就超出我的认知了呀。
所以当今天决定要一探究竟的时候,我是谨慎的。
首先,关闭自研的编译缓存,关闭所有自己注入的脚本。无效。
然后,搜索关键字
Copy Pods Resources unable to spawn process '/bin/sh' (Argument list too long)
,参考网友的各种办法Pods
版本1.7.5升级为1.8.4和1.10.1,亲测无效
New Build System
改为过时的Legacy Build System
,懒得去试
- 将
resource_bundles
的Resources/**/*
改为Resources/**/*.xcassets
,亲测无效
- 将
app
的xcconfig
的HEADER_SEARCH_PATHS
减少,这也难不到我,但也亲测无效
然后干脆,保留远程
Pods
的资源,暂时屏蔽所有本地Pods
资源,构建成功!spec.resource_bundles = nil
其实这也可以解释,
Argument list too long
嘛,这个list
减少了相当一部分,当然是有效果的。那好,还原所有本地
Pods
资源,尝试在本地模拟。但无论在
Pods-xxx-resources.sh
增加几百个install_resource
,还是增加长长路径的几百个Input Files
,本地打包都是成功的。然后对比一下环境。构建机和我本地的
Xcode
都是12.4的版本。执行命令
getconf ARG_MAX
,我本地macOS
11.2.3系统是1048576(1024k),构建机的macOS
10.15.7系统是262144(256k),不过我也不明白同样是macOS
为什么不一样。是的,我本地的
ARG_MAX
是比较大,难道是我模拟加的几百个还不够吗?这时,我突然意识到,我对
Xcode
这个Input Files
和Output Files
的作用其实不甚理解。科普一下,参考
apple
的介绍。引用关键的一段,很明显,就是用来加速增量编译的。
Specifically, Xcode runs your script when any of the following conditions are true:
Your script doesn’t have any input files.
Your script doesn’t have any output files.
Your script’s input files changed.
Your script’s output files are missing.
然后我在本地的
Xcode
里,将Copy Pods Resources
的Input Files
和Output Files
手动清空,再将Xcode
的缓存删一部分,编译,成功,没毛病。好家伙,那将构建机的
Input Files
和Output Files
也清空就完事了呀,构建机又没有这个资源缓存,不需要加速效果。然后就找到标题中的解决方案了。这样看来,这其实就是
Xcode
的Bug
。install! 'cocoapods', :disable_input_output_paths => true
只要再加个判断,只在构建机环境开启这个属性,不影响开发机的日常增量编译。
看来还是对
Xcode
和Cocoapods
不够熟悉啊。另外下次可以直接去GitHub
搜索issue
试试。
Loading Comments...