您现在的位置是:首页 > 文章详情

shell技巧6 - iOS最大构建版本文件大小

日期:2019-05-05点击:367

1、前言

在上传提交ipa文件成功后,发现AppStoreConnect后台一直不显示构建版本,最后邮箱收到:

App Store Connect

Dear Developer,

We identified one or more issues with a recent delivery for your app, "XXX". Please correct the following issues, then upload again.
Invalid Executable Size - The size of your app's executable file 'XXX.app/XXX' is 90374144 bytes, which exceeds the maximum allowed size of 80 MB.
Best regards,
The App Store Team

2、原因

Executable Sizeexecutable file ?这2个是什么东西?Executable 是可执行的意思,所以就是可执行的大小、可执行的文件。
每个 Mach-O 可执行文件(例如,app_name.app/app_name)不得超过这些正文段(__TEXT)文件大小的上限。具体 Mach-O 和 __TEXT 是什么,大家可以看看:ObjC 中国 - Mach-O 可执行文件

那从苹果文档最大构建版本文件大小 - App Store Connect 帮助,可以得到如下:

OS 版本 最大可执行文件大小 备注
iOS 9.0 或更高版本
Apple TVOS 9.0 或更高版本
500 MB 针对二进制文件中所有“__TEXT”部分的总和。
iOS 7.X 至 iOS 8.X 60 MB 针对每个 Architecture Slice(架构片段)中的“__TEXT”部分。
低于 iOS 7.0 80 MB 针对二进制文件中所有“__TEXT”部分的总和。
  • 注:Architecture Slice(架构片段)是针对特定架构的胖二进制布局文件的一部分。例如,一个胖二进制文件可能会包含针对 32 位和 64 位架构的片段。

综上,executable file 'XXX.app/XXX' is 90374144 bytes, which exceeds the maximum allowed size of 80 MB. 就是说,当前可执行文件“__TEXT”部分的总和为 90374144 bytes,超过了 80 MB

  • 是什么?
    当前可执行文件“__TEXT”部分的总和大小超过80MB!
  • 为什么?
    Mach-O可执行文件中包含__TEXT区域,__TEXT包含了被执行的代码,即编译所得到的机器码。所以,也就是我们的应用中代码量或引用的第三方库过大导致。
  • 怎么办?
    因为苹果限制,所以,

    • 第1步是减少第三方库或删除无用的代码。
    • 第2步是要找到什么计算__TEXT的大小?

3、__TEXT大小计算

怎么计算 __TEXTsize ? 在终端用 size XXX就可以打印当前应用的二进制的__TEXT字段大小:

 ~ size /Users/HTC/Downloads/WeChat/Payload/WeChat.app/WeChat __TEXT __DATA __OBJC others dec hex 53329920 7929856 0 3162112 64421888 3d70000 /Users/HTC/Downloads/WeChat/Payload/WeChat.app/WeChat (for architecture armv7) 57475072 13647872 0 4298047488 4369170432 1046c4000 /Users/HTC/Downloads/WeChat/Payload/WeChat.app/WeChat (for architecture arm64) ~ 

注:如果应用支持armv7arm64多种架构,就会显示多个,不会有i386x86_64是因为dis正式包已经移除模拟器架构。像现在新的应用,只支持arm64就不会显示具体架构:

 ~ size /Users/HTC/Downloads/Weixin/Payload/WeChat.app/WeChat __TEXT __DATA __OBJC others dec hex 65355776 15040512 0 4298145792 4378542080 104fb4000

那么知道了计算公式,根据上面苹果给出的文档要求,需要做应用最低支持系统版本判断计算方式:

  1. iOS 7.X 至 iOS 8.X 每个架构最大为 60 MB
  2. iOS 9.0 或更高版本 500 MB 针对二进制文件中所有“__TEXT”部分的总和。
  3. 低于 iOS 7.0 80 MB 针对二进制文件中所有“__TEXT”部分的总和。

根据这个要求,会出现如下2种计算方式:

  • 计算所有“__TEXT”部分的总和
size app | awk '{print $1}' | grep -E '[0-9]' | awk '{sum += $1}; END {print sum}'

运行示例:

 ~ size /Users/HTC/Downloads/WeChat/Payload/WeChat.app/WeChat | awk '{print $1}' | grep -E '[0-9]' | awk '{sum += $1}; END {print sum}' 110804992

脚本说明:首先是用size 列出全部的架构的__TEXT大小,然后用 awkawk文本处理实战 | opengers)过滤出第一列的内容输出,然后用grep -E(扩展的正则表达式)过滤数字的行,最后是计算各行数字相加的和输出。

  • 分别列出各架构的大小
size app | awk '{print $1 "," $10}' | tail -n +2

运行示例:

 ~ size /Users/HTC/Downloads/WeChat/Payload/WeChat.app/WeChat | awk '{print $1 "," $10}' | tail -n +2 53329920,armv7) 57475072,arm64)

脚本说明:首先是用size 列出全部的架构的__TEXT(第1列)大小和架构名(第10列),之前用分号,间隔,然后输出,然后用 tail 输出从第2行开始的内容。

以上就是本文的核心内容,具体shell的技巧就不深讲啦,大家有兴趣可以搜索,awktail 命令了解更多,awk文本处理实战 | opengersLinux tail 命令 | 菜鸟教程

4、shell 编程实现

需要注意一下,上面输出的是bytes,而macOS是用1000来转换成MB。

Mebibyte - 维基百科,自由的百科全书

所有版本的Windows系统都会将一个2^20 bytes的文件显示为“1.00MB”,而10^6 bytes的文件显示为976kB。在Mac OS X 10.6之后将文件和磁盘大小都用Megabytes来表示,即将10^6 bytes的文件显示为1MB。

最终效果示例:

================================================ Enter Mach-O executable file path: /Users/HTC/Downloads/WeChat/Payload/WeChat.app/WeChat Place enter the number select minimum supported system version for the app? [ 1:gt iOS9 2:lt iOS7 3:iOS7.X~8.X] 1 executable file size: 110.805 MB ⭕️ [Success] 110.805 MB, 符合苹果 iOS9 小于 500 MB 的要求! ================================================ Enter Mach-O executable file path: /Users/HTC/Downloads/WeChat/Payload/WeChat.app/WeChat Place enter the number select minimum supported system version for the app? [ 1:gt iOS9 2:lt iOS7 3:iOS7.X~8.X] 2 executable file size: 110.805 MB [Error] 110.805 MB, 不符合苹果 iOS7 小于 80 MB 的要求! ================================================ Enter Mach-O executable file path: /Users/HTC/Downloads/WeChat/Payload/WeChat.app/WeChat Place enter the number select minimum supported system version for the app? [ 1:gt iOS9 2:lt iOS7 3:iOS7.X~8.X] 3 armv7 executable file size: 53.3299 MB ⭕️ [Success] armv7 size: 53.3299 MB, 符合苹果 iOS 7.X 至 iOS 8.X 每个架构最大为 60 MB 的要求! arm64 executable file size: 57.4751 MB ⭕️ [Success] arm64 size: 57.4751 MB, 符合苹果 iOS 7.X 至 iOS 8.X 每个架构最大为 60 MB 的要求!

具体的代码,可参考我的Github代码:

calculate_Mach-0__Text-Size .sh

#!/bin/bash # 定义用到的变量 ExecutableFilePath="" # 定义读取输入字符的函数 getExecutableFilePath() { # 输出换行,方便查看 echo "================================================" # 监听输入并且赋值给变量 read -p " Enter Mach-O executable file path: " ExecutableFilePath # 如果为空值,从新监听 if test -z "$ExecutableFilePath"; then echo "Error! Should enter file path " getExecutableFilePath fi } getExecutableFilePath echo "Place enter the number select minimum supported system version for the app? [ 1:gt iOS9 2:lt iOS7 3:iOS7.X~8.X] " read number while([[ $number != 1 ]] && [[ $number != 2 ]] && [[ $number != 3 ]]) do echo "Error! Should enter 1 or 2 or 3" echo "Place enter the number you want to export ? [ 1:app-store 2:ad-hoc 3:dev] " read number done if [ $number != 3 ];then app_size=$(echo `size ${ExecutableFilePath} | awk '{print $1}' | grep -E '[0-9]' | awk '{sum += $1}; END {print sum/1000/1000}'`) echo 'executable file size:' ${app_size} 'MB' if [ $number == 1 ];then #iOS 9.0 或更高版本 500 MB 针对二进制文件中所有“__TEXT”部分的总和。 #因为bc和awk都支持浮点数,可以使用bc进行处理: if [ `echo "$app_size > 500" | bc` -eq 1 ];then echo ' [Error]' ${app_size} 'MB,' '不符合苹果 iOS9 小于 500 MB 的要求!' else echo '⭕️ [Success]' ${app_size} 'MB,' '符合苹果 iOS9 小于 500 MB 的要求!' fi else #低于 iOS 7.0 80 MB 针对二进制文件中所有“__TEXT”部分的总和。 if [ `echo "$app_size > 80" | bc` -eq 1 ];then echo ' [Error]' ${app_size} 'MB,' '不符合苹果 iOS7 小于 80 MB 的要求!' else echo '⭕️ [Success]' ${app_size} 'MB,' '符合苹果 iOS7 小于 80 MB 的要求!' fi fi else app_size=$(echo `size "$ExecutableFilePath" | awk '{print $1 "," $10}' | tail -n +2`) # iOS 7.X 至 iOS 8.X 每个架构最大为 60 MB # echo $app_size # 53329920,armv7) 57475072,arm64) arch_arr=(`echo $app_size | tr ' ' ' '`) for each in ${arch_arr[@]} do size=`echo $each | awk -F',' '{print $1}' | awk '{sum += $1}; END {print sum/1000/1000}'` arch=`echo $each | awk -F',' '{print $2}'` # echo ${arch/%)/} # 如果字符串arch以)结尾,则用空替换它 echo ${arch/%)/} 'executable file size:' ${size} 'MB' if [ `echo "$size > 60" | bc` -eq 1 ];then echo ' [Error]' ${arch/%)/} 'size:' ${size} 'MB,' '不符合苹果 iOS 7.X 至 iOS 8.X 每个架构最大为 60 MB 的要求!' else echo '⭕️ [Success]' ${arch/%)/} 'size:' ${size} 'MB,' '符合苹果 iOS 7.X 至 iOS 8.X 每个架构最大为 60 MB 的要求!' fi done fi 

5、总结

本次脚本又顺利提高了效率!本文用到非常多的脚本命令,大家不必说记住,主要是知道用来做什么的,或者有需求时要搜索也可以,通过本次脚本编写,大家应该能发现shell脚本的强大而洁的语法,要学到以用,还需要多实践!

参考


  • 如有疑问,欢迎在评论区一起讨论!
  • 如有不正确的地方,欢迎指导!


注:本文首发于 iHTCboy's blog,如若转载,请注来源


原文链接:https://yq.aliyun.com/articles/701377
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章