【UBUNTU】bazel编译C++文件,bazel的写法

1. 序言

bazel是谷歌提出的新编译工具,目的在于取代现存的make和cmake等老旧的编译工具。其具有相当优秀的编译速度,且使用方法易于上手,下面就来说说怎么使用bazel来编译C++代码。

2. bazel的工作目录

项目
├── main(源代码所在文件夹)
│   ├── BUILD
│   └── print.cpp
└── WORKSPACE
==============================
WORKSPACE用不上的话,内容可以为空,只象征着工作空间的主目录所在

3. bazel中BUILD文件的编写

3.1 第一种情况:只有一个.cpp文件

只有一个print.cpp文件,代码如下:

// Copyright [2021] 
#include 
#include 
#include 

void PrintLocaltime() {
  std::time_t result = std::time(nullptr);
  std::cout << std::asctime(std::localtime(&result));
}

int main() {
  std::cout << "I was created by bazel" << std::endl;
  PrintLocaltime();
  return 0;
}

正常情况下我们使用g++ print.cpp -o print.o来编译代码,当使用bazel编译的时候BUILD文件应该这样写:

load("@rules_cc//cc:defs.bzl", "cc_binary")
cc_binary(
    name = "print",
    srcs = ["print.cpp"],
)
===============================
编译命令如下:
bazel build //main:print
其中//表示WORKSPACE所在的工作目录,main为工作目录下的main文件夹,print为main文件夹中被编译的对象文件(即cc_binary下面的name)
3.1.1 build文件关键字的介绍
 1.load语句的作用在于加载bazel的相关扩展包
 
 2.第一个参数代表扩展包的位置,第二个参数表示扩展包中的规则、函数、常量(字符串、列表等)
 
 3.上面的语句作用为:加载@rules_cc//cc:defs.bzl并添加其中定义的符号cc_binary到当前环境
 
 4.规则的类型,一般以编程语言为前缀,例如cc,java,后缀通常有:
   *_binary 用于构建目标语言的可执行文件
   *_test 用于自动化测试,其目标是可执行文件,如果测试通过应该退出0
   *_library 用于构建目标语言的库 

3.2 第二种情况:包含.h头文件及其.cpp文件

// 文件夹的结构如下
├── main
│   ├── BUILD
│   ├── main.cpp
│   ├── print.cpp
│   └── print.h
└── WORKSPACE
3.2.1 main.cpp的代码如下
// Copyright [year] 
#include 
#include 

#include "main/print.h"

int main() {
  std::string str = "I love you.";
  PrintAny(str);
  return 0;
}
3.2.2 print.h代码如下
// Copyright [year] 

#pragma once
#include 
#include 

void One();
void PrintAny(const std::string& str);
3.2.3 print.cpp代码如下
// Copyright [year] 
#include "main/print.h"

void One() {
  std::cout << "one" << std::endl;
}

void PrintAny(const std::string& str) {
  std::cout << str << std::endl;
}
3.2.4 bazel的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)

3.3 第三种情况:依赖于另一个文件夹中的.h文件

文件目录如下:

├── lib(main源文件依赖于此文件夹下的count.h)
│   ├── BUILD
│   ├── count.cpp
│   └── count.h
├── main
│   ├── BUILD
│   └── main.cpp
└── WORKSPACE
3.3.1 lib中的count.cpp和count.h代码如下:
// 文件名:count.h
// Copyright [year] 

#include 
#include 

int Add(const int& a, const int& b);
// 文件名:count.cpp
// Copyright [year] 

#include "lib/count.h"

int Add(const int& a, const int& b) {
  return a+b;
}

其中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__
3.3.2 main文件夹下的main.cpp的代码如下:
// Copyright [year] 
#include 
#include 

#include "lib/count.h"

int main() {
  int a = 1;
  int b = 2;
  int c = Add(a, b);
  std::cout << c << std::endl;
  return 0;
}

其中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。

3.4 第四种情况:需要加入编译选项如-std=c++11等

工作目录如下:

.
├── main
│   ├── BUILD
│   ├── main.cpp
│   ├── ThreadPool.cpp
│   └── ThreadPool.h
└── WORKSPACE
3.4.1 原本makefile文件的编写

因为用到了线程,所以需要编译选项 -lpthread,makefile的编写如下:

CFLAG = -std=c++11
LIB = -lpthread
OBJECTS = test ThreadPool.o 

test: main.cpp ThreadPool.o 
	g++ main.cpp ThreadPool.o -o test $(CFLAG) $(LIB)
	
ThreadPool.o: ThreadPool.cpp
	g++ -c ThreadPool.cpp $(CFLAG) $(LIB)
.PHONY:clean
clean:
	rm $(OBJECTS)
3.4.2 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的基本使用方法就只简单介绍到这了,详细的使用方法可以查看官方的文档。

你可能感兴趣的:(ubuntu,C++,c++)