美文网首页
[openharmony]liteos-a系统编译之GN

[openharmony]liteos-a系统编译之GN

作者: itsenlin | 来源:发表于2021-10-23 23:29 被阅读0次

回顾

文章中已经分析openharmony的小型系统(liteos-a)编译过程,最主要的就是调用gn/ninja/makefs三个命令最终生成可烧录的镜像文件
从前面文件可以看到hb build调用的gn命令参数如下

hb_build_gn_cmd.png

这里详细分析一下gn工具在编译过程中的使用

GN工具

这里简单介绍下GN工具的使用方法,gn语法可以参考http://weharmonyos.com/openharmony/compile/gn/docs/
,已经熟悉的可以跳过

gn_cmd说明

从上面图中可以看到使用的命令类型为gn gen <output_dir> [options],此命令就是为了将所有需要的BUILD.gn文件生成为*.ninja文件供ninja进行编译; 可以通过gn help gen命令查看详细的用法说明, 如下

itsenlin@itsenlin-PC:~/gn$ ./gn help gen
gn gen [--check] [<ide options>] <out_dir>

  Generates ninja files from the current tree and puts them in the given output
  directory.
......
itsenlin@itsenlin-PC:~/gn$

下面重点说一下gn_cmd中的[options]

dotfile

  • --root显示指定编译系统的根目录
  • --dotfile是为了显示指定dotfile的路径;如果不指定,gn会在当前目录下寻找,并且以.gn所在目录为根目录处理转换工作
    可以通过命令gn help dotfile查看详细信息,截取部分如下
itsenlin@itsenlin-PC:~/gn$ ./gn help dotfile
.gn file

  When gn starts, it will search the current directory and parent directories
  for a file called ".gn". This indicates the source root. You can override
  this detection by using the --root command-line argument

  The .gn file in the source root will be executed. The syntax is the same as a
  buildfile, but with very limited build setup-specific meaning.

  If you specify --root, by default GN will look for the file .gn in that
  directory. If you want to specify a different file, you can additionally pass
  --dotfile:

    gn gen out/Debug --root=/home/build --dotfile=/home/my_gn_file.gn

Variables
  buildconfig [required]
      Path to the build config file. This file will be used to set up the
      build file execution environment for each toolchain.

  root [optional]
      Label of the root build target. The GN build will start by loading the
      build file containing this target name. This defaults to "//:" which will
      cause the file //BUILD.gn to be loaded.

......

Example .gn file contents

  buildconfig = "//build/config/BUILDCONFIG.gn"

  check_targets = [
    "//doom_melon/*",  # Check everything in this subtree.
    "//tools:mind_controlling_ant",  # Check this specific target.
  ]

  root = "//:root"

  secondary_source = "//build/config/temporary_buildfiles/"

  default_args = {
    # Default to release builds for this project.
    is_debug = false
    is_component_build = false
  }

itsenlin@itsenlin-PC:~/gn$

dotfile中有很多内置变量,这里用到了两个:buildconfigroot(其他的可以通过命令帮助信息中查看);这里的root与前面介绍的--root不一样,要注意这一点

liteos-a编译系统的dotfile内容如下:

itsenlin@itsenlin-PC:~/code/ohos_3.0$ cat build/lite/.gn

# The location of the build configuration file.
buildconfig = "//build/lite/config/BUILDCONFIG.gn"

# The source root location.
root = "//build/lite"
itsenlin@itsenlin-PC:~/code/ohos_3.0$ 
  • buildconfig: 安装设置编译所需要的环境,像编译工具链
  • root: 我理解BUILD.gn文件是分散在各个模块源码路径下的,要想找到这些文件就需要有一个入口(或者要根),root就是指定这个入口BUILD.gn文件所在路径
  • 这里的//表示编译系统的根目录,就是前面--root指定的目录,所以这里的//build对应的就是/home/itsenlin/code/ohos_3.0/build

编译环境配置

liteos-a是嵌入式系统,而编译环境是linux系统,这就需要用到交叉编译方式,这个就可以在环境配置中指定target_ostarget_cpuboard_cpu等等信息
这些信息就是buildconfig参数指定的BUILDCONFIG.gn文件中配置的
除了以上信息,还配置了以下几个重要信息

  • 默认编译工具链set_default_toolchain(...)
  • 默认的config信息default_target_configs
  • 可执行目标executable、静态库目标static_library、动态库目标shared_library的定义以及action的定义

详细信息可以查看//build/lite/config/BUILDCONFIG.gn文件内容

编译工具链--toolchain

toolchain定义源码编译需要的工具,像编译器、汇编器、连接器等等,一般在.gn所在目录下有一个toolchain目录,里面的BUILD.gn定义详细的编译工具链信息
这里目录结构如下:

├── toolchain
│   ├── BUILD.gn
│   ├── clang.gni
│   └── gcc.gni

从结构信息中可以看到定义了clang和gcc两种工具链,通过变量board_toolchain_type来区分(此变量也是buildconfig中定义的),具体信息参见BUILD.gn文件内容,如下

import("//build/lite/toolchain/clang.gni")
import("//build/lite/toolchain/gcc.gni")

# Set toolchain configed by board.
if (board_toolchain != "" && use_board_toolchain) {
  if (board_toolchain_type == "gcc") {
    gcc_toolchain(board_toolchain) {
      cc = ohos_current_cc_command
      cxx = ohos_current_cxx_command
      ar = ohos_current_ar_command
      ld = ohos_current_ld_command
      strip = ohos_current_strip_command
    }
  } else if (board_toolchain_type == "clang") {
    clang_toolchain(board_toolchain) {
      cc = ohos_current_cc_command
      cxx = ohos_current_cxx_command
      ar = ohos_current_ar_command
      ld = ohos_current_ld_command
      strip = ohos_current_strip_command
    }
  }
} else {
  clang_toolchain("linux_x86_64_ohos_clang") {
    cc = ohos_current_cc_command
    cxx = ohos_current_cxx_command
    ar = ohos_current_ar_command
    ld = ohos_current_ld_command
    strip = ohos_current_strip_command
  }
}

可以做为一个模板,其他项目上想使用gn+ninja编译的话就可以参考这里的设置; 另外gn下的toolchain信息可以通过命令gn help toolchain查看

BUILD.gn文件入口

在.gn文件所在目录下的BUILD.gn就是入口,此文件做了以下几个事情

  • 生成version-info文件,记录ohos-version以及ohos编译时间
  • 通过group定义一组依赖,以生成最终的依赖树
    可以通过gn help group查看详细信息,如下
itsenlin@itsenlin-PC:~/code/ohos_3.0$ ~/gn/gn help group
group: Declare a named group of targets.

  This target type allows you to create meta-targets that just collect a set of
  dependencies into one named target. Groups can additionally specify configs
  that apply to their dependents.

Variables

  Deps: data_deps, deps, public_deps
  Dependent configs: all_dependent_configs, public_configs

Example

  group("all") {
    deps = [
      "//project:runner",
      "//project:unit_tests",
    ]
  }

itsenlin@itsenlin-PC:~/code/ohos_3.0$ 

这里重点说一下target为ohosgroup如下:

group("ohos") {
  deps = []
  if (ohos_build_target == "") {
    # Step 1: Read product configuration profile.
    product_cfg = read_file("${product_path}/config.json", "json")

    # Step 2: Loop subsystems configured by product.
    foreach(product_configed_subsystem, product_cfg.subsystems) {
      subsystem_name = product_configed_subsystem.subsystem
      # Step 3: Read OS subsystems profile.
      subsystem_info =
          read_file("//build/lite/components/${subsystem_name}.json", "json")

      # Step 4: Loop components configured by product.
      foreach(product_configed_component,
              product_configed_subsystem.components) {
        # Step 5: Check whether the component configured by product is exist.
        component_found = false
        foreach(system_component, subsystem_info.components) {
          if (product_configed_component.component ==
              system_component.component) {
            component_found = true
          }
        }

        # Step 6: Loop OS components and check validity of product configuration.
        foreach(component, subsystem_info.components) {
          kernel_valid = false
          board_valid = false

          # Step 6.1: Skip component which not configured by product.
          if (component.component == product_configed_component.component) {
            # Step 6.1.1: Loop OS components adapted kernel type.
            foreach(component_adapted_kernel, component.adapted_kernel) {
              if (component_adapted_kernel == product_cfg.kernel_type &&
                  kernel_valid == false) {
                kernel_valid = true
              }
            }

            # Step 6.1.2: Add valid component for compiling.
            # Skip kernel target for userspace only scenario.
            if (!ohos_build_userspace_only ||
                (ohos_build_userspace_only && subsystem_name != "kernel" &&
                 subsystem_name != "vendor")) {
              foreach(component_target, component.targets) {
                deps += [ component_target ]
              }
            }
          }
        }
      }
    }

    # Skip device target for userspace only scenario.
    if (!ohos_build_userspace_only) {
      # Step 7: Add device and product target by default.
      deps += [ "${device_path}/../" ]
    }
  } else {
    deps += string_split(ohos_build_target, "&&")
  }
}

这里也比较好理解,里面就是读取一个配置文件,几级循环来处理配置文件中配置的内容。流程如下

  • 读取开发板对应的config.json,从配置中可以看到ohos系统分为三级: board、subsystems、components,如下
{
    "product_name": "ipcamera_hispark_taurus",
    "ohos_version": "OpenHarmony 1.0",
    "device_company": "hisilicon",
    "board": "hispark_taurus",
    "kernel_type": "liteos_a",
    "kernel_version": "",
    "subsystems": [
      {
        "subsystem": "aafwk",
        "components": [
          { "component": "aafwk_lite", "features":[ "enable_ohos_appexecfwk_feature_ability = true" ] }
        ]
      },
       ......
      {
        "subsystem": "kernel",
        "components": [
          { "component": "liteos_a", "features":[] }
        ]
      },
      ......
    "third_party_dir": "//third_party",
    "product_adapter_dir": "//vendor/hisilicon/hispark_taurus/hals"
  }
  • 对此board下的subsystems循环处理
  • 读取//build/lite/components/目录下subsystem对应的配置文件,这里以kernel为例,则读取的是//build/lite/components/kernel.json文件,定义如下:
{
  "components": [
    {
      "component": "liteos_a",
      "description": "liteos-a kernel",
      "optional": "false",
      "dirs": [
        "kernel/liteos_a"
      ],
      "targets": [
        "//kernel/liteos_a:kernel"
      ],
      "rom": "1.98MB",
      "ram": "",
      "output": [
        "liteos.bin"
      ],
      "adapted_board": [
        "hispark_aries",
        "hispark_taurus",
        "hi3518ev300",
    "hi3516dv300"
      ],
      "adapted_kernel": [ "liteos_a" ],
      "features": [],
      "deps": {
        "components": [],
        "third_party": [
          "FreeBSD",
          "musl",
          "zlib",
          "FatFs",
          "Linux_Kernel",
          "lwip",
          "NuttX",
          "mtd-utils"
        ]
      }
    },
    {
      "component": "liteos_m",
     ......
    },
    {
      "component": "linux_hi3516dv300",
      ......
    },
    {
      "component": "linux_4_1_9",
      ......
    },
    {
      "component": "linux_hi3518ev300",
      ......
    }
  ]
}
  • 对subsystem下的components循环处理
  • 做一些检查,然后将comonent里面定义的targets添加了group("ohos")的依赖库中
  • 上面所有subsystems处理完之后,将device的配置添加到默认依赖中

到此就将此board下各模块的依赖关系添加好了,然后GN会将依赖树中所有的BUILD.gn生成对应的.ninja文件,并且在out的根目录下生成下面几个ninja的入口文件以及配置文件

itsenlin@itsenlin-PC:~/code/ohos_3.0/out/hispark_taurus/ipcamera_hispark_taurus$ tree -L 2
.
├── args.gn
├── build.log
├── build.ninja
├── build.ninja.d
├── config.gni
├── config.h
├── etc
│   └── version-info
├── kconfig_env.txt
├── kconfig_files.txt
├── NOTICE_FILE
│   ├── acts
│   ├── appexecfwk_services_lite
│   ├── bundle_daemon_lite
│   ├── kernel
│   └── tools
├── obj
│   ├── applications
│   ├── base
│   ├── build
│   ├── device
│   ├── drivers
│   ├── foundation
│   ├── kernel
│   ├── test
│   ├── third_party
│   ├── utils
│   └── vendor
├── test_info
│   ├── gen
│   └── module_list_files
└── toolchain.ninja

22 directories, 10 files
itsenlin@itsenlin-PC:~/code/ohos_3.0/out/hispark_taurus/ipcamera_hispark_taurus$

其中config.h、'config.gni'、'kconfig_env.txt'、'kconfig_files.txt'等 配置文件的生成原理可以参考liteos-a全局配置文件生成原理

相关文章

网友评论

      本文标题:[openharmony]liteos-a系统编译之GN

      本文链接:https://www.haomeiwen.com/subject/jfakaltx.html