CMakeLists使用:使用cmake构建工程的详细过程

最近在做一个ADAS项目,adas项目需要将代码移植到嵌入式开发版,而开发版上恰好是ubuntu系统,所以只需要将windows开发的程序迁移到ubuntu上,然后使用cmake编译该工程就可以运行。下面主要是介绍如何使用CMake编译工程。CMake是一个跨平台的程序构建工具,通过编写cmakelist.txt文件然后通过cmake和make命令就可以编译工程。下面主要介绍一下cmakelist.txt的编写规则以及过程。先从简单的工程说起。

第一:首先构建比较简单的工程

1.构建一个工程的时候,需要做的几件事情(如果下面几件事你知道怎么做了,多大的工程就都不是问题了):

  • 源代码在什么位置?
  • 头文件在哪里?
  • 怎么生成静态或者动态库?
  • 程序链接的静态库在哪里?
  • 如果工程的代码存放在很多地方,那又该怎么找到它们呢?

第二:下面从一个最简单的HelloWorld开始,然后一步一步构建一个比较复杂的工程:

A.工程文件如下(只有一个helloworld.cpp源文件):

1
2
3
4
5
6
7
//helloworld.cpp
#include<iostream>
int main()
{
std::cout<<"hello, world"<<std::endl;
return 0;
}

B.这时候,我们要写一个CMakeLists.txt:

1
2
3
4
cmake_minimum_required(VERSION 2.8)
PROJECT(sayhello) #定义整个CMake的工程名
FILE(GLOB SOURCE "./*.cpp") #告诉CMake:工程的源文件在哪里?
ADD_EXECUTABLE(sayhello ${SOURCE}) #告诉CMake:我们要生成可执行文件(sayhello)

使用cmake . && make 就可以在目录下生成一个hello可执行文件了。
如果要添加编译选项,可以通过下面的方法添加:

1
2
3
4
5
cmake_minimum_required(VERSION 2.8)
PROJECT(sayhello) #定义整个CMake的工程名
FILE(GLOB SOURCE "./*.cpp") #告诉CMake:工程的源文件在哪里?
ADD_DEFINITIONS("-Wall -std=c++11") # 新增的编译选项
ADD_EXECUTABLE(sayhello ${SOURCE}) #告诉CMake:我们要生成可执行文件(sayhello)

第三:构建包含头文件和源文件的工程

A.代码分布如下(main.cpp是main函数,里面调用了hello.h声明的SayHello,定义在hello.cpp中):

B.main的代码:

1
2
3
4
5
6
#include"hello.h"
int main()
{
SayHello();
return 0;
}

C.CMakeLists.txt内容

1
2
3
4
5
6
cmake_minimum_required(VERSION 2.8)
PROJECT(sayhello)
FILE(GLOB SOURCE_1 "${CMAKE_SOURCE_DIR}/src/*.cpp") //程序必须链接到hello.cpp里面的函数
FILE(GLOB SOURCE_2 "${CMAKE_SOURCE_DIR}/main/*.cpp") //告诉源文件地址
INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/include/") //头文件
ADD_EXECUTABLE(${PROJECT_NAME} ${SOURCE_1} ${SOURCE_2}) //生成可执行文件,可执行文件名sayhello

第四:更高级一点工程的构建过程,生成库文件

A.工程描述:该工程在上一个工程的基础上将hello函数编译成一个动态链接库(.so文件,类似于Windows下的.dll文件)

B.CMakeLists.txt内容

1
2
3
4
5
6
7
8
9
10
cmake_minimum_required(VERSION 2.8)
PROJECT(hello)

FILE(GLOB SOURCE_1 "${CMAKE_SOURCE_DIR}/src/*.cpp")
FILE(GLOB SOURCE_2 "${CMAKE_SOURCE_DIR}/main/*.cpp")
INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/include/")
ADD_LIBRARY(hello SHARED ${SOURCE_1}) //告诉cmake生成一个动态链接库libhello.so
LINK_LIBRARIES(hello) //链接生成
ADD_EXECUTABLE(sayhello ${SOURCE_2}) //根据main.cpp生成可执行文件
TARGET_LINK_LIBRARIES(sayhello ${hello})//将libhello.so链接到可执行文件

最后编译一下就可以自动生成一个libhello.so文件和sayhello的可执行文件。如果要生成静态链接库(.a文件)的话,只需要将上面的 SHARED 参数换成 STATIC 就可以了。

整个编译的过程就是这样了,最主要的是记住上面”构建一个工程的时候,需要做的几件事情:头文件,源文件,库文件这个元素“,再复杂的工程都是这样一步一步的构建出来的。