鸿蒙HarmonyOS NEXT开发:CMake构建工程配置HarmonyOS编译工具链

往期鸿蒙全套实战精彩文章必看内容:


简介

CMake是一个跨平台的构建工具,用于管理构建过程、编译、链接和打包软件项目,它可以生成Makefile等用于不同操作系统和编译器的构建脚本。CMake的配置过程是跨平台的,因此可以在不同的操作系统上运行,例如Linux、Windows和macOS。

CMake构建过程可分为以下三个主要步骤:

  • 配置(Configuration):配置阶段是CMake解析CMakeLists.txt文件的过程。在配置阶段,CMake会读取CMakeLists.txt文件,并执行其中的命令。CMakeLists.txt文件是CMake的核心,其定义了项目的构建规则和依赖关系。
  • 生成(Generation):生成阶段是CMake根据配置阶段的结果,生成实际构建文件的过程。在生成阶段,CMake会将CMakeLists.txt文件中定义的构建规则和依赖关系转为构建工具可以理解的形式。
  • 构建(Build):构建阶段是使用构建工具(如Make或DevEco Studio)根据生成的构建文件,编译源代码并链接生成目标文件的过程。在构建阶段,构建工具会读取生成的构建文件,按照其中定义的规则和依赖关系,执行实际的编译和链接操作。

CMake构建三方库适配流程

本小节介绍如何在Linux环境下,使用CMake构建工具通过ohos sdk编译cJSON三方库源码,生成ohos平台三方库的so及二进制文件。

环境准备

  1. 首先需要Linux编译环境。

    开发者可以选择熟悉的发行版来进行环境搭建,这里以Ubuntu为例,Ubuntu目前主要支持Ubuntu18.04和Ubuntu20.04(Ubuntu22.04暂不支持)。

  2. HarmonyOS SDK镜像下载:从DevEco Studio的SDK Manager中获取SDK,或通过CI平台进行下载。
  3. tar -zxvf解压SDK文件。随着版本更新,SDK版本可能会有变动,开发者可自行下载最新版本,此处以4.0.10.5版本为例。
    owner@ubuntu:/mnt/e/ohosSDK$ tar -zxvf version-Master_Version-OpenHarmony_4.0.10.5-20230824_120921-ohos-sdk-public_monthly.tar.gz
  4. 进入到SDK的linux目录,解压工具包。
    owner@ubuntu:/mnt/e/ohosSDK$ cd ohos-sdk/linux
    owner@ubuntu:/mnt/e/ohosSDK/ohos-sdk/linux$ for i in *.zip;do unzip ${i};done                  # 通过for循环一次解压所有的工具包
    owner@ubuntu:/mnt/e/ohosSDK/ohos-sdk/linux$ ls
    ets                                 native                                    toolchains
    ets-linux-x64-4.0.10.5-Release.zip  native-linux-x64-4.0.10.5-Release.zip     toolchains-linux-x64-4.0.10.5-Release.zip
    js                                  previewer
    js-linux-x64-4.0.10.5-Release.zip   previewer-linux-x64-4.0.10.5-Release.zip
  5. 获取三方库源码(适配三方库如果没有指定版本,一般取三方库最新版本)。
    owner@ubuntu:/mnt/e/cmake$ git clone https://github.com/DaveGamble/cJSON.git -b v1.7.18        # 通过git下载指定版本的源码
    Cloning into 'cJSON'...
    remote: Enumerating objects: 4545, done.
    remote: Total 4545 (delta 0), reused 0 (delta 0), pack-reused 4545
    Receiving objects: 100% (4545/4545), 2.45 MiB | 1.65 MiB/s, done.
    Resolving deltas: 100% (3026/3026), done.
    Note: switching to 'd348621ca93571343a56862df7de4ff3bc9b5667'.
    
    You are in 'detached HEAD' state. You can look around, make experimental
    changes and commit them, and you can discard any commits you make in this
    state without impacting any branches by switching back to a branch.
    
    If you want to create a new branch to retain commits you create, you may
    do so (now or later) by using -c with the switch command. Example:
    
      git switch -c <new-branch-name>
    
    Or undo this operation with:
    
      git switch -
    
    Turn off this advice by setting config variable advice.detachedHead to false

编译三方库

  1. 新建编译目录。

    为防止污染源码目录文件,推荐在三方库源码目录新建一个编译目录,用于生成需要编译的配置文件。

    本用例中在cJSON目录下新建一个build目录:

    owner@ubuntu:/mnt/e/cmake$ cd cJSON-1.7.18                                   # 进入cJSON目录
    owner@ubuntu:/mnt/e/cmake/cJSON-1.7.18$ mkdir build && cd build              # 创建编译目录并进入到编译目录
    owner@ubuntu:/mnt/e/cmake/cJSON-1.7.18/build$
  2. 执行cmake编译命令,配置交叉编译参数,生成Makefile。
    owner@ubuntu:/mnt/e/cmake/cJSON-1.7.18/build$ /xxx/ohos-sdk/linux/native/build-tools/cmake/bin/cmake -DCMAKE_TOOLCHAIN_FILE=/xxx/ohos-sdk/linux/native/build/cmake/ohos.toolchain.cmake -DCMAKE_INSTALL_PREFIX=/xxx/cJSON -DOHOS_ARCH=arm64-v8a .. -L                                                   # 执行cmake命令
    -- The C compiler identification is Clang 12.0.1
    -- Check for working C compiler: /mnt/e/ohosSDK/ohos-sdk/linux/native/llvm/bin/clang   # 采用sdk内的编译器
    -- Check for working C compiler: /mnt/e/ohosSDK/ohos-sdk/linux/native/llvm/bin/clang -- works
    ...
    # 省略部分cmake信息
    ...
    ENABLE_PUBLIC_SYMBOLS:BOOL=ON
    ENABLE_SAFE_STACK:BOOL=OFF
    ENABLE_SANITIZERS:BOOL=OFF
    ENABLE_TARGET_EXPORT:BOOL=ON
    ENABLE_VALGRIND:BOOL=OFF
    owner@ubuntu:/mnt/e/cmake/cJSON-1.7.18/build$ ls                             # 执行完cmake成功后在当前目录生成Makefile文件
    cJSONConfig.cmake  cJSONConfigVersion.cmake  CMakeCache.txt  CMakeFiles  cmake_install.cmake  CTestTestfile.cmake  fuzzing  libcjson.pc  Makefile  tests

    参数说明:

    • CMAKE_TOOLCHAIN_FILE:交叉编译配置文件路径,设置为ohos工具链配置文件。
    • CMAKE_INSTALL_PREFIX:配置安装三方库路径。
    • OHOS_ARCH: 配置交叉编译的CPU架构,一般为arm64-v8a(编译64位的三方库)或armeabi-v7a(编译32位的三方库),本示例中设置编译为64位的cJSON库。
    • -L: 显示cmake中可配置项目。

    部分文件产物说明:

    • Makefile:构建项目的Makefile文件,包含了编译、链接等指令。
    • CMakeCache.txt:CMake的缓存文件,记录了CMake的配置选项和变量信息。
    • CMakeFiles:CMake的临时文件目录,包含了一些中间文件和构建信息,方便后续重新生成Makefile时使用。
    • cmake_install.cmake:安装规则文件,用于执行安装操作,将编译好的文件安装到指定的目录下。
    • CTestTestfile.cmake:用于执行测试的CMake脚本文件,方便进行自动化测试。
  3. 执行编译。

    执行make对cJSON进行编译:

    owner@ubuntu:/mnt/e/cmake/cJSON-1.7.18/build$ make                  # 执行make命令进行编译
    Scanning dependencies of target cjson
    [  2%] Building C object CMakeFiles/cjson.dir/cJSON.c.o
    clang: warning: argument unused during compilation: '--gcc-toolchain=/mnt/e/ohosSDK/ohos-sdk/linux/native/llvm' [-Wunused-command-line-argument]
      /mnt/e/cmake/cJSON-1.7.18/cJSON.c:561:9: warning: 'long long' is an extension when C99 mode is not enabled [-Wlong-long]
    ...
    # 省略部分make信息
    ...
    clang: warning: argument unused during compilation: '--gcc-toolchain=/mnt/e/ohosSDK/ohos-sdk/linux/native/llvm' [-Wunused-command-line-argument]
    [ 97%] Building C object fuzzing/CMakeFiles/fuzz_main.dir/cjson_read_fuzzer.c.o
    clang: warning: argument unused during compilation: '--gcc-toolchain=/mnt/e/ohosSDK/ohos-sdk/linux/native/llvm' [-Wunused-command-line-argument]
    [100%] Linking C executable fuzz_main
    [100%] Built target fuzz_main
  4. 获取编译完成后的文件。

    编译成功后开发者可以通过file命令查看文件的属性,以此判断交叉编译是否成功,如下信息显示libcjson.so为aarch64架构文件,即交叉编译成功:

    owner@ubuntu:/mnt/e/cmake/cJSON-1.7.18/cJSON/build$ file libcjson.so.1.7.18                     # 查看文件属性命令
    libcjson.so.1.7.18: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, BuildID[sha1]=a79e4b52a332702b4853f2d6cac2fcd7dff95023, with debug_info, not stripped
  5. 执行安装命令。编译成功后,执行make install将编译好的二进制文件以及头文件安装到cmake配置的安装路径下:
    owner@ubuntu:/mnt/e/cmake/cJSON-1.7.18/cJSON/build$ make install                                # 执行安装命令
    [  4%] Built target cjson
    [  8%] Built target cJSON_test
    ...
    # 省略部分make install信息
    ...
    -- Installing: /mnt/e/cmake/cJSON-1.7.18/cJSON/lib/cmake/cJSON/cJSONConfig.cmake
    -- Installing: /mnt/e/cmake/cJSON-1.7.18/cJSON/lib/cmake/cJSON/cJSONConfigVersion.cmake
    owner@ubuntu:/mnt/e/cmake/cJSON-1.7.18/cJSON/build$
    owner@ubuntu:/mnt/e/cmake/cJSON-1.7.18/build$ ls /mnt/e/cmake/cJSON-1.7.18/cJSON                # 查看安装文件
    include  lib
    owner@ubuntu:/mnt/e/cmake/cJSON-1.7.18/build$ ls /mnt/e/cmake/cJSON-1.7.18/cJSON/lib
    cmake  libcjson.so  libcjson.so.1  libcjson.so.1.7.18  pkgconfig

测试验证

交叉编译完后,需要对三方库进行测试验证。为保证三方库功能的完整性,需要基于原生库的测试用例进行测试验证。为此,需要集成一套可以在OH环境上进行make、cmake、 ctest等操作的工具,具体步骤如下:

  1. 搭建ohos测试环境:

    首先要明确需要的工具,如:camke、make、busybox、perl、shell_cmd等。

    • busybox:是一个Unix工具集合,其提供一系列的命令和工具,方便开发人员在资源受限的环境中进行系统配置和维护。
    • perl:是一种通用、直译式、动态的程序语言,具有强大的文本处理能力,适用于文本处理和各种编程任务。
    • shell_cmd:是用户向系统内核发出控制请求,与之交互的文本流,shell是一个命令行解释器,将用户命令解析为操作系统所能理解的指令,实现用户与操作系统的交互。

    下载工具源码并进行编译,将工具编译完成后生成的二进制文件拷贝到ohos设备,配置测试环境。

    1. 将工具包上传进ohos设备的/data目录。
      # 发送到ohos设备的/data目录
      hdc file send xxx\arm_cmake_make.tar.gz /data
      hdc file send xxx\arm_busybox.tar.gz /data
      hdc file send xxx\arm_perl.tar.gz /data
      hdc file send xxx\arm_shell_cmd.tar.gz /data 
    2. 进入ohos设备,手动配置环境。
      # 进入ohos设备命令行终端
      hdc shell
      # 根目录挂载 读写权限
      mount -o remount,rw /
      # 创建/usr目录
      mkdir /usr
      # 进入/data目录
      cd /data
      # 解压所有工具压缩包
      tar -zxvf *.tar.gz
      # 拷贝cmake make perl shell工具二进制到/usr目录
      cp -rf arm_cmake_make/* /usr
      cp -rf arm_perl/* /usr
      cp -rf arm_shell_cmd/* /usr
      # 验证
      cmake -version 
      make -v 
      perl -v
      # 拷贝busybox工具到/bin
      cp -rf arm_busybox/bin/busybox /bin
      # 将toybox替换为busybox
      cd /bin
      mv toybox toybox_bak
      # toybox被改为toybox_bak后, 导致原来的命令无法直接使. 需要采用"toybox_bak xxxcmd"的模式使用, 如下
      toybox_bak mv busybox toybox
      # 验证
      diff -v 
      # toybox原本是不支持diff命令,这里可以直接使用diff是因为toybox已经创建了diff的软连接, 但是toybox并没有真正实现. 因此替换为编译的busybox
      # 基本的环境搭建完成
  2. 准备测试资源。

    使用原生库的测试用例进行测试,为了保证测试时不进行编译操作,需要把整个编译的源码作为测试资源包推送到开发板,且需要保证三方库在开发板的路径与编译时路径一致。

    owner@ubuntu:/mnt/e/cmake$ tar -zcf cJSON-1.7.18.tar.gz cJSON-1.7.18/

    打包完资源后,需要将资源通过hdc命令推送到开发板:

    hdc file send xxx/cJSON-1.7.18.tar.gz /data/          # 推送资源到开发板
    hdc shell                                             # 进入开发板系统
    # mkdir -p /mnt/e                                     # 设置与编译时同样的路径
    # cd /mnt/e
    # ln -s /data/cJSON-1.7.18 ./cmake                    # 系统根目录空间有限,建议通过软链接配置路径
    # cd cmake
    # tar -zxf cJSON-1.7.18.tar.gz                        # 解压测试资源
  3. 执行测试。

    进入到cJSON的编译目录build,执行ctest测试命令进行测试:

    # cd xxx/cJSON-1.7.18/build
    # ctest                                                                    # 执行ctest测试命令,以下为测试信息
    Test project /data/cJSON-1.7.18/cJSON/build
    Start  1: cJSON_test
    1/19 Test  #1: cJSON_test .......................   Passed    0.02 sec
    Start  2: parse_examples
    2/19 Test  #2: parse_examples ...................   Passed    0.02 sec
    Start  3: parse_number
    3/19 Test  #3: parse_number .....................   Passed    0.02 sec
    Start  4: parse_hex4
    4/19 Test  #4: parse_hex4 .......................   Passed    0.10 sec
    Start  5: parse_string
    5/19 Test  #5: parse_string .....................   Passed    0.01 sec
    Start  6: parse_array
    6/19 Test  #6: parse_array ......................   Passed    0.01 sec
    Start  7: parse_object
    7/19 Test  #7: parse_object .....................   Passed    0.01 sec
    Start  8: parse_value
    8/19 Test  #8: parse_value ......................   Passed    0.01 sec
    Start  9: print_string
    9/19 Test  #9: print_string .....................   Passed    0.01 sec
    Start 10: print_number
    10/19 Test #10: print_number .....................   Passed    0.01 sec
    Start 11: print_array
    11/19 Test #11: print_array ......................   Passed    0.01 sec
    Start 12: print_object
    12/19 Test #12: print_object .....................   Passed    0.01 sec
    Start 13: print_value
    13/19 Test #13: print_value ......................   Passed    0.01 sec
    Start 14: misc_tests
    14/19 Test #14: misc_tests .......................   Passed    0.01 sec
    Start 15: parse_with_opts
    15/19 Test #15: parse_with_opts ..................   Passed    0.01 sec
    Start 16: compare_tests
    16/19 Test #16: compare_tests ....................   Passed    0.01 sec
    Start 17: cjson_add
    17/19 Test #17: cjson_add ........................   Passed    0.01 sec
    Start 18: readme_examples
    18/19 Test #18: readme_examples ..................   Passed    0.01 sec
    Start 19: minify_tests
    19/19 Test #19: minify_tests .....................   Passed    0.01 sec
    
    100% tests passed, 0 tests failed out of 19
    
    Total Test time (real) =   0.37 sec

    由以上测试结果可以看出,测试用例未出现错误,当前测试成功。

常见问题

执行ctest进行测试时,报如下错误:

解决措施

可能原因为三方库源码文件推送到开发板时的路径,与编译时的路径不一致导致。

推送路径和编译路径需要保持一致,或者参考测试流程,在文件推送到开发板后,通过配置软链接方式使路径保持一致,再执行ctest进行测试。

看完三件事❤️

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注作者 ,不定期分享原创知识。
  • 同时可以期待后续文章ing🚀。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值