bazel编译c++,调用动态链接库和静态链接库

bazel是google开源编译器,与其他编译器不同的是编译需联网,并非单机。

官方文档(编译c++)

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

先来看最简单的c++编译

代码结构:

 编译后的生成文件存放在WORKSPACE对应的目录下,编译会以BUILD文件所在目录为单元进行,多个BUILD的编译方法见官方文档

func.h

#include<stdio.h>

void func(void);

func.cc

#include "func.h"

void func()
{
    printf("This is func function
");
}

hello_world.cc

#include "func.h"

int main(void)
{
    printf("This is main function
");
    printf("Call func function now
");
    func();
    return 0;
}

BUILD

cc_library(
        name="func",
        srcs=["func.cc"],
        hdrs=["func.h"],
        )

cc_binary(
        name="hello-world",
        srcs=["hello_world.cc"],
        deps=[
                ":func",
                ],
        )

hello_world.cc是程序入口,主函数在这里面,他调用了func.h和func.cc中的函数,所以是依赖关系,func.h和func.cc作为library写到cc_library中,name是他的名字,其他cc_××依靠名字去调用他,srcs是函数所在路径,hdrs是头文件所在路径

cc_binary是生成二进制,deps表示依赖,hello_world.cc依赖名为func的cc_library。

回到WORKSPACE所在目录下进行编译

bazel build //app:hello-world

//表示从WORKSPACE所在目录开始,//app就是编译的代码所在位置(BUILD文件的位置)

hello-world是BUILD中cc_binary的name

编译结果

 编译成功后发现在WORKSPACE同目录中出现了几个新文件夹

 其中编译完成的二进制文件存放在bazel-bin/app中,运行二进制文件

生成动态链接库(.so)

代码结构

dllfunc.h

#include <stdio.h>

void dllfunc(void);

dllfunc.cc

#include "dllfunc.h"

void dllfunc()
{
    printf("This is dynamic link library function
");
}

BUILD 

cc_binary(
        name="dllfunc-0.0.1.so",
        srcs=["dllfunc.h","dllfunc.cc"],
        linkshared=True,
        )

注意name一定要命名成lib*.so形式,否则会出现gcc定位错误,linkshared表示动态链接库

执行命令

bazel build //app:dllfunc-0.0.1.so

编译结果

生成静态链接库(.a)

 static.h

#include <stdio.h>

void staticfunc(void);

static.cc

#include "static.h"

void staticfunc(void)
{
    printf("This is staticfunc
");
}

BUILD

cc_library(
        name="static",
        srcs=["static.h","static.cc"],
        linkstatic=True,
        )

动态链接库是cc_binary(二进制文件),静态链接库是cc_library(代码段?),动态链接库是linkshared,静态链接库是linkstatic

bazel build //app:static

生成结果会自动在前面加上lib,在后面加上.a

调用第三方动态链接库和静态链接库

 将前两个生成的静态链接库和动态链接库以及他们对应的头文件放入到app目录中

头文件代码前面有这里就不放了

main.cc

#include "dllfunc.h"
#include "static.h"

int main(void)
{
    printf("Main function
");
    dllfunc();
    staticfunc();
    return 0;
}

BUILD

cc_import(
        name="dllfunc",
        hdrs=["dllfunc.h"],
        shared_library="libfunc.so",
        )

cc_import(
        name="staticfunc",
        hdrs=["static.h"],
        static_library="libstatic.a",
        )
cc_binary(
        name="dll_test",
        srcs=["main.cc"],
        deps=[":dllfunc",":staticfunc"],
        )

将动态链接库和静态链接库写入cc_import中,然后让cc_binary去依赖cc_import动态链接库是shared_library,静态链接库是static_library

cc_import以及其他cc_*写法

https://docs.bazel.build/versions/4.0.0/be/c-cpp.html#cc_import

bazel build //app:dll_test

找到生成的二进制文件并运行

 发现可以正常运行动态链接库和静态链接库中的函数

编译后的目录结构

 可以看到存放编译后文件的目录在缓存文件夹中也有保存,下面四个文件夹的结构大致相似,他们之间的关系暂时还没弄清

solib_k8文件夹还有我动态链接库的历史版本,因为之前名字的问题前面没有lib导致编译都不成功

 

 

 

 感觉前三个目录存储有比较大的冗余,具体为什么这么保存还没弄清楚

一些关于bazel的杂项

bazel代理设置

https://docs.bazel.build/versions/master/external.html#using-proxies

说是把环境变量写成大写的HTTP_PROXY就可以被bazel自动识别,但是我试过了没什么鸟用,还是不好使

离线编译

https://docs.bazel.build/versions/master/external.html#offline-builds

一个编译器非要联网才能工作也是挺离谱的,好象是加上--distdir就可以脱机使用了,目前还没试过

编译其他平台或语言的官方文档

https://docs.bazel.build/versions/4.0.0/be/overview.html

编译时联网失败怎么办

试试离线编译,不行的话下一个有bazel的docker镜像(要是devel版本的),比如我下载了tensorflow-serving的devel docker,然后进到docker中用里面自带的bazel编译就没问题了,可以编译完之后把文件从容器中取出,传到需要的地方

无情的摸鱼机器
原文地址:https://www.cnblogs.com/wangtianning1223/p/14414911.html