由一个编译参数引发的Gn构建依赖图谱查询

系统 OpenHarmony
本篇真实记录了一次出现问题,排查问题,解决问题并进行深层次思考的过程,最后通过不断的查找资料,找到了一个可以瞬间生成依赖树的强大工具,为以后解决问题提供了一种思路。

想了解更多关于开源的内容,请访问:

​51CTO 开源基础软件社区​

​https://ost.51cto.com​

起因

事情的起因是这样子的,在给学生上课的时候,想演示一下kv存储(小熊派nano开发板),代码版本​​master​​,结果发现编译竟然出错了,错误提示如下:

#创作者激励#由一个编译参数引发的gn构建依赖图谱查询-开源基础软件社区

显示的是在链接阶段没有找到如opendir,closedir等符号,这显然就是kv_store库编译有问题。

原因及措施

经过几分钟的查找,最后发现是kv_store库的gn文件里面默认给了这个参数:

#创作者激励#由一个编译参数引发的gn构建依赖图谱查询-开源基础软件社区

这个参数一加,我们kv的编译就会使用posix相关的接口去实现,而在3861里面应该是没有实现posix相关的文件接口,所以导致链接的时候出现opendir等等通不过,那么将这个参数置false再编译试试看:

#创作者激励#由一个编译参数引发的gn构建依赖图谱查询-开源基础软件社区

不出意外的编译成功了,说明问题出在这里。

隐患

你以为问题到这里就完了吗,当然,如果只是以解决问题作为目的,我们当前确实已经达到目的了。
作为一个自律的工程师,我们知道:我们在做应用的时候不应该做侵入式修改,什么是侵入式修改呢:

一句话概括就是,你的代码需要依赖框架的代码,如果把框架拿掉或者换一个框架,就需要重新修改代码。

也就是说: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文档里也有介绍,比如:

#创作者激励#由一个编译参数引发的gn构建依赖图谱查询-开源基础软件社区

比如我们现在是在编译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构建依赖图谱查询-开源基础软件社区

这样再编译就成功了。

探究一下原理,在gn进行build的时候,会在out目录下生成一个args.gn文件,这个文件里保存了所有需要用到的args,如:

#创作者激励#由一个编译参数引发的gn构建依赖图谱查询-开源基础软件社区

这里的args都是顺序排列的,在gn进行构建的时候会读取里面所有的参数。

另外一个问题

kv_store是什么时候调用并编译的?到这里问题应该就解决了,但是刚刚我发现另外一个问题,在添加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 = \"//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": "//device/soc/hisilicon/hi3861v100/sdk_liteos/third_party",
"product_adapter_dir": "//vendor/bearpi/bearpi_hm_nano/hals"
}

找了一圈,并没有找到kv相关的库,看来kv_store是由别的子系统或组件库依赖的。

那是由谁依赖的呢?

#查找依赖kv_store的库或组件。

首先,一个库被依赖通常会写在gn的deps列表内,比如这种:

#创作者激励#由一个编译参数引发的gn构建依赖图谱查询-开源基础软件社区

如果还不明白,建议找几篇gn相关的文章看看就懂了。

现在的办法就是一层一层的找到是谁调用的kv_store库,回到之前编译出错的地方:

#创作者激励#由一个编译参数引发的gn构建依赖图谱查询-开源基础软件社区

可以看到有一个名为utils_kv_store的lib文件,先找一下:

#创作者激励#由一个编译参数引发的gn构建依赖图谱查询-开源基础软件社区

#创作者激励#由一个编译参数引发的gn构建依赖图谱查询-开源基础软件社区

然后再去找由谁依赖了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为例:

#创作者激励#由一个编译参数引发的gn构建依赖图谱查询-开源基础软件社区

#创作者激励#由一个编译参数引发的gn构建依赖图谱查询-开源基础软件社区

#创作者激励#由一个编译参数引发的gn构建依赖图谱查询-开源基础软件社区

可以看到很轻松就找到了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 开源基础软件社区​

​https://ost.51cto.com​

责任编辑:jianghua 来源: 51CTO 开源基础软件社区
相关推荐

2017-08-25 16:38:05

表达式正则血案

2019-02-27 08:26:06

算法大数据社交

2011-11-25 13:04:43

空格usr

2021-07-27 07:12:11

Getter接口Setter

2009-03-13 16:39:16

Linux开源改变

2010-11-04 09:11:34

Fedora 14评测

2010-05-14 00:19:43

2013-12-19 09:58:36

移动应用产品市场

2021-12-01 06:59:27

架构

2024-02-28 08:12:25

SSE接口代理

2024-01-11 16:02:38

OHOS依赖关系检查编译构建系统

2013-03-05 10:05:52

2015-02-04 14:36:07

格式串漏洞Ghost漏洞安全漏洞

2011-04-27 10:02:54

兼容墨盒用户体验

2021-07-24 13:11:19

Redis数据技术

2022-04-17 10:04:32

HerokuPaaSPorter

2021-06-06 16:15:57

地区接口项目

2020-11-09 06:38:00

ninja构建方式构建系统

2022-11-07 19:08:28

transform属性浏览器

2011-06-10 10:11:44

点赞
收藏

51CTO技术栈公众号