Edk2 compiler cache enabling steps on Linux - shijunjing/edk2 GitHub Wiki

GCC and CLANG support, based on ccache: https://ccache.samba.org/. Clean build performance can be improved 60+% and even more!

Fit for both individual and CI (continue integration) build usage scenario

Useful links

Other Academic solution

Build ccache

  1. Download source and build latest ccache-3.5:
  • $ wget ccache-3.5 source https://www.samba.org/ftp/ccache/ccache-3.5.tar.bz2

  • $ tar -xf ccache-3.5.tar.bz2

  • $ cd ccache-3.5

  • $ sudo apt-get install autoconf gperf asciidoc

  • $ ./autogen.sh

  • $ ./configure

  • $ make

  • $ sudo make install (optional)

    You can also directly install ccache from your OS distribution

  • $ sudo apt-get install ccache

  1. Create edk2 build tool bin symbolic links in ccache build folder and map compiler to ccache
  • $ cd ccache-3.5

  • $ ln -s ccache gcc

  • $ ln -s ccache g++

  • $ ln -s ccache clang

  • $ ln -s ccache clang++

  • $ ln -s /usr/bin/objcopy objcopy (check your local path, if you build&install compiler by yourself, you might need ln -s /usr/local/bin/objcopy objcopy. Same for below tool bins)

  • $ ln -s /usr/bin/gcc-ar gcc-ar

  • $ ln -s /usr/bin/ar ar

  • $ ln -s /usr/bin/llvm-ar llvm-ar

  1. Set edk2 build bin path to ccache build folder. Below is my example. Then build edk2 as normal.
  • export CLANG38_BIN=~/wksp_efi/ccache/ccache-3.5/
  • export GCC5_BIN=~/wksp_efi/ccache/ccache-3.5/
  • export GCC49_BIN=~/wksp_efi/ccache/ccache-3.5/

Frequently asked questions

Does ccache support Compiling In Different Directories and share the same cache for the different directories?

Yes. You can specify a "base directory" by setting the CCACHE_BASEDIR variable to an absolute path to the directory. ccache will then rewrite absolute paths that are under the base directory (i.e., paths that have the base directory as a prefix) to relative paths when constructing the hash. More details see the "Compiling In Different Directories" section in https://linux.die.net/man/1/ccache

Can a group of developers share the cache directory to each other?

Yes. A group of developers can increase the cache hit rate by sharing a cache directory. To share a cache without unpleasant side effects, the following conditions should to be met.More details see the "Sharing A Cache" section in https://linux.die.net/man/1/ccache

  • Use the same CCACHE_DIR environment variable setting.
  • Unset the CCACHE_HARDLINK environment variable.
  • Make sure everyone sets the CCACHE_UMASK environment variable to 002. This ensures that cached files are accessible to everyone in the group.
  • Make sure that all users have write permission in the entire cache directory (and that you trust all users of the shared cache).
  • Make sure that the setgid bit is set on all directories in the cache. This tells the filesystem to inherit group ownership for new directories. The command "find $CCACHE_DIR -type d | xargs chmod g+s" might be useful for this.

Does ccache support to set different cache folder for different project?

Yes. The CCACHE_DIR environment variable specifies where ccache will keep its cached compiler output. The default is $HOME/.ccache.

Does ccache support to set different maximum size of the files stored in the cache?

Yes. Set option -M, --max-size=SIZE is to set the maximum size of the files stored in the cache. You can specify a value in gigabytes, megabytes or kilobytes by appending a G, M or K to the value.

Build performance data (Build 5 times for every platform, first is ccache disabled, others are ccache enabled.)

CLANG38+NOOPT

  • export CCACHE_DISABLE=1 // disable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t CLANG38 -a IA32 -a X64 -b NOOPT -n 5
  • real 1m33.076s
  • user 3m12.913s
  • sys 0m37.689s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t CLANG38 -a IA32 -a X64 -b NOOPT -n 5
  • real 2m2.072s
  • user 4m4.150s
  • sys 0m58.894s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t CLANG38 -a IA32 -a X64 -b NOOPT -n 5
  • real 0m31.758s
  • user 0m39.712s
  • sys 0m13.123s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t CLANG38 -a IA32 -a X64 -b NOOPT -n 5
  • real 0m33.002s
  • user 0m39.591s
  • sys 0m13.335s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t CLANG38 -a IA32 -a X64 -b NOOPT -n 5
  • real 0m31.718s
  • user 0m39.512s
  • sys 0m13.362s

CLANG38+DEBUG

  • export CCACHE_DISABLE=1 // disable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t CLANG38 -a IA32 -a X64 -b DEBUG -n 5
  • real 2m2.667s
  • user 5m57.243s
  • sys 0m39.721s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t CLANG38 -a IA32 -a X64 -b DEBUG -n 5
  • real 2m27.909s
  • user 6m36.979s
  • sys 0m57.632s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t CLANG38 -a IA32 -a X64 -b DEBUG -n 5
  • real 0m59.107s
  • user 2m28.691s
  • sys 0m14.924s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t CLANG38 -a IA32 -a X64 -b DEBUG -n 5
  • real 1m2.329s
  • user 2m32.836s
  • sys 0m15.145s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t CLANG38 -a IA32 -a X64 -b DEBUG -n 5
  • real 0m58.419s
  • user 2m31.057s
  • sys 0m14.991s

CLANG38+RELEASE

  • export CCACHE_DISABLE=1 // disable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t CLANG38 -a IA32 -a X64 -b RELEASE -n 5
  • real 2m1.673s
  • user 5m30.296s
  • sys 0m39.266s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t CLANG38 -a IA32 -a X64 -b RELEASE -n 5
  • real 2m27.049s
  • user 6m12.606s
  • sys 1m0.264s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t CLANG38 -a IA32 -a X64 -b RELEASE -n 5
  • real 0m53.605s
  • user 2m4.319s
  • sys 0m15.554s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t CLANG38 -a IA32 -a X64 -b RELEASE -n 5
  • real 0m51.757s
  • user 2m4.821s
  • sys 0m15.136s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t CLANG38 -a IA32 -a X64 -b RELEASE -n 5
  • real 0m55.083s
  • user 2m10.031s
  • sys 0m15.622s

GCC5+NOOPT

  • export CCACHE_DISABLE=1
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC5 -a IA32 -a X64 -b NOOPT -n 5
  • real 1m35.062s
  • user 3m57.638s
  • sys 0m30.266s
  • export -n CCACHE_DISABLE
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC5 -a IA32 -a X64 -b NOOPT -n 5
  • real 2m1.809s
  • user 4m56.289s
  • sys 0m41.580s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC5 -a IA32 -a X64 -b NOOPT -n 5
  • real 0m32.727s
  • user 0m37.567s
  • sys 0m12.200s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC5 -a IA32 -a X64 -b NOOPT -n 5
  • real 0m32.511s
  • user 0m37.323s
  • sys 0m11.907s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC5 -a IA32 -a X64 -b NOOPT -n 5
  • real 0m31.636s
  • user 0m37.591s
  • sys 0m11.718s

GCC5+DEBUG

  • export CCACHE_DISABLE=1 // disable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC5 -a IA32 -a X64 -b DEBUG -n 5
  • real 2m56.388s
  • user 9m30.974s
  • sys 0m42.456s
  • export -n CCACHE_DISABLE // enable ccache
  • ccache -C // clear the cache completely
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC5 -a IA32 -a X64 -b DEBUG -n 5
  • real 3m25.597s
  • user 10m54.142s
  • sys 0m56.322s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC5 -a IA32 -a X64 -b DEBUG -n 5
  • real 1m49.702s
  • user 5m38.929s
  • sys 0m22.409s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC5 -a IA32 -a X64 -b DEBUG -n 5
  • real 1m39.818s
  • user 5m4.784s
  • sys 0m20.968s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC5 -a IA32 -a X64 -b DEBUG -n 5
  • real 1m41.136s
  • user 5m4.463s
  • sys 0m20.925s

GCC5+RELEASE

  • export CCACHE_DISABLE=1 // disable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC5 -a IA32 -a X64 -b RELEASE -n 5
  • real 2m26.923s
  • user 7m41.147s
  • sys 0m39.726s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC5 -a IA32 -a X64 -b RELEASE -n 5
  • real 2m37.894s
  • user 8m17.724s
  • sys 0m50.524s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC5 -a IA32 -a X64 -b RELEASE -n 5
  • real 1m28.608s
  • user 4m15.156s
  • sys 0m21.183s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC5 -a IA32 -a X64 -b RELEASE -n 5
  • real 1m29.328s
  • user 4m19.114s
  • sys 0m21.348s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC5 -a IA32 -a X64 -b RELEASE -n 5
  • real 1m33.035s
  • user 4m25.023s
  • sys 0m21.752s

GCC49+DEBUG

  • export CCACHE_DISABLE=1 // disable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC49 -a IA32 -a X64 -b DEBUG -n 5
  • real 2m40.643s
  • user 7m59.878s
  • sys 0m33.698s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC49 -a IA32 -a X64 -b DEBUG -n 5
  • real 3m7.480s
  • user 9m0.065s
  • sys 0m45.559s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC49 -a IA32 -a X64 -b DEBUG -n 5
  • real 0m34.040s
  • user 0m37.513s
  • sys 0m12.291s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC49 -a IA32 -a X64 -b DEBUG -n 5
  • real 0m33.151s
  • user 0m38.046s
  • sys 0m12.518s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC49 -a IA32 -a X64 -b DEBUG -n 5
  • real 0m33.084s
  • user 0m37.719s
  • sys 0m12.602s

GCC49+RELEASE

  • export CCACHE_DISABLE=1 // disable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC49 -a IA32 -a X64 -b RELEASE -n 5
  • real 2m26.955s
  • user 7m19.728s
  • sys 0m33.801s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC49 -a IA32 -a X64 -b RELEASE -n 5
  • real 3m0.185s
  • user 8m17.908s
  • sys 0m45.666s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC49 -a IA32 -a X64 -b RELEASE -n 5
  • real 0m31.884s
  • user 0m36.345s
  • sys 0m11.683s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC49 -a IA32 -a X64 -b RELEASE -n 5
  • real 0m33.044s
  • user 0m36.137s
  • sys 0m11.900s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC49 -a IA32 -a X64 -b RELEASE -n 5
  • real 0m32.632s
  • user 0m36.281s
  • sys 0m11.774s

GCC49+NOOPT

  • export CCACHE_DISABLE=1 // disable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC49 -a IA32 -a X64 -b NOOPT -n 5
  • real 1m36.715s
  • user 4m5.113s
  • sys 0m30.563s
  • export -n CCACHE_DISABLE
  • ccache -C // clear the cache completely
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC49 -a IA32 -a X64 -b NOOPT -n 5
  • real 2m3.280s
  • user 4m55.942s
  • sys 0m41.884s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC49 -a IA32 -a X64 -b NOOPT -n 5
  • real 0m33.510s
  • user 0m37.192s
  • sys 0m11.953s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC49 -a IA32 -a X64 -b NOOPT -n 5
  • real 0m33.033s
  • user 0m37.074s
  • sys 0m12.325s
  • export -n CCACHE_DISABLE // enable ccache
  • rm Build -r
  • time build -p OvmfPkg/OvmfPkgIa32X64.dsc -t GCC49 -a IA32 -a X64 -b NOOPT -n 5
  • real 0m34.066s
  • user 0m37.381s
  • sys 0m11.759s