【UBUNTU】bazel编译C++文件,bazel的写法_剑客无名的博客-CSDN博客
bazel:为非bazel项目指定本地BUILD文件 - 知乎
bazel c++ 编译入门 - 简书
一. bazel工作目录
项目
├── main(源代码所在文件夹)
│ ├── BUILD
│ └── print.cpp
└── WORKSPACE
WORKSPACE用不上的话,内容可以为空,只象征着工作空间的主目录所在。
二. BUILD文件的编写
(一)本地单bazel工程(只一个WORKSPACE文件)
1. 单目录
① 单源文件
例如只有一个print.cpp文件,正常情况下我们使用g++ print.cpp -o print.o来编译代码。当使用bazel编译,BUILD文件:
load("@rules_cc//cc:defs.bzl", "cc_binary")
cc_binary(
name = "print",
srcs = ["print.cpp"],
)
1)load语句指加载bazel的相关扩展包 (第一个参数代表扩展包的位置,第二个参数表示扩展包中的规则、函数、常量(字符串、列表等))。
上面的语句作用为:加载@rules_cc//cc:defs.bzl并添加其中定义的符号cc_binary到当前环境。
规则的类型(比如此例的cc_binary),一般以编程语言为前缀,例如cc,java。后缀通常有: *_binary 用于构建目标语言的可执行文件
*_test 用于自动化测试,其目标是可执行文件,如果测试通过应该退出0
*_library 用于构建目标语言的库
注:
WORKSPACE加载扩展.bzl规则
其中local_repository与new_local_repository可以不执行load,其余的必须执行load:
2)编译命令: bazel build //main:print
其中//表示WORKSPACE所在的工作目录,main为工作目录下的main文件夹,print为main文件夹中被编译的对象文件(即cc_binary下面的name)。
注:bazel run //main:print 指定编译并执行package(main)下的target(print)。
② 多源文件
// 文件夹的结构如下
├── main
│ ├── BUILD
│ ├── main.cpp
│ ├── print.cpp
│ └── print.h
└── WORKSPACE
BUILD文件:
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")
cc_library(
name = "print",
srcs = ["print.cpp"],
hdrs = ["print.h"],
)
cc_binary(
name = "main",
srcs = ["main.cpp"],
deps = [
"//main:print",
],
)
load中加入的规则有:cc_binary和cc_library,其中cc_library用来编译头文件。
在cc_binary中加入了deps,构建的可执行文件依赖于main文件夹下的print(即cc_library中的name)。
2. 多目录
├── lib(main源文件依赖于此文件夹下的count.h)
│ ├── BUILD
│ ├── count.cpp
│ └── count.h
├── main
│ ├── BUILD
│ └── main.cpp
└── WORKSPACE
lib文件夹下的BUILD文件:
load("@rules_cc//cc:defs.bzl", "cc_library")
cc_library(
name = "count",
srcs = ["count.cpp"],
hdrs = ["count.h"],
visibility = ["//main:__pkg__"],
)
要使count对main文件夹下的文件可见,需要在./lib/BUILD文件中添加属性visibility,值为//main:__pkg__
main文件夹下的BUILD文件:
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")
cc_binary(
name = "main",
srcs = ["main.cc"],
deps = [
"//lib:count",
],
)
因为要依赖于lib文件夹中的count,所以要加入deps来表示可执行文件需要依赖于lib文件夹中的count。lib与main在同个WORKSPACE下,所以是deps = ["//lib:count", ],
而非deps = ["@lib:count", ]
注:
(1)当需要加入编译选项如-std=c++11等的时候
.
├── main
│ ├── BUILD
│ ├── main.cpp
│ ├── ThreadPool.cpp
│ └── ThreadPool.h
└── WORKSPACE
BUILD文件:
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")
cc_library(
name = "ThreadPool",
srcs = ["TC_ThreadPool.cpp"],
hdrs = ["TC_ThreadPool.h"],
)
cc_binary(
name = "main",
srcs = ["main.cpp"],
deps = [
":ThreadPool",
],
linkopts = ["-lpthread", "-std=c++11"],
)
因为编译时需要多线程以及C++11的支持,所以在编译target对应的cc_binary中加入了linkopts,只需要在其中放置编译选项即可。
(二)本地多bazel工程(不只一个WORKSPACE文件)
本地不同bazel工程之间的依赖
.
├── sub1
│ ├── src
│ │ ├── BUILD
│ │ └── main.cc
│ └── WORKSPACE
└── sub2
├── lib
│ ├── BUILD
│ └── print.h
└── WORKSPACE
sub1/WORKSPACE
local_repository(
name = "sub2",
path = "../sub2",
)
sub1/src/BUILD
cc_binary(
name = "hello-bazel",
srcs = ["main.cc"],
deps = [
"@sub2//lib:print",
],
)
注:sub2与sub1不在同个WORKSPACE下,所以是deps = ["@sub2//lib:print", ] ,
而非deps = ["//sub2:",]
sub2/lib/BUILD
cc_library(
name = "print",
hdrs = ["print.h"],
visibility = ["//visibility:public"],
)
(三)本地含非bazel工程(部分文件夹不含BUILD文件)
.
├── sub1
│ ├── src
│ │ ├── BUILD
│ │ └── main.cc
│ ├── sub2.BUILD
│ └── WORKSPACE
└── sub2
└── lib
└── print.h
sub1/WORKSPACE(指向非bazel工程)
new_local_repository(
name = "sub2",
path = "../sub2",
build_file = "sub2.BUILD",
)
sub1/src/BUILD(执行函数)
cc_binary(
name = "hello-bazel",
srcs = ["main.cc"],
deps = [
"@sub2//:print",
],
)
sub1/sub2.BUILD(指向非bazel工程,库函数)
cc_library(
name = "print",
hdrs = glob(["lib/**"]),
visibility = ["//visibility:public"],
)
(四)远程bazel工程
.
├── BUILD
├── main.cc
└── WORKSPACE
WORKSPACE
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "gtest",
sha256 = "9dc9157a9a1551ec7a7e43daea9a694a0bb5fb8bec81235d8a1e6ef64c716dcb",
strip_prefix = "googletest-release-1.10.0",
urls = [
"https://apollo-system.cdn.bcebos.com/archive/6.0/release-1.10.0.tar.gz",
"https://github.com/google/googletest/archive/release-1.10.0.tar.gz",
],
)
BUILD
cc_test(
name = "gtest",
srcs = ["main.cc"],
copts = ["-Iexternal/gtest/include"],
deps = [
"@gtest//:gtest_main",
],
)
(五)远程非bazel工程
.
├── BUILD
├── gtest.BUILD
├── main.cc
└── WORKSPACE
BUILD
cc_test(
name = "gtest",
srcs = ["main.cc"],
copts = ["-Iexternal/gtest/include"],
deps = [
"@gtest//:main",
],
)
gtest.BUILD
cc_library(
name = "main",
srcs = glob(
["src/*.cc"],
exclude = ["src/gtest-all.cc"]
),
hdrs = glob([
"include/**/*.h",
"src/*.h"
]),
copts = ["-Iexternal/gtest/include"],
linkopts = ["-pthread"],
visibility = ["//visibility:public"],
)
WORKSPACE
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "gtest",
url = "https://github.com/google/googletest/archive/release-1.7.0.zip",
sha256 = "b58cb7547a28b2c718d1e38aee18a3659c9e3ff52440297e965f5edffe34b6d0",
build_file = "@//:gtest.BUILD",
strip_prefix = "googletest-release-1.7.0",
)
注:全局配置
针对每个target,我们可以采用copts参数来配置编译参数,但是如果有些参数需要全局配置时,通过copts就比较麻烦。针对这种场景,bazel提供了一个方案:在根目录创建.bazelrc文件,比如配置c++11作为c++标准。
build --copt=-std=c++11