
??想了解更多關于開源的內容,請訪問:??
??51CTO 開源基礎軟件社區(qū)??
??https://ost.51cto.com??
起因
事情的起因是這樣子的,在給學生上課的時候,想演示一下kv存儲(小熊派nano開發(fā)板),代碼版本??master?
?,結果發(fā)現編譯竟然出錯了,錯誤提示如下:

顯示的是在鏈接階段沒有找到如opendir,closedir等符號,這顯然就是kv_store庫編譯有問題。
原因及措施
經過幾分鐘的查找,最后發(fā)現是kv_store庫的gn文件里面默認給了這個參數:

這個參數一加,我們kv的編譯就會使用posix相關的接口去實現,而在3861里面應該是沒有實現posix相關的文件接口,所以導致鏈接的時候出現opendir等等通不過,那么將這個參數置false再編譯試試看:

不出意外的編譯成功了,說明問題出在這里。
隱患
你以為問題到這里就完了嗎,當然,如果只是以解決問題作為目的,我們當前確實已經達到目的了。
作為一個自律的工程師,我們知道:我們在做應用的時候不應該做侵入式修改,什么是侵入式修改呢:
一句話概括就是,你的代碼需要依賴框架的代碼,如果把框架拿掉或者換一個框架,就需要重新修改代碼。
也就是說:kv是openharmony里面的一個組件,我們使用openharmony的代碼框架的時候如果碰到問題,是不能通過侵入式修改達到目的的,因為這樣會破壞原有的代碼邏輯,假如后面如果有其他項目要使用這個代碼的話,就可能會出現問題,有時候甚至會是災難性的后果.
而且,侵入式修改有一個問題是:如果sdk或框架升級,往往意味著要在新的sdk或者框架上進行修改,當這種修改多起來的話工作量也是非常大的,如果沒有準確的文檔進行check,往往不能修改成功。
非侵入修改
那么不能用侵入式修改,又想達到正確編譯kv庫的目的,要怎么做呢,有一個辦法是使用gn的args,使用方法如下:
hb build -f --gn-args enable_ohos_utils_native_lite_kv_store_use_posix_kv_api=false這種方法會強制覆蓋代碼中的已聲明的變量,同樣能達到編譯通過的辦法。
那么這種方法有什么缺點嗎:當然有,就是每次編譯都需要帶上長長的一串東西,且不說記不記得住吧,使用起來也是非常的不方便。
另外一種方法就是:在vendor對應的目錄下的config.json里,對應的組件內feature添加對應的參數聲明,這一種方式,在產品的readme文檔里也有介紹,比如:

比如我們現在是在編譯bearpi_hm_nano,那么我們只需要在vendor/bearpi/bearpi_hm_nano/config.json里面編輯,把kv_store庫添加對應的參數即可,這里不知道是bug還是gn的原理就是這樣,我們不需要找到kv_store真正的庫聲明位置,而是隨便一個地方加上"enable_ohos_utils_native_lite_kv_store_use_posix_kv_api=false"就可以正常編譯通過了,比如:

這樣再編譯就成功了。
探究一下原理,在gn進行build的時候,會在out目錄下生成一個args.gn文件,這個文件里保存了所有需要用到的args,如:

這里的args都是順序排列的,在gn進行構建的時候會讀取里面所有的參數。
另外一個問題
kv_store是什么時候調用并編譯的?到這里問題應該就解決了,但是剛剛我發(fā)現另外一個問題,在添加feature的時候我們并沒有找到kv_store在config.json文件里顯示聲明組件,那么到底是在什么時候kv_store參與編譯了呢?
這里是config.json的內容:
{
"product_name": "bearpi_hm_nano",
"type": "mini",
"version": "3.0",
"ohos_version": "OpenHarmony 1.1.0",
"device_company": "bearpi",
"device_build_path": "device/board/bearpi/bearpi_hm_nano",
"board": "bearpi_hm_nano",
"kernel_type": "liteos_m",
"kernel_is_prebuilt": true,
"kernel_version": "",
"subsystems": [
{
"subsystem": "iothardware",
"components": [
{ "component": "peripheral", "features":[] }
]
},
{
"subsystem": "hiviewdfx",
"components": [
{ "component": "hilog_lite", "features":[] },
{ "component": "hievent_lite", "features":[] },
{ "component": "blackbox", "features":[] },
{ "component": "hidumper_mini", "features":[] }
]
},
{
"subsystem": "systemabilitymgr",
"components": [
{ "component": "samgr_lite", "features":[] }
]
},
{
"subsystem": "security",
"components": [
{ "component": "device_auth", "features":[] },
{ "component": "huks", "features":
[
"disable_huks_binary = false",
"disable_authenticate = false",
"huks_use_lite_storage = true",
"huks_use_hardware_root_key = true",
"huks_config_file = \"hks_config_lite.h\"",
"ohos_security_huks_mbedtls_porting_path = \"http://device/soc/hisilicon/hi3861v100/sdk_liteos/third_party/mbedtls\""
]
}
]
},
{
"subsystem": "startup",
"components": [
{ "component": "bootstrap_lite", "features":[] },
{ "component": "init_lite", "features":
[
"enable_ohos_startup_init_feature_begetctl_liteos=true",
"enable_ohos_startup_init_lite_use_thirdparty_mbedtls = false"
]
}
]
},
{
"subsystem": "communication",
"components": [
{ "component": "wifi_lite", "features":[] },
{ "component": "dsoftbus", "features":[] },
{ "component": "wifi_aware", "features":[]}
]
},
{
"subsystem": "updater",
"components": [
{ "component": "ota_lite", "features":[] }
]
},
{
"subsystem": "commonlibrary",
"components": [
{ "component": "file", "features":[] }
]
},
{
"subsystem": "xts",
"components": [
{ "component": "xts_acts", "features":
[
"enable_ohos_test_xts_acts_use_thirdparty_lwip = false"
]
},
{ "component": "xts_tools", "features":[] }
]
}
],
"third_party_dir": "http://device/soc/hisilicon/hi3861v100/sdk_liteos/third_party",
"product_adapter_dir": "http://vendor/bearpi/bearpi_hm_nano/hals"
}
找了一圈,并沒有找到kv相關的庫,看來kv_store是由別的子系統(tǒng)或組件庫依賴的。
那是由誰依賴的呢?
#查找依賴kv_store的庫或組件。
首先,一個庫被依賴通常會寫在gn的deps列表內,比如這種:

如果還不明白,建議找?guī)灼猤n相關的文章看看就懂了。
現在的辦法就是一層一層的找到是誰調用的kv_store庫,回到之前編譯出錯的地方:

可以看到有一個名為utils_kv_store的lib文件,先找一下:?


然后再去找由誰依賴了utils_kv_store。
現在問題出來了,openharmony里面這么多代碼,如果每一個庫都要這樣不停的搜索相關字才能找到最終依賴的地方,效率低不說,還容易出錯,而且很容易跟著就跟丟了,這是因為人的記憶力畢竟有限,函數調用太多層就會丟失路徑,這也就是為什么人類下棋永遠下不過電腦。
請出神器
這時候就輪到了我們gn desc這個神器出廠了,我們先來看一下效果,這是依靠gn desc生成的依賴樹信息:
//out/bearpi_hm_nano/bearpi_hm_nano/build_configs/device_bearpi_hm_nano/device_bearpi_hm_nano:device_bearpi_hm_nano_info
//device/soc/hisilicon/hi3861v100:hi3861v100
//device/soc/hisilicon/hi3861v100/sdk_liteos:run_wifiiot_scons
//base/security/device_auth/frameworks/deviceauth_lite:hichainsdk
//base/security/device_auth/frameworks/deviceauth_lite/source:hichainsdk
//base/security/huks/interfaces/innerkits/huks_lite:huks_3.0_sdk
//base/security/huks/interfaces/innerkits/huks_lite:huks_3.0_sdk__notice
//third_party/musl:sysroot_lite
//third_party/mbedtls:mbedtls_static
//third_party/musl:sysroot_lite
//third_party/musl:sysroot_lite
//third_party/musl:sysroot_lite
//build/lite:ohos
//base/hiviewdfx/blackbox:blackbox
//third_party/musl:sysroot_lite
//base/hiviewdfx/hidumper_lite/mini:hidumper_mini
//third_party/musl:sysroot_lite
//base/hiviewdfx/hievent_lite:hievent_lite
//base/hiviewdfx/hievent_lite:hievent_lite_static
//base/hiviewdfx/hiview_lite:hiview_lite
//base/hiviewdfx/hiview_lite:hiview_lite_static
//third_party/musl:sysroot_lite
//third_party/musl:sysroot_lite
//base/hiviewdfx/hilog_lite/frameworks/mini:hilog_lite
//base/hiviewdfx/hilog_lite/frameworks/mini:hilog_lite_static
//base/hiviewdfx/hiview_lite:hiview_lite...
//third_party/musl:sysroot_lite
//base/iothardware/peripheral:iothardware
//device/soc/hisilicon/hi3861v100/hi3861_adapter/hals/iot_hardware/wifiiot_lite:hal_iothardware
//third_party/musl:sysroot_lite
//base/security/device_auth:deviceauth_build
//base/security/device_auth/services:deviceauth
//base/hiviewdfx/hilog_lite/frameworks/mini:hilog_lite...
//base/security/device_auth/deps_adapter:deviceauth_hal_liteos
//base/hiviewdfx/hilog_lite/frameworks/mini:hilog_lite...
//base/security/huks/interfaces/innerkits/huks_lite:huks_3.0_sdk...
//base/startup/init/interfaces/innerkits:libbegetutil
//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_static
//third_party/bounds_checking_function:libsec_static
//third_party/musl:sysroot_lite
//base/startup/init/interfaces/hals/utils/sys_param:hal_sys_param
//third_party/musl:sysroot_lite
//base/startup/init/services/log:init_log
//third_party/musl:sysroot_lite
//base/startup/init/services/modules/init_hook:inithook
//third_party/musl:sysroot_lite
//base/startup/init/services/param/liteos:param_client_lite
//base/startup/init/services/param/liteos:lite_ohos_param_to
//third_party/musl:sysroot_lite
//third_party/musl:sysroot_lite
//base/startup/init/services/utils:libinit_utils
//third_party/musl:sysroot_lite
//third_party/bounds_checking_function:libsec_static
//third_party/musl:sysroot_lite
//vendor/bearpi/bearpi_hm_nano/hals/utils/sys_param:hal_sysparam
//third_party/musl:sysroot_lite
//build/lite/config/component/cJSON:cjson_shared
//commonlibrary/utils_lite:utils
//commonlibrary/utils_lite/file:file
//commonlibrary/utils_lite/file:native_file
//commonlibrary/utils_lite/hals/file:static_hal_file
//commonlibrary/utils_lite/hals/file:static_hal_file__notice
//third_party/musl:sysroot_lite
//third_party/musl:sysroot_lite
//device/soc/hisilicon/hi3861v100/hi3861_adapter/hals/utils/file:hal_file_static
//third_party/musl:sysroot_lite
//third_party/musl:sysroot_lite
//foundation/distributeddatamgr/kv_store/interfaces/inner_api/kv_store:kv_store
//foundation/distributeddatamgr/kv_store/interfaces/inner_api/kv_store:utils_kv_store
//third_party/musl:sysroot_lite
//third_party/musl:sysroot_lite
//build/lite/config/component/cJSON:cjson_shared
//commonlibrary/utils_lite:utils...
//foundation/communication/dsoftbus/sdk:softbus_client
//foundation/communication/dsoftbus/adapter:softbus_adapter
//base/hiviewdfx/hilog_lite/frameworks/mini:hilog_lite...
//third_party/mbedtls:mbedtls
//device/soc/hisilicon/hi3861v100/sdk_liteos/third_party/mbedtls:mbedtls
//third_party/musl:sysroot_lite
//foundation/communication/dsoftbus/core/common:softbus_utils
//base/hiviewdfx/hilog_lite/frameworks/mini:hilog_lite...
//build/lite/config/component/cJSON:cjson_static
//third_party/musl:sysroot_lite
//foundation/communication/dsoftbus/adapter:softbus_adapter...
//third_party/musl:sysroot_lite
//third_party/musl:sysroot_lite
//third_party/musl:sysroot_lite
//base/security/device_auth:deviceauth_sdk_build
//base/security/device_auth:deviceauth_service_build
//base/security/device_auth/frameworks/deviceauth_lite:hichainsdk...
//base/security/huks:fwk_group
//base/security/huks/frameworks/huks_lite:huks_sdk
//base/security/huks/interfaces/innerkits/huks_lite:huks_3.0_sdk...
//base/security/huks/test:unittest
//base/security/huks:service_group
//base/startup/bootstrap_lite/services/source:bootstrap
//third_party/musl:sysroot_lite
//base/startup/init/services:startup_init
//base/startup/init/services/begetctl:begetctl_cmd
//base/startup/init/services/loopevent:loopeventgroup
//base/startup/init/services/modules:modulesgroup
//base/startup/init/services/param:parameter
//base/startup/init/ueventd:startup_ueventd
//base/startup/init/watchdog:watchdog
//base/update/ota_lite/frameworks:ota_lite
//base/update/ota_lite/frameworks/source:hota
//base/startup/init/interfaces/innerkits:libbegetutil...
//device/soc/hisilicon/hi3861v100/hi3861_adapter/hals/update:hal_update_static
//third_party/musl:sysroot_lite
//third_party/musl:sysroot_lite
//commonlibrary/utils_lite/file:file...
//foundation/communication/dsoftbus:dsoftbus
//foundation/communication/dsoftbus/core:softbus_server
//foundation/communication/dsoftbus/adapter:softbus_adapter...
//foundation/communication/dsoftbus/core/common:softbus_utils...
//foundation/communication/dsoftbus/core/frame:softbus_server_frame
//base/security/device_auth/services:deviceauth...
//base/security/huks/interfaces/innerkits/huks_lite:huks_3.0_sdk...
//base/startup/init/interfaces/innerkits:libbegetutil...
//build/lite/config/component/cJSON:cjson_static...
//build/lite/config/component/cJSON:cjson_static...
//foundation/communication/dsoftbus/adapter:softbus_adapter...
//foundation/communication/dsoftbus/components/nstackx/nstackx_ctrl:nstackx_ctrl
//foundation/communication/dsoftbus/components/nstackx/nstackx_util:nstackx_util.open
//third_party/musl:sysroot_lite
//third_party/musl:sysroot_lite
//foundation/communication/dsoftbus/core/common:softbus_utils...
//third_party/musl:sysroot_lite
//foundation/communication/dsoftbus/sdk:softbus_client...
//foundation/communication/dsoftbus/tests:softbus_test
//foundation/communication/wifi_aware:wifiaware
//device/soc/hisilicon/hi3861v100/hi3861_adapter/hals/communication/wifi_lite/wifiaware:hal_wifiaware
//third_party/musl:sysroot_lite
//third_party/musl:sysroot_lite
//foundation/communication/wifi_lite:wifi
//foundation/systemabilitymgr/samgr_lite:samgr
//foundation/systemabilitymgr/samgr_lite/communication/broadcast:broadcast
//third_party/musl:sysroot_lite
//foundation/systemabilitymgr/samgr_lite/samgr:samgr
//foundation/systemabilitymgr/samgr_lite/samgr/adapter:samgr_adapter
//third_party/musl:sysroot_lite
//foundation/systemabilitymgr/samgr_lite/samgr/source:samgr_source
//foundation/systemabilitymgr/samgr_lite/samgr/adapter:samgr_adapter...
//third_party/musl:sysroot_lite
//third_party/musl:sysroot_lite
//device/soc/hisilicon/hi3861v100/sdk_liteos:sdk
//build/lite/config/component/cJSON:cjson_static...
//build/lite/config/component/cJSON:cjson_static...
//device/soc/hisilicon/hi3861v100/hi3861_adapter/hals/communication/wifi_lite/wifiservice:wifiservice
//third_party/musl:sysroot_lite
//device/soc/hisilicon/hi3861v100/hi3861_adapter/hals/communication/wifi_lite/wifiservice:wifiservice...
//device/soc/hisilicon/hi3861v100/hi3861_adapter/kal:kal
//device/soc/hisilicon/hi3861v100/hi3861_adapter/kal/cmsis:cmsis
//third_party/musl:sysroot_lite
//device/soc/hisilicon/hi3861v100/hi3861_adapter/kal/posix:posix
//third_party/musl:sysroot_lite
//device/soc/hisilicon/hi3861v100/hi3861_adapter/kal:kal...
//third_party/musl:sysroot_lite
//third_party/musl:sysroot_lite
看起來有點亂,沒關系,主要我們根據這個樹狀結構找到我們所有的依賴,有了這樣的依賴關系之后,我們如果想要查找某兩個模塊的關系就非常簡單了,以我們剛剛說了kv_store為例:



可以看到很輕松就找到了kv_store是怎么被一層一層依賴的了,而且通過關系圖可以得知kv_store竟然是由device_auth引入的,那么這個工具的意義就在于:有了依賴樹,以后出現依賴相關的問題都可以通過它快速分析并定位問題了。
看到這里是不是好心動,是不是想學習一下怎么用呢?
只需要在命令行輸入gn help desc就能得知用法了:
root@346a62050f11:/home/openharmony# gn help desc
gn desc
gn desc <out_dir> <label or pattern> [<what to show>] [--blame]
[--format=json]
Displays information about a given target or config. The build parameters
will be taken for the build in the given <out_dir>.
The <label or pattern> can be a target label, a config label, or a label
pattern (see "gn help label_pattern"). A label pattern will only match
targets.
...
其中 <out_dir>就是我們編譯的輸出目錄
<label or pattern> 可以是一個目標標簽,配置標簽,或者一個匹配模式標簽。只有匹配成功的才會顯示。
<what to show> 包括如下(如果不指定,默認顯示):
all_dependent_configs
allow_circular_includes_from
arflags [–blame] args
cflags [–blame]
cflags_c [–blame]
cflags_cc [–blame]
check_includes
configs [–tree] (see below)
data_keys
defines [–blame]
depfile
deps [–all] [–tree] (see below)
framework_dirs
frameworks
include_dirs [–blame]
inputs ldflags [–blame]
lib_dirs libs
metadata
output_conversion
outputs
public_configs
public
rebase
script
sources
testonly
visibility
walk_keys
weak_frameworks
runtime_deps
[–format=json] 以JSON的格式輸出。
根據以上提示,我們制作查詢語句:root@346a62050f11:/home/openharmony# gn desc out/bearpi_hm_nano/bearpi_hm_nano //out/bearpi_hm_nano/bearpi_hm_nano/build_configs/device_bearpi_hm_nano/device_bearpi_hm_nano:device_bearpi_hm_nano --tree ,即可得到依賴樹等內容。
總結
本篇真實記錄了一次出現問題,排查問題,解決問題并進行深層次思考的過程,最后通過不斷的查找資料,找到了一個可以瞬間生成依賴樹的強大工具,為以后解決問題提供了一種思路。
希望各位熱愛學習的朋友,能夠沉心靜氣,耐住寂寞,永不言棄,因為只有經過這樣的過程,技術才能得到精進,然后總結出自己的學習套路,學習有一萬種方法,最重要的是行動。
??想了解更多關于開源的內容,請訪問:??
??51CTO 開源基礎軟件社區(qū)??
??https://ost.51cto.com??