CMake 与Ninja 组合的关键点

4 篇文章 0 订阅
1 篇文章 0 订阅

在这里插入图片描述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 很容易。其构建步骤如下所示:

安装最新版本的 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 i n / F o in /Fo in/Foout /Fd$builddir$pdb description = CXX o u t d e p s = m s v c r u l e a r c o m m a n d = l i b / n o l o g o / l t c g / o u t : 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 l d f l a g s / o u t : 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 组合。

点击了解 Incredibuild 加速 Visual Studio C++ 构建编译的解决方案!
在这里插入图片描述

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值