Google出版的多语言(C++,Java,Go..)编译工具 - Bazel

bazel

Bazel is an open-source build and test tool similar to Make, Maven, and Gradle. It uses a human-readable, high-level build language. Bazel supports projects in multiple languages and builds outputs for multiple platforms. Bazel supports large codebases across multiple repositories, and large numbers of users.

Bazel是一个开源的、支持多种语言、跨平台、跟Make相似的编译工具。

安装
官方例子

先克隆项目:

:git clone https://github.com/bazelbuild/examples
正克隆到 'examples'...
remote: Enumerating objects: 14, done.
remote: Counting objects: 100% (14/14), done.
remote: Compressing objects: 100% (12/12), done.
remote: Total 1183 (delta 3), reused 6 (delta 2), pack-reused 1169
接收对象中: 100% (1183/1183), 362.71 KiB | 113.00 KiB/s, 完成.
处理 delta 中: 100% (439/439), 完成.

examples提供了多种语言的,先看cpp的:

:cd examples/cpp-tutorial

看看目录下都有哪些文件:

:tree
.
├── README.md
├── stage1
│   ├── README.md
│   ├── WORKSPACE
│   └── main
│       ├── BUILD
│       └── hello-world.cc
├── stage2
│   ├── README.md
│   ├── WORKSPACE
│   └── main
│       ├── BUILD
│       ├── hello-greet.cc
│       ├── hello-greet.h
│       └── hello-world.cc
└── stage3
    ├── README.md
    ├── WORKSPACE
    ├── lib
    │   ├── BUILD
    │   ├── hello-time.cc
    │   └── hello-time.h
    └── main
        ├── BUILD
        ├── hello-greet.cc
        ├── hello-greet.h
        └── hello-world.cc

7 directories, 20 files

As you can see, there are three sets of files, each set representing a stage in this tutorial. In the first stage, you will build a single target residing in a single package. In the second stage, you will split your project into multiple targets but keep it in a single package. In the third and final stage, you will split your project into multiple packages and build it with multiple targets.

看到首先是有一个WORKSPACE规定区域的,然后里面有BUILD文件中定义了不同文件的编译规则。

设置工作空间

Before you can build a project, you need to set up its workspace. A workspace is a directory that holds your project’s source files and Bazel’s build outputs. It also contains files that Bazel recognizes as special:

  • The WORKSPACE file, which identifies the directory and its contents as a Bazel workspace and lives at the root of the project’s directory structure
  • One or more BUILD files, which tell Bazel how to build different parts of the project. (A directory within the workspace that contains a BUILD file is a package. You will learn about packages later in this tutorial.)

WORKSPACE file用来区别一个工程,它应该位于工程的根目录下。

一个或多个BUILD file定义如何编译一个工程中不同的模块。

To designate a directory as a Bazel workspace, create an empty file named WORKSPACE in that directory.

When Bazel builds the project, all inputs and dependencies must be in the same workspace. Files residing in different workspaces are independent of one another unless linked, which is beyond the scope of this tutorial.

Bazel在编译项目的时候,所有的输入和依赖文件应该在同一个工作空间(workspace)下,如果在不同的工作空间且没有链接的话,Bazel没有办法编译。

BUILD

A BUILD file contains several different types of instructions for Bazel. The most important type is the build rule, which tells Bazel how to build the desired outputs, such as executable binaries or libraries. Each instance of a build rule in the BUILD file is called a target and points to a specific set of source files and dependencies. A target can also point to other targets.

一个BUILD file包含Bazel的不同类型的指令,最重要的是编译规则,指定了如何输出(比如可执行二进制文件或库)。一个编译规则是一个目标,它指向多个源文件和依赖文件,也可以指向另一个目标。

举个例子:

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

the hello-world target instantiates Bazel’s built-in cc_binary rule. The rule tells Bazel to build a self-contained executable binary from the hello-world.cc source file with no dependencies.

上面定义了一个cc_binary类型的名字为hello-world的编译规则,它将hello-world.cc文件编译成可执行文件。

编译项目 Build the project

命令如下:

bazel build //main:hello-world

Notice the target label - the //main: part is the location of our BUILD file relative to the root of the workspace, and hello-world is what we named that target in the BUILD file. (You will learn about target labels in more detail at the end of this tutorial.)

bazel build //path/to/package:target-name
bazel build //相对于workspace的目录:规则名称
执行:

:cd stage1
:bazel build //main:hello-world
Starting local Bazel server and connecting to it...
INFO: Analyzed target //main:hello-world (13 packages loaded, 49 targets configured).
INFO: Found 1 target...
Target //main:hello-world up-to-date:
  bazel-bin/main/hello-world
INFO: Elapsed time: 31.900s, Critical Path: 1.47s
INFO: 2 processes: 2 darwin-sandbox.
INFO: Build completed successfully, 5 total actions

如果想运行文件:

bazel-bin/main/hello-world

看一下bazel build后产生了哪些文件:

:cd stage1
:ls
README.md	WORKSPACE	bazel-bin	bazel-out	bazel-stage1	bazel-testlogs	main
:tree
.
├── README.md
├── WORKSPACE
├── bazel-bin -> /private/var/tmp/_bazel_lurongming/f341b2c050b4058e9d9fef7c2d35da5d/execroot/__main__/bazel-out/darwin-fastbuild/bin
├── bazel-out -> /private/var/tmp/_bazel_lurongming/f341b2c050b4058e9d9fef7c2d35da5d/execroot/__main__/bazel-out
├── bazel-stage1 -> /private/var/tmp/_bazel_lurongming/f341b2c050b4058e9d9fef7c2d35da5d/execroot/__main__
├── bazel-testlogs -> /private/var/tmp/_bazel_lurongming/f341b2c050b4058e9d9fef7c2d35da5d/execroot/__main__/bazel-out/darwin-fastbuild/testlogs
└── main
    ├── BUILD
    └── hello-world.cc

5 directories, 4 files
Review
:bazel query --notool_deps --noimplicit_deps 'deps(//main:hello-world)'   --output graph
digraph mygraph {
  node [shape=box];
  "//main:hello-world"
  "//main:hello-world" -> "//main:hello-world.cc"
  "//main:hello-world.cc"
}

使用bazel query可以查询编译规则。

再看一下复杂一点的:

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

它的编译规则:

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",
    ],
)

Notice that for the build to succeed, we make the //lib:hello-time target in lib/BUILD explicitly visible to targets in main/BUILD using the visibility attribute. This is because by default targets are only visible to other targets in the same BUILD file. (Bazel uses target visibility to prevent issues such as libraries containing implementation details leaking into public APIs.)

默认BUILD file只能中的目标只能被本文件中的可见,如果其他BUILD需要看见,请使用visibility。

发布了99 篇原创文章 · 获赞 5 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/LU_ZHAO/article/details/104756897