文章目录
- 前言
- 生成动态链接库
- 样例项目说明
- 修改cmakelist
- 调用动态链接库
- 修改配置文件
- 修改原来外层的CMakeLists.txt
- 总结
前言
此前有写过用编译工具链直接通过命令行的方式生成与调用C++动态链接库的方法,本文记录下通过cmake来实现so的生成。
生成动态链接库
样例项目说明
以下笔者通过具体的开源项目代码进行演示。
通过以上项目的层级结构,我们可以看到有两个CMakeLists.txt。
其中外层CMakeLists.txt内容为:
# Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
# 最低CMake版本
cmake_minimum_required(VERSION 3.5.1)
# 项目名
project(HelmetIdentification)
# 配置环境变量MX_SDK_HOME,如:/home/xxxxxxx/MindX_SDK/mxVision,可在远程环境中用指令env查看
set(MX_SDK_HOME $ENV{MX_SDK_HOME})
if (NOT DEFINED ENV{MX_SDK_HOME})
set(MX_SDK_HOME "/usr/local/Ascend/mindx_sdk")
message(STATUS "set default MX_SDK_HOME: ${MX_SDK_HOME}")
else ()
message(STATUS "env MX_SDK_HOME: ${MX_SDK_HOME}")
endif()
add_subdirectory("./src")
src中的CMakeLists.txt内容为:
# CMake lowest version requirement
cmake_minimum_required(VERSION 3.5.1)
# project information
project(Individual)
# Compile options
add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0 -Dgoogle=mindxsdk_private)
add_compile_options(-std=c++11 -fPIC -fstack-protector-all -Wall -D_FORTIFY_SOURCE=2 -O2)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "../../")
set(CMAKE_CXX_FLAGS_DEBUG "-g")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,relro,-z,now,-z,noexecstack -s -pie -pthread")
set(CMAKE_SKIP_RPATH TRUE)
SET(CMAKE_BUILD_TYPE "Debug")
SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g2 -ggdb")
SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")
# Header path
include_directories(
${MX_SDK_HOME}/include/
${MX_SDK_HOME}/opensource/include/
${MX_SDK_HOME}/opensource/include/opencv4/
/home/HwHiAiUser/Ascend/ascend-toolkit/latest/include/
./
)
# add host lib path
link_directories(
${MX_SDK_HOME}/lib/
${MX_SDK_HOME}/lib/modelpostprocessors
${MX_SDK_HOME}/opensource/lib/
${MX_SDK_HOME}/opensource/lib64/
/usr/lib/aarch64-linux-gnu/
/home/HwHiAiUser/Ascend/ascend-toolkit/latest/lib64/
/usr/local/Ascend/driver/lib64/
./
)
aux_source_directory(. sourceList)
add_executable(main ${sourceList})
target_link_libraries(main mxbase opencv_world boost_filesystem glog avformat avcodec avutil cpprest yolov3postprocess ascendcl acl_dvpp_mpi)
install(TARGETS main DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
项目的主要目的是把src中的main.cpp文件编译成可执行文件输出到指定的地址。我们需要做的是把除main.cpp以外的文件编译成一个so,通过so来编译main.cpp,而不是通过源码的方式。(为了方便,我下面实现的时候把main.cpp也打包进了so)
修改cmakelist
src中的cmakelist,将原来:
aux_source_directory(. sourceList)
add_executable(main ${sourceList})
target_link_libraries(main mxbase opencv_world boost_filesystem glog avformat avcodec avutil cpprest yolov3postprocess ascendcl acl_dvpp_mpi)
install(TARGETS main DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
修改为:
aux_source_directory(. sourceList)
# add_executable(main ${sourceList})
add_library(ai_detection310 SHARED ${sourceList})
target_link_libraries(ai_detection310 mxbase opencv_world boost_filesystem glog avformat avcodec avutil cpprest yolov3postprocess ascendcl acl_dvpp_mpi)
install(TARGETS ai_detection310 DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
编译运行后将会得到ai_detection310.so
调用动态链接库
修改配置文件
将生成的ai_detection310.so
移动台指定的位置,为了方便我在原来的同级目录下,新建了test_so
的文件夹,把需要用的文件都复制了过来,结构如下:
其中test_so中的CMakeLists.txt为src中的文件的拷贝,然后再对test_so中的CMakeLists.txt进行修改:
将CMakeLists.txt中:
aux_source_directory(. sourceList)
# add_executable(main ${sourceList})
add_library(ai_detection310 SHARED ${sourceList})
target_link_libraries(ai_detection310 mxbase opencv_world boost_filesystem glog avformat avcodec avutil cpprest yolov3postprocess ascendcl acl_dvpp_mpi)
install(TARGETS ai_detection310 DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
修改为:
include_directories(${PROJECT_SOURCE_DIR}/include/)
message(STATUS "Include directories: ${PROJECT_SOURCE_DIR}")
add_executable(main ${PROJECT_SOURCE_DIR}/main.cpp)
target_link_libraries(main mxbase opencv_world boost_filesystem glog avformat avcodec avutil cpprest yolov3postprocess ascendcl acl_dvpp_mpi)
target_link_libraries(main ${PROJECT_SOURCE_DIR}/lib/libai_detection310.so)
install(TARGETS main DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
修改原来外层的CMakeLists.txt
将原来外层CMakeLists.txt中:
add_subdirectory("./src")
修改为:
add_subdirectory("./test_so")
编译运行后将会得到main的可执行文件。
总结
通过cmake进行so编译还是比较简单的,主要是用add_library(ai_detection310 SHARED ${sourceList})
生成so替换原来add_executable(main ${sourceList})
生成的可执行文件,然后对main.cpp进行配置,能够正确调用生成的so。这样我们就实现了通过cmakelist生成与调用C++动态链接库。
如果阅读本文对你有用,欢迎一键三连呀!!!
2024年5月14日16:25:40