HarmonyOS鸿蒙Next中子目录native模块怎么链接系统库?

HarmonyOS鸿蒙Next中子目录native模块怎么链接系统库? 根目录模块在链接例如libvulkan.zo库时,在键入库内对象时可以正常联想并补全,当移动模块至非根目录(例如features/)下时,应该如何设置并正常联想补全呢?
是否需要将外部库中对应的so库移动到模块的lib目录下?

15 回复

假设你这个A模块从项目根目录移动到个子目录,然后在A模块里编辑键入代码系统库的对象时,代码补全的功能失效了,对吧。

代码补全失效主要原因是,DevEco 的索引失效了或者配置未能正确同步。

首先通过清理工程和清缓存,重新索引试试。

cke_6386.png

如果问题还在,先验证下,在移动后子目录随便找个或建个ets 引用个ArkTS库测试下补全,这步确保补全功能好使。

功能好使,就再检查各个目录的oh-package.json5CMakeLists.txt,确保他们的配置和配置路径正确。如有修改再同步一下工程或清缓存重新索引。

如问题仍有,可以把你的工程框架和问题点截图发下,看看。

更多关于HarmonyOS鸿蒙Next中子目录native模块怎么链接系统库?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


嗯嗯,谢谢大佬指教🥰

请问下cmakelists中使用find_library检索库时,会自动包含sdk中包含的库目录嘛。

这个无法补全的问题是在win deveco中出现的,在鸿蒙版和mac版上没出现(clone下来建立索引后即可补全)🥲,而在win上重新索引后也还是无法补全,

找HarmonyOS工作还需要会Flutter的哦,有需要Flutter教程的可以学学大地老师的教程,很不错,B站免费学的哦:https://www.bilibili.com/video/BV1S4411E7LY/?p=17,

不过虽然不能补全,但是如果完整输入名称,还是能识别出对应的内容(可以ctrl+左键跳转到正确位置),

find_library会检索配置的库,SDK的库加载是IDE负责的。编译链的知识可就海了,可以慢慢学习,针对C/C++编译原理花两周认真研究,也能通透的,再去解决问题就知道哪里下手了。

那这个就是个例了,win 中IDE会卡吗?卡的话,可能是就电脑配置撑不起IDE了,用的时候可以看看电脑进程。

有用给个采纳:)

一般不需要把系统库的 .so 手动拷到你模块自己的 lib 目录里。

结论

对于 HarmonyOS/OpenHarmony 的 系统库

  • 子目录模块也可以正常链接
  • 关键不是“模块在不在根目录”,而是:
    • 这个模块本身有没有正确配置 CMakeLists.txt
    • DevEco 有没有把这个模块识别成一个 native 构建单元
    • 你的头文件/库搜索路径是不是还写死成了“根目录相对路径”

先说你这个现象的本质

你说:

  • 根目录模块里链接 libvulkan.so 时,可以正常联想补全
  • 挪到 features/ 下后,不正常了

这通常说明不是 Vulkan 库本身的问题,而是下面几类问题之一:

  1. 模块自己的 CMakeLists.txt 没被正确接入
  2. build-profile.json5 / 模块配置没有声明 native 构建
  3. 原来写的相对路径在子目录下失效了
  4. IDE 的代码补全依赖的头文件路径没有跟着更新
  5. 你引用的是外部库头文件,不是系统库头文件,但路径仍按根目录写法

系统库怎么链接

如果是系统库,比如:

  • libvulkan.so
  • libEGL.so
  • libGLESv3.so
  • libhilog_ndk.z.so
  • libace_ndk.z.so

通常做法是直接在模块自己的 CMakeLists.txt 里链接,不需要复制系统库文件。

例如:

target_link_libraries(your_target PUBLIC libvulkan.so)

或者常见写法:

target_link_libraries(your_target PUBLIC
    libhilog_ndk.z.so
    libace_ndk.z.so
    libvulkan.so
)

这里的前提是:

  • 这个模块本身已经被 DevEco/NDK 正确识别并参与构建
  • 使用的是 SDK/NDK 提供的系统桩库

子目录模块要重点检查什么

1. 模块自己的 build-profile.json5

要确认这个 features/xxx 模块本身有 native 构建配置。

例如要有类似:

{
  "buildOption": {
    "externalNativeOptions": {
      "path": "./src/main/cpp/CMakeLists.txt"
    }
  }
}

如果这个配置只在根模块里有,子模块没有,那 IDE 往往不会正确给你做 native 解析和补全。

2. 模块自己的 CMakeLists.txt

子模块应该有自己独立的 CMakeLists.txt,不要继续依赖根模块那一份的相对路径逻辑。

3. 不要写死根目录相对路径

很多人从根模块搬到 features/ 后,问题出在这里。

比如原来这么写:

include_directories(../../../../somepath/include)

模块位置一变,这种路径就错了。

更稳妥的写法是尽量基于:

  • ${CMAKE_CURRENT_SOURCE_DIR}
  • ${CMAKE_CURRENT_LIST_DIR}

例如:

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)

或者引第三方库头文件:

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/include)

这样你至少知道路径是相对“当前模块的 CMake 文件”算的。

为什么“联想补全”会失效

IDE 补全主要依赖两类东西:

  1. 头文件路径
  2. 当前 target 的编译配置

不是靠你有没有把 .so 拷到 lib/ 目录来补全的。

也就是说:

  • 补全正常,通常说明头文件路径和 native target 配好了
  • 补全失效,通常说明 IDE 没拿到这个子模块的 C/C++ 编译信息

所以你要查的是:

  • 这个子模块的 native target 有没有被构建系统识别
  • 头文件 include path 是否正确
  • CMakeLists.txt 是否实际参与同步

而不是先去拷系统 .so

什么时候才需要把 .so 放到模块里

只有在链接的是第三方预编译库时,才通常需要自己管理:

  • 头文件放到某个 include/
  • 预编译 .so 放到例如 libs/arm64-v8a/
  • 用 add_library(... SHARED IMPORTED) + set_target_properties(...)
  • 再 target_link_libraries(...)

例如第三方库才会这样:

add_library(thirdparty SHARED IMPORTED)
set_target_properties(thirdparty PROPERTIES
    IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/libs/arm64-v8a/libthirdparty.so
)

target_link_libraries(your_target PUBLIC thirdparty)

系统库不是这个思路

对你这个问题的直接回答

是否需要将外部库中对应的 so 库移动到模块的 lib 目录下?

  • 系统库:不需要
  • 第三方预编译库:通常需要自己管理路径,但也不一定非得叫 lib 目录,只要 CMake 配对即可

子目录 native 模块应该如何设置并正常联想补全?

重点做这几件事:

  1. 给子模块单独配置 externalNativeOptions
  2. 确保子模块有自己的 CMakeLists.txt
  3. 修正所有相对路径,避免继续按根目录写法
  4. 系统库直接 target_link_libraries(...)
  5. 头文件路径用 include_directories(...) 或 target_include_directories(...)
  6. 重新 Sync / Rebuild,让 IDE 重新生成 native 索引

更推荐的写法

比起全局 include_directories,更建议:

target_include_directories(your_target PUBLIC
    ${CMAKE_CURRENT_SOURCE_DIR}/include
)

然后:

target_link_libraries(your_target PUBLIC
    libhilog_ndk.z.so
    libace_ndk.z.so
    libvulkan.so
)

这样 target 级别更清晰,搬模块时也更不容易坏。

如果你现在就要排查

你可以按这个顺序看:

  1. features/xxx/build-profile.json5 里有没有 native 配置
  2. features/xxx/src/main/cpp/CMakeLists.txt 是否真实生效
  3. #include <vulkan/vulkan.h> 能不能跳转
  4. target_link_libraries 写的是不是系统库名
  5. 是否还残留根模块时代的相对路径
  6. Sync Project / Clean / Rebuild 后是否恢复补全

最后给你一个判断标准

如果你遇到的是:

  • #include <vulkan/vulkan.h> 都不补全
    那多半是头文件路径/模块 native 配置问题

如果你遇到的是:

  • 头文件能补全,但链接时报找不到符号
    那多半是**target_link_libraries 问题**

find_library 在 DevEco/Hvigor 注入的 OHOS CMake toolchain 下,会基于当前 SDK/NDK 的 sysroot 和目标架构去找系统库,一般不需要把 openharmony/hms 下的系统 so 再手工拷贝到模块目录。你可以在 CMakeLists 里打印 CMAKE_SYSROOT、CMAKE_FIND_ROOT_PATH、OHOS_ARCH 等变量确认实际搜索路径。现在“完整输入能识别、Ctrl+左键能跳转,但 Windows 版不能补全”,更像 IDE 索引/语言服务问题,不是链接配置问题。建议先以编译和链接结果为准;Win 端可尝试删除 .cxx、.hvigor、.idea 缓存后重新 Sync/Index。

嗯嗯,感谢🙏一会儿我去尝试下这些方法☺,

系统库不需要拷到模块的 libs 目录,关键是子目录 native 模块的 CMakeLists.txt 路径基准变了。建议用 CMAKE_CURRENT_SOURCE_DIR 固定当前模块根路径,再配置 include 路径和 target_link_libraries。系统库按 SDK 实际库名直接链接,例如 libace_napi.z.so、libhilog_ndk.z.so;三方 so 才放到 libs/<abi> 并用相对当前 CMakeLists.txt 的路径引用。移动到 features/ 后重点检查 CMake 是否被构建配置引用、include 路径是否指向新模块、库名是否写对。

是不是find_library会包含对sdk目录的库搜索啊,

不要把 libvulkan.so 复制到你的 jniLibs /lib 目录,复制会导致:冲突、上架被拒、版本不兼容、崩溃等问题。

系统库是手机系统自带的,你只需要在 CMakeLists.txt 里正确配置路径即可

cmake_minimum_required(VERSION 3.10)

include_directories(${OHOS_SDK_ROOT}/sysroot/usr/include)
link_directories(${OHOS_SDK_ROOT}/sysroot/usr/lib/${OHOS_ARCH})

# 你的库
add_library(my_native_lib SHARED my.cpp)

# 查找系统库
find_library(log-lib log)
find_library(vulkan-lib vulkan)

# 链接
target_link_libraries(
        my_native_lib
        ${log-lib}
        ${vulkan-lib}
)

你好,请问这里的ohos_sdk_root是包含了 openharmony 和 hms 两个库目录的嘛,是否需要单独添加一遍 openharmony的库路径?
在deveco的外部库中看,像是vulkan.so是在前者的lib目录下的。

我尝试了向cmake中添加库和头文件路径,但是仍然无法自动联想补全🥲,

但是完整输入后,是能正确c+左键指向到对应头文件位置的,是否是需要添加什么额外设置?🥹,

在 HarmonyOS Next 的 native 模块中,通过 CMakeLists.txttarget_link_libraries 指令直接指定系统库名称(如 hilog_ndkace_napi)。系统库路径已预置,无需额外配置。若使用 BUILD.gn,在 deps 中引用对应 ohos_shared_library 目标即可。

系统库无需移动so到模块目录。

非根目录下无法联想补全,通常是因为IDE没有正确解析到C API的声明头文件。你需要做的是在子模块的构建配置中,明确添加系统库的头文件路径。

如果使用oh-package.json5管理的C API: 确保子模块的oh-package.json5native字段正确配置了依赖的外部C API,IDE会自动解析其头文件。写法如下:

{
  "name": "子模块名",
  "dependencies": {
    "@ohos/vulkan": "file:../../libs/vulkan"
  }
}

如果直接使用CMakeLists.txt: 在子模块的CMakeLists.txt中使用target_include_directories,显式添加对应系统库SDK的头文件路径。以libvulkan为例:

target_include_directories(你的库名 PUBLIC
    ${OHOS_SDK}/native/sysroot/usr/include
    ${OHOS_SDK}/native/sysroot/usr/include/vulkan
)

其中${OHOS_SDK}是DevEco Studio内置的宏,指向当前HarmonyOS SDK路径。

这样配置后,IDE的索引服务就能找到声明,恢复代码补全。

回到顶部