1.预定义宏
bash
宏 功能
PROJECT_SOURCE_DIR 使用cmake命令后紧跟的目录,一般是工程的根目录
PROJECT_BINARY_DIR 执行cmake命令的目录
CMAKE_CURRENT_SOURCE_DIR 当前处理的CMakeLists.txt所在的路径
CMAKE_CURRENT_BINARY_DIR target编译目录
EXECUTABLE_OUTPUT_PATH 重新定义目标二进制可执行文件的存放位置
LIBRARY_OUTPUT_PATH 重新定义目标链接库文件的存放位置
PROJECT_NAME 返回通过PROJECT指令定义的项目名称
CMAKE_BINARY_DIR 项目实际构建路径,假设build目录下进行构建,那么得到的就是这个目录的路径
例如:
bash
cmake_minimum_required(VERSION 3.10)
project(MyProject)
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_COMPILER "clang++")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_executable(MyProject main.cpp)
#这是一个CMakeLists.txt文件 -#注释
#[[ 块注释 大小写可以混用]]
cmake_minimum_required(VERSION 3.0.0) #指定使用的cmake的最低版本,可选
project(APP) #定义工程名称
set(CMAKE_BUILD_TYPE Debug) #指定为Debug模式
find_package(a REQUIRED)# 查找 a
2.执行程序
bash
#[[ add_executable(可执行程序名 源文件名称)
#这里的可执行程序名和project中项目名没有任何关系
#源文件名称可以多个,用" ;"间隔 ]]
add_executable(app add.c;div.c;main.c)
3.定义变量
bash
#[[定义变量 SETSET(VAR [VALUE]) AR:变量名 VALUE:变量值 ]]
#各源文件之间使用空格 或 分号;间隔
set(SRC_LIST add.c div.c main.c)
set(SRC_LIST add.c;div.c;main.c)
add_executable(app ${SRC_LIST})
4.指定使用的C++标准
bash
#c++11,c++14,c++17,c++20
bash
#g++ *.cpp -std=c++11 -o app
#在CMakeLists.txt增加-std=c++11 宏DCMAKE_CXX_STANDARD
set(CMAKE_CXX_STANDARD 11)
#在执行cmake命令时制定出这个宏的值
cmake .. -DMAKE_CXX_STANDARD=11
5.指定输出路径
bash
#宏EXECUTABLE_OUTPUT_PATH
set(HOME /home/robin/linux/sort)
set(EXCUTABLE_OUTPUT_PATH ${HOME}/bin)
6.搜索文件
bash
#使用aux_source_directory或file
#aux_source_directory(<dir> <variable>)
#dir:要搜索的目录,variable:将从dir目录下搜索到的源文件列表存储到该变量中
#搜索src目录下的源文件
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src SRC_LIST)
add_executable(app ${SRC_LIST})
#file搜索想要的文件
#file(GLOB/GLOB_RECURSE 变量名 要搜索的文件路径和文件类型)
#GLOB:将指定目录下搜索到的满足条件的所有文件名生成一个列表,
#并将其存储到变量中
#GLOB_RECURSE:递归搜索指定目录,将搜索到满足条件的文件名生成一个列表,并将其存储到变量中
#搜索到当前目录的src目录下的所有源文件,并将其存储到变量中
file(GLOB MAIN_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
file(GLOB MAIN_HEAD ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h)
#CMAKE_CURRENT_SOURCE_DIR宏表示当前访问的CMakeLists.txt文件所在的路径
#关于要搜索的文件路径可加引号,也可不加
file(GLOB MAIN_HEAD "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h")
7.包含头文件
bash
#include_directories(headpath)
include_directories(${PROJECT_SOURCE_DIR}/include)
#PROJECT_SOURCE_DIR宏对应是工程的根目录
8.制作动态库或静态库
8.1 制作静态库
bash
#add_library(库名称 STATIC 源文件1 [源文件2] ...)
#在Linux中,静态库名字分为三部分:lib+库名称 +.a
include_directories(${PROJECT_SOURCE_DIR}/include)
file(GLOB SRC_LIST "${CMAKE_CURRENT_DIR}/src/*.cpp")
add_library(calc STATIC $(SRC_LIST})
#生成libcalc.a
8.2 制作动态库
bash
#add_library(库名称 SHARED 源文件1 [源文件2] ...)
#在Linux中,动态库名字分为三部分:lib+库名称 +.so
include_directories(${PROJECT_SOURCE_DIR}/include)
file(GLOB SRC_LIST "${CMAKE_CURRENT_DIR}/src/*.cpp")
add_library(calc SHARED ${SRC_LIST})
#生成libcalc.so
8.3 指定输出的路径
bash
#方式1-适用于动态库
include_directories(${PROJECT_SOURCE_DIR}/include)
file(GLOB SRC_LIST "${CMAKE_CURRENT_DIR}/src/*.cpp")
#设置动态库生成路径
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
add_library(calc SHARED ${SRC_LIST})
#方式2-都适用
#LIBRARY_OUTPUT_PATH
include_directories(${PROJECT_SOURCE_DIR}/include)
file(GLOB SRC_LIST "${CMAKE_CURRENT_DIR}/src/*.cpp")
#设置动态库/静态库生成路径
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
#add_library(calc SHARED ${SRC_LIST})
add_library(calc STATIC ${SRC_LIST})
9.包含库文件
9.1 链接静态库
bash
#链接静态库命令:
#link_library(<static lib> ...])
#参数1:指定出要链接静态库的名字
#参数2:要链接的其他静态库的名字
#如果静态库是自定义的,可以将静态库的路径指定出来
#link_directories(<lib path>)
cmake_minimum_required(VERSION 3.0)
project(CALC)
#搜索指定目录下的源文件
file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
#包含静态库路径
link_directories(${PROJECT_SOURCE_DIR}/include)
#链接静态库
link_library(calc)
add_executable(app ${SRC_LIST})
#例如:
cmake_minimum_required(VERSION 3.0)
project(YourProjectName)
# 查找ncurses库
find_package(Curses REQUIRED)
# 添加可执行文件
add_executable(your_target_name your_source_files.cpp)
# 包含ncurses头文件和链接ncurses库
include_directories(${CURSES_INCLUDE_DIR})
target_link_libraries(your_target_name ${CURSES_LIBRARIES})
9.2 链接动态库
bash
target_link_libraries(
<target>
<PRIVATE|PUBLIC|INTERFACE> <item>...)
)
用于指定一个目标(如可执行文件或库)在编译时需要链接哪些库。它支持指定库的名称、路径以及链接库的顺序。
target:指定要加载的库的文件名字
该文件可能是一个源文件
该文件可能是一个动态库/静态库文件
该文件可能是一个可执行文件
PRIVATE|PUBLIC|INTERFACE:动态库的访问权限,默认为PUBLIC
bash
#在cmake中指定要链接的动态库的时候,应该将命令写到生成了可执行文件之后
file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
# 添加并指定最终生成的可执行程序名
add_executable(app ${SRC_LIST})
# 指定可执行程序要链接的动态库名字
target_link_libraries(app pthread)
#app:对应的是最终生成的可执行程序的名字
#phread:可执行程序要加载的动态库,全名libpthread.so
10日志
bash
#message([STATUS|WARNING|AUTHOR_WARNING|FATAL_ERROR|SEND_ERROR]
#"message to display" ...)
#(无):重要信息
#STATUS:非重要信息
#WARNING:CMake警告,会继续执行
#AUTHOR_WARNING:CMake警告(dev),会继续执行
#SEND_ERROR:CMake错误,继续执行,但是会跳过生成的步骤
#FATAL_ERROR:CMake错误,终止所有处理过程
#输出一般日志信息
message(STATUS "source path:${PROJECT_SOURCE_DIR}")
#输出警告信息
message(WARNING "source path:${PROJECT_SOURCE_DIR}")
#输出错误信息
message(FATAL_ERROR "source path:${PROJECT_SOURCE_DIR}")
11变量操作
11.1 追加
源文件不在同一目录下,但是需要进行编译来生成最终的可执行文件或者库文件
file命令对源文件进行搜索,字符串拼接set,也可以使用list命令
bash
#使用set拼接
#set(变量名 ${变量名1} ${变量名2})
cmake_minimum_required(VERSION 3.0)
project(TEST)
set(TEMP "hello world")
file(GLOB SRC_1 ${PROJECT_SOURCE_DIR}/src1/*.cpp)
file(GLOB SRC_2 ${PROJECT_SOURCE_DIR}/src2/*.cpp)
#追加(拼接)
set(SRC_1 ${SRC_1} ${SRC_2} ${TEMP})
message(STATUS "message:${SRC_1}")
#使用list拼接
list(APPEND <list> [<element> ...])
#list命令比set强大,字符串拼接只是它的其中一个功能,APPEND表示进行数据追加,后面的参数和set一样
#在CMake中,使用set命令可以创建一个list。一个在list内部是一个由"分号;"
#分割的一组字符串。例如,set(var a b c d e)命令将会创建一个list:a;b;c;d;e,但是会跳过生成的步骤
#最终打印变量值的时候得到的是abcde.
set(tmp1 a;b;c;d;e)
set(tmp2 a b c d e)
message(${tmp1})
message(${tmp2})
#输出结果
#abcde
#abcde
11.2字符串移除
bash
#list(REMOVE_ITEM <list> <value> [<value> ...])
cmake_minimum_required(VERSION 3.0)
project(TEST)
set(TEMP "hello,world")
file(GLOB SRC_1 ${PROJECT_SOURCE_DIR}/*.cpp)
#移除前日志
message(STATUS "message:${SRC_1}")
#移除main.cpp 绝对路径
list(REMOVE_ITEM SRC_1 ${PROJECT_SOURCE_DIR}/main.cpp)
#移除后日志
message(STATUS "message:${SRC_1})
12.宏定义
bash
#gcc test.c -DDEBUG -o app
#-D指定出要定义的宏的名字,其名字为DEBUG
CMake中对应命令为add_definitions
add_definitions(-D宏名称)
13.嵌套的CMake
bash
#根节点CMakeLists.txt中的变量全局有效
#父节点CMakeLists.txt中的变量可以在子节点中使用
#子节点CMakeLists.txt中的变量只能再当前节点中使用
add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
14.流程控制
bash
if(<condition>)
<commands>
elseif(<condition>)
<commands>
else()
<commands>
endif()
14.1 文件操作
bash
#判断文件或者目录是否存在
if(EXISTS path-to-file-or-directory)
如果文件或者目录存在返回True,否则返回False
#判断是不是目录
if(IS_DIRECTORY path)
path必须是绝对路径,存在返回True,不存在返回False
#判断是不是软链接
if(IS_SYMLINK file-name)
此处的file-name对应的路径必须是绝对路径
如果软链接存在返回True,软链接不存在返回False
软链接相当于windows里的快捷方式
#判断是不是绝对路径
if(IS_ABSOLUTE path)
是True
14.2循环
bash
foreach 和 while
#foreach
foreach(<loop_var> RANGE <stop>)
RANGE:关键字,表示要遍历范围 [0,stop],右侧是闭区间包含 stop 这个值。
stop:这是一个正整数,表示范围的结束值,在遍历的时候从0开始,最大值为stop
loop_var:存储每次循环取出的值
foreach(item RANGE 10)
message(STATUS "当前遍历的值为:${item}")
endforeach()
foreach(<loop_var> RANGE <start><stop>[<step>])
step默认步长为1,可以不设置
foreach(item RANGE 10 30 2)
message(STATUS "当前遍历的值为:${item}")
endforeach()
foreach(<loop_var> IN [LISTS [<lists>]] [ITEMS[items]])
cmake_minimum_required(VERSION 3.2)
project(test)
#创建list
set(WORD a b c d e)
set(NAME ace sabo luffy)
#遍历list
foreach(item IN LISTS WORD NAME)
message(STATUS "当前遍历的值为:${item}")
endforeach()
#或者
foreach(item IN INTEMS ${WORD}${NAME})
message(STATUS "当前遍历的值为:${item}")
endforeach()
while()
<commands>
endwhile()