文章目录
catkin_make编译系统
编译库
项目名称为autodrive_common
,对应头文件在include
目录下,需要在catkin_package
1中添加INCLUDE_DIRS
和LIBRARIES
,表示当前package(autodrive_common)对外提供的库以及头文件。
project(autodrive_common)
catkin_package(INCLUDE_DIRS include
LIBRARIES autodrive_common)
添加库编译,库由common_lib.cc
源文件生成,最终生成libcomman_lib.so
add_library(common_lib SHARED src/common_lib.cc)
调用库
在需要调用库的包的package.xml
中添加对autodrive_common包的编译和运行依赖:
<build_depend>autodrive_common</build_depend>
<run_depend>autodrive_common</run_depend>
在需要调用库的包中的CMakeLists.txt中用find_package
将查找autodrive_common包作为catkin的components。autodrive_common对外export的头文件和库就会分别添加在变量${catkin_INCLUDE_DIRS}
和${catkin_LIBRARIES}
中,之后在头文件目录设置include_directories
和库链接设置target_link_libraries
时就可以使用这两个变量。
find_package(catkin REQUIRED COMPONENTS
autodrive_common
)
include_directories(
include
${catkin_INCLUDE_DIRS}
)
target_link_libraries(planning_node ${catkin_LIBRARIES})
第三方库的调用
#设置头文件目录
include_directories(
include
)
#指定库所在的目录
link_directories(lib)
#应用程序node链接library库
target_link_libraries(node library )
依赖其他功能包生成的msg targets
假如某功能包需要使用msgpackage包中定义的消息,则需要在构建任何依赖于该消息生成的目标文件的任何程序之前,编译消息并生成目标文件。这就需要使用add_dependencies()
命令声明该程序所依赖的前置项。
#利用find_package将msgpackage设置为catkin的COMPONENTS
find_package(catkin REQUIRED COMPONENTS msgpackage)
#添加可执行程序的编译
add_executable(message_program src/main.cpp)
#设置message_program的依赖为${catkin_EXPORTED_TARGETS}
add_dependencies(message_program ${catkin_EXPORTED_TARGETS})
那么${catkin_EXPORTED_TARGETS}
是什么?在CMakeLists.txt中我们可以利用message()
函数去debug,例如,
message("catkin_EXPORTED_TARGETS=${catkin_EXPORTED_TARGETS}")
都是些形如packagename_generate_messages_cpp
的flag,所以对msg/service等的依赖,既可以使用packagename_generate_messages_cpp
这种形式,也可以一劳永逸的通过find_package
和catkin_EXPORTED_TARGETS
或${PROJECT_NAME}_EXPORTED_TARGETS
进行设置。
${PROJECT_NAME}_EXPORTED_TARGETS
中存放的是PROJECT_NAME
包所生成的目标文件的flag,而catkin_EXPORTED_TARGETS
存放的是所有包生成的的目标文件的flag。
因为catkin会自动install message, service and action targets,并添加到 ${PROJECT_NAME}_EXPORTED_TARGETS
和catkin_EXPORTED_TARGETS
,所以无需使用install()
命令手动安装。
ament_cmake构建工具
ament_package()
项目设置由ament_package()
完成,并且一个包必须且只能调用一次。ament_package()
安装package.xml
,为功能包注册ament index,并且为Cmake安装配置文件(和目标文件)以便被其他功能包使用find_package()
发现。因为ament_package()
从CmakeLists.txt
收集了大量信息,所以u它应该在最后被调用。
ament_package()
有两个参数:
-
CONFIG_EXTRAS
:一系列应该被提供给该功能包的用户的Cmake文件(.cmake or .cmake.in模板被
configure_file()
扩充) -
CONFIG_EXTRAS_POST
:与CONFIG_EXTRAS
相同,只是文件添加的顺序不同。CONFIG_EXTRAS
files在ament_export_*
生成的文件之前被include,而CONFIG_EXTRAS_POST
在之后被include。
添加${PROJECT_NAME}_CONFIG_EXTRAS
和 ${PROJECT_NAME}_CONFIG_EXTRAS_POST
有同样的效果。
文件被添加的全部顺序:
- files added by
CONFIG_EXTRAS
- files added by appending to
${PROJECT_NAME}_CONFIG_EXTRAS
- files added by appending to
${PROJECT_NAME}_CONFIG_EXTRAS_POST
- files added by
CONFIG_EXTRAS_POST
添加依赖
有两种方法将功能包和新的依赖链接起来
第一种方式也是推荐的方式是用ament宏ament_target_dependencies
第二种方式是使用target_link_libraries
现代CMake的推荐方法是仅使用targets,导出和与链接。CMake目标是包含命名空间的,类似于C ++。例如,Eigen3定义了目标Eigen3 :: Eigen。
构建库
当构建可重复使用的库时,需要将一些信息导出到下游包
ament_export_targets(my_libraryTargets HAS_LIBRARY_TARGET)
ament_export_dependencies(some_dependency)
install(
DIRECTORY include/
DESTINATION include
)
install(
TARGETS my_library
EXPORT my_libraryTargets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include
)
ament_export_targets
宏为Cmake导出targets,这允许你的库的用户使用target_link_libraries(client my_library::my_library)
。ament_export_targets
能列出一个名为EXPORT
的目标列表在install
调用中使用
附加选项HAS_LIBRARY_TARGET
:添加潜在的库到环境变量ament_export_dependencis
导出依赖到下游包。这使得该库的使用者对于这些依赖无需调用find_package()
。- 关于
INCLUDES DESTINATION include
,install
命令仅将信息添加到CMake,实际上并未安装includes文件夹,这是通过install(DIRECTORY <dir> DESTINATION <dest>)
命令来复制头文件。
还有两个附加函数,但对于基于目标的安装是多余的
-
ament_export_include_directories(include)
标记导出的include目录,等同于
install
调用的INCLUDES DESTINATION
-
ament_export_libraries(my_library)
标记安装的library的位置,这被
ament_export_targets
调用的HAS_LIBRARY_TARGET
参数
Compiler and linker options
尽管现代CMake建议按目标添加complier flags
target_compile_options(my_target PRIVATE -Wall)
It is recommended to at least cover the following warning levels:
- For Visual Studio, the default
W1
warnings are kept - For GCC and Clang:
-Wall -Wextra -Wpedantic
are required and-Wshadow -Werror
are advisable (the latter makes warnings errors).
但现在建议使用目录级函数add_compile_options(-Wall)
Adding resources
特别是在开发允许插件的插件或软件包时,通常必须从另一个ROS包中添加资源(例如插件)。
这可以使用ament index(也称为“resource index”)来实现。
通常,ament index包含在install/share/<your-package>
目录下,包含获取资源的所需内容,比如resource的安装目录的相对路径。
当提供插件时,你需要提供一个plugin_description.xml
文件,被pluginlib安装和使用 to load the plugins。为了实现这个目的,plugin_description.xml
is registered as a resource in the resource _index 通过
pluginlib_export_plugin_description_file(plugin_name plugins_description.xml)
Querying the ament index
ament_index_has_resource
:如果存在,获得资源的前缀路径var
: the output parameter: fill this variable with FALSE if the resource does not exist or the prefix path to the resource otherwiseresource_type
: The type of the resource (e.g.rviz_common__pluginlib__plugin
)resource_name
: The name of the resource which usually amounts to the name of the package having added the resource of type resource_type (e.g.rviz_default_plugins
)
ament_index_get_resource
:获取特定资源的内容,即ament index中标记文件的内容var
: the output parameter: filled with the content of the resource marker file if it exists.resource_type
: The type of the resource (e.g.rviz_common__pluginlib__plugin
)resource_name
: The name of the resource which usually amounts to the name of the package having added the resource of type resource_type (e.g.rviz_default_plugins
)PREFIX_PATH
: The prefix path to search for (usually, the defaultament_index_get_prefix_path()
will be enough).
ament_index_get_resources
:获取所有从索引中注册特定类型的资源的软件包var
: Output parameter: filled with a list of names of all packages which registered a resource of resource_typeresource_type
: The type of the resource (e.g.rviz_common__pluginlib__plugin
)PREFIX_PATH
: The prefix path to search for (usually, the defaultament_index_get_prefix_path()
will be enough).
catkin_package()
[macro defined in catkin_package.cmake]
该命令生成find_package
和pkg-config所需的代码,使得其他功能包可以获得该功能包的信息,包括该功能包的头文件目录、库、依赖和CMake变量。
一个功能包中只能有一个catkin_package
,一般放在较为靠前的位置,以使之后可以使用一些额外变量。 ↩︎