UBUNTU bazel编译C++文件

【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
  • git_repository
  • new_git_repository
  • http_archive
  • http_file

其中local_repository与new_local_repository可以不执行load,其余的必须执行load:

  • git_repository:load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
  • new_git_repository:load("@bazel_tools//tools/build_defs/repo:git.bzl", "new_git_repository")
  • http_archive:load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
  • http_file:load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_file")

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

UBUNTU bazel编译C++文件_第1张图片

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

你可能感兴趣的:(C++,c++,开发语言)