bazel使用教程 转

bazel使用教程

bazel的所有代码都在当前工程,每个工程都是一个 WORKSPACE。每个WORKSPACE下有多个package(包含BUILD文件的文件夹被称为package),BUILD内是多个targets,同一个package内的targets默认互相可见,不同package之间targets的可见性需要手动定义,可以在每个package的BUILD文件顶部声明其中的targets对其他包的默认可见性。

一、安装bazel

参考:Installing Bazel on Ubuntu 

sudo apt install curl
curl https://bazel.build/bazel-release.pub.gpg | sudo apt-key add -
echo "deb [arch=amd64] https://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list
sudo apt-get update 
sudo apt-get install bazel # 安装bazel
sudo apt-get install --only-upgrade bazel # 升级bazel到最新版本


查看bazel版本

bazel version


BUILD构建文件用"#" 开头来添加单行注释 

二、编译运行

参考:Command-Line Reference

bazel clean

bazel clean # 不会删除外部依赖
bazel clean --expunge # 会删除外部依赖
bazel clean --expunge --async
bazel build

bazel build :<exe name> # 在BUILD所在的package目录下执行,编译指定的target
bazel build :all  # 编译该package下的所有target
bazel build ...  # 编译该package下的所有target
bazel build <//path/to/package>:<exe name> # 在workspace下的任意目录执行,“//”表示workspace所在目录
bazel build :<exe name> --compilation_mode=dbg # debug mode
bazel build :<exe name> -c dbg # debug mode
bazel build :<exe name> --keep_going # 看到所有的错误
bazel build :<exe name> --config=<asan/tsan/msan> # Build the project with sanitizers by adding the --config=<asan/tsan/msan> build flag to select AddressSanitizer (asan), ThreadSanitizer (tsan) or MemorySanitizer (msan) accordingly.
bazel build :<exe name> --config local_first
bazel run

bazel run :<target name>
bazel run -- :<target name>


不需要先执行build,在执行run,run的时候会自动先build再执行

bazel test

bazel test:<target name>


工作原理

加载与target有关的BUILD文件
分析inputs和dependencies,生成 action graph
执行graph,产出outputs
action graph: bazel依赖这个图来追踪文件变化,以及是否需要重新编译,并且还可以为用户提供代码之间的依赖关系图。

bazel query 'deps(//<path_to_package>:<target_name>)' # 查看target的依赖
bazel query "somepath(//<path_to_package>:<target1_name>,//<path_to_package>:<target2_name>)"


三、WORKSPACE文件

参考:Working with external dependencies

WORKSPACE文件主要就是命名workspace以及声明外部的依赖,这就包括外部依赖的获取方式及获取方法。WORKSPACE文件告诉Bazel如何去得到其他的工程源,然后package中的BUILD文件就可以根据WORKSPACE中的外部target名字写依赖关系。WORKSPACE文件允许用户的目标依赖其他文件系统的目标或者从网上下载的目标。除了通过bazel build可以自动获取外部依赖之外,还可以通过bazel fetch来获得。Bazel会缓存外部依赖,并且只有在WORKSPACE文件更改后才再次下载和更新。WORKSPACE文件的语法和BUILD文件一致,不过会用到一些特定的内置rule。所有的外部依赖会都下载到一个名为的软连接目录。具体的内容可以通过命令行获得:

ls $(bazel info output_base)/external


一共有三种外部依赖的主要类型:

1、依赖于其他Bazel工程

根据这个Bazel工程所处的位置不同,调用不同的内置rule来获得:

local_repository:本地
git_repository:git仓库
http_archive:网络下载


2、依赖于其他非Bazel工程

还有一种情况是另外一个工程不是Bazel工程,那么就需要另外一种方法来添加依赖引用

new_local_repository:本地
new_git_repository:git仓库
new_http_archive:网络下载


3、依赖于外部包

Maven仓库:Use the rule maven_jar (and optionally the rule maven_server) to download a jar from a Maven repository and make it available as a Java dependency.

Workspace Rules

参考:C / C++ Rules

bind

bind(name, actual, compatible_with, deprecation, distribs, features, licenses, restricted_to, tags, testonly, visibility)


给target命别名,不推荐使用

git_repository

git_repository(name, commit, init_submodules, remote, sha256, tag)
这个有很多限制不推荐使用,用http_archive 来代替使得更加鲁棒以及安全性能。

http_archive

http_archive(name, sha256, strip_prefix, type, url, urls)
下载一个压缩格式的Bazel仓库,并解压出来,然后绑定使用。这个Rule有一个属性strip_prefix,用来消除前缀目录。

举例:

(1) glog / gflags

目录结构

├── WORKSPACE
├── BUILD
└── main.cc


WORKSPACE

workspace(name = "bazel_test")
 
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
 
git_repository(
    name = "com_github_gflags_gflags",
    commit = "f7388c6655e699f777a5a74a3c9880b9cfaabe59",
    remote = "https://github.com/gflags/gflags.git",
)
 
git_repository(
    name = "glog",
    commit = "0a2e5931bd5ff22fd3bf8999eb8ce776f159cda6",
    remote = "https://github.com/google/glog.git",
)
BUILD

cc_binary(
    name = "bazel_test",
    srcs = ["main.cc"],
    deps = [
      "@com_github_gflags_gflags//:gflags",
      "@glog",
    ],
)


main.cc

#include <glog/logging.h>
#include <gflags/gflags.h>
 
DEFINE_string(name, "alan", "your name");
 
int main(int argc, char *argv[]) {
    google::InitGoogleLogging(argv[0]);
    FLAGS_logtostderr = 1;
    FLAGS_colorlogtostderr = 1;
    gflags::ParseCommandLineFlags(&argc, &argv, true);
 
    LOG(INFO) << "hello " << FLAGS_name;
 
    return 0;
}


执行

bazel run -- :bazel_test --name alan


(2) gtest

目录结构

├── WORKSPACE
├── gtest.BUILD
├── main.cc
└── BUILD
WORKSPACE

workspace(name = "bazel_test")
 
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",
)


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


BUILD

cc_test(
    name = "bazel_test",
    srcs = ["main.cc"],
    copts = ["-Iexternal/gtest/include"],
    deps = [
        "@gtest//:main",
    ],
)


 main.cc

#include "gtest/gtest.h"
 
int abs(int x) {
  return x >= 0? x : -x;
}
 
TEST(BazelTest, AbsTest) {
  EXPECT_EQ(abs(-1), 1);
}


执行

bazel test :bazel_test


参考:Introduction to Bazel: Common C++ Build Use Cases

(3) proto

目录结构

├── WORKSPACE
├── BUILD
├── main.cc
└── foo.proto

WORKSPACE

workspace(name = "bazel_test")
 
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 
http_archive(
    name = "rules_proto",
    sha256 = "602e7161d9195e50246177e7c55b2f39950a9cf7366f74ed5f22fd45750cd208",
    strip_prefix = "rules_proto-97d8af4dc474595af3900dd85cb3a29ad28cc313",
    urls = [
        "https://mirror.bazel.build/github.com/bazelbuild/rules_proto/archive/97d8af4dc474595af3900dd85cb3a29ad28cc313.tar.gz",
        "https://github.com/bazelbuild/rules_proto/archive/97d8af4dc474595af3900dd85cb3a29ad28cc313.tar.gz",
    ],
)
load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains")
rules_proto_dependencies()
rules_proto_toolchains()
BUILD

#load("@rules_cc//cc:defs.bzl", "cc_proto_library")
#load("@rules_proto//proto:defs.bzl", "proto_library")
 
cc_binary(
    name = "bazel_test",
    srcs = ["main.cc"],
    deps = [":foo_cc_proto"],
)
 
proto_library(
    name = "foo_proto",
    srcs = [
        "foo.proto",
    ],
)
 
cc_proto_library(
    name = "foo_cc_proto",
    deps = [
        ":foo_proto",
    ],
)


 main.cc

#include "foo.pb.h"
 
int main(int argc, char *argv[]) {
    foo::Bar bar;
    bar.set_id(10);
    std::cout << "id: " << bar.id() << std::endl;
    return 0;
}

foo.proto 

syntax = "proto3";
 
package foo;
 
message Bar {
  int32 id = 1;
}


执行

bazel run :bazel_test


参考:GitHub - bazelbuild/rules_proto: Protocol buffer rules for Bazel 

(4) eigen

目录结构

├── WORKSPACE
├── BUILD
└── main.cc
WORKSPACE

workspace(name = "bazel_test")
 
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 
http_archive(
    name = "com_github_eigen_eigen",
    sha256 = "dd254beb0bafc695d0f62ae1a222ff85b52dbaa3a16f76e781dce22d0d20a4a6",
    strip_prefix = "eigen-eigen-5a0156e40feb",
    urls = [
        "http://bitbucket.org/eigen/eigen/get/3.3.4.tar.bz2",
    ],
    build_file_content =
"""
cc_library(
    name = 'eigen',
    srcs = [],
    includes = ['.'],
    hdrs = glob(['Eigen/**']),
    visibility = ['//visibility:public'],
)
"""
)
BUILD

cc_binary(
    name = "bazel_test",
    srcs = ["main.cc"],
    deps = [
        "@com_github_eigen_eigen//:eigen",
    ],
)


main.cc

#include <iostream>
#include <Eigen/Dense>
 
int main(int argc, char *argv[])
{
    Eigen::Matrix3d m = Eigen::Matrix3d::Identity();
    std::cout << m << std::endl;
    return 0;
}


执行

bazel run :bazel_test


(5) ceres (依赖gflags、glog、eigen、benchmark)

目录结构

├── WORKSPACE
├── BUILD
└── main.cc
WORKSPACE

workspace(name = "bazel_test")
 
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
# External dependency: Google Flags; has Bazel build already.
http_archive(
    name = "com_github_gflags_gflags",
    sha256 = "6e16c8bc91b1310a44f3965e616383dbda48f83e8c1eaa2370a215057b00cabe",
    strip_prefix = "gflags-77592648e3f3be87d6c7123eb81cbad75f9aef5a",
    urls = [
        "https://mirror.bazel.build/github.com/gflags/gflags/archive/77592648e3f3be87d6c7123eb81cbad75f9aef5a.tar.gz",
        "https://github.com/gflags/gflags/archive/77592648e3f3be87d6c7123eb81cbad75f9aef5a.tar.gz",
    ],
)
# External dependency: Google Log; has Bazel build already.
http_archive(
    name = "com_github_google_glog",
    sha256 = "7083af285bed3995b5dc2c982f7de39bced9f0e6fd78d631f3285490922a0c3d",
    strip_prefix = "glog-3106945d8d3322e5cbd5658d482c9ffed2d892c0",
    urls = [
        "https://github.com/drigz/glog/archive/3106945d8d3322e5cbd5658d482c9ffed2d892c0.tar.gz",
    ],
)
# External dependency: Eigen; has no Bazel build.
http_archive(
    name = "com_github_eigen_eigen",
    sha256 = "dd254beb0bafc695d0f62ae1a222ff85b52dbaa3a16f76e781dce22d0d20a4a6",
    strip_prefix = "eigen-eigen-5a0156e40feb",
    urls = [
        "http://bitbucket.org/eigen/eigen/get/3.3.4.tar.bz2",
    ],
    build_file_content =
"""
# TODO(keir): Replace this with a better version, like from TensorFlow.
# See https://github.com/ceres-solver/ceres-solver/issues/337.
cc_library(
    name = 'eigen',
    srcs = [],
    includes = ['.'],
    hdrs = glob(['Eigen/**']),
    visibility = ['//visibility:public'],
)
"""
)
# External dependency: Google Benchmark; has no Bazel build.
http_archive(
    name = "com_github_google_benchmark",
    urls = ["https://github.com/google/benchmark/archive/56f52ee228783547f544d9ac4a533574b9010e3f.zip"],
    sha256 = "8c1c6e90cd320b07504fabb86400f390faff2e599183ebd9396908817968ae79",
    strip_prefix = "benchmark-56f52ee228783547f544d9ac4a533574b9010e3f",
    build_file_content =
"""
cc_library(
    name = "benchmark",
    srcs = glob([
        "src/*.h",
        "src/*.cc",
    ]),
    hdrs = glob(["include/benchmark/*.h"]),
    copts = [
        "-DHAVE_STD_REGEX",
    ],
    includes = [
        "include",
    ],
    visibility = ["//visibility:public"],
)
"""
)
 
local_repository(
    name = "ceres",
    path = "/home/alan/3rdparty/ceres-solver-1.14.0",
)


BUILD

cc_binary(
    name = "bazel_test",
    srcs = ["main.cc"],
    deps = [
      "@ceres",
    ],
)


main.cc

#include <iostream>
#include <Eigen/Dense>
 
int main(int argc, char *argv[])
{
    Eigen::Matrix3d m = Eigen::Matrix3d::Identity();
    std::cout << m << std::endl;
    return 0;
}


执行

bazel run :bazel_test
参考:

Non-linear Least Squares — Ceres Solver

https://ceres-solver.googlesource.com/ceres-solver/+/master/WORKSPACE

(6) opencv

链接本地编译安装好的opencv库

git clone https://github.com/opencv/opencv.git
cd opencv/
mkdir build install
cd build
cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/home/alan/3rdparty/opencv/install ..
make install


目录结构

├── WORKSPACE
├── opencv.BUILD
├── main.cc
└── BUILD
WORKSPACE

workspace(name = "bazel_test")
 
new_local_repository(
    name = "opencv",
    path = "/home/alan/3rdparty/opencv/install",
    build_file = "opencv.BUILD",
)
opencv.BUILD

cc_library(
    name = "opencv",
    srcs = glob(["lib/*.so*"]),
    hdrs = glob(["include/**/*.hpp"]),
    includes = ["include"],
    visibility = ["//visibility:public"], 
    linkstatic = 1,
)
BUILD

cc_binary(
    name = "bazel_test",
    srcs = ["main.cc"],
    deps = [
      "@opencv//:opencv",
    ],
)
 main.cc

#include <opencv2/opencv.hpp>
 
int main(int argc, char *argv[]) {
    cv::Mat img = cv::imread("/home/alan/1.jpg");
    std::cout << "Resolution: " << img.rows << " x " << img.cols << std::endl;
    return 0;
}
执行

bazel run :bazel_test
参考:Building OpenCV code using Bazel

tf_cc_binary:目标文件编译规则,为一个二进制可执行文件。name必须唯一,srcs指定了源文件,linkopts指定了链接规则,deps指定了依赖文件

cc_library:库文件编译规则,name指定了编译为库文件后的文件名,srcs和hdrs指定源文件和头文件,deps指定需要依赖的其他文件

tf_cc_test:测试文件规则

package:通用方法,定义的值会作用到下面的每个子rule中。default_visibility指定了这个包的默认可见规则。可见的情况下才能被其他package调用。

licenses:通用方法,默认的license

load:通用方法,加载.bzl文件

filegroup:通用方法,为多个编译目标target指定一个名字,glob是一个帮助函数,指定了目录中哪些文件会include,哪些会exclude。visibility指定了target的可见性,也就是可以被哪些package调用
 

name属性来命名规则,

deps属性来描述规则之间的依赖关系。使用冒号来分隔包名和规则名。如果某条规则所依赖的规则在其他目录下,就用"//"开头,如果在同一目录下,可以忽略包名而用冒号开头。

linkopts指定了链接规则
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
VSCode 是一个功能强大的代码编辑器,可以与不同的构建工具集成,包括 Bazel。下面是一些使用 VSCode 和 Bazel 的基本步骤: 1. 安装 VSCode:首先,你需要下载并安装 VSCode。你可以从 https://code.visualstudio.com/ 下载适用于你的操作系统的安装程序,并按照说明进行安装。 2. 安装 Bazel 插件:打开 VSCode,点击左侧侧边栏的“扩展”(Extensions)图标。在搜索栏中输入“Bazel”,然后选择并安装适用于 VSCode 的 Bazel 插件。 3. 创建工作区:打开一个包含 Bazel 项目的文件夹。点击“文件”(File)菜单,选择“打开文件夹”(Open Folder),然后选择你的 Bazel 项目所在的文件夹。 4. 配置 Bazel 插件:点击 VSCode 左下角的设置图标,选择“设置”(Settings)。在搜索栏中输入“Bazel”,然后找到“Bazel: Build Target”。点击“编辑设置 JSON”链接,将你要构建的目标添加到设置中。例如: ```json { "bazel.buildTarget": "//path/to:target" } ``` 将 `//path/to:target` 替换为你的 Bazel 目标。 5. 构建和运行:打开一个 Bazel 目标的 BUILD 文件,点击右上角的 Bazel 插件图标,选择 “Build” 或者 “Run” 来构建或运行你的代码。 上述步骤应该能帮助你开始使用 VSCode 和 Bazel。记得根据你的项目进行适当的调整和配置。如果你想了解更多关于使用 Bazel 和 VSCode 的详细信息,可以查阅官方文档或搜索相关教程和资源。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值