有关cmake的入门简介可参见
CMake入门教程_cmake静态test.c编译-CSDN博客
本文是进一步对cmake常用命令做进一步详述
配置项目
cmake_minimum_required
作用
配置cmake最低版本
用法
cmake_minimum_required(VERSION 3.0)
project
作用:设置预设变量
- PROJECT_NAME
- PROJECT_SOURCE_DIR
- ROJECT_BINARY_DIR
用法
project(demo_project c cxx)
其中,后边的c和cxx用于设置编译的语言,一般可以不用
案例:创建CMakeLists.txt,编写该文件内容,使用project命令设置项目名称,然后打印上述预设变量
cmake_minimum_required(VERSION 3.0)
project(demo_project)
#打印预设变量
message(STATUS "PROJECT_NAME:${PROJECT_NAME}")
message(STATUS "PROJECT_SOURCE_DIR:${PROJECT_SOURCE_DIR}")
message(STATUS "PROJECT_BINARY_DIR:${PROJECT_BINARY_DIR}")
保存退出后,使用下述命令编译cmake
cmake -S . -B build
- -S选项表示指定CMakeLists.txt文件的目录文件,后边的.表示当前目录
- -B选项表示指定生成的文件存放在哪里
因此上述命令表示使用当前目录下的 CMakeLists.txt 生成Makefile文件等文件,并将生成的文件放到build文件夹内(注意build文件夹需要首先创建好)
运行结果
信息打印
上述命令中message函数可以帮助我们打印相关信息,如
message(STATUS "This is a status message.")
message(WARNING "This is a warning message.")
message(FATAL_ERROR "This is a fatal error message.")
STATUS
:打印一般信息,输出为绿色。WARNING
:打印警告信息,输出为黄色。FATAL_ERROR
:打印错误信息并停止配置过程。
同时可以设置 CMake 的调试输出,可以在命令行中设置 CMAKE_VERBOSE_MAKEFILE
变量,以显示详细的构建命令。例如:
cmake -S . -B build -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON
这将使 CMake 在执行构建时打印每个命令的详细信息。
添加头文件目录
添加头文件搜索路径的命令有两种
- include_directories:指定的头文件路径会被应用于整个 CMakeLists 文件中所有后续的目标。
- target_include_directories:允许你为特定的目标(例如库或可执行文件)设置头文件路径。
以下是两种方式使用代码实例
include_directories(${PROJECT_SOURCE_DIR}/include)
该代码表示整个项目所有源文件的自定义头文件搜索路径都指定为include
add_executable(app main.cc)
target_include_directories(app PRIVATE ${PROJECT_SOURCE_DIR}/include)
而该代码表示仅为目标文件app中包含的自定义头文件搜索路径指定为include
target_include_directories命令的语法格式为
target_include_directories(<target> <INTERFACE|PUBLIC|PRIVATE> <directory1> <directory2> ...)
如上所示,该命令会为指定的头文件添加三个属性
- INTERFACE
- PUBLIC
- PRIVATE
要理解上述三个属性的区别,首先要知道,Cmake会为每个目标文件设置两个属性,分别是
- INCLUDE_DIRECTORIES:只在当前目标文件中有效
- INTERFACE_INCLUDE_DIRECTORIES:随着目标文件的依赖而传播
上述两个属性的区别在于:
- 如果使用PRIVATE,则只会在INCLUDE_DIRECTORIES属性中添加头文件搜索路径
- 如果使用INTERFACE,则只会在INTERFACE_INCLUDE_DIRECTORIES属性中添加头文件搜索路径
- 如果使用PUBLIC,则相当于同时使用INCLUDE_DIRECTORIES和INTERFACE_INCLUDE_DIRECTORIES
如下所示,如果使用PRIVATE,则每个目标文件(在这里是base和app)的头文件的搜索路径包含在各自维护的INCLUDE_DIRECTORIES变量里
add_library(base base/base.cc)
target_include_directories(base PRIVATE ${PROJECT_SOURCE_DIR}/util)
add_executable(app base)
target_include_directories(app
PRIVATE ${PROJECT_SOURCE_DIR}/base
PRIVATE ${PROJECT_SOURCE_DIR}/util
)
但是如果使用的是PUBLIC,那么util的路径就会被同时存储在INTERFACE_INCLUDE_DIRECTORIES变量里,同时这个路径会跟随base这个目标文件存在,因此当第二个target_include_directories包含base的时候,base就已经包含了util路径,将不再需要单独列出这个路径了
add_library(base base/base.cc)
target_include_directories(base PUBLIC ${PROJECT_SOURCE_DIR}/util)
add_executable(app base)
target_include_directories(app
PRIVATE ${PROJECT_SOURCE_DIR}/base
)
编译可执行程序
添加可执行程序的命令为
add_executable(app main.cc)
add_executable(app2 EXCLUDE_FROM_ALL main.cc)
app为最后编译成功的可执行程序,main.cc表示编译这个可执行程序需要的源文件,而可选项EXCLUDE_FROM_ALL 表示将可执行程序app2排除在all之外,需要明确指定才能编译
EXCLUDE_FROM_ALL 这个可选项什么意思呢?
我们在CMakeLists.txt文件中写入以下内容
cmake_minimum_required(VERSION 3.0)
project(demo_project)
add_executable(app main.cc)
add_executable(app2 EXCLUDE_FROM_ALL main.cc)
然后执行
cmake -S . -B build
首先进入build文件夹
先执行
make
可以看到,此时使用make,仅仅只编译了app,并未编译app2
事实上,make命令其实执行的是make all
接下来我们重新执行
make app2
可以看到,由于EXCLUDE_FROM_ALL 的作用,我们在使用make命令编译时,必须手动指明要编译的目标文件名
库文件编译
如果要编译库文件,则使用的命令是
add_library(<name>[STATICSHAREDMODULE]
[EXCLUDE FROM ALL][<source>...])
其使用方式与add_executable一样,只是库文件有静态库和动态库之分,因此add_library命令有一个可选项用于指定编译动态库还是静态库,默认情况下不指定选项时编译为静态库
add_library(mprpc mprpcapplication.cpp)
如上述命令表示将 mprpcapplication.cpp文件编译为静态库
而如果要编译为动态库,则需要指定为
add_library(mprpc SHARED mprpcapplication.cpp)
引用库文件
引用库文件时使用命令
target_link_libraries
比如以下命令,表示我要编译生成一个静态库文件mprpc,而这个库文件在编译时要依赖于其他的第三方库,这是就需要使用target_link_libraries命令
add_library(mprpc ${SRC_LIST})
target_link_libraries(mprpc muduo_net muduo_base pthread zookeeper_mt)