【CMakeLists.txt生成链接第三方动态链接库的用法】

一. 使用find_package链接

如果 CMake 通过find_package找到一个包,它会自动创建几个CMake的环境变量,包括以下:
- <NAME>_FOUND, 如果找到该值为true,否则为false.
- <NAME>_INCLUDE_DIRS 或 <NAME>_INCLUDES, 包导出的包含路径.
- <NAME>_LIBRARIES 或 <NAME>_LIBS, 包导出的库

所以,只有使用find_package时,才能使用 ${<NAME>_INCLUDE_DIRS},或者 ${<NAME>_LIBRARIES} 这种变量.

示例:以OpenCV库为例

find_package(OpenCV REQUIRED)

# OpenCV_INCLUDE_DIRS 是由于使用了find_package命令,CMake就会自动定义该变量,该变量代表OpenCV库的头文件夹路径
include_directories(${OpenCV_INCLUDE_DIRS})

# OpendCV_LIBS 来源同上,该变量代表了 OpenCV库的库文件路径, 注意,这里不是文件夹三个字。
target_link_libraries(MY_TARGET_NAME ${OpenCV_LIBS})

find_package的优点是可以批量引入, 由于库的头文件路径 或者库文件路径不止一个,但是find_package可以将多个头文件路径整合为 <NAME>_INCLUDE_DIRS, 将多个库文件路径整合为 <NAME>_LIBRARIES

缺点是:有些库直接没有配置cmake,使用find_package命令会找不到。

二. 直接设置头文件和库文件的路径

关于include:

CMakeLists引入头文件的方式只有include_directories()指令。
区别是: 如果使用find_package命令,就会有 <NAME>_INCLUDE_DIRS 直接放include_directories()就行了。
而直接设置头文件的方式,需要你自己知道头文件在哪个位置。
(1)如果你直接将头文件放在 工程内 CMakeLists同级目录的include文件夹下
include_directories(include)  即可。

(2)如果你将头文件放在 工程内 CMakeLists同级目录的lib文件夹下, 第三方包命名,include下
include_directories(${PROJECT_SOURCE_DIR}/lib/第三方包命名/include)

(3)如果你将头文件放在 工程外 某个目录下,就需要使用绝对路径写全
include_directories(/opt/ros/foxy/include)

(4)如果你直接将第三方包,通过 make install命令安装在系统中了,比如/usr/include, 就不需要配置了

链接第三方库的用法:

如果使用 find_package命令,就会有 <NAME>_LIBRARIES 直接放在 target_link_libraries()就行了

而直接设置库文件的方式,需要你自己知道库文件在哪个位置。
link_directories() 将库文件所在文件夹加载进 CMakeLists.txt 工程
target_link_libraries() 指定具体哪个库文件,链接进编译工程

三、生成动态链接库到本地lib文件夹内

# 生成动态链接库
add_library(canHandle SHARED src/localization.cpp src/Dbc.cpp src/CanIO.cpp)

# 指定动态链接库的生成路径为本地lib文件夹内
set_target_properties(canHandle PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib)

四、本地lib文件夹内的动态链接库如果想被链接,编译

# 编译指令
link_directories(lib)
add_executable(${PROJECT_NAME} src/main.cpp )
target_link_libraries(${PROJECT_NAME} ${PROJECT_SOURCE_DIR}/lib/libcanHandle.so yaml-cpp ${rclcpp_LIBRARIES} ${sensor_msgs_LIBRARIES} ${interfaces_LIBRARIES})

针对(二)的示例:

  1. 首先声明我要链接哪个文件夹内的库

    link_directories(lib) # 本地lib文件夹内有动态链接库需要链接

  2. 使用 target_link_libraries() 指令将动态库链接到可执行文件,本以为 link_directories 已经设置了链接路径,动态库直接输名就可以了。测试发现,动态库需要完整的路径才能链接到。

    target_link_libraries( ${PROJECT_SOURCE_DIR}/lib/libcanHandle.so )

    ${PROJECT_SOURCE_DIR} 表示 当前工程目录绝对路径。

  3. 此处 libcanHandle.so只有一个文件,写起来较简单,但是对于很多第三方库,会生成多个so文件,需要一一链接,比较繁琐。所以,推荐使用find_package的方式,就会有<NAME>_LIBRARIES变量。

五、CMakeLists.txt安装

如果想使用 ros2 run localization localization 指令启动可执行文件,需要将so库安装到install文件夹内的lib文件夹。

安装库的语句

# 为了ros2启动,需要将so库安装到install里的lib文件夹下
install(FILES lib/libcanHandle.so
	DESTINATION lib
)

安装可执行文件的语句

install(TARGETS
  nav2_costmap_2d
  nav2_costmap_2d_markers
  nav2_costmap_2d_cloud
  RUNTIME DESTINATION lib/${PROJECT_NAME}
)

安装头文件的语句

install(DIRECTORY include/
  DESTINATION include/
)

安装其他文件的语句

install(FILES costmap_plugins.xml
  DESTINATION share/${PROJECT_NAME}
)

安装launch文件的语句

install(
  DIRECTORY include launch params
  DESTINATION share/${PROJECT_NAME}
)

六、动态链接库的使用

1. 动态链接库既需要在编译生成可执行文件时,被链接,作用类似于库的实现cpp文件;

不然会报错,下面错误:

undefined reference to `rosidl_message_type_support_t const* rosidl_typesupport_cpp::get_message_type_support_handle<std_msgs::msg::UInt32_<std::allocator<void> > >()'

某个函数未被定义的引用。

2. 动态链接库也需要程序运行时,被动态加载,也就是这些so库确保位于${LD_LIBRARY_PATH} 里的路径中;

不然会报错,下面错误:

error while loading shared libraries: libcanHandle.so: cannot open shared object file: No such file or directory.
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CMakeLists.txt可以通过定义变量INC_DIR和LINK_DIR来加载第三方。INC_DIR用来指定头文件路径,而LINK_DIR用来指定的路径。在CMakeLists.txt中,可以使用include_directories命令将INC_DIR添加到头文件搜索路径中,使用link_directories命令将LINK_DIR添加到的搜索路径中。这样就可以在项目中使用第三方了。如果需要生成自己的,需要在CMakeLists.txt中导入第三方的具体步骤如下:首先,使用find_package命令找到需要的,例如find_package(wfdb REQUIRED)。然后,使用include_directories命令将找到的的头文件路径添加到头文件搜索路径中。接下来,使用target_link_libraries命令将找到的链接到目标或可执行文件中,例如target_link_libraries(mylibrary wfdb)。最后,使用add_library命令生成自己的,例如add_library(mylibrary SHARED mylibrary.cpp)。这样就完成了CMakeLists.txt加载第三方的过程。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [C++版本使用CMakeLists.txt编译(同目录多个源文件)可执行文件](https://download.csdn.net/download/Zhangyanfeng1/12603209)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [使用CMake导入第三方](https://blog.csdn.net/alan711/article/details/86248612)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值