bazel使用匯總


最近重構代碼之后,打算在本地用bazel來作項目構建。主要是因為brpc已經支持了bazel,所以在此之前料想會簡單許多。

安裝比較簡單,centos直接用yum就行。按照這個指示:

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

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就行了。

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

常用的也就是cc_library和cc_binary。(因為我現在用blade也是這樣……)

當然寫c++,這里有個common case可以看看。

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

頭文件

頭文件的引入比較復雜些,分幾種情況:

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

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM