[触觉智能RK3568]OpenHarmony NDK工具(上)

系统 OpenHarmony
NDK (原生开发套件) 是一套工具,使开发者能够在 OpenHarmony hap应用中使用 C/C++ 代码。

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

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

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

在OpenHarmony应用开发中选择Native C ++开发方式需要使用OpenHarmony NDK工具,或者想移植一个C/C ++的三方库到OpenHarmony中也可以使用NDK。NDK使用到的编译工具是cmake,也就是CMakeLists.txt那一套。Native C ++应用开发方式可以做直接编译三方库的so库再利用NAPI框架实现能力的调用(只需要在三方库原生的CMakeLists.txt中修改小部分的内容就可以实现)。

一、OpenHarmony NDK

  • NDK (原生开发套件) 是一套工具,使开发者能够在 OpenHarmony hap应用中使用 C/C++ 代码。
  • NDK提供了一系列的工具可以帮助开发者快速的开发C/C++的动态库、静态库和可执行文件。
  • OpenHarmony 应用开发的​​Native C++​​​开发方式就要依赖NDK。NDK被包含在OpenHarmony SDK中。可以在​​DevEco Studio​​​使用 NDK 将 C/C ++ 代码编译到so库中,然后使用 DevEco Studio 的构建插件​​hvigor-ohos-plugin​​​将so库打包到 Hap 中。ArkTS代码随后可以通过​​NAPI框架​​调用SO库中的函数。

二、获取NDK的方式

1、从每日构建中获取

每日构建地址: http://ci.openharmony.cn/dailys/dailybuilds。

组件形态选择ohos-sdk,版本选择最新版本的sdk一般是没有问题的(但是笔者之前遇到下载的ndk中的clang工具找不到libatomic.so无法工作的情况的情况)。

下载解压后可以得到如下文件,根据linux或者windows端解压不同文件得到sdk。

2、编译源码得到SDK中的NDK

安装依赖
./build/build_scripts/env_setup.sh

执行完上述命令后记得执行source ~/.bashrc或者重启终端
source ~/.bashrc

安装编译SDK需要的依赖包(编译镜像的时候是不依赖这些包的)
sudo apt-get install libxcursor-dev libxrandr-dev libxinerama-dev

./build.sh --product-name ohos-sdk --ccache --build-target ohos_ndk

写文章提的issue https://gitee.com/openharmony/build/issues/I6H8IO?from=project-issue

  • 在对应的目录底下找到编译成功的NDK,相关路径out/sdk/packages/ohos-sdk/linux/native,根据linux或者windows端解压不同文件得到sdk

 #创作者激励#[触觉智能RK3568]OpenHarmony NDK工具(上)-开源基础软件社区

二、NDK目录

native
├── NOTICE.txt 声明文件
├── build
└── cmake
├── ohos.toolchain.cmake ---->编译的工具链
└── sdk_native_platforms.cmake ---->编译的工具链(在DevEco Studio中编译打包so要用到)
├── build-tools ---->cmake编译工具所在目录(NDK提供的编译工具)
├── llvm ---->编译器所在目录(NDK提供的编译工具)
├── sysroot ---->编译器的 sysroot 目录,存放 SDK 内部的已经包含的库和对应的头文件
├── ndk_system_capability.json ---->NDK自带so库能力描述文件
├── nativeapi_syscap_config.json ---->调用NDK自带so库能力相关头文件
├── docs ---->调用NDK自带so库能力相关文档
└── oh-uni-package.json ---->SDK 信息描述
  • llvm中bin目录下的编译器有。
FileCheck    clang-format      ld64.lld        lldb-vscode      llvm-cxxfilt     llvm-objdump   llvm-strip       yaml2obj
clang clang-tidy lld llvm-addr2line llvm-dis llvm-profdata llvm-symbolizer
clang++ clangd lld-link llvm-ar llvm-lib llvm-ranlib not
clang-12 count lldb llvm-as llvm-link llvm-readelf sancov
clang-check dsymutil lldb-argdumper llvm-cfi-verify llvm-modextract llvm-readobj sanstats
clang-cl git-clang-format lldb-mi llvm-config llvm-nm llvm-size scan-build
clang-cpp ld.lld lldb-server llvm-cov llvm-objcopy llvm-strings scan-view

三、linux下使用NDK编译库文件和可执行文件

1、使用NDK编译一个简单demo

shared-library            
├── CMakeLists.txt 外部CMakeLists.txt
├── include 头文件目录
└── shared
└── Hello.h
└── src 源文件目录
├── CMakeLists.txt 内部CMakeLists.txt
├── Hello.cpp
└── main.cpp
  • 外部CMakeLists.txt
#cmake的版本
CMAKE_MINIMUM_REQUIRED(VERSION 3.16)
#工程名称
PROJECT(HELLO_LIBRARY)
#添加一个子目录并构建该子目录
ADD_SUBDIRECTORY(src)

cmake的内置命令是不区分大小写的,因此add_subdirectory与ADD_SUBDIRECTORY作用一致。但是cmake的所有变量都是区分大小写的

  • 内部CMakeLists.txt
#设置可执行文件输出路径
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/output)
# 设置so库文件输出路径
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/output)

############################################################
# Create a library
############################################################

#SHARED表示生成的是动态库,动态库的名字是hello_shared_library。生成动态库的源文件是Hello.cpp
ADD_LIBRARY(hello_shared_library SHARED
Hello.cpp
)
#为生成的动态库添加一个别名,后续hello::library可使用来替代hello_shared_library
ADD_LIBRARY(hello::library ALIAS hello_shared_library)

#为指定目标hello_shared_library添加头文件搜索路径(这个指定目标决不能是alias target,也就是指定的别名hello::library)
TARGET_INCLUDE_DIRECTORIES(hello_shared_library
PUBLIC
${PROJECT_SOURCE_DIR}/include
)

############################################################
# Create an executable
############################################################

# 使用指定的源文件main.cpp创建出一个可执行文件hello_shared_binary
ADD_EXECUTABLE(hello_shared_binary
main.cpp
)

#TARGET_LINK_LIBRARIES指令的作用为将目标文件与库文件进行链接
#将可执行文件hello_shared_binary与库文件hello::library进行链接
TARGET_LINK_LIBRARIES( hello_shared_binary
PRIVATE
hello::library
)

3、进行cmake编译

(1)NDK自带的cmake编译工具添加到环境变量

1、第一种方法:

#将其临时加入环境变量中(适用于临时想用用NDK)
export PATH=$PATH:/ohos-sdk/linux/native/build-tools/cmake/bin(你自己解压的NDK目录)

2、第二种方法:

#将其永远加入环境变量中
#打开.bashrc文件
vim ~/.bashrc
#在文件最后添加cmake路径,该路径是自己的放置文件的路径,之后保存退出
export PATH=/ohos-sdk/linux/native/build-tools/cmake/bin:$PATH
#在命令行执行source ~/.bashrc使环境变量生效
source ~/.bashrc

3、查看环境变量添加是否成功。

cmake -version

 #创作者激励#[触觉智能RK3568]OpenHarmony NDK工具(上)-开源基础软件社区

可知cmake的版本是3.16.5 ,所以编写CMakeLists.txt可参考的链接为 https://cmake.org/cmake/help/v3.16/guide/tutorial/

(2)安装make

如果没有安装make会出现以下报错,则执行sudo apt-get install make。(如果已经安装make,请忽略)。

(3)cmake的几个参数

1、OHOS_STL参数,其类型可以是c++_shared和c++_static,默认是c++_shared。

 #创作者激励#[触觉智能RK3568]OpenHarmony NDK工具(上)-开源基础软件社区

2、OHOS_ARCH参数(设置应用程序二进制接口ABI),其类型是armeabi-v7a、x86_64 ,默认值是arm64-v8a。每一种ABI定义了相应的二进制文件。

  • armeabi-v7a (选择这个是编译32位的二进制文件)。
  • arm64-v8a (选择这个是编译64位的二进制文件)。
  • x86_64 (现在不使用,OpenHarmony现在在适配x86的芯片)。

3、OHOS_PLATFORM参数,其类型为OHOS(只能选择OHOS平台)。

4、 CMAKE_TOOLCHAIN_FILE参数指向的是工具链文件所在的位置,就是ohos.toolchain.cmake的路径(对于编译不同平台二进制文件是很重要的)。

  • build目录中的工具链文件ohos.toolchain.cmake,cmake编译时需要读取该文件中的默认值,比如编译器的选择、编译平台,例如ohos.toolchain.cmake文件中,
# Common default settings
39:if(NOT DEFINED OHOS_PLATFORM_LEVEL)
set(OHOS_PLATFORM_LEVEL 1)
endif()
43:if(NOT DEFINED OHOS_TOOLCHAIN)
set(OHOS_TOOLCHAIN clang)
endif()
47:if(NOT DEFINED OHOS_STL)
set(OHOS_STL c++_shared)
endif()
51:if(NOT DEFINED OHOS_PIE)
set(OHOS_PIE TRUE)
endif()
55:if(NOT DEFINED OHOS_ARM_NEON)
set(OHOS_ARM_NEON thumb)
endif()
60:if(NOT DEFINED OHOS_ARCH)
set(OHOS_ARCH arm64-v8a)
endif()
  • 在编译时需要指出该文件的所在路径,以便于cmake在编译时定位到该文件。在编译的时候需要为cmake指定参数来控制编译目标的属性。

(4)使用CMake进行构建,并传递工具链文件及cmake参数

# dmeo目录下创建build目录,用来放置cmake构建时产生的中间文件。
mkdir build && cd build

# 传递OHOS_STL(可选,默认就是c++_shared)、OHOS_ARCH、OHOS_PLATFORM、工具链文件
# CMAKE_TOOLCHAIN_FILE是ohos.toolchain.cmake具体放置的路径
# 这一步会检查CMakeLists.txt是否有语法错误
# 不要忘记在ohos.toolchain.cmake路径后面加上 ..
cmake -D OHOS_STL=c++_shared -D OHOS_ARCH=armeabi-v7a -D OHOS_PLATFORM=OHOS -D CMAKE_TOOLCHAIN_FILE=/xxx/build/cmake/ohos.toolchain.cmake ..

cmake --build .

1、执行如下过程如下:

 #创作者激励#[触觉智能RK3568]OpenHarmony NDK工具(上)-开源基础软件社区

2、可以注意到执行cmake --build .时会有warning: -Wunused-command-line-argument,通过在内部的CMakeLists.txt中添加如下语句消除warning。

set(CMAKE_CXX_FLAGS "-Wno-unused-command-line-argument")

 #创作者激励#[触觉智能RK3568]OpenHarmony NDK工具(上)-开源基础软件社区

  • 注意:.c文件时是使用CMAKE_C_FLAGS,.cpp文件时是使用CMAKE_CXX_FLAGS。

3、编译结果如下:

生成可执行文件和动态库。

 #创作者激励#[触觉智能RK3568]OpenHarmony NDK工具(上)-开源基础软件社区

4、要编译静态库及其可执行文件,内部的CMakeLists.txt中添加如下语句

############################################################
# Create a library
############################################################

#Generate the static library from the library sources
ADD_LIBRARY(hello_static_library STATIC
Hello.cpp
)

TARGET_INCLUDE_DIRECTORIES(hello_static_library
PUBLIC
${PROJECT_SOURCE_DIR}/include
)

############################################################
# Create an executable
############################################################

# Add an executable with the above sources
ADD_EXECUTABLE(hello_static_binary
main.cpp
)

# link the new hello_library target with the hello_binary target
TARGET_LINK_LIBRARIES( hello_static_binary
PRIVATE
hello_static_library
)

编译结果如下,生成静态库及其可执行文件。

 #创作者激励#[触觉智能RK3568]OpenHarmony NDK工具(上)-开源基础软件社区

5、编译64位的库文件和可执行文件,OHOS_ARCH参数选择arm64-v8a或者编译时不传递该参数。

(5)使用CMake进行构建,选择ninja生成器并生成编译流程图

1、执行cmake -G查看linux环境下的生成器,ndk中自带的生成器是Ninja。

 #创作者激励#[触觉智能RK3568]OpenHarmony NDK工具(上)-开源基础软件社区

2、使用CMake进行构建时添加上-G “Ninja”。

 #创作者激励#[触觉智能RK3568]OpenHarmony NDK工具(上)-开源基础软件社区

第一步:mkdir build && cd build

第二步:cmake -G "Ninja" -D OHOS_STL=c++_shared -D OHOS_ARCH=armeabi-v7a -D OHOS_PLATFORM=OHOS -D CMAKE_TOOLCHAIN_FILE=/xxx/build/cmake/ohos.toolchain.cmake ..

第三步:cmake --build .或者ninja -f build.ninja

执行完第二步后,build目录下会生成build.ninja,有了build.ninja可以使用ninja生成程序的编译流程图。

3、使用ninja工具生成库文件和可执行文件的编译流程图。

# 将libhello_shared_library.so动态库的编译流程转为dot
ninja -t graph libhello_shared_library.so > xxx.dot

# 将dot格式转化为png格式的流程图
dot -T png xxx.dot -o libhello_shared_library.so.png
# 将dot格式转化为svg格式的流程图
dot -T svg xxx.dot -o libhello_shared_library.so.svg

 #创作者激励#[触觉智能RK3568]OpenHarmony NDK工具(上)-开源基础软件社区

如果生成图片格式太小的话,可以生成svg格式到浏览器打开,这一点很重要,请参考该 issue

(6)使用NDK中的cmake-gui进行图形化操作编译

1、native/build-tools/cmake/bin目录有cmake-gui,可以用它图形化传入编译参数进行编译。

 #创作者激励#[触觉智能RK3568]OpenHarmony NDK工具(上)-开源基础软件社区

2、首先点击Where is source code行的Browser Source,加载工程所在目录。再点击Where to build the binarys行的Browser Source,加载点击“Where is source code”行的Browser Source,加载源码所在目录。点击“Where to build the binarys行的Browser Source,加载工程所在目录下的build目录(没有就创建一个)。

3、点击Add Entry传入cmake 参数。勾选把旁边的Grouped选项。

 #创作者激励#[触觉智能RK3568]OpenHarmony NDK工具(上)-开源基础软件社区

4、点击Configure选择Current Generator生成器为Unix Makefiles。

5、最后打开Where to build the binarys加载构建目录终端,执行make -j 8命令。

make -j n含义是 让make最多允许n个编译命令同时执行,这样可以更有效的利用CPU资源。假设系统cpu是12核,在不影响其他工作的情况下,我们可以make -j 12将cpu资源充分利用起来,一般来说,最大并行任务数为cpu_num * 2。

 #创作者激励#[触觉智能RK3568]OpenHarmony NDK工具(上)-开源基础软件社区

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

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

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

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

2023-03-16 15:37:48

像素密度触觉智能

2023-03-03 21:36:02

鸿蒙操作系统

2022-04-25 09:10:50

RK3568鸿蒙

2023-02-10 15:34:45

Node.jsN-API组件

2023-03-07 15:54:45

鸿蒙Mesa库

2023-03-13 11:58:03

拓扑架构模块

2023-08-18 14:34:09

HDF驱动框架

2023-11-24 09:48:29

C++鸿蒙

2023-08-08 14:26:59

开源开发板鸿蒙

2021-09-08 15:23:51

鸿蒙HarmonyOS应用

2023-05-15 15:27:20

鸿蒙智能开发套件

2023-05-26 16:01:32

驱动开发鸿蒙

2023-05-08 15:48:13

智能音箱鸿蒙

2022-05-23 10:45:34

DAYU200鸿蒙

2022-03-17 15:55:19

播放数字音频解码鸿蒙

2022-01-26 15:07:04

bytrace工具OpenHarmon

2024-03-04 15:06:38

鸿蒙智能教室应用开发

2023-02-20 15:29:14

分布式相机鸿蒙

2023-01-13 16:54:38

2022-10-08 16:19:40

智能喂食器鸿蒙
点赞
收藏

51CTO技术栈公众号