㈠ 5分鍾掌握cmake(18): 在MSVC下加速編譯OpenGV
記錄使用 VS2022 里的 cl.exe 作為 C++ 編譯器時,將開源項目 opengv 的編譯耗時縮短的相關技巧。
環境:Windows 11, VS2022 17.8.0, CMake 3.27.4。 耗時:Release模式的耗時從157分鍾減少到115分鍾; Debug模式的耗時從176秒減少到49秒。
首先澄清, Linux 上編譯 OpenGV 很快,幾十秒到幾分鍾的樣子。
Windows 上編譯 OpenGV 慢,整體的原因是:依賴了 Eigen 這個 header-only 庫,且構建的大量時間是在處理 Eigen 的3個頭文件,每次出現34次,耗時非常可觀。
在微軟官方的討論帖 Slow C++ compiling on some eigen heavy code 中,給出了 Eigen 代碼在 Release 模式下編譯較慢的原因:forceinline 關鍵字需要被編譯器展開,耗時較多。因此,嘗試將 Debug 模式的編譯耗時縮短,再將相關的編譯加速技巧應用到 Release 模式上。
在 Debug 模式編譯耗時優化方面,包括使用 msbuild + MTT(環境變數 UseMultiToolTask 設置為 true),使用 ninja 替代 msbuild,以及 Unity(Jumbo) build。
ninja 默認使用並行編譯,且使用 -G Ninja Multi-Config 可以在 build 階段自由切換 debug / release。因此,我們使用它來做構建。在使用 ninja 構建時,耗時結果為49秒,稍快於 msbuild + ninja。
Unity(Jumbo) build 通過設置環境變數 EnableUnitySupport=true 來啟用,觀察到 msbuild 自動創建了單一的 cpp 文件,耗時為 1分8秒(68秒),無需考慮是否開啟 MTT。
顯式設定 cl.exe 並行數量,通過在 cmake --build 時傳入 -- /p:CL_MP=true /p:CL_MPCount=12 參數,讓 cl.exe 使用12個並行進程,構建耗時為 2分4秒。
Debug 模式編譯耗時匯總:ninja 最快,msbuild + MTT 則接近 ninja,unity build 有加速但不夠快。MTT 的實用性很強。
對於 Release 模式的構建,CI 伺服器上使用 vs2019 的耗時為 Debug + Release 兩種模式的總耗時,Release 模式的編譯耗時在2小時左右,遠遠高於 Debug 耗時;Ninja 方式的構建速度快於其他方式。
總結:通過優化編譯器配置、利用並行編譯技術、改進構建策略等方法,可以顯著縮短編譯時間,提升開發效率。