CMake 与Ninja 组合的关键点
Ninja(忍者)一詞讓人聯想到潛行和速度。在開發“另一個構建系統”時——正如 Ninja 的創造者 Evan Martin 在其手冊中提到的那樣——速度是最重要的。將構建系統命名為 Ninja 非常恰當,我將在這篇博文中向您展示它的功能,并強調它的獨特之處。讓我們開始吧。
Ninja 是什么,為什么是另一個構建系統?
讓我們從為什么發明 Ninja 開始討論。在將 Chromium 從 Windows 移植到其他操作系統期間,構建性能成為了一大障礙。點擊此處了解全部詳情。使用 Makefiles 被認為是次優選擇,有一個新的構建系統在概念上非常類似于 Make,但它側重于速度。它將 Chrome 的構建啟動時間縮短到不到一秒,并且很快就實現開源了。它通過以下方式實現了這一壯舉:
- 在設計原則上,側重速度而非便捷
- 擁有最少的策略或內置規則集(由 ninja 輸入文件處理)
- 構建始終并行運行,默認基于系統擁有的 CPU 數量
每個構建系統最終都會通過解析構建文件來創建依賴關系圖。(在下一節中,我列出了一張 Ninja 本身的圖像)。構建過程遍歷此圖,以獲得最終輸出。對于 Ninja,這是一個兩階段的遍歷,其中:
- 在第一階段中,將圖形從最終輸出向上遍歷到輸入文件,以查看是否有任何修改,并為構建創建一個計劃
- 在第二階段中,按照計劃將圖形從輸入文件向下遍歷并并行執行
此外,以下低級設計決策有助于 Ninja 提速:
- Re2c 用于解析構建文件,效率很高
- Ninja 將構建文件中的路徑規范化。它不是將文件路徑視為字符串,而是將路徑轉換為 Node 對象,從而消除用于路徑相等性檢查的成本昂貴的字符串比較。若要比較兩條路徑是否相等,Ninja 只需要進行非常快速的指針比較
- Ninja 以二進制序列化格式保存構建的配置(例如使用的編譯標志)。要確定輸出是否因構建配置更改而過期,只需要進行二進制哈希比較即可。
所有這些低級優化使 Ninja 快速高效。
獲取 Ninja
在 Windows 上,從源代碼構建 Ninja 很容易。其構建步驟如下所示:
- git clone https://github.com/ninja-build/ninja.git
- cd ninja && python configure.py –bootstrap
安裝最新版本的 Python,并打開 Visual Studio x64 本機工具命令提示符。發出上述兩個命令,其中第一個命令將從其 GitHub 倉庫下載 Ninja 源代碼,第二個命令將神奇地構建 Ninja。
Ninja 是使用 Ninja 和一種稱為引導的技術構建的。引導步驟首先構建一個名為 ninja.bootstrap.exe 的可執行文件和一個 build.ninja 文件。此引導可執行文件進一步用于構建 ninja.exe。構建速度非常快,因為 Ninja 本身的依賴項非常小。我使用命令生成了以下 Ninja 依賴關系圖:
- ninja -t graph ninja.exe > graph_ninja.dot
- dot -Tpng graph_ninja.dot > graph_ninja.png
使用 Ninja
要使用 Ninja 進行軟件構建,我們需要創建默認名為 build.ninja 的輸入構建文件。下面我們以構建 Ninja 所創建的 build.ninja 部分為例:
# This file is used to build ninja itself.# It is generated by configure.py.ninja_required_version = 1.3# The arguments passed to configure.py, for rerunning it.configure_args =root = .builddir = buildcxx = clar = linkcflags = /showIncludes /nologo /Zi /W4 /WX /wd4530 /wd4100 /wd4706 /wd4244 $ /wd4512 /wd4800 /wd4702 /wd4819 /wd4127 /wd4355 /wd4091 /GR- /wd4267 $ /DNOMINMAX /D_CRT_SECURE_NO_WARNINGS /D_HAS_EXCEPTIONS=0 $ /DNINJA_PYTHON=“python.exe” /FS /Ox /DNDEBUG /GL -I.ldflags = /DEBUG /libpath:$builddir /LTCG /OPT:REF /OPT:ICFrule cxx command = $cxx $cflags -c in/Foin /Foin/Foout /Fd$builddir$pdb description = CXX outdeps=msvcrulearcommand=lib/nologo/ltcg/out:out deps = msvcrule ar command = lib /nologo /ltcg /out:outdeps=msvcrulearcommand=lib/nologo/ltcg/out:out $in description = LIB $outrule link command = $cxx $in $libs /nologo /link ldflags/out:ldflags /out:ldflags/out:out description = LINK $out
手動創建這樣一個文件非常麻煩。輸入 CMake,它有一個專為 Ninja 設計的后端生成器!
通過 CMake 使用 Ninja
手動創建 Ninja 的輸入文件非常難。諸如 CMake 構建生成器系統可用于為 Ninja 創建輸入文件。為了展示如何通過 CMake 使用 Ninja,讓我們使用 CMake 構建 Ninja,并將 Ninja 作為后端。
從您下載 Ninja 的目錄發出以下命令:
cmake -Bbuild-cmake -H. -GNinja
這將創建一個名為 build-cmake 的文件夾,您會在其中找到一個名為 build.ninja 的文件。這是 CMake 生成的 build.ninja 的第一部分
# CMAKE generated file: DO NOT EDIT!# Generated by “Ninja” Generator, CMake Version 3.19# This file contains all the build statements describing the# compilation DAG.# =================================================# Write statements declared in CMakeLists.txt:## Which is the root file.# =================================================# =================================================# Project: ninja# Configurations: Debug# =================================================############################################## Minimal version of Ninja required by this fileninja_required_version = 1.5############################################## Set configuration variable for custom commands.CONFIGURATION = Debug# =================================================# Include auxiliary files.############################################## Include rules file.include CMakeFiles\rules.ninja
確保路徑中包含引導版本創建的 ninja.exe。現在發出以下命令:
- cd build-cmake && cmake –build .
這將使用帶有 CMake Ninja 后端的 Ninja 構建 Ninja。默認情況下,Ninja 會根據系統上可用 CPU 的數量并行運行構建命令。下面我們修改 cmake build 命令,使 Ninja 顯示構建統計信息。
- cmake –build . — -d stats
注:之后的所有參數都由 CMake 傳遞給底層構建系統。
這給了我們很好的構建統計數據:
Finished generating code
metric count avg (us) total (ms)
.ninja parse 2 1221.5 2.4
canonicalize str 899 0.0 0.0
canonicalize path 9473 0.0 0.4
lookup node 1563 0.0 0.0
.ninja_log load 1 51.0 0.1
.ninja_deps load 1 32.0 0.0
node stat 443 24.9 11.0
StartEdge 72 62498.4 4499.9
FinishCommand 69 2493.7 172.1
CLParser::Parse 61 1157.5 70.6
path->node hash load 0.72 (367 entries / 512 buckets)
我從之前的博客中復制了一張圖片,其中清楚地展示了 Ninja 與 Make 在兩個開源項目(bullet3 和 LLVM)的編譯時間上的對比情況。
這是另一項研究,它展示了 Ninja 在編譯時間方面如何優于 Make。
結論
在我之前的一篇博客中,我曾將 Ninja 描述為一個專注于速度的小型開源構建系統。在這篇博文中,我們(可以從我們使用 ninja -t 命令創建的依賴關系圖中)看到了整個 Ninja 源代碼有多小,以及設置和使用它有多容易。我們還可以看到 CMake 如何與 Ninja 完美配合,因為 CMake 內置了用以支持 Ninja 的生成器。正是由于這些原因,Visual Studio 2019 將默認生成器作為 Ninja 用于 WSL2 構建。如果您想為您的項目提供一個簡潔的構建系統,請考慮使用 CMake 和 Ninja 組合。
點擊獲取試用License!
總結
以上是生活随笔為你收集整理的CMake 与Ninja 组合的关键点的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 翻译原版教材的一些技巧和心得
- 下一篇: vue前端+springboot后台实现