ROS1、ROS2如何把预编译好的二进制文件封装成功能包?
当我们编译一个第三方功能包的时候,会通过cmake指令,将源码编译好,并通过make install安装到系统目录下。
如果希望预编译好的二进制文件,封装成一个ros的功能包,该怎么做呢?
本文要求你掌握Cmake和ROS1、ROS2的基础,涉及到的细节操作这里不做介绍,只介绍核心操作步骤。
第一步,先找到编译好的二进制文件和头文件
假如我们的库名叫xxx,那么make install后,头文件会放在/usr/local/include/xxx/下;而.so则会放在/usr/local/lib/下,例如/usr/local/lib/libxxx.so。
第二步,创建ros功能包(以ROS2为例)
ros2 pkg create xxx --build-type ament_cmake
第三步,将第一步找到的头文件和.so文件,挪到你创建的功能包下
此处自行操作。可以把头文件的内容放到功能包的include目录下,相关的lib文件,放到libamd64 或 libarm64 目录下。
第四步,修改CmakeLists(核心):
cmake_minimum_required(VERSION 3.8)
project(xxx)if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")add_compile_options(-Wall -Wextra -Wpedantic)
endif()find_package(ament_cmake REQUIRED)if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")set(LIB_PATH "libarm64") # ARM架构
else()set(LIB_PATH "libamd64") # x86_64架构
endif()
# 收集所有动态库文件(包括带版本号的文件)
file(GLOB LIBRARY_FILES "${CMAKE_CURRENT_SOURCE_DIR}/${LIB_PATH}/*.so*")# 过滤掉符号链接,只保留真实文件
set(REAL_LIBS "")
foreach(file IN LISTS LIBRARY_FILES)if(NOT IS_SYMLINK ${file})list(APPEND REAL_LIBS ${file})endif()
endforeach()# 为每个真实库文件创建 IMPORTED 目标
set(ALL_IMPORTED_LIBS "")
foreach(lib_file IN LISTS REAL_LIBS)get_filename_component(lib_name ${lib_file} NAME)# 生成唯一的目标名称(例如:libxxx.so.3.7 → xxx_so_3_7)string(REGEX REPLACE "^lib" "" base_name ${lib_name}) # 移除前缀 "lib"string(REGEX REPLACE "[.]" "_" target_name ${base_name}) # 替换 "." 为 "_"# 创建 IMPORTED 目标add_library(${target_name} SHARED IMPORTED)set_target_properties(${target_name} PROPERTIESIMPORTED_LOCATION ${lib_file} # 指向真实文件路径)# 将目标名称加入列表,用于后续导出list(APPEND ALL_IMPORTED_LIBS ${target_name})
endforeach()# 安装头文件和库文件
install(DIRECTORY include/ DESTINATION include)
install(FILES ${REAL_LIBS} DESTINATION lib) # 安装真实文件而非符号链接ament_export_include_directories(include)
ament_export_libraries(${ALL_IMPORTED_LIBS}) # 导出所有 IMPORTED 目标if(BUILD_TESTING)find_package(ament_lint_auto REQUIRED)# the following line skips the linter which checks for copyrights# comment the line when a copyright and license is added to all source filesset(ament_cmake_copyright_FOUND TRUE)# the following line skips cpplint (only works in a git repo)# comment the line when this package is in a git repo and when# a copyright and license is added to all source filesset(ament_cmake_cpplint_FOUND TRUE)ament_lint_auto_find_test_dependencies()
endif()ament_package()
这里有两点核心:
1.通过for指令,反复使用add_library 和 set_target_propeties,把你文件夹下的二进制文件打成一个library。
2.通过ament_export相关指令,导出这些内容,使得其他功能包可以正常使用。当然,如果你用的是ROS1的caktin编译系统,则换成catkin_package系列指令:
catkin_package(INCLUDE_DIRS includeLIBRARIES my_library
)