CCache

什么是CCache:

CCache 是一个能够把编译的中间产物缓存起来的工具,它会在实际编译之前先检查缓存。
根据bestswifter的这篇文章其实有提到,在我们平时的开发环境中,Xcode其实自己会做增量编译,也就是说默认会使用上次编译留下的缓存,但是在进行持续集成的时候,缓存不被推荐使用,但这是因为苹果的缓存不稳定,某些情况下依然有bug的原因。因此我们只能手动删除 Derived Data 文件夹,还是调用 xcodebuild clean 命令,都会把缓存清空。或者直接使用 xcodebuild archive,会自动忽略缓存。每次都要全部重编译,因此时间当然慢了哦。
那么,要是我们有一个把编译缓存做的很好的东西,是不是就可以好很多了~~
接入 CCache 的教程参见 贝聊科技CCache,为方便阅读,这里做搬运工作:

安装CCache

通过 Homebrew 安装 CCache, 在命令行中执行

$ brew install ccache

命令执行无异常便是安装成功

创建 CCache 编译脚本

为了能让 CCache 介入到整个编译的过程,我们要把 CCache 作为项目的 C 编译器,当 CCache 找不到编译缓存时,它会再把编译指令传递给真正的编译器 clang。
新建一个文件命名为 ccache-clang

  $ touch ccache-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

在命令行中,cd 到 ccache-clang 文件的目录,把它的权限改成可执行文件

  $ chmod 777 ccache-clang

如果你的代码或者是第三方库的代码用到了C++,则把 ccache-clang这个文件复制一份,重命名成 ccache-clang++。相应的对clang的调用也要改成clang++,否则 CCache 不会应用在 C++ 的代码上。

#!/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 项目的调整
  • 定义CC常量

在你项目的构建设置 (Build Settings)中,添加一个常量 CC,这个值会让 Xcode 在编译时把执行路径的可执行文件当做 C 编译器。


CC 常量的值为  $(SRCROOT)/ccache-clang,如果你的脚本不是放在项目根目录,则自行调整路径。如果一运行项目就报错,检查下路径是不是填错了。

  • 关闭 Clang Modules,这一步真的很恶心

因为 CCache 不支持 Clang Modules,所以需要把 Enable Modules 的选项关掉。这个问题在 CocoaPods 上如何处理,后面会讲。



关闭了 Enable Modules 后需要作出的调整
因为关闭了 Enable Modules,所以必须删除所有的 @import语句,替换为#import的语法例如将 @import UIKit 替换为 #import 。之后,如果你用到了其他的系统框架例如 AVFoundation、CoreLocation等,现在 Xcode 不会再帮你自动引入了,你得要在项目 Target 的 Build Phrase -> Link Binary With Libraries 里面自己手动引入。

  • CocoaPods 的 处理

如果你的项目不用 CocoaPods 来做包管理,那你已经完全接入成功了,不用执行下面的操作。
因为 CocoaPods 会单独把第三方库打包成一个 Static Library(或者是Dynamic Framework,如果用了 use_frameworks!选项),所以 CocoaPods 生成的 Static Library 也需要把 Enable Modules 选项给关掉。但是因为 CocoaPods 每次执行 pod update 的时候都会把 Pods 项目重新生成一遍,如果直接在 Xcode 里面修改 Pods 项目里面的 Enable Modules 选项,下次执行pod update的时候又会被改回来。我们需要在 Podfile 里面加入下面的代码,让生成的项目关闭 Enable Modules 选项,同时加入 CC 参数,否则 pod 在编译的时候就无法使用 CCache 加速:

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

需要注意的是,如果你使用的某个 Pod 引用了系统框架,例如AFNetworking引用了System Configuration,你需要在你自己项目的Build Phrase -> Link Binary With Libraries里面代为引入,否则你编译时可能会收到 Undefined symbols xxx for architecture yyy一类的错误。有点回到了原始时代的感觉,但考虑到编译速度的极大提升,这一点代价可以接受。

好了,到目前为止,你可以开始 cmd+b了,第一次会比较慢,第二次或者往后,你就会发现 cache hit 变大了,随着它的变大,时间你会发现越来越少

好了,看看集成了 CCache 的效果!!!!!,你没看错,时间真的少了一半


你以为文章就到此截止了?不行,还有问题没有解决:

  • 不支持 PCH 文件 怎么办?一定要移除么,可我真的不想移除

其实贝聊有提到,当你修改了PCH或者PCH引用的到的头文件时,会造成缓存失效,只能全部重新编译,所以,只要你不会频繁的更改PCH文件的话,或者不改,其实问题都不大,还是可以接受的,起码能享受到CCache带来的快感



作者:YeeChain
链接:https://www.jianshu.com/p/980b21c2a6b0
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

你可能感兴趣的:(CCache)