极简原理
一般来说,一个 C/C++ 工程可以被编译为三种目标结果:静态库、动态库、可执行程序。
无论要编译的工程是一个静态库、动态库还是可执行程序,一般来说,需要四大输入:头文件目录、源码、链接库目录、链接库名称。
所以,CMakeLists.txt 的主要内容就是写好所需的目标结果、以及为了目标结果的输入。
极简语法
shell 中的语法
CMakeLists.txt
是编译时的输入文件,即,在 shell 环境中输入cmake <dir>
例如cmake .
时,dir 目录 (例如当前目录)中必须有CMakeLists.txt
文件。- 在
CMakeLists.txt
所在的目录输入cmake .
即可把该CMakeLists.txt
中定义的内容通过 cmake 编译成对应的 Makefile 文件以便继续 make、make install。 - 使用
cmake . -Bbuild -DCMAKE_BUILD_TYPE=Debug
可以编译工程的可调式版本。-D<KEY>=<VALUE>
可以给相应的CMake源码中的参数KEY
赋值VALUE
。-B
表示把构建中间文件及结果文件放到后面的目录文件夹./build
中,如果不存在该文件夹,则创建该文件夹。 - 也可以直接在包含
CMakeLists.txt
的目录中创建 build 文件夹,然后在 build 文件夹中执行cmake .. -DCMAKE_BUILD_TYPE=Debug
。
CMake 源码中的语法
- CMake 源码中不区分大小写,但一般把语句用小写,变量用大写。
- CMake 中有些保留语句(方法)以及保留关键词(变量),常见的语句及变量会在接下来谈及。
cmake_minimum_required(VERSION x.x.x)
作为 CMakeLists.txt 第一行内容,规定了 CMake 的最低版本,因为有些 CMake 语句是在较高的版本上才有的(比如target_link_libraries
在最低 3.13.0 以上才有),所以,这一句可以避免因 CMake 版本不够而导致的编译报错。project(example)
用于定义该项目的名称。保留变量 PROJECT_NAME 将会被赋值为 “example”。include_directories(path1 path2 path3)
是把path1
path2
path3
告诉编译器去这些路径中找头文件。link_directories(lpath1 ... lpathn)
是告诉链接器去这些目录下找被链接的库。link_libraries(-lavfilter -ogg -lz)
是告诉链接器需要链接avfilter ogg z
这三个库。add_library(example STATIC a.cpp b.cpp c.cpp)
是把a.cpp
b.cpp
c.cpp
这三个源码文件编译成静态库libexample.a
。把STATIC
换成SHARED
即可编译出动态库libexample.so
。去掉STATIC
或SHARED
把library
换成executable
则编译出可执行文件example
。- 使用
${PROJECT_NAME}
可以使用变量的值,例如add_executable(${PROJECT_NAME} a.cpp b.cpp c.cpp)
等价于add_executable(example a.cpp b.cpp c.cpp)
。
示例代码
cmake_minimum_required(VERSION 3.0.0)
project(example)
include_directories(/usr/include /usr/local/include ./include)
link_directories(/usr/lib /usr/local/lib /home/myname/installedprogram/lib/)
link_libraries(-lz -logg -lavfilter)
add_executable(${PROJECT_NAME} src/a.cpp src/b.cpp src/c.cpp src/main.cpp)
add_library(example STATIC src/a.cpp src/b.cpp src/c.cpp)