最近重构代码之后,打算在本地用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.-bin:/usr/local/apache-hive-2.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. ],

bazel使用汇总的更多相关文章

  1. 使用Bazel构建C/C++项目

    目录 前提 基本概念 速查链接汇总 stage1: 一个package, 一个target stage2: 一个package,多个target stage3: 多package,多target st ...

  2. 常用 Gulp 插件汇总 —— 基于 Gulp 的前端集成解决方案(三)

    前两篇文章讨论了 Gulp 的安装部署及基本概念,借助于 Gulp 强大的 插件生态 可以完成很多常见的和不常见的任务.本文主要汇总常用的 Gulp 插件及其基本使用,需要读者对 Gulp 有一个基本 ...

  3. 异常处理汇总 ~ 修正果带着你的Net飞奔吧!

    经验库开源地址:https://github.com/dunitian/LoTDotNet 异常处理汇总-服 务 器 http://www.cnblogs.com/dunitian/p/4522983 ...

  4. UWP开发必备:常用数据列表控件汇总比较

    今天是想通过实例将UWP开发常用的数据列表做汇总比较,作为以后项目开发参考.UWP开发必备知识点总结请参照[UWP开发必备以及常用知识点总结]. 本次主要讨论以下控件: GridView:用于显示数据 ...

  5. Oracle手边常用70则脚本知识汇总

    Oracle手边常用70则脚本知识汇总 作者:白宁超 时间:2016年3月4日13:58:36 摘要: 日常使用oracle数据库过程中,常用脚本命令莫不是用户和密码.表空间.多表联合.执行语句等常规 ...

  6. Oracle 数据库知识汇总篇

    Oracle 数据库知识汇总篇(更新中..) 1.安装部署篇 2.管理维护篇 3.数据迁移篇 4.故障处理篇 5.性能调优篇 6.SQL PL/SQL篇 7.考试认证篇 8.原理体系篇 9.架构设计篇 ...

  7. Vertica 数据库知识汇总篇

    Vertica 数据库知识汇总篇(更新中..) 1.Vertica 集群软件部署,各节点硬件性能测试 2.Vertica 创建数据库,创建业务用户测试 3.Vertica 数据库参数调整,资源池分配 ...

  8. 读书笔记汇总 - SQL必知必会(第4版)

    本系列记录并分享学习SQL的过程,主要内容为SQL的基础概念及练习过程. 书目信息 中文名:<SQL必知必会(第4版)> 英文名:<Sams Teach Yourself SQL i ...

  9. 关于DDD的学习资料汇总

    DDD(Domain-Driven Design)领域驱动设计,第一次看到DDD是在学习ABP时,在其中的介绍中看到的.what,DDD是个什么鬼,我不是小白,是大白,没听过.于是乎,度娘查查查,找到 ...

随机推荐

  1. 拦截asp.net输出流做处理

    本文标题是指对已经生成了HTML的页面做一些输出到客户端之前的处理. 方法的原理是:把Response的输出重定向到自定义的容器内,也就是我们的StringBuilder对象里,在HTML所有的向页面 ...

  2. 【不能继续浪啦】BZ做题记录[7.01~7.06]

    距离上次提交..><居然已经过去一个半月了... 然后再去看看人家RXDoi.. 差距越来越大啦... 最后更新时间:7.06 19:06 [07.03 21:02]夏令营自修课逃逃真爽. ...

  3. 【CodeForces】915 E. Physical Education Lessons 线段树

    [题目]E. Physical Education Lessons [题意]10^9范围的区间覆盖,至多3*10^5次区间询问. [算法]线段树 [题解]每次询问至多增加两段区间,提前括号分段后线段树 ...

  4. Vue 使用自定义组件时报错:Uncaught TypeError: Cannot assign to read only property 'exports' of object '#<Object>'

    自己试做了一下vue的插件 参考element-ui: 写了一个组件 import message from './packages/message/index.js'; const install ...

  5. 天梯赛 L2-009 抢红包

    题目链接 没有人没抢过红包吧-- 这里给出N个人之间互相发红包.抢红包的记录,请你统计一下他们抢红包的收获. 输入格式: 输入第一行给出一个正整数N(<= 104),即参与发红包和抢红包的总人数 ...

  6. ubuntu16.04中启动anaconda图形化界面

    $ source ~/anaconda3/bin/activate root $ anaconda-navigator

  7. VC孙鑫老师第八课:你能捉到我吗?

    第一步,首先在对话框窗口上放上两个一模一样的按钮控件 第二步,由于是按钮响应鼠标移动上去的事件,因此需要重新派生按钮类: 第三步,在窗口类中声明并使用自定义按钮对象(记得在窗口类中包含自定义按钮类的头 ...

  8. uboot之---make smdk2410_config命令详细解析

    先进入顶层Makefile.有很多相对不同板子的配置,如: gec2440_config:unconfig @$(MKCONFIG) $(@:_config=) arm arm920t gec2440 ...

  9. 如何在LINUX中开机、登陆、退出、定时、定期自动运行程序

    1.开机启动时自动运行程序 Linux加载后, 它将初始化硬件和设备驱动, 然后运行第一个进程init.init根据配置文件继续引导过程,启动其它进程.通常情况下,修改放置在 /etc/rc或 /et ...

  10. 制作自动化系统安装U盘

    1.挂载CentOS6.6镜像 [root@test88 ~]# mkdir /application/tools -p [root@test88 ~]# cd /application/tools/ ...