CMakeListx.txt文件必须准守下面的这些守则,否则的话,程序包将不能被正确的构建。在配置文件中,下面的顺序很重要。
Required CMake Version (cmake_minimum_required)
Package Name (project())
Find other CMake/Catkin packages needed for build (find_package())
Enable Python module support (catkin_python_setup())
Message/Service/Action Generators (add_message_files(), add_service_files(), add_action_files())
Invoke message/service/action generation (generate_messages())
Specify package build info export (catkin_package())
Libraries/Executables to build (add_library()/add_executable()/target_link_libraries())
Tests to build (catkin_add_gtest())
Install rules (install())
在catkin_make运行后终端输出文件部分解析
#基本路径
Base path: /home/user/catkin_ws
Source space: /home/user/catkin_ws/src
Build space: /home/user/catkin_ws/build
Devel space: /home/user/catkin_ws/devel
Install space: /home/user/catkin_ws/install
#catkin_make 封装运行中cmake运行的情况
Running command: "cmake /home/user/catkin_ws/src -DCATKIN_DEVEL_PREFIX=/home/user/catkin_ws/devel
-DCMAKE_INSTALL_PREFIX=/home/user/catkin_ws/install" in "/home/user/catkin_ws/build"
#编译工具查找
-- Using CATKIN_DEVEL_PREFIX: /tmp/catkin_ws/devel
-- Using CMAKE_PREFIX_PATH: /opt/ros/groovy
-- This workspace overlays: /opt/ros/groovy
#编译的包
#catkin_make 封装运行中make运行的情况
$ catkin_make -DCATKIN_WHITELIST_PACKAGES=“package1;package2”
恢复编译所有的包
$ catkin_make -DCATKIN_WHITELIST_PACKAGES=""
如果一个软件包被CMake通过find_package函数找到,那么系统会自动的生成一系列描述软件包的CMake 环境变量。这些环境变量会稍后被CMake脚本使用。与此同时,这些环境变量描述了软件包会把头文件导出到了那里,以及哪些被软件包依赖的库和这些库的路径。环境变量的命名通常是:_ :
_ FOUND 当库被找到的时候,被设置为true;否则,设置为false;
_ INCLUDE_DIRS 或者 _ INCLUDES 包含了软件包导出的路径
_ LIBRARIES 或者 _ LIBS 被软件包导出的库
_ DEFINITIONS- ?
例如:
#查找OpenCV是否安装
find_package(OpenCV REQUIRED core highgui imgproc imgcodecs)
if (OPENCV_FOUND)
message(STATUS "找到OpenCV:\"${OpenCV_INCLUDE_DIRS}\",ENABLE_OPENCV宏已打开")
message(STATUS "找到OpenCV:\"${OpenCV_LIBS}\"")
include_directories(${OpenCV_INCLUDE_DIRS})
add_definitions(-DENABLE_OPENCV)
list(APPEND LINK_LIB_LIST ${OpenCV_LIBS})
endif (OPENCV_FOUND)
其中REQUIRED表示要寻找的依赖包对我来说很重要,如果找不到就不编译了。COMPONENTS它表示我们要找的包需要后面的这些库或者包。
如果你有很多的opencv版本,尤其是一个是opencv2.x.x一个是opencv3.x.x,因为2和3在数据结构上有相对较大的变化,所以如果引入错误的版本可能导致程序的无法运行。因为find_package找默认路径下的OpenCV,但是很多时候安装多个版本的库的时候都会make install在opt目录下。安装在opt的文件中会有share文件夹,这里面就有咱们需要的OpenCV文件夹,所以如果要自己有选择的控制版本,则在find_package这句话前面去设置opencv的OpenCV文件夹在哪里,添加set(OpenCV_DIR /opt/opencv-2.4.11/share/OpenCV)这句话。因为我的opencv2.4.11版本install在/opt/opencv-2.4.11文件夹下。这个可以根据你install的位置去变化。
使用Set增加搜索目录
catkin_package()是一个catkin_provided 的CMake macro文件。构建系统必须要指定catkin特定的信息,而系统又用于生成类pkg-config和CMake文件。
在使用add_library()和add_executable()函数声明目标之前,必须的调用这个函数。这个函数有5个可选的参数。
INCLUDE_DIRS - 包含了导出软件包头文件的路径
LIBRARIES - 项目导出的库
CATKIN_DEPENDS - 这个项目依赖的其他catkin项目
DEPENDS - 这个项目依赖的其他non-catkin项目。
CFG_EXTRAS - 其他额外的一些配置选择
catkin_package(
INCLUDE_DIRS include
LIBRARIES ${PROJECT_NAME}
CATKIN_DEPENDS roscpp nodelet
DEPENDS eigen opencv)
非常重要的是需要注意,catkin中构建目标的名称必须是唯一的,不管它们是构建/安装到哪个文件夹。这是CMake的要求。但是,目标的名称仅在CMake内部是必需的。可以使用set_target_properties()函数将目标重命名为其他目标:
set_target_properties(rviz_image_view
PROPERTIES OUTPUT_NAME image_view
PREFIX "")
虽然可执行文件和库的默认输出目录通常被设置为合理的值,但在某些情况下必须自定义。比如,包含Python绑定的库必须放在不同的文件夹中,以便可以在Python中导入,如下:
set_target_properties(python_module_library
PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION})
如果你的ROS包提供了一些Python模块,你应该创建一个setup.py文件并调用
catkin_python_setup()
http://docs.ros.org/api/catkin/html/user_guide/setup_dot_py.html
http://docs.ros.org/api/catkin/html/howto/format2/installing_python.html
根目录下建立setup.py文件
from distutils.core import setup
from catkin_pkg.python_setup import generate_distutils_setup
d = generate_distutils_setup(
packages=['mypkg'],
scripts=['bin/myscript'],
package_dir={'': 'src'}
)
setup(**d)
catkin_install_python(PROGRAMS scripts/myscript
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})
使用上述函数需要在调用generate_messages()和catkin_package()之前
ROS中的messages(.msg),services(.srv)和action(.action)文件在构建和使用ROS包之前,需要进行特殊的预处理器构建步骤。这些宏是生成指定编程语言的文件的关键,以便可以使用所选编程语言中的消息,服务和操作。构建系统可以使用所有可用的生成(例如gencpp,genpy,genlisp等)。
提供了三个宏来分别处理消息,服务和操作:
add_message_files
add_service_files
add_action_files
必须在调用生成的宏之后调用这些宏以生成对应的.h文件:
generate_messages()
要指定必须构建的可执行目标,我们使用add_executable()这个CMake函数。
add_executable(does_not_use_local_messages_program src/main.cpp)
include_directories(include ${Boost_INCLUDE_DIRS} ${catkin_INCLUDE_DIRS})
link_directories(${catkin_LIB_DIRS} lib)
link_directories(~/my_libs)
其中 ,catkin_LIB_DIRS 表示创建的环境变量(必须要有,可以是任意名称,但建议此名方便理解),${catkin_LIB_DIRS} 为取该环境变量的值,lib 是相对于当前功能包所在路径的相对路径,此法默认以 当前功能包路径为基准添加额外的库路径。
该指令的作用主要是指定要链接的库文件的路径,该指令有时候不一定需要。因为find_package和find_library指令可以得到库文件的绝对路径。不过你自己写的动态库文件放在自己新建的目录下时,可以用该指令指定该目录的路径以便工程能够找到。
add_library()这个 Make函数用来指定库来构建,将功能包的cpp生成一个库给别人用。默认情况下,catkin会构建共享库
add_library( [STATIC | SHARED | MODULE]
[EXCLUDE_FROM_ALL]
[source1] [source2] [...])
其中表示库文件的名字,该库文件会根据命令里列出的源文件来创建。而STATIC、SHARED和MODULE的作用是指定生成的库文件的类型。STATIC库是目标文件的归档文件,在链接其它目标的时候使用。SHARED库会被动态链接(动态链接库),在运行时会被加载。MODULE库是一种不会被链接到其它目标中的插件,但是可能会在运行时使用dlopen-系列的函数。默认状态下,库文件将会在于源文件目录树的构建目录树的位置被创建,该命令也会在这里被调用。
target_link_libraries(, , , ... )
例如:
add_executable(foo src/foo.cpp)
add_library(moo src/moo.cpp)
target_link_libraries(foo moo) -- This links foo against libmoo.so
如果你有一个包编译.msg .srv,并且可执行文件要使用他们,那么你就需要创建一个显式的依赖项,自动生成message的target。这里的some_target是add_executable()设置的target的名字。
add_dependencies(some_target ${PROJECT_NAME}_generate_messages_cpp)
find_package(Boost REQUIRED)
但boost thread 运行时需要库,必须指出组件thread .
find_package(Boost REQUIRED COMPONENTS thread)
find_package()之后就可以用此编译和连接了. 命名规则基本是这样: ${name}_INCLUDE_DIRS and${name}_LIBRARIES
经过构建之后,需要将目标放置到catkin工作空间的开发空间中。但是,我们通常希望在系统中安装目标(有关安装路径的信息可以在REP 122中找到 ),以便其他人或本地文件夹可以使用它们来测试系统级安装。换句话说,如果您希望能够对代码进行“make install”,则需要指定目标应该结束的位置。
这是由CMake install()函数完成的,该函数有下面的几个参数:
TARGETS - 那个被安装的目标
ARCHIVE DESTINATION - 静态库和DLL(Windows).lib存根
LIBRARY DESTINATION - 非DLL共享库和模块
RUNTIME DESTINATION - 可执行目标和DLL(Windows)样式共享库
install(DIRECTORY include/${PROJECT_NAME}/
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
PATTERN ".svn" EXCLUDE
)
install(DIRECTORY launch/
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch
PATTERN ".svn" EXCLUDE)
cmake_minimum_required(VERSION 2.8.3)
project(robot)
# Get the information about this package's buildtime dependencies
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})
http://wiki.ros.org/catkin/CMakeLists.txt