中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

使用genrule如何從makefile向bazel轉變

發布時間:2021-11-22 18:07:14 來源:億速云 閱讀:719 作者:柒染 欄目:云計算

使用genrule如何從makefile向bazel轉變,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

0x01 背景

現有的makefile構建工程如何切換到bazel構建系統。

bazel提供了豐富的擴展方式,當然也支持從目前的makefile過渡到bazel構建。

再次說明下其特性:

  1. 多語言支持,并且支持擴展到任何語言的構建。
    擴展DSL是starlyke語言,為Python的一個子集,容易上手。這一點是cmake和其他構建系統不具備的。

  2. 支持緩存。

  3. 支持分布式構建。

  4. 支持最小化構建。
    在一個大型系統中,一個人可能只需要負責其中的一個小組件,這個組件可能又依賴其他組件。當這個組件需要更新測試時,只希望去構建這個組件依賴的組件和這個組件本身,其他不相關的可以不構建,這樣可以使用構建過程更快捷。bazel就支持這種方式。

0x02 makefile的問題

上文中說過makefile在處理小規模軟件時還不錯,當規模增大時,makefile有以下問題。

  1. 各個組件之間的依賴難以管理。 makefile只支持將所有的源碼放在一個目錄下,然后由頂層的。
    這個依賴關系只能是有經驗的人知道,新人想最小化編譯時,只能試錯,發現有依賴未構建時,再去手動構建。

  2. 增量式構建難以控制。
    這一點和第1點是相關的,因為依賴不能自動化構建,所以增量式構建也不具備。

  3. 構建速度不足,難以做緩存。
    makefile本身不支持緩存,需要額外的工作自行實現緩存。

0x03 需要解決的問題

雖然說bazel兼容makefile的構建,但也不是直接的支持。需要對bazel的擴展方式有一些了解。也有以下幾個問題需要解決。

  1. bazel的規則中需要定義輸入輸出
    makefile中的輸出一般不定義。比如如下的makefile中。這個makefile中就沒有定義明確的輸出。

all:
	gcc hello.c

或者是這樣的。在makefile中規則中是去執行一個make.sh腳本。

install:
	bash -x make.sh
  1. makefile一般需要在當前目錄下執行
    makefile中定義的輸入和輸出,都是基于當前的目錄,而bazel是在頂層執行的,它的工作目錄就是頂層的WORKSPACE所在的目錄。這對makefile來說是不友好的。

針對這2個問題,通過查看bazel的issue和文檔并沒有發現好的解決方式。回答人基本上就推薦你去用對應語言的擴展,這對很多發有工程來說是不現實的。原因有:

  1. 對應語言的擴展不大可能無縫支持。
    多半需要自己去修改構建的代碼。比如我遇到的1個c語言的工程,使用cc_external_rule就行不通。

  2. 額外的學習成本。
    這個對應的語言的擴展也是需要時間去學習的,也是隱藏的成本。

所以,對bazel有興趣的多語言構建項目,希望以這樣的理想方式過渡。

  1. 現有的makefile工程可以無痛過渡。

  2. 新開發或者大規模重構的工程,可以直接上bazel。

通過總結,給出了以下的過渡方案,基本上可以滿足再有的makefile工程。

0x04 過渡方案

方案要點:

  1. 使用bazel的沙盒環境變量,保留makefile的構建時的環境變量。
    這些環境變量可能INSTALLROOT這種安裝環境變量,也可能有LD_LIBRARY_PATH這種編譯鏈接環境變量。

  2. 使用genrule規則,可以快速切換到makefile所在的目錄,執行make。

示例工程見gitee。https://gitee.com/ul1n/bazel-demo/tree/makefile 包含src和lib兩個目錄。各自有自己的makefile。其中src依賴lib。

方案中的第1點可以非常方便地通過bazel build時的選項--action_env傳遞。第2點實現有點曲折,不過并不復雜。這里詳細說明下。

通過熟悉bazel文檔我們知道genrule可以實現任何構建過程。這里我們希望如下的genrule。只定義基本的屬性,其中cmd里可以cd到BUILD_PATH,BUILD_PATH可以自動變化,不同的子目錄,就變化為所屬的目錄相對路徑。同時可以生成一個偽目標,滿足genrule的要求。

genrule(
    name="hello",
    srcs=["srcs"],
    cmd="cd $(BUILD_PATH) && make",
    outs=["test"]
)

那么如何自動地控制BUILD_PATH的環境變量呢?bazel不支持直接傳遞環境變量給genrule的上下文,換說法就是cmd中的環境變量,需要提前聲明好。通過查看官方的一些示例,可以這樣來實現。

注:BUILD文件中涉及的bazel的語法可以參考官方文檔進行熟悉。

定義一個def.bzl文件。這個bzl就是可以為引用它的BUILD文件中引入一個BUILD_PATH的環境變量。

def _var_providing_rule_impl(ctx):
    build_path = ctx.build_file_path
    loc, _ = build_path.rsplit('/', 2)

    return [platform_common.TemplateVariableInfo({"BUILD_PATH":loc}),]

var_providing_rule = rule(
    implementation = _var_providing_rule_impl,
    attrs = { "var_value": attr.string() }
)

然后在lib目錄下添加一個BUILD文件。這份文件編寫的非常通用,可以放在任何一個makefile目錄下。除了有其他依賴需要在genrule的srcs屬性中添加。

load("//:def.bzl", "var_providing_rule")

var_providing_rule(
    name="set_build_path",
    var_value=""
)

filegroup(
    name="srcs",
    srcs=glob(["**"])
)

genrule(
    name = "default",
    srcs=["srcs"],
    cmd="cd $(BUILD_PATH) && make && cd - && touch $(RULEDIR)/out.txt",
    visibility=["//visibility:public"],
    outs=["out.txt"],
    toolchains=[":set_build_path"]
)

在src目錄下添加如下的BUILD文件,與lib中的基本上一致,只是srcs中多了對lib中規則的依賴。

load("//:def.bzl", "var_providing_rule")

var_providing_rule(
    name="set_build_path",
    var_value=""
)

filegroup(
    name="srcs",
    srcs=glob(["**"])
)

genrule(
    name = "default",
    srcs=["srcs", "//lib:default"],
    cmd="cd $(BUILD_PATH) && make && cd - && touch $(RULEDIR)/out.txt",
    outs=["out.txt"],
    toolchains=[":set_build_path"]
)

這里對cmd參數做一下說明。

1 切換到BUILD文件所在的目錄。
2 執行make。這個也可以換成需要的命令,比如make install。
3 切換到上一個目錄,也就是WORKSPACE文件所在的目錄。
4 創建一個偽輸出out.txt。RULEDIR是bazel約定的規則產出物的目錄。是一個相對路徑,這是為什么第3步中要切回目錄的原因。

用&&連接是為了在失敗時能立刻退出執行。

添加完成后,就可以通過如下的命令執行這個構建過程了。

bazel build --sandbox_writable_path=$INSTALLROOT --action_env=C_INCLUDE_PATH=$INSTALLROOT/include --action_env=INSTALLROOT=$INSTALLROOT //src:default

其中--sandbox_writable_path選項是為了開放權限,保證makefile中需要執行的目錄創建操作。另外兩個環境變量,則是為了保證原來的makefile可以成功構建。執行完成后,會在當前目錄的tmp/bin/目錄下生成app可執行文件。tmp/lib下生成動態鏈接庫。這樣一來,只要配置的環境變量合適,就可以完美執行原有的構建流程了。

0x05 總結

這種實現方式可能不是最好的,但目前來說是最直接的。當然也希望有知道更好方式的同學告知下。目前這種實現方式還有以下幾個問題。

  1. 產出物是偽造的,對于bazel來說不是sound(可感知)的。無法緩存INSTALLROOT的產生物。

  2. 產生物不可感知,那么INSTALLROOT被刪除的情況下,bazel的構建可能什么都不會做,因為它不知道INSTALLROOT的存在。

這2個問題作如下解答: 如果是需要緩存的大型模塊,那么可以產生真正的產出物,同時復制一份到RULEDIR。但INSTALLROOT被刪除這一塊無法通過技術手段保證。

關于使用genrule如何從makefile向bazel轉變問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

米脂县| 合江县| 白水县| 鹤峰县| 万安县| 林口县| 甘洛县| 广宁县| 保定市| 汾西县| 黄石市| 淳化县| 翁牛特旗| 应城市| 昌平区| 南涧| 勃利县| 宁都县| 株洲县| 鹤山市| 德江县| 灵川县| 潮安县| 建瓯市| 万安县| 唐海县| 丰宁| 南丹县| 全南县| 香港| 泰兴市| 长丰县| 丽江市| 徐汇区| 天峻县| 开江县| 红桥区| 寻乌县| 安阳县| 南溪县| 迁安市|