Bazel使用:编译C++项目

官网:https://www.bazel.build
Github: https://github.com/bazelbuild/bazel

1、安装bazel(使用二进制文件安装的方法)

  • 安装所需的包
sudo apt-get install pkg-config zip g++ zlib1g-dev unzip python3
  • 下载Bazel
    二进制文件bazel--installer-linux-x86_64.sh 从GitHub上的Bazel发布页面(https://github.com/bazelbuild/bazel/releases)下载Bazel二进制安装程序。
  • 安装程序
    按如下方式运行Bazel安装程序:
$chmod +x bazel--installer-linux-x86_64.sh
$./bazel--installer-linux-x86_64.sh --user

该–user标志将Bazel安装到HOME/bin系统上的目录,并设置.bazelrc路径HOME/.bazelrc。
使用该–help命令可以查看其他安装选项。

  • 设置环境变量
    如果您使用–user上面的标志运行Bazel安装程序,则Bazel可执行文件将安装在您的HOME/bin目录中。将此目录添加到默认路径是个好主意,如下所示:
    export PATH="$PATH:$HOME/bin"

您也可以将此命令添加到您的~/.bashrc文件中。

$gedit ~/.bashrc

打开.bashrc文件,并添加

    export PATH="$PATH:$HOME/bin"

2、编译C++项目

下载示例(https://github.com/bazelbuild/examples/)
下载的示例中cpp-tutorial文件夹为C++项目示例,包含了这么些文件:

examples
└── cpp-tutorial
    ├──stage1
    │  └── main
    │      ├── BUILD
    │      ├── hello-world.cc
    │  └── WORKSPACE
    ├──stage2
    │  ├── main
    │  │   ├── BUILD
    │  │   ├── hello-world.cc
    │  │   ├── hello-greet.cc
    │  │   ├── hello-greet.h
    │  └── WORKSPACE
    └──stage3
       ├── main
       │   ├── BUILD
       │   ├── hello-world.cc
       │   ├── hello-greet.cc
       │   └── hello-greet.h
       ├── lib
       │   ├── BUILD
       │   ├── hello-time.cc
       │   └── hello-time.h
       └── WORKSPACE

可以看到分成了3组文件,分别对应本文中的3个例子。在第一个例子中,我们首先学习如何构建单个package中的单个target。在第二个例子中,我们将把整个项目拆分成单个package的多个target。第三个例子则将项目拆分成多个package,用多个target编译。

2.1、编译你的第一个Bazel项目

首先进入到cpp-tutorial/stage1目录下,然后运行以下指令:

$ bazel build //main:hello-world

注意target中的//main:是BUILD文件相对于WORKSPACE文件的位置,hello-world则是我们在BUILD文件中命名好的target的名字。
Bazel使用:编译C++项目_第1张图片
Bazel将编译的输出放在项目根目录下的bazel-bin目录下,可以看一下这个目录,理解一下Bazel的输出结构。

测试刚刚生成的二进制文件:

$ bazel-bin/main/hello-world

2.2、多个target的编译

单个target的方式对于小项目来说是高效的,但是对于大项目来说,你可能会想把它拆分成多个target和多个package来实现快速增量的编译(这样就只需要重新编译改变过的部分)。

首先我们来尝试着把项目拆分成两个target。看一下cpp-tutorial/stage2/main目录下的BUILD文件,它是这样的:

cc_library(
    name = "hello-greet",
    srcs = ["hello-greet.cc"],
    hdrs = ["hello-greet.h"],
)

cc_binary(
    name = "hello-world",
    srcs = ["hello-world.cc"],
    deps = [
        ":hello-greet",
    ],
)

我们看到在这个BUILD文件中,Bazel首先编译了hello-greet这个库(利用Bazel内置的cc_library编译指令),然后编译hello-world这个二进制文件。hello-world这个target的deps属性告诉Bazel,要构建hello-world这个二进制文件需要hello-greet这个库。

好,让我们编译一下新的版本。进入到cpp-tutorial/stage2目录下然后运行以下指令:

$ bazel build //main:hello-world

Bazel使用:编译C++项目_第2张图片
现在又可以测试刚刚生成的二进制文件了:

$ bazel-bin/main/hello-world

注意,如果你现在修改一下hello-greet.cc然后重新编译整个项目的话,Bazel其实只会编译修改过的那个文件。

2.3、多个package的编译

我们现在再将项目拆分成多个package。看一下cpp-tutorial/stage3目录下的内容:

└──stage3
   ├── main
   │   ├── BUILD
   │   ├── hello-world.cc
   │   ├── hello-greet.cc
   │   └── hello-greet.h
   ├── lib
   │   ├── BUILD
   │   ├── hello-time.cc
   │   └── hello-time.h
   └── WORKSPACE

注意到我们现在有两个子目录了,每个子目录中都包含了BUILD文件。因此,对于Bazel来说,整个工作区现在就包含了两个package:lib和main。

lib/BUILD文件长这样:

cc_library(
    name = "hello-time",
    srcs = ["hello-time.cc"],
    hdrs = ["hello-time.h"],
    visibility = ["//main:__pkg__"],
)

main/BUILD文件长这样:

cc_library(
    name = "hello-greet",
    srcs = ["hello-greet.cc"],
    hdrs = ["hello-greet.h"],
)

cc_binary(
    name = "hello-world",
    srcs = ["hello-world.cc"],
    deps = [
        ":hello-greet",
        "//lib:hello-time",
    ],
)

可以看出hello-world这个mainpackage中的target依赖于lib package中的hello-time target(即target label为://lib:hello-time)- Bazel是通过deps这个属性知道自己的依赖项的。
注意到lib/BUILD文件中我们将hello-time这个target显式可见了(通过visibility属性)。这是因为默认情况下,targets只对同一个BUILD文件里的其他targets可见(Bazel使用target visibility来防止像公有API中库的实现细节的泄露等情况)。

好,让我们编译一下新的版本。进入到cpp-tutorial/stage3目录下然后运行以下指令:

bazel build //main:hello-world

Bazel使用:编译C++项目_第3张图片
现在又可以测试刚刚生成的二进制文件了:

$ bazel-bin/main/hello-world

参考:
https://blog.csdn.net/u012342051/article/details/98496778
https://blog.csdn.net/elaine_bao/article/details/78668657

你可能感兴趣的:(Google工具,linux,google,c++)