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

Windows, based on clcache: https://github.com/frerich/clcache. 10+% build performance improved directly.

clcache enabling steps for edk2 windows build:

  1. Install python3.7 32bits

    if you already installed python3.7 in before, check it in C:\Users\xxx\AppData\Local\Programs\Python\Python37-32
    try py in command:
    c:\steven\edk2>py
    Python 3.7.1 (v3.7.1:260ec2c36a, Oct 20 2018, 14:05:16) [MSC v.1915 32 bit (Intel)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>>
    set python3.7 in your default path
    path=C:\Users\jshi19\AppData\Local\Programs\Python\Python37-32;C:\Users\jshi19\AppData\Local\Programs\Python\Python37-32\Scripts;%path%
  2. git clone the clcache edk2 branch code from https://github.com/shijunjing/clcache.git

    checkout edk2 branch: git checkout edk2
  3. Install the pyinstaller and clcache lib

    • py -m pip install pyinstaller

      if you have network issue, please ensure the python network proxy variables are set correctly. Below are examples:
      set http_proxy=http://jshi19:********@child-prc.intel.com:***
      set https_proxy=http://jshi19:********@child-prc.intel.com:***
  4. go to the clcache pyinstaller folder and create the clcache_main.exe with pyinstaller. Below is my side example:

    • D:\Project\Edk2Git\workspace\clcache-fork\pyinstaller>py -m pip uninstall clcache

    • D:\Project\Edk2Git\workspace\clcache-fork\pyinstaller>py -m pip install d:\Project\Edk2Git\workspace\clcache-fork\

    • remove pycache, build and dist folders in D:\Project\Edk2Git\workspace\clcache-fork\pyinstaller if they already exist

    • D:\Project\Edk2Git\workspace\clcache-fork\pyinstaller>py -m PyInstaller clcache_main.py (one folder, fast)

    • D:\Project\Edk2Git\workspace\clcache-fork\pyinstaller>py -m PyInstaller clcache_main.py --onefile (one file, slow, not suggest to use)

      You should see the clcache_main.exe generated in in clcache\pyinstaller\dist\clcache_main\clcache_main.exe:
      D:\Project\Edk2Git\workspace\clcache-fork\pyinstaller\dist\clcache_main\clcache_main.exe
    • Note that on Windows at least the module name is case-sensitive (uppercase 'P' and 'I').

    • Note: The --onefile argument to PyInstaller will make it generate a single monolithic executable file which is very convenient, but also slows things down. See the Caveats wiki page ([Caveats wiki page ](https://github.com/frerich/clcache/wiki/Caveats#slow-performance-when-using-a-clcache-executable-built-via-pyinstaller)) for some further discussion

  5. Change the clcache_main.exe name to cl.exe

    D:\Project\Edk2Git\workspace\clcache-fork\pyinstaller\dist\clcache_main>move clcache_main.exe cl.exe
  6. Change the real cl.exe in below VS2015 installation folders to cl.ori.exe (the "cl.ori.exe" name can vary):

    C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin
    C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\x86_amd64
  7. copy all files in the D:\Project\Edk2Git\workspace\clcache-fork\pyinstaller\dist\clcache_main to above VS2015 two folders.

  8. Add two CLCACHE_CL.ini in above VS2015 two folders, with real compiler cl.ori.exe path.

    C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\CLCACHE_CL.ini
     [CL_PATH]
     cl_path =C:\Program Files (x86)\Microsoft Visual Studio 14.0\Vc\bin\cl.ori.exe
    C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\x86_amd64\CLCACHE_CL.ini
     [CL_PATH]
     cl_path =C:\Program Files (x86)\Microsoft Visual Studio 14.0\Vc\bin\x86_amd64\cl.ori.exe
    • Note: the above steps 6~7 are to work around a clcache limitation which only support one compiler path. I have to customize clcache code and add a feature to support it in my clcache edk2 branch. This is why you cannot directly use the normal clcache release to build edk2 platforms which have both -a IA32 and -a X64 arches. Background details see this issue link: https://github.com/frerich/clcache/issues/343

  9. Set two system variables (optional now, have set them as the default values in the clcache code)

  10. Update edk2 VS2015x86 toolchain to replance the /Zi with /Z7 debug flag.

    • Note: Detail see https://github.com/frerich/clcache/issues/30. Please be aware that this change has no any impact to edk2 module level PDB file generation, and we still can get the PDB debug file for a .efi module. The /Z7 only impact intermediate obj files level PDB files, which is usually one PDB file (vc140.pdb) per obj folder. I will formally send the patch to edk2 upstream later. And we should don’t need this patch after the patch is accept in the future.

    • diff --git a/BaseTools/Conf/tools_def.template b/BaseTools/Conf/tools_def.template

    • index 2bd0982872..3c25bfc5b2 100755

    • --- a/BaseTools/Conf/tools_def.template

    • + b/BaseTools/Conf/tools_def.template

    • - DEBUG_VS2015x86_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /Gw

    • + DEBUG_VS2015x86_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Z7 /Gw^M

    • -NOOPT_VS2015x86_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /Od

    • +NOOPT_VS2015x86_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Z7 /Od^M

    • - DEBUG_VS2015x86_X64_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Gw

    • + DEBUG_VS2015x86_X64_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Z7 /Gw^M

    • -NOOPT_VS2015x86_X64_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od

    • +NOOPT_VS2015x86_X64_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Z7 /Od^M

Caution
Don’t change the /Zi flag in DEBUG_VS2015x86_IA32_ASM_FLAGS and NOOPT_VS2015x86_IA32_ASM_FLAGS, because some assembly compiler don’t support the /Z7 and we should skip to cache assembly code build.

Testing edk2 OVMF build performance in windows

  1. Launch "Developer Command Prompt for VS2015" and apply the new tools_def configure:

    • c:\workspace\edk2>edksetup.bat Reconfig

    • c:\workspace\edk2>set CLCACHE_DIR=C:\CLCACHE_DIR (if you don’t add it as a windows environment variable)

  2. clear statistics of the clcache cl.exe, and show the statistics result to check the CLCACHE_DIR is correctly configured c:\steven\edk2>"C:\Program Files (x86)\Microsoft Visual Studio 14.0\Vc\bin\x86_amd64\cl.exe" -z

    Statistics reset
    c:\steven\edk2>"C:\Program Files (x86)\Microsoft Visual Studio 14.0\Vc\bin\x86_amd64\cl.exe" -s
    clcache statistics:
      current cache dir         : Disk cache at C:\CLCACHE_DIR
      cache size                : 463,132,812 bytes
      maximum cache size        : 1,073,741,824 bytes
      cache entries             : 7677
      cache hits                : 0
      cache misses
        total                      : 0
        evicted                    : 0
        header changed             : 0
        source changed             : 0
      passed to real compiler
        called w/ invalid argument : 0
        called for preprocessing   : 0
        called for linking         : 0
        called for external debug  : 0
        called w/o source          : 0
        called w/ multiple sources : 0
        called w/ PCH              : 0
  3. Clean build the OVMF OvmfPkgIa32X64 platform to create the cache all the three build targets firstly:

    • c:\steven\edk2>rmdir Build /Q /S

    • c:\steven\edk2>build -t VS2015x86 -p OvmfPkg\OvmfPkgIa32X64.dsc -a IA32 -a X64 -b NOOPT

    • c:\steven\edk2>rmdir Build /Q /S

    • c:\steven\edk2>build -t VS2015x86 -p OvmfPkg\OvmfPkgIa32X64.dsc -a IA32 -a X64 -b DEBUG

    • c:\steven\edk2>rmdir Build /Q /S

    • c:\steven\edk2>build -t VS2015x86 -p OvmfPkg\OvmfPkgIa32X64.dsc -a IA32 -a X64 -b RELEASE

  4. OK, everything is ready. Clean build the OVMF OvmfPkgIa32X64 platform with clcache enabled and disable again:

NOOPT clean build:

  • c:\steven\edk2>set CLCACHE_DISABLE=1 (clcache is disabled)

  • c:\steven\edk2>rmdir Build /Q /S

  • c:\steven\edk2>build -t VS2015x86 -p OvmfPkg\OvmfPkgIa32X64.dsc -a IA32 -a X64 -b NOOPT Build total time: 00:03:15

  • c:\steven\edk2>set CLCACHE_DISABLE= (clcache is enabled)

  • c:\steven\edk2>rmdir Build /Q /S

  • c:\steven\edk2>build -t VS2015x86 -p OvmfPkg\OvmfPkgIa32X64.dsc -a IA32 -a X64 -b NOOPT Build total time: 00:02:38

    Improvement: (00:03:15 (195s) - 00:02:38(158s))/00:03:15 = 18.9%, or 00:02:38/00:03:15 = 1.23x

DEBUG clean build:

  • c:\steven\edk2>set CLCACHE_DISABLE=1 (clcache is disabled)

  • c:\steven\edk2>rmdir Build /Q /S

  • c:\steven\edk2>build -t VS2015x86 -p OvmfPkg\OvmfPkgIa32X64.dsc -a IA32 -a X64 -b DEBUG Build total time: 00:03:45

  • c:\steven\edk2>set CLCACHE_DISABLE= (clcache is enabled)

  • c:\steven\edk2>rmdir Build /Q /S

  • c:\steven\edk2>build -t VS2015x86 -p OvmfPkg\OvmfPkgIa32X64.dsc -a IA32 -a X64 -b NOOPT Build total time: 00:03:22

    Improvement: (00:03:45 (225s) - 00:03:22(202s))/00:03:45 = 10.2%, or 00:03:44/00:03:07 = 1.11x

RELEASE clean build:

  • c:\steven\edk2>set CLCACHE_DISABLE=1 (clcache is disabled)

  • c:\steven\edk2>rmdir Build /Q /S

  • c:\steven\edk2>build -t VS2015x86 -p OvmfPkg\OvmfPkgIa32X64.dsc -a IA32 -a X64 -b RELEASE Build total time: 00:03:44

  • c:\steven\edk2>set CLCACHE_DISABLE= (clcache is enabled)

  • c:\steven\edk2>rmdir Build /Q /S

  • c:\steven\edk2>build -t VS2015x86 -p OvmfPkg\OvmfPkgIa32X64.dsc -a IA32 -a X64 -b RELEASE Build total time: 00:03:07

    Improvement: (00:03:44 (224s) - 00:03:07(187s))/00:03:44 = 16.5%, or 00:03:44/00:03:07 = 1.19x
  • Note: The larger compiling phase, the more improvement you can get.

How to solve the clcache limitations for edk2 build

  1. clcache assume only one arch cl.exe compiler is used in build, e.g. either x64\cl.exe or x86\cl.exe. But edk2 might use both arch cl.exe. e.g OvmfPkgIa32X64.dsc platform.

    • We have solved this limitation by customizing the clcache to support a configure file in the same folder of clcache executable binary to specify the real cl path.

  2. clcache does not support generate PDB. Blow is the required command line rules(see clcache README). You can see these rules in the clcache readme.

    • The /link switch must not be present

    • The /c switch must be present

    • The /Zi switch must not be present (/Z7 is okay though)

Will send patch to update the edk2 build file tools_def.template to replace the /Zi with /Z7. See the step 11 in the clache enabling part.

(update) We have solved this /Zi limitation: Have sent the patch to replace the /Zi to /Z7 in MSVC build option, detail see: https://lists.01.org/pipermail/edk2-devel/2019-January/035964.html

Future possible work

  1. Look for distcc like tool for windows and combine clcache+ windows version distcc

⚠️ **GitHub.com Fallback** ⚠️