目录[-]


1、CMakeLists文件理解

      在一个Cmake工程中,我们会用cmake 命令生成一个makefile 文件,然后,用make命令根据这个makefile 文件的内容编译整个工程。 其中CMakeLists.txt 文件用来告诉cmake命令我们要对这个目录下的文件做什么事情。CMake_Lists.txt 文件的内容需要遵守cmake的语法。


2、生成执行程序

      理论上说,任意一个C++ 程序都可以用g++ 来编译。但当程序规模越来越大时,一个工程可能有许多个文件夹和源文件,这时输入的编译命令将越来越长。通常一个小型C++ 项目可能含有十几个类,各类间还存在 着复杂的依赖关系。其中一部分要编译成可执行文件,另一部分编译成库文件。如果仅靠g++ 命令,我们需 要输入大量的编译指令,整个编译过程会变得异常烦琐。因此,对于C++ 项目,使用一些工程管理工具会更 加高效。在历史上工程师们曾使用makefile进行自动编译,但下面要谈的cmake比它更加方便。并且,我们会看到后面提到的大多数库都使用cmake 来管理源代码。在一个cmake工程中,我们会用cmake 命令生成一个makefile 文件,然后,用make命令根据这个makefile 文件的内容编译整个工程。
以下指令是根据communication.cpp源文件生成 communication 执行文件。

add_excutable(communication communication.cpp)

在一个C++ 项目工程中,并不是所有的代码都需要编译成可执行文件。只有带有main 函数的文件才会生成可执行程序。而另一些代码,我们可能只想把它们打包成一个东西,供其他程序调用。这个东西叫作库。在Linux 中,库文件分成静态库和共享库两种。静态库以.a 作为后缀名,共享库以.so 结尾。所有库都是一些函数打包后的集合,差别在于静态库每次被调用都会生成一个副本,而共享库则只有一个副本,更省空间。


3、生成静态库文件

在生成的静态库cpp源文件中不需要存在main函数,生成函数如下:

add_library(usbcan usbcan.cpp)

此时在使用catkin_make指令后,会在/build文件夹下生成一个usbcan.a 文件,该文件就是我们得到的静态库文件。


4、生产动态库文件

在生成的动态库cpp源文件中也不需要存在main函数,生成函数如下:

add_library(usbcan SHARED usbcan.cpp)

此时在使用catkin_make指令后,会在/build文件夹下生成一个usbcan.so 文件,该文件就是我们得到的动态库文件。


5、引用静态/动态库文件

      库文件是一个压缩包,里面是编译好的二进制函数。但是如果仅有.a 或.so 库文件,我们是不会知道里面的函数实现到底是什么,更无法知道如何去调用相关的函数,所以为了正常的去使用这个库文件,我们需要提供一个头文件,说明这些库里都有些什么。因此,对于库的使用者,只要拿到了头文件和库文件,就可以调用这个库 了。

add_excutable(communication communication.cpp)
target_link_libraried(communication usbcan)

通过在CMakeLists.txt文件中设置这两句,生成的communication执行程序就可以顺利使用前面生产的usbcan库文件了。


6、变量管理及引入

• catkin CMakeLists.txt 都要以指定cmake版本指令开始,catkin编译需要2.8.3版本以上的cmake,指令如下:

cmake_minimum_required(VERSION 2.8.3)

• 通过project()指定包的名字,在cmake中指定后,可在其他地方通过使用变量${PROJECT_NAME}来引用包的名字

project(test_node)

• 指定构建本package需要依赖的package,由于项目使用catkin_make的编译方式,所以至少需要catkin这个package。

find_package(catkin REQUIRED)

• 当编译一个需要使用的第三方库的package时,我们需要知道 "去哪里找.h头文件""去哪里找.so .dll .lib .dylib库文件";以及需要知道"需要链接的库文件的名字"
• 当一个package被find_package时,就会产生一些CMAKE变量,这些变量可以在CMake的脚本中使用,这些变量描述了所依赖的包的头文件,源文件以及库文件在哪里。

catkin_FOUND:这个变量说明这个库是否被找到,找到为true,否则为false;
catkin_INCLUDE_DIRS 或 catkin_INCLUDES:这个变量是包输出的头文件目录。
catkin_LIBRARIES 或catkin_LIBS:这个变量是包输出的库文件

• 每个find_package()都会产生一组变量,比如:

find_package(roscpp REQUIRED)
find_package(rospy REQUIRED)
find_package(std_msgs REQUIRED)

三条指令产生了三组变量,roscpp_ INCLUDE_DIRS,rospy_INCLUDE_DIRS和std_msgs_INCLUDE_DIRSd等。但这样产生了三组变量,管理很不方便,所以还有另外一种方式:

find_package(catkin REQUIRED COMPONENTS
   roscpp
   rospy
   std_msgs
)

这样,会把相关的变量全部添加到catkin_INCLUDE_DIRS等一组变量上,比较方便管理。