1 整体结构
CMakeList.txt文件必须遵循以下的格式:
所需的CMake版本(cmake_minimum_required)
软件包的名称(project())
查找构建所需要的其他CMake/Catkin软件包(find_package())
消息/服务/运动生成器(add_message_files() add_service_files() add_action_files())
调用消息/服务/动作生成(generate_message())
制定package build info export(catkin_package())
需要建立的库/可执行文件(add_library() add_executable() target_link_libraries())
安装规则(install())
1.1 CMake版本
每个catkin CMakeList.txt文件都必须以需要的CMake版本。
cmake_minimum_required(VERSION 2.8.3)
1.2 软件包名称
由CMake项目功能指定的包的名称。这里我们制作一个名为robot_brain的软件包。
project(robot_brain)
1.3 查找相关的CMake包
我们需要使用find_package函数来制定需要找到哪些其他的CMake包来构建我们的项目
find_package(catkin REQUIRED)
对于find_package来说,有两种不同的表达方式分别为:
find_package(catkin REQUIRE COMPONENTS nodelet)
或者
find_package(catkin REQUIRE)
find_package(nodelet REQUIRE)
对于两者的区别。如果通过了find_package找到了一个包,会创建几个提供有关找到的包的消息的Cmake环境变量。
这些环境变量导出了头文件的位置,源文件的位置,包所依赖的库以及这些库的地址。
如果find_package作为catkin的组件(例如第一种方式),这是有好处的。
find_package(catkin REQUIRE COMPONENTS nodelet)
这意味着由nodelet导出的include路径,库等也附加到了catkin_变量,这里的变量是上面指示的
1.4 Boost
如果想使用Boost,并制定用作组件的Boost的哪些方面,如你想要使用Boost线程,则
find_package(Boost REQUIRE COMPONENTS thread)
1.5 catkin_package()
catkin_package()是一个catkin提供的CMake宏。这是为构建系统指定catkin特定消息所必须的。后者又用于生成pkg_config和CMake文件。
在使用add_library()或者add_executable()声明任何目标之前,必须调用此函数
举例:
catkin_package(
INCLUDE_DIRS include
LIBRARIES ${PROJECT_NAME}
CATKIN_DEPENDS roscpp nodelet
DEPENDS eigen opencv)
这表示,包文件夹中的文件夹"include"是导出标题的地方。CMake环境变量${PROJECT_NAME}评估到之前传给project()函数的任何东西。在当前情况,它将是"robot_brain","roscpp,nodelet"是需要存在来构建运行此程序包的软件包,“eigen”+"opencv"是需要存在来构建运行此程序包的系统依赖项.
1.6 指定构建目标
构建目标可以有多种形式,但一般有两种形式:
可执行目标-我们可以运行的程序
库目标-可以在构建和运行时可执行目标使用的库
1.6.1 目标命名
需要注意,catkin中构建目标的名称必须是唯一的。但是,目标的唯一名称只能在CMake内部进行。
可以使用set_target_properties()函数重命名为其他的目标。
例如:
set_target_properties(rviz_image_view
PROPERTIES OOUTPUT_NAME image_view
PREFIX "")
这表示将目标rviz_image_view名称更改为image_view
1.6.2 包括路径和库路径
在指定目标之前,需要指定可以为所述目标找到资源的位置,特别是头文件和库:
包括路径-在哪里可以找到代码的头文件
库路径-哪些库用于该可执行目标建立对象
例如:
包括路径:include_directories()
include_derectories()的参数应该是find_package调用和需要包含的任何其他目录生成的_INCLUDE_DIRS变量。如果你使用catkin和Boost,你的include_directories()调用应该如下所示:
include_directories(include ${Boost_INCLUDE_DIRS} ${catkin_INCLUDE_DIRS})
第一个参数include表示包中的Include/目录 也是路径的一部分。
库路径:link_directories()
link_directories()函数可以用于添加额外的库路径。对于catkin与CMake软件包在find_package时会自动添加链接消息。只需要链接到target_link_libraries()中的库
如:link_direstories(~/my_libs)
1.6.3 可执行目标
要指定可执行目标,我们必须使用add_executable()CMake函数
add_executable(myProgram src/main.cpp src/some_file.cpp src/another_file.cpp)
这将构建一个名为myProgram的目标可执行文件,由后面的三个源文件构成
1.6.4 库目标
add_library()CMake函数用于指定要构建的库。默认情况下,catkin构建共享库。
add_library(${PROJECT_NAME} ${${PROJECT_NAME}_SRCS})
1.6.5 target_link_libraries
使用target_link_libreries()函数用来指定可执行目标链接的库,这通常在add_executable()调用之后完成。
如果找不到ros,则添加${catkin_LIBRARIES}
句法:
target_ink_libraries(
对于整体构建目标的实例如下:
add_executable(foo src/foo.cpp)
add_library(moo src/moo.cpp)
target_link_libraries(foo moo) --This links foo against libmoo.so
对于大多数情况都不需要link_directories(),因为信息通过find_package()自动拉入。
1.7 消息,服务和动作
消息(.msg),服务(.srv),动作(.action)文件在ROS包构建和使用之前需要一个特殊的预处理构建步骤。CMake提供了三个宏来处理消息,服务和动作
add_message_files
add_service_files
add_action_files
这些宏的要点是生成编程语言特定的文件,以便可以利用其选择的编程语言中的i消息,服务和动作。构建系统将使用所有可用的生成器(例如gencpp,genpy等)生成绑定。
这些宏之后必须跟随调用生成的宏,声明你所用的消息/服务/动作的依赖项:
generate_message()
1.7.1 重要先决条件/限制
这些宏必须在catkin_package()宏之前,以便生成才能正常工作
如:
find_package(catkin REQUIRED COMPONENTS ...)
add_message_files(...)
add_service_files(...)
add_action_files(...)
generate_messages(...)
catkin_package(...)
...
你的catkin_package()宏必须对message_runtime具有CATKIN_DEPENDS依赖关系。
catkin_package(
...
CATKIN_DEPENDS message_runtime ...
...)
你必须对message_generation使用find_package(),单独或作为catkin的组件:
find_package(catkin REQUIRED COMPONENTS messafef_generation)
同时,你的package.xml文件必须包含对message_generation的构建依赖关系以及message_runtime上的运行时依赖关系。如果依赖关系从其他软件包中过渡出来则不需要这样做。
如果您有一个目标,依赖于需要构建消息/服务/运动的其他一些目标,则需要向目标catkin_EXPORTED_TARGETS添加明确的依赖关系,以便它们以正确的顺序构建。(some_target是由add_executable()设置的目标的名称)
即不使用自己功能包的消息/服务/动作,而是依赖于外部功能包
add_dependencies(some_target ${catkin_EXPORTED_TARGETS})
如果你有一个构建消息或服务的包以及使用这些消息/服务的可执行文件,则需要为自动生成的消息目标创建明确的依赖关系,以便以正确的顺序构建它们
add_dependencies(some_target ${${PROJECT_NAME}_EXPORTED_TARGETS})
如果两者都符合则:
add_dependencies(some_target ${catkin_EXPORTED_TARGETS} ${${PROJECT_NAME}_EXPORTED_TARGETS})
例如:
你的包有名为“MyMessage1.msg”和“MyMessage.msg”的名为“msg”目录中的两条消息,这些消息依赖于std_msgssensor_msgs,名为"src"的名为"MyService.srv"的目录中的服务,定义使用这些消息和服务的可执行文件messagge_program,并且使用ROS其他某些部分的可执行的do_not_us_local_message_program,不使用此包中定义的i消息/服务,那么CMakeList.txt文件需要:
find_package(catkin REQUIRED COMPONENTS message_generation std_msgs sensor_msgs) # Declare the message files to be built add_message_files(FILES MyMessage1.msg MyMessage2.msg ) # Declare the service files to be built add_service_files(FILES MyService.srv ) # Actually generate the language-specific message and service files generate_messages(DEPENDENCIES std_msgs sensor_msgs) # Declare that this catkin package's runtime dependencies catkin_package( CATKIN_DEPENDS message_runtime std_msgs sensor_msgs ) # define executable using MyMessage1 etc. add_executable(message_program src/main.cpp) add_dependencies(message_program ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) # define executable not using any messages/services provided by this package add_executable(does_not_use_local_messages_program src/main.cpp) add_dependencies(does_not_use_local_messages_program ${catkin_EXPORTED_TARGETS})
另外,如果要构建actionlib操作,并且在action目录中有一个名为"MyAction.action"的操作规范文件,必须将
action_msgs添加到使用catkin进行find_package的组件列表中,然后添加如下对generate_message()的调用
add_action_files(FILES
MyAction.action
)
此外,该包必须具有对actionlib_msgs的构建依赖。(在generate_message与catkin_package中)
1.8 安装选项(install)
构建目标后,目标被放置在catkin开发空间中。通常我们希望目标安装到系统中,即希望做一个make install的代码,你必须制定目标应该在哪里
使用install()函数作为参数完成:
目标-目标是安装
ARCHIVE DESTINATION-静态库和DLL.lib(Windows)存根
LIBRARY DESTINATION-非DLL共享库和模块
RUNTIME DESTINATION-可执行目标和DLL(Windows)样式共享库
如:
install(TARGETS ${PROJECT_NAME}
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
除了这些标准目标,一些文件必须安装到特殊文件夹。即一个包含Python绑定的库必须安装到不同的文件夹中才能在Python中导入:
install(TARGETS python_module_library
ARCHIVE DESTINATION ${CATKIN_PACKAGE_PYTHON_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_PYTHON_DESTINATION}
)
1.9 安装python可执行脚本
对于启动Python模块支持,当ROS包提供一些Pyhton模块时,您应该创建一个setup.py文件并调用.不提供任何模块则不需要这些操作。
catkin_python_setup()
之前调用generate_message()和catkin_package()
对于Python代码,安装规则是不同的,因为没有使用add_library()和add_executable()函数。在CMakeList.txt文件中,加入如下的内容
catkin_install_python(PROGRAMS scripts/myscript
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})
1.10 安装头文件
标题文件必须安装到"include"文件中,这通常是通过安装整个文件夹的文件来完成的。可以通过如下所示的安装规则:
install(DIRECTORY include/${PROJECT_NAME}/ DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} PATTERN ".svn" EXCLUDE )
或者包含的子文件夹与包名不匹配,则
install(DIRECTORY include/ DESTINATION ${CATKIN_GLOBAL_INCLUDE_DESTINATION} PATTERN ".svn" EXCLUDE )
1.11 安装roslaunch文件或者其他资源
其他资源可以安装到${CATKIN_PACKAGE_SHARE_DESTINATION}
install(DIRECTORY launch/ DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch PATTERN ".svn" EXCLUDE)