Argument list too long 与 disable_input_output_paths
Tags
iOS
Date
Apr 24, 2021
故事要从一个使用CocoapodsiOS 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没有关系?
 
这就超出我的认知了呀。
 
notion image
 
所以当今天决定要一探究竟的时候,我是谨慎的。
 
首先,关闭自研的编译缓存,关闭所有自己注入的脚本。无效。
 
然后,搜索关键字Copy Pods Resources unable to spawn process '/bin/sh' (Argument list too long),参考网友的各种办法
 
  1. Pods版本1.7.5升级为1.8.4和1.10.1,亲测无效
  1. New Build System改为过时的Legacy Build System,懒得去试
  1. resource_bundlesResources/**/*改为Resources/**/*.xcassets,亲测无效
  1. appxcconfigHEADER_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,我本地macOS11.2.3系统是1048576(1024k),构建机的macOS10.15.7系统是262144(256k),不过我也不明白同样是macOS为什么不一样。
 
是的,我本地的ARG_MAX是比较大,难道是我模拟加的几百个还不够吗?
 
这时,我突然意识到,我对Xcode这个Input FilesOutput 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 ResourcesInput FilesOutput Files手动清空,再将Xcode的缓存删一部分,编译,成功,没毛病。
 
好家伙,那将构建机的Input FilesOutput Files也清空就完事了呀,构建机又没有这个资源缓存,不需要加速效果。
 
然后就找到标题中的解决方案了。这样看来,这其实就是XcodeBug
install! 'cocoapods', :disable_input_output_paths => true
只要再加个判断,只在构建机环境开启这个属性,不影响开发机的日常增量编译。
 
看来还是对XcodeCocoapods不够熟悉啊。另外下次可以直接去GitHub搜索issue试试。
 

Loading Comments...