I've been working on a flutter using firebase dependencies. (cloud store, cloud storage, cloud_function so on...)
The build time has always been painful with ios build. On my local machine (MacBook pro 16" with 32GB ram, intel), It takes 10min for a clean build. 2-5min for a rebuild. (Slow, but maybe not too wrong. I can live with that, but..)
When I run the build from the GitHub action for CI/CD, It takes almost an hour without a cache. Not only the time consuming but also the $$$$ (macOS runner costs $0.08 per min * 60 = 4.8$ per build)
Two years back, to address this issue, I found this and applied: https://github.com/invertase/firestore-ios-sdk-frameworks
This helped to save 40min in the CI/CD, but It's always been painful to update firebase related dependencies. Since I have fixed the iOS SDK version, it easily introduces regression or builds fail when it doesn't match with flutter's firebase dependency.
For the moment, the pre-compiled SDK doesn't work with the latest flutter firebase libraries: https://github.com/firebase/flutterfire/issues/9761
So it takes an hour to build my project in GitHub action. I can't live with it!
Solution: the ccache!
After some research, I found from the React Native doc about the caching for iOS build: https://reactnative.dev/docs/build-speed#use-a-compiler-cache
I instantly thought that I could apply this to my flutter project too.
It was done in simple steps.
For the local machine (Same as the react native doc)
- Install the ccache
brew install ccache
ln -s ccache /usr/local/bin/gcc ln -s ccache /usr/local/bin/g++ ln -s ccache /usr/local/bin/cc ln -s ccache /usr/local/bin/c++ ln -s ccache /usr/local/bin/clang ln -s ccache /usr/local/bin/clang++
Make sure it's used
$ which gcc /usr/local/bin/gcc
If it doesn't show the
/usr/local/bin/gcc, make sure adjust your $PATH in
Update the Podfile
post_install do |installer| react_native_post_install(installer) # ...possibly other post_install items here installer.pods_project.targets.each do |target| target.build_configurations.each do |config| # Using the un-qualified names means you can swap in different implementations, for example ccache config.build_settings["CC"] = "clang" config.build_settings["LD"] = "clang" config.build_settings["CXX"] = "clang++" config.build_settings["LDPLUSPLUS"] = "clang++" end end __apply_Xcode_12_5_M1_post_install_workaround(installer) end
Export the ccache config before building
export CCACHE_SLOPPINESS=clang_index_store,file_stat_matches,include_file_ctime,include_file_mtime,ivfsoverlay,pch_defines,modules,system_headers,time_macros export CCACHE_FILECLONE=true export CCACHE_DEPEND=true export CCACHE_INODECACHE=true
Test your build:
flutter build ios
The first build would still be slow since the caches are not generated yet.
Check if the cache is created.
$ ccache -s Summary: Hits: 196 / 3068 (6.39 %) Direct: 0 / 3068 (0.00 %) Preprocessed: 196 / 3068 (6.39 %) Misses: 2872 Direct: 3068 Preprocessed: 2872 Uncacheable: 1 Primary storage: Hits: 196 / 6136 (3.19 %) Misses: 5940 Cache size (GB): 0.60 / 20.00 (3.00 %)
Rerun the build:
flutter build ios
The build time should be much faster now on your local machine.
For the GitHub Action
Same steps as the local machine. We need to use ccache-action to install the ccache easily and let it automatically store and restore the cache: https://github.com/hendrikmuhs/ccache-action
Add this to the workflow file
- name: Install Ccache uses: firstname.lastname@example.org with: max-size: 5G
The max cache size is 500M by default, but it was too small for my project. With the default setting, it didn't hit the cache, so I had to increase it to 5G.
Update the build command
- name: Build flutter app run: | export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" export CCACHE_SLOPPINESS=clang_index_store,file_stat_matches,include_file_ctime,include_file_mtime,ivfsoverlay,pch_defines,modules,system_headers,time_macros export CCACHE_FILECLONE=true export CCACHE_DEPEND=true export CCACHE_INODECACHE=true ccache -s flutter build ipa --export-options-plist=ios/exportOptions.plist --release
Like the local machine, the first build will still be slow but from the second build with the cache built, you'll see it's much faster.
You can inspect the action if the cache hits.
With this, I was able to reach almost the same build time (around 20min) without using the pre-compiled firestore SDK.
Top comments (0)