bazel使用汇总

最近重构代码以后,打算在本地用bazel来做项目构建。主要是由于brpc已经支持了bazel,因此在此以前料想会简单许多。html

安装比较简单,centos直接用yum就行。按照这个指示:c++

https://docs.bazel.build/versions/master/install-redhat.htmlgit

1 wget https://copr.fedorainfracloud.org/coprs/vbatts/bazel/repo/epel-7/vbatts-bazel-epel-7.repo -O /etc/yum.repos.d/
2 yum install bazel

 最基本的使用,参考tutorial就好了。github

https://docs.bazel.build/versions/master/tutorial/cpp.htmlapache

经常使用的也就是cc_library和cc_binary。(由于我如今用blade也是这样……)centos

固然写c++,这里有个common case能够看看。ide

https://docs.bazel.build/versions/master/cpp-use-cases.htmlui

头文件

头文件的引入比较复杂些,分几种状况:google

1. 多文件。(使用通配符)spa

1 cc_library( 2     name = "build-all-the-files", 3     srcs = glob(["*.cc"]), 4     hdrs = glob(["inlcude/**/*.h"]), 5 )

2. 使用copts来指定引用目录。

1 cc_library( 2     name = "some_lib", 3     srcs = ["some_lib.cc"], 4     hdrs = ["include/some_lib.h"], 5     copts = ["-Ilegacy/some_lib/include"], 6 )

这里就涉及到另外一个参数,includes。includes和copts的使用区别主要有两点:

a. includes不须要加-I,并且直接是相对路径就行。也就是说,若是相对于主目录是./sub/subsub/a.h,sub/BUILD里,includes只须要写['subsub'], 若是是copts则须要写['-Isub/subsub/']。

b. copts只在当前目标里生效。includes则全部依赖到该目录都会继承。因此通常library仍是用includes。

这里还要注意,若是用cc_binary,srcs里也要包含引用的头文件,否则也会报错。

其余参数就看看文档:

https://docs.bazel.build/versions/master/be/c-cpp.html

外部引用

能够在WORKSPACE文件里写。

https://docs.bazel.build/versions/master/be/workspace.html

具体个人使用场景是把第3方库代码download下来放在项目里,而后经过WORKSPACE来设置。因此我会用到的是local_repository。好比我在个人项目WORKSPACE里这样写:

 1 local_repository(  2   name = "com_google_protobuf",  3   path = "3rdlib/protobuf-3.6.1/",  4 )  5 
 6 local_repository(  7   name = "com_github_google_leveldb",  8   path = "3rdlib/leveldb-1.20",  9 ) 10 
11 local_repository( 12   name = "com_github_gflags_gflags", 13   path = "3rdlib/gflags-master", 14 )

而后把brpc里对应的leveldb.BUILD拷到leveldb的源码目录,这样brpc的BUILD基本就不须要改了。

可是这里碰到另外一个坑,就是编译protobuf要指定HAVE_LIB=1。这里就经过在项目根目录的.bazelrc里写:

1 build --copt -DHAVE_ZLIB=1

这样bazel build就会默认调用这句命令。这里有个问题,是必需要在项目的根目录.bazelrc里写,在第三方目录里写是没用的。

https://github.com/bazelbuild/bazel/issues/6319

https://github.com/brpc/brpc/issues/275

外部非bazel的项目也能够用genrule,使用make来编译。genrule会自动执行。被依赖的文件,可能经过filegroup暴露出去。

https://docs.bazel.build/versions/master/be/general.html

genrule能够用到一些内置变量。系统变量用$$引用。内置变量见:

https://docs.bazel.build/versions/master/be/make-variables.html

可是获取不了本项目的绝对路径。因此我也不知道应该怎么捞取,获得的都是sandbox里的,只能用..来取到项目目录。

 1 genrule(  2     name = "libevent-srcs",  3     outs = include_files + lib_files,  4     cmd = "\n".join([  5         "export INSTALL_DIR=$$(pwd)/$(@D)/libevent",  6         "export TMP_DIR=$$(mktemp -d -t libevent.XXXXXX)",  7         "mkdir -p $$TMP_DIR",  8         "cp -R $$(pwd)/../../../../../external/com_github_libevent_libevent/* $$TMP_DIR",  9         "cd $$TMP_DIR", 10         "./autogen.sh", 11         "./configure --prefix=$$INSTALL_DIR CFLAGS=-fPIC CXXFLAGS=-fPIC --enable-shared=no --disable-openssl", 12         "make install", 13         "rm -rf $$TMP_DIR", 14  ]), 15 )

动态库查找问题

有个库用到了boost。boost太大没有包含到项目里,放在另外一个目录里,可是bazel找不到库目录,虽然已经export了LIBRARY_PATH和LD_LIBRARY_PATH。可是实际执行时是:

1 exec env - \ 2     LD_LIBRARY_PATH=:/home/myaccount/boost_1_68_0/release/lib/ \ 3     PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/usr/local/apache-hive-2.3.3-bin:/usr/local/apache-hive-2.3.3-bin:/home/xxj/.local/bin \ 4     PWD=/proc/self/cwd \ 5     TMPDIR=/tmp \

由于没有传递LIBRARY_PATH,因此boost库找不到。LIBRARY_PATH和LD_LIBRARY_PATH的区别见:

https://stackoverflow.com/questions/4250624/ld-library-path-vs-library-path

IBRARY_PATH is used by gcc before compilation to search directories containing static libraries that need to be linked to your program.
LD_LIBRARY_PATH is used by your program to search directories containing shared libraries after it has been successfully compiled and linked.

解决方案就在经过--action_env指定。

1 bazel build //3rdlib/test:bintest --action_env=LIBRARY_PATH=:/home/myaccount/boost_1_68_0/release/lib/

https://bazel.build/designs/2016/06/21/environment.html

Currently, Bazel provides a cleaned set of environment variables to the actions in order to obtain hermetic builds.

If the effective option for a variable has an unspecified value, the value from the invocation environment of Bazel is taken.

因此这里也能够不给LIBRARY_PATH指定值,这样就会直接使用环境变量。

1 bazel build //3rdlib/test:bintest --action_env=LIBRARY_PATH

 

proto处理

https://blog.bazel.build/2017/02/27/protocol-buffers.html

定义一个proto_library和对应的cc_proto_library。

 1 proto_library(  2         name = "http_proto",  3         srcs = [  4                 "http.proto",  5  ],  6 )  7 
 8 cc_proto_library(  9         name = "http_cc_proto", 10         deps = [":http_proto"], 11 )

这里cc_proto_library的deps必定要指向proto_library。

https://docs.bazel.build/versions/master/be/c-cpp.html#cc_proto_library

而后对应的cc_binary能够依赖到它和它产生的文件:

1 cc_binary( 2     name = "http_server", 3     srcs = ["http_server.cpp"], 4         deps = [ 5                 ":http_cc_proto", 6                 "//3rdlib/brpc-0.9.5:brpc", 7  ], 8 )

不过要想include生成的.pb.h文件,须要用相对于workspace的相对路径才行。

待定问题

1. -fopenmp这类参数无法继承。好比某个库编译须要用到-fopenmp。那么依赖到的binary的copts也要加上这个。如今尚未其余方案。

1 copts = [ 2     '-fopenmp', 3     '-march=native', 4 ],
相关文章
相关标签/搜索