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 ],
  • 相关阅读:
    mac zsh选择到行首的快捷键
    phalcon下拉列表
    tinycore remaster方法
    bundle安装方法
    centos7安装avahi
    pydoc介绍
    macosx下apache的默认用户为daemon
    centos配置ssh免密码登录后,仍提示输入密码
    xampp默认项目文件夹htdocs
    微信开发:"errcode": -1000,"errmsg": "system error"错误的解决办法
  • 原文地址:https://www.cnblogs.com/linyx/p/10133709.html
Copyright © 2011-2022 走看看