本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
极简原理
一般来说,一个 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)是把path1path2path3告诉编译器去这些路径中找头文件。link_directories(lpath1 ... lpathn)是告诉链接器去这些目录下找被链接的库。link_libraries(-lavfilter -ogg -lz)是告诉链接器需要链接avfilter ogg z这三个库。add_library(example STATIC a.cpp b.cpp c.cpp)是把a.cppb.cppc.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)