移植speexdsp到OpenHarmony标准系统③

speexdsp移植后已提交至openhamrony sig仓库:https://gitee.com/openharmony-sig/contest/tree/master/2022_OpenHarmony_thirdparty/speexdsp


四、将三方库加入到OpenHarmony的编译体系

根据上一步分析结果,编写gn文件,将三方库加入到OpenHarmony的编译体系。

OpenHarmony编译构建子系统提供了一个基于Gn和ninja的编译构建框架。根据产品配置,编译生成对应的镜像包。其中编译构建流程为:

  • 使用Gn配置构建目标。
  • Gn运行后会生成ninja文件。
  • 通过运行ninja来执行编译任务。

OpenHarmony三方库编译环境搭建

本次移植时在openharmony3.2Beta1版本上运行的,所以需要准备openharmony3.2Beta1的源码。
先在Widows上安装虚拟机,在虚拟机上安装Ubuntu18.04或者20.04。笔者使用的为Ubuntu20.04。

1.将Ubuntu Shell环境修改为bash

  • 打开终端执行
sudo dpkg-reconfigure dash
  • 将Shell由dash改为bash。
  • 选择<否>
  • 更改成功如下:

2.下载华为集成开发环境 DevEco Device Tool Linux版本,目前最新版本号为3.1.0.200

HUAWEI DevEco Device Tool(以下简称DevEco Device Tool)是OpenHarmony面向智能设备开发者提供的一站式集成开发环境,支持OpenHarmony的组件按需定制,支持代码编辑、编译、烧录和调试等功能,支持C/C++语言,以插件的形式部署在Visual Studio Code上。

  • 直接在Ubuntu上打开firefox输入下载地址下载
  • 解压DevEco Device Tool安装包,并对解压后的文件赋权
unzip devicetool-linux-tool-3.1.0.200.zip
chmod u+x devicetool-linux-tool-3.1.0.200.sh
  • 安装DevEco Device

  • 执行命令安装DevEco Device

sudo ./devicetool-linux-tool-3.1.0.200.sh

终端打印出这条信息说明安装成功

3.获取标准系统源码
执行命令sudo apt-get install git git-lfs安装git客户端和git-lfs

  • 配置git用户信息
git config --global user.name "yourname"
git config --global user.email "your-email-address"
git config --global credential.helper store

git config --global credential.helper store执行这个命令会在本地生成一个文本,上边记录配置。然后再拉取代码就不用再输入账号信息了。

  • 进入gitee官网个人主页,个人头像下方就是user.name
  • 再进入设置点击邮箱管理就可以得到你的your-email-address

  • 安装gitee码云repo工具

sudo apt-get install curl
sudo curl https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 -o /usr/local/bin/repo
sudo chmod a+x /usr/local/bin/repo
sudo pip3 install -i https://repo.huaweicloud.com/repository/pypi/simple requests
  • 使用repo+https下载发布Tag节点源码

创建源码存放目录
进入创建的源码存放目录,执行以下命令下载源码

sudo ln -sf /usr/bin/python3 /usr/bin/python
repo init -u https://gitee.com/openharmony/manifest -b refs/tags/OpenHarmony-v3.2-Beta1 --no-repo-verify
repo sync -c
repo forall -c 'git lfs pull'

如果要下载最新分支的代码则执行:
repo init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verify

3.在源码目录下执行脚本安装编译器及二进制工具
下载的prebuilts二进制默认存放在与OpenHarmony同目录下的OpenHarmony_2.0_canary_prebuilts下。

bash build/prebuilts_download.sh

如果执行bash build/prebuilts_download.sh出现以下warning,在源码/prebuilts/python/linux-x86/3.9.2/bin/执行python -m pip install --user --upgrade pip==22.3.1(22.3.1是要升级的版本号)

4.安装依赖工具

sudo apt-get install binutils git git-lfs gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z1-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip m4 bc gnutls-bin python3.8 python3-pip ruby

如果安装了如上的依赖工具不行,执行以下语句安装最新的依赖工具

unix_time=`date '+%s'`;for one_tools in `curl -s -k https://gitee.com/landwind/openharmony_oneclick_env_init/raw/master/apt_install.list`;do echo "apt-get install -y ${one_tools}">>/tmp/openharmony_deps_${unix_time}.sh; done;sudo apt-get update;sudo bash -x /tmp/openharmony_deps_${unix_time}.sh

依赖工具列表 https://gitee.com/landwind/openharmony_oneclick_env_init/raw/master/apt_install.list

5.将python 3.8设置为默认python版本。

  • 查看python 3.8的位置:
which python3.8

将python和python3切换为python3.8

sudo update-alternatives --install /usr/bin/python python {python3.8 路径} 1    
sudo update-alternatives --install /usr/bin/python3 python3 {python3.8 路径} 1  

6.最后测试一下OpenHarmony三方库编译环境

在源码根目录下执行编译命令

./build.sh --product-name rk3568 --ccache --build-target=要编译的部件名 --target-cpu arm64
#其中:--product-name rk3568 指定产品名为rk3568 
#其中:--ccache              编译使用ccache
#其中:--target-cpu arm64    编译构建64位系统

在源码目录下执行编译zlib命令,生成libzlib.z.so

./build.sh --product-name rk3568 --ccache --build-target=zlib

编译生成了libzlib.z.so,编译环境没问题。

OpenHarmony环境重置

  • 安装依赖包: unix_time=date '+%s';for one_tools incurl -s -k https://gitee.com/landwind/openharmony_oneclick_env_init/raw/master/apt_install.list;do echo "apt-get install -y ${one_tools}">>/tmp/openharmony_deps_${unix_time}.sh; done;sudo apt-get update;sudo bash -x /tmp/openharmony_deps_${unix_time}.sh
  • 删除out: rm -rf out
  • 重置工作区,删除所有修改(记得备份你改的代码): repo forall -c "pwd;git reset --hard; git clean -fd"
  • 更新最新代码: repo sync -c -j8; repo forall -c "pwd;git lfs install;git lfs pull"
  • 执行prebuilts下载脚本: bash build/prebuilts_download.sh

配置speexdsp源码

下载完openharmony3.2Beta1源码后,将speexdsp的源码拷贝到openhamony的third_party目录下。

在OpenHarmony/sources/third_party/speexdsp和OpenHarmony/sources/third_party/speexdsp/libspeexdsp下分别编写一份BUILD.gn文件,完成speexdsp的gn及测试用例的gn化。测试用例指的是测试speexdsp功能的程序。

speexdsp编译gn化,新增工程构建脚本。

OpenHarmony/sources/third_party/speexdsp下添加BUILD.gn脚本文件。

OpenHarmony/sources/third_party/speexdsp/BUILD.gn内容如下:

import("//build/ohos.gni")  

config("speexdsp_nowarn_config"){
    cflags = [
         "-Wno-implicit-function-declaration",
         "-Wno-pointer-sign",
         "-Wno-unused-variable",
    ]
}

config("speexdsp_cflag_config"){
    cflags = [
         "-g",
         "-O2",
         "-fvisibility=hidden",
         "-DHAVE_CONFIG_H",

    ]
    ldflags = [
         "-lm"
    ]
}

ohos_shared_library("speexdsp_share") {
    sources = [
         "libspeexdsp/preprocess.c",
         "libspeexdsp/jitter.c",
         "libspeexdsp/mdf.c",
         "libspeexdsp/fftwrap.c",
         "libspeexdsp/filterbank.c",
         "libspeexdsp/resample.c",
         "libspeexdsp/buffer.c",
         "libspeexdsp/scal.c",
         "libspeexdsp/smallft.c",
         ]

    defines = [
        "NL_DEBUG",
        "speexdsp_EXPORTS",
    ]

    configs = [ 
         ":speexdsp_cflag_config", 
         ":speexdsp_nowarn_config"
    ] 
    include_dirs = [
         ".",
         "libspeexdsp",
         "include"
    ]
    part_name = "speexdsp"
}

代码解析

第一行:

import("//build/ohos.gni") 

import函数将ohos.gni文件导入到当前作用域。导入的文件是独立执行的,生成的作用域被复制到当前文件中。一个.gni文件会定义构建参数和模板。build目录下ohos.gni文件内容如下

import("//build/config/sanitizers/sanitizers.gni")
import("//build/ohos/ndk/ndk.gni")
import("//build/ohos/notice/notice.gni")
import("//build/ohos/sa_profile/sa_profile.gni")
import("//build/ohos_var.gni")
import("//build/toolchain/toolchain.gni")

# import cxx base templates
import("//build/templates/cxx/cxx.gni")
if (support_jsapi) {
  import("//build/ohos/ace/ace.gni")
  import("//build/ohos/app/app.gni")
}

import("//build/templates/common/ohos_templates.gni")

# import prebuilt templates
import("//build/templates/cxx/prebuilt.gni")

第三行到第九行:

config("speexdsp_nowarn_config"){
    cflags = [
         "-Wno-implicit-function-declaration",
         "-Wno-pointer-sign",
         "-Wno-unused-variable",
    ]
}
  • configs定义了该模块编译配置的环境变量speexdsp_nowarn_config,第24行ohos_shared_library定义了最终生成的模块名,这里代表此模块为最终生成libspeexdsp.z.so。所以在第五行到第七行中config中添加了编译libspeexdsp.z.so需要添加的编译器标志
    • 但是"-Wno-implicit-function-declaration"、“-Wno-pointer-sign”"、-Wno-unused-variable"并非是分析speexdsp原生库得来的cflag编译器标志。
    • 而是后来在ohos上编译验证过程中,根据编译报错信息添加的。如果不添加它们,执行./build.sh --product-name rk3568 --ccache --build-target=speexdsp命令后,则无法编译生成openharmony上的运行的libspeexdsp.z.so库,会出现编译警告信息-W-implicit-function-declaration、-W-pointer-sign、-W-unused-variable。解决办法就是在gn化时添加cflag标志"-Wno-implicit-function-declaration"、“-Wno-pointer-sign”“、-Wno-unused-variable”。
  • clang编译器警告消除:
    1.出现警告的就是直接在-W后面加no,比如-Wimplicit-function-declaration改为 -Wno-implicit-function-declaration
    2.还有另外的一种方法:-Wimplicit-function-declaration=no

第十一到第二十二行:

config("speexdsp_cflag_config"){
    cflags = [
         "-g",
         "-O2",
         "-fvisibility=hidden",
         "-DHAVE_CONFIG_H",

    ]
    ldflags = [
         "-lm"
    ]
}
  • configs定义了该模块编译配置的环境变量speexdsp_cflag_config,在第十三行到第十六行添加了编译需要添加的编译器标志 “-g”,“-O2”,“-fvisibility=hidden”, “-DHAVE_CONFIG_H”。
    • “-g”,“-O2”,"-fvisibility=hidden"通过分析原生库config.log和makefile文件,具体请查看第二期内容。
    • "-DHAVE_CONFIG_H"通过分析执行build命令后编译ohos上speexdsp的so库报错信息得来
  • 添加"-DHAVE_CONFIG_H"后仍然有报错信息,解决办法是把linux下编译speexdsp原生库./configure后生成的config.h放置在thrid_party/speexdsp下。

第二十四行到第五十二行:

ohos_shared_library("speexdsp_share") {
    sources = [
         "libspeexdsp/preprocess.c",
         "libspeexdsp/jitter.c",
         "libspeexdsp/mdf.c",
         "libspeexdsp/fftwrap.c",
         "libspeexdsp/filterbank.c",
         "libspeexdsp/resample.c",
         "libspeexdsp/buffer.c",
         "libspeexdsp/scal.c",
         "libspeexdsp/smallft.c",
         ]

    defines = [
        "NL_DEBUG",
        "speexdsp_EXPORTS",
    ]

    configs = [ 
         ":speexdsp_cflag_config", 
         ":speexdsp_nowarn_config"
    ] 
    include_dirs = [
         ".",
         "libspeexdsp",
         "include"
    ]
    part_name = "speexdsp"
}
  • 第24行ohos_shared_library定义了最终生成的模块名,这里代表此模块为最终生成libspeexdsp.z.so/动态库

如果是生成静态库ohos_static_library(" ") { }

  • 第二十五行到第三十五行sources模块包含了需要编译的源码文件

  • 第四十六行到五十行include_dirs模块包含了编译依赖的头文件路径

  • 第五十一行part_name 该模块编译依赖的编译子系统组件名。该配置项是为了模块最终生成的so文件能在系统编译完后自动拷贝到系统目录中。如果没有配置该项,系统编译完后是不会自动将生成的so文件拷贝到系统目录。

测试用例gn化,新增工程构建脚本

OpenHarmony/sources/third_party/speexdsp/libspeexdsp下添加BUILD.gn脚本文件。

import("//build/ohos.gni")

config("test_nowarn_config"){
    cflags = [
         "-Wno-sign-compare",
         "-Wno-pointer-sign"
    ]
}

config("speexdsp_cflag_config") {
    ldflags = [ "-lm" ]
    cflags_cc = [
         "-g",
         "-O2",
         "-fvisibility=hidden",
    ]
}

config("speexdsp_config") {
    include_dirs = [
         "//third_party/speexdsp/include"
     ]
}

ohos_executable("testdenoise"){
    public_configs = [ 
          ":speexdsp_config",
          ":test_nowarn_config"
    ]
    sources = [
         "testdenoise.c"
    ]
    configs = [
         ":speexdsp_cflag_config",

    ]

    deps = [
         "//third_party/speexdsp:speexdsp_share"
    ]

    part_name = "speexdsp"
}

ohos_executable("testecho"){
    public_configs = [ 
          ":speexdsp_config",
          ":test_nowarn_config"
    ]
    sources = [
         "testecho.c"
    ]

    configs = [
         ":speexdsp_cflag_config"
    ]

    deps = [
         "//third_party/speexdsp:speexdsp_share"
    ]

    part_name = "speexdsp"
}

ohos_executable("testjitter"){
    public_configs = [ 
          ":speexdsp_config",
          ":test_nowarn_config"
    ]
    sources = [
         "testjitter.c"
    ]

    configs = [
         ":speexdsp_cflag_config"
    ]

    deps = [
         "//third_party/speexdsp:speexdsp_share"
    ]

    part_name = "speexdsp"
}

ohos_executable("testresample"){
    public_configs = [ 
          ":speexdsp_config",
          ":test_nowarn_config"
    ]
    sources = [
         "testresample.c"
    ]

    configs = [
         ":speexdsp_cflag_config"
    ]

    deps = [
         "//third_party/speexdsp:speexdsp_share"
    ]

    part_name = "speexdsp"
}

ohos_executable("testresample2"){
     public_configs = [ 
          ":speexdsp_config",
          ":test_nowarn_config"
    ]
    sources = [
         "testresample2.c"
    ]

    configs = [
         ":speexdsp_cflag_config"
    ]

    deps = [
         "//third_party/speexdsp:speexdsp_share"
    ]
    part_name = "speexdsp"

}

代码解析

测试用例gn化代码解析的内容与speexdsp编译gn化内容相似,这里不做重复解释,只补充以下几点。

  • 测试用例是在ohos上测试libspeexdsp.z.so功能用的。
  • 第28、48、68、88、108行:gn中的目标类型executable表示生成可执行文件testdenoise、testecho、testjitter、testresample、testresample2。
  • 第41、61、81、101、121行:deps表示测试用例模块编译依赖其他模块,这里指的是测试用例的编译依赖。libspeexdsp.z.so库。
  • 第45、65、85、105、125行:part_name表示测试用例模块编译依赖的编译子系统组件名。该配置项是为了模块最终生成的so文件能在系统编译完后自动拷贝到系统目录中。如果没有配置该项,系统编译完后是不会自动将生成的so文件拷贝到系统目录。

OpenHarmony/sources/third_party/speexdsp目录下添加ohos.build。

  • 定义子系统并加入到编译框架
    在系统源码根目录下创建一个目录作为子系统目录,子系统目录可创建在OpenHarmony源码目录任意位置。
    • 本项目以third_party/speexdsp作为为子系统目录,子系统名字即为speexdsp。

子系统speexdsp目录下创建ohos.build文件,build构建时会先读取该文件。

  "subsystem": "speexdsp",
  "parts": {
    "speexdsp": {
      "module_list": [
        "//third_party/speexdsp/libspeexdsp:testdenoise",
        "//third_party/speexdsp/libspeexdsp:testecho",
        "//third_party/speexdsp/libspeexdsp:testjitter",
        "//third_party/speexdsp/libspeexdsp:testresample",
        "//third_party/speexdsp/libspeexdsp:testresample2"
      ],
      "inner_kits": [
              ],
      "system_kits": [
      ],
      "test_list": [
      ]
    }
  }
}
  • build文件夹下的subsystem_config.json文件,主要包含子系统名称与路径信息,在preloader阶段被加载,根据子系统名称和路径信息查找该路径下的ohos.build文件。
  • 其中需要包含module_list、inner_kits、system_kits、test_list四个部分的声明:
    • module_list:部件包含的模块列表
    • inner_kits:部件提供其它部件的接口
    • system_kits:部件提供给生成应用的接口
    • test_list:部件对应模块的测试用例

修改build/subsystem_config.json,新增子系统定义。

在源码/build/subsystem_config.json中增加子系统选项,把子系统speexdsp配置到build/subsystem_config.json。

 "speexdsp": {
    "path": "third_party/speexdsp",
    "name": "speexdsp"
  },

注意:要求符合json语法规范,要在}前加,(如下图所示)

修改vendor/hihope/rk3568/config.json文件将speexdsp添加至rk3568开发板,在vendor目录下新增产品的定义。

将子系统及其组件加入产品定义中,以rk3568为例,产品定义文件在vendor/hihope/rk3568/config.json,需要将以下内容添加到config.json中:

{
      "subsystem": "speexdsp",
      "components": [
        {
          "component": "speexdsp",
          "features": []
        }
      ]
    },

下期分享内容:在OpenHarmony的编译体系下编译speexdsp的so和测试用的可执行文件,以及编译报错的解决办法

知识点附送

本文中知识点附送的内容并不和移植speexdsp到openharmony标准系统直接相关,仅作为拓展阅读的知识点,因此读者可以不作过细的了解。

gn

  • generate ninja工具,在out目录下生成ninja编译文件*.ninja,gn的可执行文件位置在prebuilts/build-tools/linux-x86目录里

  • GN基础语法介绍:https://gitee.com/personal-summary/gn

jiajiahao@ubuntu:~/Desktop/OpenHarmony/sources/prebuilts/build-tools/linux-x86/bin$ ./gn --help

Commands (type "gn help <command>" for more help):
  analyze: Analyze which targets are affected by a list of files.
  args: Display or configure arguments declared by the build.
  check: Check header dependencies.
  clean: Cleans the output directory.
  desc: Show lots of insightful information about a target or config.
  format: Format .gn files.
  gen: Generate ninja files.
  help: Does what you think.
  ls: List matching targets.
  meta: List target metadata collection results.
  path: Find paths between two targets.
  refs: Find stuff referencing a target or file.

Target declarations (type "gn help <function>" for more help):
  action: Declare a target that runs a script a single time.
  action_foreach: Declare a target that runs a script over a set of files.
  bundle_data: [iOS/macOS] Declare a target without output.
  copy: Declare a target that copies files.
  create_bundle: [iOS/macOS] Build an iOS or macOS bundle.
  executable: Declare an executable target.
  generated_file: Declare a generated_file target.
  group: Declare a named group of targets.
  loadable_module: Declare a loadable module target.
  rust_library: Declare a Rust library target.
  rust_proc_macro: Declare a Rust procedural macro target.
  shared_library: Declare a shared library target.
  source_set: Declare a source set target.
  static_library: Declare a static library target.
  target: Declare an target with the given programmatic type.

Buildfile functions (type "gn help <function>" for more help):
  assert: Assert an expression is true at generation time.
  config: Defines a configuration object.
  declare_args: Declare build arguments.
  defined: Returns whether an identifier is defined.
  exec_script: Synchronously run a script and return the output.
  foreach: Iterate over a list.
  forward_variables_from: Copies variables from a different scope.
  get_label_info: Get an attribute from a target's label.
  get_path_info: Extract parts of a file or directory name.
  get_target_outputs: [file list] Get the list of outputs from a target.
  getenv: Get an environment variable.
  import: Import a file into the current scope.
  not_needed: Mark variables from scope as not needed.
  pool: Defines a pool object.
  print: Prints to the console.
  process_file_template: Do template expansion over a list of files.
  read_file: Read a file into a variable.
  rebase_path: Rebase a file or directory to another location.
  set_default_toolchain: Sets the default toolchain name.
  set_defaults: Set default values for a target type.
  set_sources_assignment_filter: Set a pattern to filter source files.
  split_list: Splits a list into N different sub-lists.
  string_join: Concatenates a list of strings with a separator.
  string_replace: Replaces substring in the given string.
  string_split: Split string into a list of strings.
  template: Define a template rule.
  tool: Specify arguments to a toolchain tool.
  toolchain: Defines a toolchain.
  write_file: Write a file to disk.

Built-in predefined variables (type "gn help <variable>" for more help):
  current_cpu: [string] The processor architecture of the current toolchain.
  current_os: [string] The operating system of the current toolchain.
  current_toolchain: [string] Label of the current toolchain.
  default_toolchain: [string] Label of the default toolchain.
  gn_version: [number] The version of gn.
  host_cpu: [string] The processor architecture that GN is running on.
  host_os: [string] The operating system that GN is running on.
  invoker: [string] The invoking scope inside a template.
  python_path: [string] Absolute path of Python.
  root_build_dir: [string] Directory where build commands are run.
  root_gen_dir: [string] Directory for the toolchain's generated files.
  root_out_dir: [string] Root directory for toolchain output files.
  target_cpu: [string] The desired cpu architecture for the build.
  target_gen_dir: [string] Directory for a target's generated files.
  target_name: [string] The name of the current target.
  target_os: [string] The desired operating system for the build.
  target_out_dir: [string] Directory for target output files.

Variables you set in targets (type "gn help <variable>" for more help):
  aliased_deps: [scope] Set of crate-dependency pairs.
  all_dependent_configs: [label list] Configs to be forced on dependents.
  allow_circular_includes_from: [label list] Permit includes from deps.
  arflags: [string list] Arguments passed to static_library archiver.
  args: [string list] Arguments passed to an action.
  asmflags: [string list] Flags passed to the assembler.
  assert_no_deps: [label pattern list] Ensure no deps on these targets.
  bundle_contents_dir: Expansion of {{bundle_contents_dir}} in create_bundle.
  bundle_deps_filter: [label list] A list of labels that are filtered out.
  bundle_executable_dir: Expansion of {{bundle_executable_dir}} in create_bundle
  bundle_resources_dir: Expansion of {{bundle_resources_dir}} in create_bundle.
  bundle_root_dir: Expansion of {{bundle_root_dir}} in create_bundle.
  cflags: [string list] Flags passed to all C compiler variants.
  cflags_c: [string list] Flags passed to the C compiler.
  cflags_cc: [string list] Flags passed to the C++ compiler.
  cflags_objc: [string list] Flags passed to the Objective C compiler.
  cflags_objcc: [string list] Flags passed to the Objective C++ compiler.
  check_includes: [boolean] Controls whether a target's files are checked.
  code_signing_args: [string list] Arguments passed to code signing script.
  code_signing_outputs: [file list] Output files for code signing step.
  code_signing_script: [file name] Script for code signing.
  code_signing_sources: [file list] Sources for code signing step.
  complete_static_lib: [boolean] Links all deps into a static library.
  configs: [label list] Configs applying to this target or config.
  contents: Contents to write to file.
  crate_name: [string] The name for the compiled crate.
  crate_root: [string] The root source file for a binary or library.
  crate_type: [string] The type of linkage to use on a shared_library.
  data: [file list] Runtime data file dependencies.
  data_deps: [label list] Non-linked dependencies.
  data_keys: [string list] Keys from which to collect metadata.
  defines: [string list] C preprocessor defines.
  depfile: [string] File name for input dependencies for actions.
  deps: [label list] Private linked dependencies.
  externs: [scope] Set of Rust crate-dependency pairs.
  framework_dirs: [directory list] Additional framework search directories.
  frameworks: [name list] Name of frameworks that must be linked.
  friend: [label pattern list] Allow targets to include private headers.
  include_dirs: [directory list] Additional include directories.
  inputs: [file list] Additional compile-time dependencies.
  ldflags: [string list] Flags passed to the linker.
  lib_dirs: [directory list] Additional library directories.
  libs: [string list] Additional libraries to link.
  metadata: [scope] Metadata of this target.
  output_conversion: Data format for generated_file targets.
  output_dir: [directory] Directory to put output file in.
  output_extension: [string] Value to use for the output's file extension.
  output_name: [string] Name for the output file other than the default.
  output_prefix_override: [boolean] Don't use prefix for output name.
  outputs: [file list] Output files for actions and copy targets.
  partial_info_plist: [filename] Path plist from asset catalog compiler.
  pool: [string] Label of the pool used by the action.
  precompiled_header: [string] Header file to precompile.
  precompiled_header_type: [string] "gcc" or "msvc".
  precompiled_source: [file name] Source file to precompile.
  product_type: [string] Product type for Xcode projects.
  public: [file list] Declare public header files for a target.
  public_configs: [label list] Configs applied to dependents.
  public_deps: [label list] Declare public dependencies.
  rebase: [boolean] Rebase collected metadata as files.
  response_file_contents: [string list] Contents of .rsp file for actions.
  script: [file name] Script file for actions.
  sources: [file list] Source files for a target.
  testonly: [boolean] Declares a target must only be used for testing.
  visibility: [label list] A list of labels that can depend on a target.
  walk_keys: [string list] Key(s) for managing the metadata collection walk.
  write_runtime_deps: Writes the target's runtime_deps to the given path.
  xcode_extra_attributes: [scope] Extra attributes for Xcode projects.
  xcode_test_application_name: [string] Name for Xcode test target.

Other help topics:
  all: Print all the help at once
  buildargs: How build arguments work.
  dotfile: Info about the toplevel .gn file.
  execution: Build graph and execution overview.
  grammar: Language and grammar for GN build files.
  input_conversion: Processing input from exec_script and read_file.
  label_pattern: Matching more than one label.
  labels: About labels.
  metadata_collection: About metadata and its collection.
  ninja_rules: How Ninja build rules are named.
  nogncheck: Annotating includes for checking.
  output_conversion: Specifies how to transform a value to output.
  runtime_deps: How runtime dependency computation works.
  source_expansion: Map sources to outputs for scripts.
  switches: Show available command-line switches.

ninja

ninja构建工具,编译时根据gn生成的*.ninja文件进行编译构建,ninjiad的可执行文件位置在prebuilts/build-tools/linux-x86目录里

jiajiahao@ubuntu:~/Desktop/OpenHarmony/sources/prebuilts/build-tools/linux-x86/bin$ ./ninja --help
usage: ninja [options] [targets...]

if targets are unspecified, builds the 'default' target (see manual).

options:
  --version      print ninja version ("1.10.1")
  -v, --verbose  show all command lines while building

  -C DIR   change to DIR before doing anything else
  -f FILE  specify input build file [default=build.ninja]

  -j N     run N jobs in parallel (0 means infinity) [default=18 on this system]
  -k N     keep going until N jobs fail (0 means infinity) [default=1]
  -l N     do not start new jobs if the load average is greater than N
  -n       dry run (don't run commands but act like they succeeded)

  -d MODE  enable debugging (use '-d list' to list modes)
  -t TOOL  run a subtool (use '-t list' to list subtools)
    terminates toplevel options; further flags are passed to the tool
  -w FLAG  adjust warnings (use '-w list' to list warnings)

关于deps、external_deps的使用

在添加一个模块的时候,需要在BUILD.gn中声明它的依赖,为了便于后续处理部件间依赖关系,我们将依赖分为两种——部件内依赖deps和部件间依赖external_deps。

依赖分类:

如上图所示,主要分为部件内依赖(图左)和部件间依赖(图右)。

部件内依赖: 现有模块module1属于部件part1,要添加一个属于部件part1的模块module2,module2依赖于module1,这种情况就属于部件内依赖。

部件间依赖: 现有模块module1属于部件part1,要添加一个模块module2,module2依赖于module1,module2属于部件part2。模块module2与模块module1分属于两个不同的部件,这种情况就属于部件间依赖。

部件内依赖示例:

import("//build/ohos.gni")
ohos_shared_library("module1") {
  ……
  part_name = "part1"   # 必选,所属部件名称
  ……
}


import("//build/ohos.gni")
ohos_shared_library("module2") {
  ……
  deps = [
    "module1的gn target",
  ……
 ]                        # 部件内模块依赖
part_name = "part1"       # 必选,所属部件名称
}

部件间依赖示例:

import("//build/ohos.gni")
ohos_shared_library("module1") {
  ……
  part_name = "part1"   # 必选,所属部件名称
  ……
}

import("//build/ohos.gni")
ohos_shared_library("module2") {
  ……
  external_deps = [
    "part1:module1",
  ……
  ]                      # 部件间模块依赖,这里依赖的模块必须是依赖的部件声明在inner_kits中的模块
  part_name = "part2"    # 必选,所属部件名称
}

注意:部件间依赖要写在external_deps里面,格式为”部件名:模块名"的形式,并且依赖的模块必须是依赖的部件声明在inner_kits中的模块。

查看.ninja_log文件可以知道每个模块编译的开始和结束时间

out/rk3568/.ninja_log文件记录了每个模块编译的开始和结束时间(ms),结束时间和开始时间间隔越短表示模块的编译时间越短,编译性能越高。

从左到右分别表示:start time|end time|mtime|command hash。
mtime(modify time)显示的是文件内容被修改的最后时间

写在最后

如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙

  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新学习知识点,请移步前往小编:https://gitee.com/MNxiaona/733GH/blob/master/jianshu
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,013评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,205评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,370评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,168评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,153评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,954评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,271评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,916评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,382评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,877评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,989评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,624评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,209评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,199评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,418评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,401评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,700评论 2 345

推荐阅读更多精彩内容