项目配置
cmake_minimum_required(VERSION 3.0) # 最低 cmake 版本
project(app C) # 项目名称和开发语言
add_executable(可执行文件名称 源文件) # 生成可执行文件指定C++标准
方法1
set(CMAKE_CXX_STANDARD 11)
方法2 使用命令时指定
cmake CMakeLists.txt -DCMAKE_CXX_STANDARD=14指定输出路径
set(EXECUTABLE_OUTPUT_PATH 完整路径)注意:指定相对路径的话就是 Makefile 所在的目录而言
变量与LIST
定义变量
写法1
set(SRC_LIST add.c div.c main.c mult.c sub.c)
写法2
set(SRC_LIST add.c;div.c;main.c;mult.c;sub.c)使用变量
${变量名}
变量拼接
写法1
set(新的变量名 ${变量名1} ${变量名2} ...)
写法2
list(APPEND 新的变量名 ${变量名1} ${变量名2} ...)移除字符串
list(REMOVE_ITEM 变量 要移除的那个文件)引入源文件
可以在 add_executable 中手动添加文件,但是不推荐。
方法1
aux_source_directory(选择的目录 将这些文件存储到哪个变量中)
方法2
file(GLOB或者GLOB_RECURSE 变量名 要搜索的文件路径和文件类型)file("") 双引号可加可不加
GLOB:不递归搜索
GLOB_RECURSE:递归搜索
对于file第二个参数,使用通配符
/src/*.cpp引入头文件
include_directories(头文件所在路径)路径使用空格隔开,但是推荐使用多个 include_directories,或是换行
库文件制作
不仅可以制作可执行文件,还可以制作库文件。
静态库与动态库?
静态库:在编译时直接链接到可执行文件中,程序可直接执行而不依赖外部的库文件。
Windows:.lib
Linux:.a
动态库:编译时不会链接到可执行文件中,而是在程序启动或运行时动态的加载库文件。因此想让程序运行,除了可执行文件,还得有这些库。
Windows:.dll
Linux:.so
优缺点显而易见:
系统库与第三方库?
系统库:
第三方库:你自己写的库,或者从网上下载的库,除了系统库呗。
静态库制作
add_library(库名称 STATIC 库文件(多个使用空格隔开,可使用变量))linux中:lib库名称.a
指定输出路径
只能
set(LIBRARY_OUTPUT_PATH 路径)动态库制作
add_library(库名称 SHARED 库文件(多个使用空格隔开,可使用变量))linux中:lib库名称.so
指定输出路径
set(EXECUTABLE_OUTPUT_PATH 路径)
或者
set(LIBRARY_OUTPUT_PATH 路径)引入库文件
手动引入
【cmake学习】cmake 引入第三方库(头文件目录、库目录、库文件)_cmake添加第三方库-CSDN博客
注意,链接库一定要放在 add_executable 后面!!!
库的名称可以是 libxxx.a 也可以是 xxx
引入库路径,如果你需要系统库就不用填这个
link_directories(库的路径)引入库文件,这里指定的是全局默认库,所有工程都会链接到。
link_libraries(库名称)一个项目中的多个工程使用的库可能不一样,使用全局默认库的话,对于那些不需要的库也链接进去了,占空间。
target_link_libraries 可以指定某个工程需要哪些库文件。
这个一定要放在 add_executable 后面,因为你只有指定了项目的可执行文件或库,才能去给它分配库。
target_link_libraries(工程名
第一个库文件
第二个库文件
...
)也可以使用空格隔开
批量引入
手动引入麻烦了,要写一大堆。
打印日志
相当于 printf()
message(等级 "字符串")添加宏定义
add_definitions(-D宏名称)// 例如需要 DENUG 这个宏
add_definitions(-DDEBUG)使用宏定义可以
CMake宏
CMake嵌套
对于复杂的需要分层的项目,就要用到 CMake 嵌套,和 Maven 一个道理。
在工程的主目录下有一个 CMakeLists.txt,称为父节点,同时在项目的不同子目录中也有很多 CMakeLists.txt,称为子节点。
子节点可以使用父节点的变量,父节点不能使用子节点的变量,经常在父节点中定义全局变量。
在父节点中
add_subdirectory(子目录路径 [binary_dir] [EXCLUDE_FROM_ALL])
binary_dir:指定了输出文件的路径,一般不需要指定,忽略即可。
EXCLUDE_FROM_ALL:在子路径下的目标默认不会被包含到父路径的ALL目标里,并且也会被排除在IDE工程文件之外。用户必须显式构建在子路径下的目标。子节点只关心它的目录,和之前的一样,只不过可以使用父节点中的变量了。
流程控制
条件判断
if(条件)
...
elseif(条件1)
...
else()
...
endif()elseif和else可选
条件表达式
逻辑
NOT 条件
条件1 AND 条件2
条件1 OR 条件2
大小
文件
是否存咋
if(EXISTS path-to-file-or-directory)是不是目录
if(IS_DIRECTORY path)是不是软链接
if(IS_SYMLINK file-name)是不是绝对路径
if(IS_ABSOLUTE path)其它
是否在列表中
v >= 3.3
if(<variable|string> IN_LIST <variable>)路径是否相等
v >= 3.24
if(<variable|string> PATH_EQUAL <variable|string>)也可以直接使用字符串比较
循环
foreach
foreach(变量 源)
....
endforeach()while
while(<condition>)
<commands>
endwhile()while(${LEN} GREATER 0)
message(STATUS "names = ${NAME}")
# 弹出列表头部元素
list(POP_FRONT NAME)
# 更新列表长度
list(LENGTH NAME LEN)
endwhile()
交叉编译
例如交叉编译工具链使用的是 arm-linux-gnueabihf
# 指定目标平台和芯片架构
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
# 交叉编译工具链所在路径
set(CMAKE_FIND_ROOT_PATH /home/toolchain/arm)
# 指定交叉编译工具
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
set(CMAKE_ASM_COMPILER arm-linux-gnueabihf-as)
# 只在当前系统下查找可执行文件,不考虑目标系统路径
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# 只从目标系统路径中查找库文件,不考虑主机系统路径
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
# 只从目标系统路径中查找头文件,不考虑主机系统路径。
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
# 设置编译器标志,这里要根据不同的芯片架构进行修改
set(CMAKE_C_FLAGS "-mcpu=cortex-a7 -mthumb")
set(CMAKE_CXX_FLAGS "-mcpu=cortex-a7 -mthumb")CMAKE_FIND_ROOT_PATH 是一个变量,可以设置,用于指定目标平台的根目录。
比如你要交叉编译到 ARM32位架构的芯片,你把你要用到的该平台的库、头文件和其他资源放在这里。
设置了这些参数,CMake就不会乱找了,有可能你需要a文件,结果虚拟机上库中也有a文件,那就会引起变编译错误。
交叉编译模板
cmake_minimum_required(VERSION 3.10)
project(mycrossapp)
file(GLOB SRC_LIST ${PROJECT_BINARY_DIR}/*.cpp)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 交叉编译配置
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_FIND_ROOT_PATH /Embbed_WorkSpace/ARM_TOOLCHAIN/arm-linux-gnueabihf-7.5.0)
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
set(CMAKE_ASM_COMPILER arm-linux-gnueabihf-as)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_C_FLAGS "-mcpu=cortex-a7 -mthumb")
set(CMAKE_CXX_FLAGS "-mcpu=cortex-a7 -mthumb")
include_directories(
${PROJECT_BINARY_DIR}/lib/ffmpeg/include
)
link_directories(
${PROJECT_BINARY_DIR}/lib/ffmpeg/lib
)
add_executable(mycrossapp${SRC_LIST})
target_link_libraries(mycrossapp
PRIVATE
avcodec
avformat
swscale
avutil
swresample
)