Open Harmony移植:build lite編譯構建過程
摘要:本文介紹了build lite 輕量級編譯構建系統編譯構建過程,呼叫依賴關係等等。
本文分享自華為雲社群《移植案例與原理 - build lite編譯構建過程》,作者: zhushy。
配置完畢產品解決方案、晶片開發板解決方案,就可以執行 hb build進行編譯。但是產品解決方案程式碼是如何被呼叫編譯的?
晶片開發板解決方案程式碼是如何被呼叫編譯的?核心程式碼如何被呼叫編譯的?解決了這些疑惑,會對build lite編譯構建過程有個更深入的理解。
1、產品解決方案程式碼是如何被呼叫編譯的
在檔案build\lite\BUILD.gn配置檔案中的構建目標//build/lite:product的程式碼片段如下,可以看出產品解決方案是被//build/lite:product呼叫的。其中⑴處的ohos_build_target,由hb build -T XX 構建引數指定,一般不指定時為空。
group("product") { deps = [] # build product, skip build single component scenario. ⑴ if (ohos_build_target == "") { deps += [ "${product_path}" ] } }
//build/lite:product 又進一步被什麼模組呼叫?在恆玄的程式碼配置檔案device\soc\bestechnic\bes2600\BUILD.gn中使用了,非恆玄的沒有呼叫//build/lite:product。所以,除了//build/lite:product,還有其他呼叫編譯產品解決方案程式碼的地方。
以vendor\goodix\gr5515_sk_iotlink_demo為例,來了解下什麼地方會呼叫編譯產品解決方案程式碼。產品解決方案根目錄下有檔案vendor\goodix\gr5515_sk_iotlink_demo\ohos.build,片段如下。可以看到,有子系統subsystem和部件資訊parts。
{ "parts": { "product_gr5515_sk_iotlink_demo": { "module_list": [ "//vendor/goodix/gr5515_sk_iotlink_demo:gr5515_sk_iotlink_demo", "//vendor/goodix/gr5515_sk_iotlink_demo:image" ] } }, "subsystem": "product_gr5515_sk_iotlink_demo" }
在編譯構建時,會基於ohos.build檔案,解析子系統和部件資訊,生成到out\gr5515_sk\gr5515_sk_iotlink_demo\build_configs\parts_info\subsystem_parts.json檔案中,片段如下。這些解析出來的子系統和部件資訊,編譯構建構建hb會組織進行編譯構建。
"product_gr5515_sk_iotlink_demo": [ "product_gr5515_sk_iotlink_demo" ],
2、晶片開發板解決方案程式碼是如何被呼叫編譯的
在檔案kernel\liteos_m\BUILD.gn中定義的名為modules構建目標,這個modules構建目標依賴晶片開發板解決方案的程式碼。。⑴處判斷晶片和開發板是否是否進行了資料夾解耦,如果開發板路徑包含“/board/”,說明soc和board進行了解耦。根據是否解耦,依賴的晶片開發板的構建配置檔案路徑是不同的,見⑵。
# board and soc decoupling feature, device_path should contains board ⑴ BOARD_SOC_FEATURE = device_path != string_replace(device_path, "/board/", "") ...... group("modules") { deps = [ "arch", "components", "kal", "kernel", "testsuites", "utils", HDFTOPDIR, ] ⑵ if (BOARD_SOC_FEATURE) { deps += [ "//device/board/$device_company" ] deps += [ "//device/soc/$LOSCFG_SOC_COMPANY" ] } else { if (HAVE_DEVICE_SDK) { deps += [ device_path ] } } }
名為modules構建目標又被libkernel構建目標、進一步被名為kernel的構建目標呼叫,如下所示。核心的kernel構建目標如何被呼叫,下一小節分析。
static_library("libkernel") { deps = [ ":modules" ] complete_static_lib = false } group("kernel") { deps = [ ":libkernel" ] }
3、核心程式碼如何被呼叫編譯的
上文分析了產品解決方案、晶片開發板解決方案如何被呼叫的。本小節,追蹤下核心程式碼是如何被呼叫編譯的。
在生成的檔案out\v200zr\display_demo\build_configs\kernel\liteos_m\BUILD.gn中,會呼叫名為kernel、build_kernel_image的構建目錄。怎麼生成的這個檔案,需要研究下hb的程式碼,深入瞭解下後臺的機制,希望後續有時間可以繼續深入一些。
import("//build/ohos/ohos_kits.gni") import("//build/ohos/ohos_part.gni") import("//build/ohos/ohos_test.gni") ohos_part("liteos_m") { subsystem_name = "kernel" module_list = [ "//kernel/liteos_m:kernel", "//kernel/liteos_m:build_kernel_image", ] origin_name = "liteos_m" variant = "phone" }
構建目標build_kernel_image可以生成bin檔案,該目標依賴copy_liteos,copy_liteos依賴liteos構建目標,該目標會進一步呼叫//build/lite:ohos。//build/lite:ohos檔案會依次呼叫各個子系統和部件的構建目標。
executable("liteos") { configs += [ ":public", ":los_config", ] ldflags = [ "-static", "-Wl,--gc-sections", "-Wl,-Map=$liteos_name.map", ] output_dir = target_out_dir if (liteos_kernel_only) { deps = [ ":kernel" ] } else { deps = [ "//build/lite:ohos" ] } } copy("copy_liteos") { deps = [ ":liteos" ] sources = [ "$target_out_dir/unstripped/bin/liteos" ] outputs = [ "$root_out_dir/$liteos_name" ] } build_ext_component("build_kernel_image") { deps = [ ":copy_liteos" ] exec_path = rebase_path(root_out_dir) objcopy = "${compile_prefix}objcopy$toolchain_cmd_suffix" objdump = "${compile_prefix}objdump$toolchain_cmd_suffix" command = "$objcopy -O binary $liteos_name $liteos_name.bin" command += " && sh -c '$objdump -t $liteos_name | sort >$liteos_name.sym.sorted'" command += " && sh -c '$objdump -d $liteos_name >$liteos_name.asm'" }
4、名為public的config
在檔案kernel\liteos_m\BUILD.gn中,名為public的config定義如下。⑴處判斷晶片和開發板是否是否進行了資料夾解耦,如果開發板路徑包含“/board/”,說明soc和board進行了解耦。根據是否解耦,依賴的public的配置集的位置是不同的,見⑵。在晶片、開發板程式碼目錄中的BUILD.gn檔案中並沒有發現config(“public”),這個比較奇怪。
# board and soc decoupling feature, device_path should contains board ⑴ BOARD_SOC_FEATURE = device_path != string_replace(device_path, "/board/", "") config("public") { configs = [ "arch:public", "kernel:public", "kal:public", "components:public", "utils:public", ] ⑵ if (BOARD_SOC_FEATURE) { configs += [ "//device/board/$device_company:public" ] configs += [ "//device/soc/$LOSCFG_SOC_COMPANY:public" ] } else { if (HAVE_DEVICE_SDK) { configs += [ "$device_path:public" ] } } }
參考站點