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\n"); }
hello_world.cc
#include "func.h" int main(void) { printf("This is main function\n"); printf("Call func function now\n"); 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\n"); }
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\n"); }
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\n"); 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編譯就沒問題了,可以編譯完之后把文件從容器中取出,傳到需要的地方