使用genrule如何從makefile向bazel轉(zhuǎn)變,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
成都創(chuàng)新互聯(lián)是一家專業(yè)提供吳川企業(yè)網(wǎng)站建設,專注與做網(wǎng)站、成都網(wǎng)站設計、html5、小程序制作等業(yè)務。10年已為吳川眾多企業(yè)、政府機構(gòu)等服務。創(chuàng)新互聯(lián)專業(yè)網(wǎng)絡公司優(yōu)惠進行中。
現(xiàn)有的makefile構(gòu)建工程如何切換到bazel構(gòu)建系統(tǒng)。
bazel提供了豐富的擴展方式,當然也支持從目前的makefile過渡到bazel構(gòu)建。
再次說明下其特性:
多語言支持,并且支持擴展到任何語言的構(gòu)建。
擴展DSL是starlyke語言,為Python的一個子集,容易上手。這一點是cmake和其他構(gòu)建系統(tǒng)不具備的。
支持緩存。
支持分布式構(gòu)建。
支持最小化構(gòu)建。
在一個大型系統(tǒng)中,一個人可能只需要負責其中的一個小組件,這個組件可能又依賴其他組件。當這個組件需要更新測試時,只希望去構(gòu)建這個組件依賴的組件和這個組件本身,其他不相關(guān)的可以不構(gòu)建,這樣可以使用構(gòu)建過程更快捷。bazel就支持這種方式。
上文中說過makefile在處理小規(guī)模軟件時還不錯,當規(guī)模增大時,makefile有以下問題。
各個組件之間的依賴難以管理。 makefile只支持將所有的源碼放在一個目錄下,然后由頂層的。
這個依賴關(guān)系只能是有經(jīng)驗的人知道,新人想最小化編譯時,只能試錯,發(fā)現(xiàn)有依賴未構(gòu)建時,再去手動構(gòu)建。
增量式構(gòu)建難以控制。
這一點和第1點是相關(guān)的,因為依賴不能自動化構(gòu)建,所以增量式構(gòu)建也不具備。
構(gòu)建速度不足,難以做緩存。
makefile本身不支持緩存,需要額外的工作自行實現(xiàn)緩存。
雖然說bazel兼容makefile的構(gòu)建,但也不是直接的支持。需要對bazel的擴展方式有一些了解。也有以下幾個問題需要解決。
bazel的規(guī)則中需要定義輸入輸出
makefile中的輸出一般不定義。比如如下的makefile中。這個makefile中就沒有定義明確的輸出。
all: gcc hello.c
或者是這樣的。在makefile中規(guī)則中是去執(zhí)行一個make.sh腳本。
install: bash -x make.sh
makefile一般需要在當前目錄下執(zhí)行
makefile中定義的輸入和輸出,都是基于當前的目錄,而bazel是在頂層執(zhí)行的,它的工作目錄就是頂層的WORKSPACE所在的目錄。這對makefile來說是不友好的。
針對這2個問題,通過查看bazel的issue和文檔并沒有發(fā)現(xiàn)好的解決方式?;卮鹑嘶旧暇屯扑]你去用對應語言的擴展,這對很多發(fā)有工程來說是不現(xiàn)實的。原因有:
對應語言的擴展不大可能無縫支持。
多半需要自己去修改構(gòu)建的代碼。比如我遇到的1個c語言的工程,使用cc_external_rule就行不通。
額外的學習成本。
這個對應的語言的擴展也是需要時間去學習的,也是隱藏的成本。
所以,對bazel有興趣的多語言構(gòu)建項目,希望以這樣的理想方式過渡。
現(xiàn)有的makefile工程可以無痛過渡。
新開發(fā)或者大規(guī)模重構(gòu)的工程,可以直接上bazel。
通過總結(jié),給出了以下的過渡方案,基本上可以滿足再有的makefile工程。
方案要點:
使用bazel的沙盒環(huán)境變量,保留makefile的構(gòu)建時的環(huán)境變量。
這些環(huán)境變量可能INSTALLROOT這種安裝環(huán)境變量,也可能有LD_LIBRARY_PATH這種編譯鏈接環(huán)境變量。
使用genrule規(guī)則,可以快速切換到makefile所在的目錄,執(zhí)行make。
示例工程見gitee。https://gitee.com/ul1n/bazel-demo/tree/makefile 包含src和lib兩個目錄。各自有自己的makefile。其中src依賴lib。
方案中的第1點可以非常方便地通過bazel build時的選項--action_env傳遞。第2點實現(xiàn)有點曲折,不過并不復雜。這里詳細說明下。
通過熟悉bazel文檔我們知道genrule可以實現(xiàn)任何構(gòu)建過程。這里我們希望如下的genrule。只定義基本的屬性,其中cmd里可以cd到BUILD_PATH,BUILD_PATH可以自動變化,不同的子目錄,就變化為所屬的目錄相對路徑。同時可以生成一個偽目標,滿足genrule的要求。
genrule( name="hello", srcs=["srcs"], cmd="cd $(BUILD_PATH) && make", outs=["test"] )
那么如何自動地控制BUILD_PATH的環(huán)境變量呢?bazel不支持直接傳遞環(huán)境變量給genrule的上下文,換說法就是cmd中的環(huán)境變量,需要提前聲明好。通過查看官方的一些示例,可以這樣來實現(xiàn)。
注:BUILD文件中涉及的bazel的語法可以參考官方文檔進行熟悉。
定義一個def.bzl文件。這個bzl就是可以為引用它的BUILD文件中引入一個BUILD_PATH的環(huán)境變量。
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中規(guī)則的依賴。
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參數(shù)做一下說明。
1 切換到BUILD文件所在的目錄。 2 執(zhí)行make。這個也可以換成需要的命令,比如make install。 3 切換到上一個目錄,也就是WORKSPACE文件所在的目錄。 4 創(chuàng)建一個偽輸出out.txt。RULEDIR是bazel約定的規(guī)則產(chǎn)出物的目錄。是一個相對路徑,這是為什么第3步中要切回目錄的原因。 用&&連接是為了在失敗時能立刻退出執(zhí)行。
添加完成后,就可以通過如下的命令執(zhí)行這個構(gòu)建過程了。
bazel build --sandbox_writable_path=$INSTALLROOT --action_env=C_INCLUDE_PATH=$INSTALLROOT/include --action_env=INSTALLROOT=$INSTALLROOT //src:default
其中--sandbox_writable_path選項是為了開放權(quán)限,保證makefile中需要執(zhí)行的目錄創(chuàng)建操作。另外兩個環(huán)境變量,則是為了保證原來的makefile可以成功構(gòu)建。執(zhí)行完成后,會在當前目錄的tmp/bin/目錄下生成app可執(zhí)行文件。tmp/lib下生成動態(tài)鏈接庫。這樣一來,只要配置的環(huán)境變量合適,就可以完美執(zhí)行原有的構(gòu)建流程了。
這種實現(xiàn)方式可能不是最好的,但目前來說是最直接的。當然也希望有知道更好方式的同學告知下。目前這種實現(xiàn)方式還有以下幾個問題。
產(chǎn)出物是偽造的,對于bazel來說不是sound(可感知)的。無法緩存INSTALLROOT的產(chǎn)生物。
產(chǎn)生物不可感知,那么INSTALLROOT被刪除的情況下,bazel的構(gòu)建可能什么都不會做,因為它不知道INSTALLROOT的存在。
這2個問題作如下解答: 如果是需要緩存的大型模塊,那么可以產(chǎn)生真正的產(chǎn)出物,同時復制一份到RULEDIR。但INSTALLROOT被刪除這一塊無法通過技術(shù)手段保證。
關(guān)于使用genrule如何從makefile向bazel轉(zhuǎn)變問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識。
當前題目:使用genrule如何從makefile向bazel轉(zhuǎn)變
網(wǎng)站網(wǎng)址:http://aaarwkj.com/article38/isjdpp.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供自適應網(wǎng)站、網(wǎng)站維護、微信小程序、網(wǎng)站排名、品牌網(wǎng)站設計、響應式網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)