#创作者激励#由一个编译参数引发的gn构建依赖图谱查询 原创 精华

物联风景
发布于 2023-3-14 22:23
浏览
8收藏

【本文正在参加2023年第一期优质创作者激励计划】
@toc

起因

事情的起因是这样子的,在给学生上课的时候,想演示一下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_storeconfig.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 ,即可得到依赖树等内容.

总结

本篇真实记录了一次出现问题,排查问题,解决问题并进行深层次思考的过程,最后通过不断的查找资料,找到了一个可以瞬间生成依赖树的强大工具,为以后解决问题提供了一种思路.
希望各位热爱学习的朋友,能够沉心静气,耐住寂寞,永不言弃,因为只有经过这样的过程,技术才能得到精进,然后总结出自己的学习套路,学习有一万种方法,最重要的是行动.

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2023-3-14 22:23:53修改
13
收藏 8
回复
举报
11条回复
按时间正序
/
按时间倒序
离北况归
离北况归

大佬厉害

1
回复
2023-3-14 23:37:29
红叶亦知秋
红叶亦知秋

老师技术过硬能在现场快速解决问题

1
回复
2023-3-15 11:04:50
喝一大口可乐
喝一大口可乐

侵入式修改使代码代码更耦合了

1
回复
2023-3-15 12:16:29
0aaron
0aaron

已经将文章分享给敲代码的同事了

1
回复
2023-3-15 18:23:44
物联风景
物联风景 回复了 0aaron
已经将文章分享给敲代码的同事了

记得点赞支持啊哈哈

1
回复
2023-3-15 20:39:06
liangkz_梁开祝
liangkz_梁开祝


我以前还手动整理过小型系统foundation进程的依赖关系,早知道有这个神器,效率不知道高了多少倍!!

1
回复
2023-3-16 10:04:33
物联风景
物联风景 回复了 liangkz_梁开祝
我以前还手动整理过小型系统foundation进程的依赖关系,早知道有这个神器,效率不知道高了多少倍!!

哈哈,那不一样,用自动化工具是为了快速定位问题,手动整理学的更扎实


2
回复
2023-3-16 10:57:05
liurick
liurick

才知道作者是老师

1
回复
2023-3-16 15:52:12
物联风景
物联风景 回复了 liurick
才知道作者是老师

偶尔讲讲课,但确实在教育岗

回复
2023-3-16 20:01:35
麻辣香锅配馒头
麻辣香锅配馒头

学校老师就经常说看问题不能看表面,真正弄懂问题才能有收获


1
回复
2023-3-17 14:54:34
喝一大口可乐
喝一大口可乐

改框架确实风险比较大

1
回复
2023-3-17 18:42:33
回复
    相关推荐