ccache - 让Xcode编译速度飞起来
今天来介绍一个小工具ccache
,其可以提高xcode
的编译速度。说起缘由,是因为我的苹果电脑配置比较低,而每次开发调试或测试打包都需要编译工程,虽然项目工程代码量不算大,但是编译的时间还是很长,尤其是修改了头文件或者Archive
打包时,看着进度条像蜗牛在爬一样,心里都有小动物在奔腾......
好在遇到了ccache
,其原理是通过把项目的源文件用ccache
编译器编译,然后缓存编译生成的信息,从而在下一次编译时,利用这个缓存加快编译的速度,目前支持的语言有:C
、C++
、Objective-C
、Objective-C++
,但是如果找不到ccache
编译器,那么还是会选择clang
编译器来编译源文件。下面介绍一下具体的应用过程:
添加ccache脚本
下面是ccache
的编译脚本,命名为:ccache-clang
,需要添加到工程根目录,ccache
就是通过这个脚本来选择编译器的,该脚本的详细介绍如下:
第1行:指定这是一个bash
脚本
第2行:type -p ccache
判断是否存在ccache
命令,/dev/null
是空设备文件,2>&1
是把标准错误流重定向到标准输出流,所以整行的作用是先判断命令是否存在,如果不存在就把标准错误流重定向成标准输出流后,再重定向到空文件,这样错误就不会在控制台上打印出来了
第3行:设置最大的缓存
第4行:设置源文件的编译模式,默认是true
,ccache
会先处理源文件,如果缓存没有命中,就编译源文件;而如果是false
,就会在缓存没有命中时,不是直接编译源文件,而是编译处理后的文件,但是这可能会有问题,因为不同的编译器,预处理后的文件内容不完全相同
第5行:设置为true
,表明ccache
直接利用缓存目录下的文件,而不是拷贝后的文件,这样可以加快编译速度,默认是false
第6行:设置提高缓存命中率,忽略__FILE__、DATE、__TIME__等宏,也不检查文件的修改和创建时间是否是最新的等等
第9行:指定日志文件的路径
第10行:执行/usr/bin/clang
命令,"$@"
是指所有参数
第12行:执行系统默认的clang
命令,"$@"
是指所有参数
#!/bin/sh
if type -p ccache >/dev/null 2>&1; then
export CCACHE_MAXSIZE=10G
export CCACHE_CPP2=true
export CCACHE_HARDLINK=true
export CCACHE_SLOPPINESS=file_macro,time_macros,include_file_mtime,include_file_ctime,file_stat_matches
# 指定日志文件路径到桌面,等下排查集成问题有用,集成成功后删除,否则很占磁盘空间
export CCACHE_LOGFILE='~/Desktop/CCache.log'
exec ccache /usr/bin/clang "$@"
else
exec clang "$@"
fi
如果你的代码或者三方库里的代码中有C++
文件,则需要把脚本命名为:ccache-clang++
,同时,脚本中的clang
也需要修改为clang++
,如下:
#!/bin/sh
if type -p ccache >/dev/null 2>&1; then
export CCACHE_MAXSIZE=10G
export CCACHE_CPP2=true
export CCACHE_HARDLINK=true
export CCACHE_SLOPPINESS=file_macro,time_macros,include_file_mtime,include_file_ctime,file_stat_matches
# 指定日志文件路径到桌面,等下排查集成问题有用,集成成功后删除,否则很占磁盘空间
export CCACHE_LOGFILE='~/Desktop/CCache.log'
exec ccache /usr/bin/clang++ "$@"
else
exec clang++ "$@"
fi
配置Xcode项目
1.添加一个CC常量
在项目的Build Settings
里,添加一个常量:CC
,值为脚本的完整路径:$(SRCROOT)/ccache-clang
(脚本在根目录下)
添加CC
常量
因为ccache
不支持Clang Modules
,所以需要关闭项目的Modules
选项,如果你的工程里有用的@import UIKit
等,那么现在需要替换为#import <UIKit/UIKit>
,这是因为关闭Moduels
后,Xcode
不会再自动导入模块了,对于其他的模块,你还需要在Linked Frameworks and Libraries
里手动导入所需模块。
配置Pod项目
如果项目中用到了CocoaPods
,还需要设置Pod
工程,因为Pod
工程也需要关闭Modules
选项,我们可以按照修改Xcode
项目的方法来修改Pod
工程的modules
配置,但是每次pod update
会把Pod
工程重新生成,Modules
选项又被改回去了,所以我们直接在Podfile
里加入下面的代码,让Pod
工程在生成的时候就关闭Modules
选项,同时加入CC
常量,就可以在编译时用缓存加速了。
但是,由于我们关闭了modules
选项,如果某个Pod
工程用到了系统的框架,则需要按照Xcode
工程的方法添加到对应的Pod
工程里,否则会提示Undefined symbols xxx for architecture arm7
等等,尽管每次更新Pod
后,都需要重新添加所需的框架,但是考虑到编译速度的提升,而Pod
不会经常更新,所以也不是很麻烦。
post_install do |installer_representation|
installer_representation.pods_project.targets.each do |target|
target.build_configurations.each do |config|
#关闭 Enable Modules
config.build_settings['CLANG_ENABLE_MODULES'] = 'NO'
# 在生成的 Pods 项目文件中加入 CC 参数,路径的值根据你自己的项目来修改
config.build_settings['CC'] = '$(PODS_ROOT)/ccache-clang'
end
end
end
应用ccache
设置完成后,就可以利用ccache
了,首次因为还没有缓存,要添加缓存,所以编译的时间会比没有用ccache
要多一会儿,但是从第二次之后,会有缓存命中,就可以加快编译速度了,多次之后,可以明显感觉到,编译的速度快了许多,一般至少了加快一倍以上,我们也可以用命令来查看ccache -s
的缓存的命中情况:
可以看到,现在的缓存命中率是53.01%
,以前打包需要10分钟,现在3分钟搞定,喝茶的时间又多了,是不是很开森,_。