zoukankan      html  css  js  c++  java
  • 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 = "
    ".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 ],
  • 相关阅读:
    51nod 1179 最大的最大公约数 (数论)
    POJ 3685 二分套二分
    POJ 3045 贪心
    LIC
    HDU 1029 Ignatius and the Princess IV
    HDU 1024 Max Sum Plus Plus
    HDU 2389 Rain on your Parade
    HDU 2819 Swap
    HDU 1281 棋盘游戏
    HDU 1083 Courses
  • 原文地址:https://www.cnblogs.com/linyx/p/10133709.html
Copyright © 2011-2022 走看看