All You Need for CMake系列02——Hello Headers

准备代码

代码结构如下:

.
├── CMakeLists.txt
├── include
│   └── Hello.h
└── src
    ├── Hello.cpp
    └── main.cpp

这是一个经典结构,moveit里面单独的包都是用这种方式写的。

Hello.h里内容如下:

#ifndef __HELLO_H__
#define __HELLO_H__

class Hello
{
public:
    void print();
};

#endif

Hello.cpp里内容如下:

#include <iostream>

#include "Hello.h"

void Hello::print()
{
    std::cout << "Hello Headers!" << std::endl;
}

main.cpp

#include "Hello.h"

int main(int argc, char *argv[])
{
    Hello hi;
    hi.print();
    return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.5)
project (hello_headers)

# Create a sources variable with a link to all cpp files to compile
set(SOURCES
    src/Hello.cpp
    src/main.cpp
)

add_executable(hello_headers ${SOURCES})

# Set the directories that should be included in the build command for this target
# when running g++ these will be included as -I/directory/path/
target_include_directories(hello_headers
    PRIVATE 
        ${PROJECT_SOURCE_DIR}/include
)

要点

  1. 在本教程中演示了如何在CMakeLists.txt中添加对header的引用。核心是target_include_directories()
    • 这个函数的基本用法是target_include_directories(target PRIVATE path/to/include)
    • target名和add_executable的第一个input变量一样,这里是和PROJECT_NAME一致,但当然也可以不一样。
    • PRIVATE在这里是限制了include的访问范围
    • 关于target_include_directories函数的全面解释可以看这里
  2. set()是一个很有用的函数,作用就是定义变量。语法是set(NAME, content),多个content还是像上一章那样依次写即可,不需要加括号,逗号,引号等
    • 在这里,set函数定义了SOURCES,然后放到add_exeuctable。当然我们可以进一步地把add_executable的输入变量写成全引用的方式add_executable($PROJECT_NAME$ ${SOURCES}),注意这里第一个变量是默认的,第二个变量是我们自己定义的。
  3. 几个默认路径变量:
    • CMAKE_SOURCE_DIR:项目的source目录
    • CMAKE_CURRENT_SOURCE_DIR:当前的source目录,用于多层cmake
    • PROJECT_SOURCE_DIR:当前项目的source目录
    • CMAKE_BINARY_DIR:build的路径(含build)
    • CMAKE_CURRENT_BINARY_DIR:当前所在的build目录
    • PROJECT_BINARY_DIR:对当前project的build目录,多层cmake的时候有用

编译流程

基本步骤和上述步骤一致

mkdir build
cd build
cmake ..
make

这里我们进一步学两个make的arguments

  • make clean:清理之前make的结果
  • make VERBOSE=1:make过程中显示的信息会比之前更详细一点。VERBOSE=1是我们比较经常看到的项目编译中使用的等级。