目录

构建系统介绍

简介:cmake, make, bazel, ninja 的简单介绍和使用。

构建系统

构建系统(build system)是用来从源代码生成用户可以使用的目标(targets)的自动化工具。目标可以包括库、可执行文件、或者生成的脚本等等。

image-20220907025552843

cmake

CMake是一个跨平台的编译工具,可以用简单的语句来描述所有平台的安装和编译过程。CMake 并不直接建构出最终的软件,而是产生标准的建构脚本,然后再使用相应的工具进行编译

  • 可以用于生成makeFile.ninja等其他构建系统的文件。

make

make 是 GNU 软件包中的一个构建工具,可用于构建并管理项目的目标文件和可执行文件。我们可以编写 Makefile 作为批处理命令的定义。由于属于 GNU 中的工具之一,所以 make + Makefile 的项目管理工具必须用于类 unix 环境。

缺点:

  1. makefile编写麻烦。
  2. 不跨平台。

bazel

Bazel 是一个开源的构建和测试工具,类似于Make、Maven及Gradle。它使用一种人易于理解的高级构建语言。Bazel 支持多种开发语言的项目,能够基于多个平台来构建。Bazel支持跨多个制品库和大规模用户的大型代码仓库。

优点:

  1. 高级构建语言。Bazel使用一种抽象的、人易于理解的、语义级别的高级语言来描述项目的构建属性。与其他工具不同,Bazel基于库,二进制文件,脚本和数据集的概念进行操作,使您免于陷入将单个调用编写到编译器和链接器等工具的复杂性。

  2. Bazel高效可靠。Bazel缓存以前完成的所有工作,并跟踪文件内容和构建命令的更改。通过这种方式,Bazel知道何时需要重建某些东西,并仅重建那些东西。为了进一步加快构建速度,您可以将项目设置为以并行和增量的方式构建。

  3. Bazel是跨平台的。Bazel可以在Linux,macOS和Windows上运行。Bazel可以为同一个项目中的多个平台(包括桌面,服务器和移动设备)构建二进制文件和可部署软件包。

  4. Bazel扩展性强。Bazel在使用100k+源文件处理构建时仍然保持良好的性能表现。它适用于多个制品存储库和10K用户规模。

ninja

ninja一个专注于速度的小型构建系统。它在两个主要方面与其他构建系统不同:它被设计为由更高级别的构建系统生成其输入文件,并且它被设计为尽可能快地运行构建。

优点:

  1. 简单。不像bazel的脚本那么复杂,.ninja类似于一个配置文件,没有分支和决策。
  2. 构建速度快。适合大型应用。
  3. 增量构建。不用每次都重新构建。

Demo1——hello

构建一个简单的项目。

image-20220907013513815

源代码

1
2
3
4
5
// CMakeLists.txt
cmake_minimum_required(VERSION 3.22)
project(demo1)
set(CMAKE_CXX_STANDARD 14)
add_executable(demo1 main.cpp myFunc.h myFunc.cpp)
1
2
3
4
5
// myFunc.h
#ifndef NINJA_TEST_MYFUNC_H
#define NINJA_TEST_MYFUNC_H
bool sayHello();
#endif //NINJA_TEST_MYFUNC_H
1
2
3
4
5
6
7
// myFunc.cpp
#include "myFunc.h"
#include <iostream>
bool sayHello() {
    std::cout << "Hello" << std::endl;
    return true;
}
1
2
3
4
5
6
7
8
9
// main.cpp
#include <cstdlib>
#include "myFunc.h"
int main(int argc, char* argv[]) {
    if (sayHello()) {
        return EXIT_SUCCESS;
    }
    return EXIT_FAILURE;
}

依赖关系

1
bazel query --nohost_deps --noimplicit_deps 'deps(//:main)'  --output graph
image-20220907015817734

使用make构建

  1. 使用cmake生成makefile文件

    1
    
    cmake .
    
    image-20220907014055875
  2. 运行make

    1
    
    make
    
    image-20220907014159847

使用bazel构建

  1. 编辑bazel脚本文件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    
    load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")
    
    # 构建一个lib
    cc_library(
        name = "myFunc",
        srcs = ["myFunc.cpp"],
        hdrs = ["myFunc.h"],
    )
    
    # 构建二进制文件 main
    cc_binary(
        name = "main",
        srcs = ["main.cpp"],
        deps = [
            ":myFunc",
        ],
    )
    
    image-20220907020127224
  2. bazel build

    1
    
    bazel build //:main
    
image-20220907020420058
  1. 运行

image-20220907020636497

使用ninja构建

  1. 使用cmake生成.ninja文件

    1
    
    cmake -B build -G Ninja
    
    image-20220907020943399 image-20220907021139206
  2. 构建

    1
    
    cd build && ninja
    
    image-20220907021242343

Demo2——re2

构建re2.

依赖关系

1
bazel query --nohost_deps --noimplicit_deps 'deps(//:regexp_benchmark)'  --output graph
regexp_benchmark

使用make构建

  1. 使用cmake生成makefile文件

    1
    
    cmake .
    
    image-20220907021841349
  2. 运行make

    1
    
    make
    
    image-20220907022018658 image-20220907021954243
  3. 运行

    image-20220907022140441

使用bazel构建

  1. 编辑bazel脚本文件

    image-20220907030836104
  2. bazel build

    1
    
    bazel build //:regexp_benchmark
    
image-20220907022843547
  1. 运行
image-20220907022856882

使用ninja构建

  1. 使用cmake生成.ninja文件

    1
    
    cmake -B build -G Ninja
    
    image-20220907023331314 image-20220907023430892
  2. 构建

    1
    
    cd build && ninja
    
    image-20220907023538182
  3. 运行

    image-20220907023616559