ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Cmake入门

Cmake入门 1、 Cmake概述Cmake是一个项目构建工具并且是跨平台的。他解决了自己写MakeFile不能跨平台文件依赖关系太强的问题。Cmake允许开发者指定整个工程的编译流程自动生成本地化的Makefile和工程文件最后用户只需要make编译即可。2、Cmake使用步骤如下图所示的文件目录所有的源文件都在一个目录下编写CmakeLists.txt如下当前目录下编写CmakeLists.txtcmake_minimum_required(VERSION3.1)project(PCF)add_executable(app.exe add.c div.c main.c multi.c sub.c)如上图所示为一个最简单的CmakeLists.txt的使用方法。新建build文件夹并进入mkdirbuildcdbuild执行Cmakecmake..make3、定义变量3.1 定义和使用变量set(SRC add.c div.c mult.c main.c)set(SRC add.c;div.c;mult.c;main.c)add_executable(app.exe${SRC})3.2 指定C标准#增加-stdc11set(CMAKE_CXX_STANDARD11)#增加-stdc14set(CMAKE_CXX_STANDARD14)#增加-stdc17set(CMAKE_CXX_STANDARD17)3.3 指定输出路径set(HOME/home/pcf)set(WORDDIR ./3rdparty/workdir)set(EXECUTABLE_OUTPUT_PATH${HOME}/bin)如果这个路径不存在会自动创建3.4 指定编译标准在 CMake 中CMAKE_CXX_FLAGS是一个用于指定 C 编译器选项的变量。你可以将不同的编译选项添加到这个变量中以影响编译过程的行为。以下是一些常用的CMAKE_CXX_FLAGS值及其说明优化选项-O0禁用优化默认选项。-O1启用一级优化。-O2启用二级优化推荐用于生产。-O3启用三级优化适用于对性能要求极高的程序。-Os优化生成的代码大小。-Ofast启用所有的优化并可能不符合标准如允许不精确的浮点运算。警告和错误-Wall启用所有常见的警告。-Wextra启用额外的警告。-Werror将所有警告视为错误。-Wpedantic启用严格的标准遵循警告。调试选项-g生成调试信息通常在调试版本中使用。-g3生成详细的调试信息。语言标准-stdc11启用 C11 标准。-stdc14启用 C14 标准。-stdc17启用 C17 标准。-stdc20启用 C20 标准。-stdgnu11启用 GNU 扩展的 C11 标准。特定于平台的选项-m32生成 32 位程序在支持的系统上。-m64生成 64 位程序在支持的系统上。-fPIC生成位置无关的代码通常用于共享库。其他选项-fopenmp启用 OpenMP 支持并行编程。-fsanitizeaddress启用地址消毒检测内存错误。-fsanitizeundefined启用未定义行为消毒。示例如果你想在 CMakeLists.txt 中设置这些选项可以这样做target_compile_options(my_app PRIVATE-stdc17-O2-Wall)设置构建类型你还可以通过设置CMAKE_BUILD_TYPE来指定常用的构建选项set(CMAKE_BUILD_TYPE Release)# 对于优化set(CMAKE_BUILD_TYPE Debug)# 对于调试特定构建类型的标志CMake 还提供了一些预定义的构建类型标志可以在不同的构建类型中使用set(CMAKE_CXX_FLAGS_RELEASE “-O2”) # Release 构建set(CMAKE_CXX_FLAGS_DEBUG “-g -O0”) # Debug 构建set(CMAKE_CXX_FLAGS_MINSIZEREL “-Os”) # MinSizeRel 构建set(CMAKE_CXX_FLAGS_RELWITHDEBINFO “-O2 -g”) # RelWithDebInfo 构建设置编译选项的方法有一些老的设置编译选项的方法set(CMAKE_CXX_FLAGS -O2 -Wall -Wextra -g -stdc17),这种适合在顶层配置基础属性然后在字目录的CMake中使用target_compile_options追加编译选项特性add_compile_optionstarget_compile_optionsset_target_properties‌作用范围‌‌目录级/全局‌影响当前目录及之后所有子目录中创建的目标。‌目标级 (Target)‌仅影响指定的某个具体目标库或可执行文件。‌目标级 (Target)‌仅影响指定的某个具体目标。‌控制粒度‌粗粒度。无法区分不同目标的需求容易导致“选项污染”。细粒度。支持 PRIVATE/PUBLIC/INTERFACE 关键字精确控制依赖传递。属性级。用于设置目标的元数据或特定行为属性。‌主要用途‌快速为整个项目或子模块统一添加编译标志如警告选项。为特定库或可执行文件定制编译参数如优化级别、特定警告、标准版本。设置版本号、输出文件名、链接属性、包含目录路径等非标志类属性。‌现代实践推荐度‌❌ ‌不推荐‌除非是非常简单的单目标项目否则易引发维护问题。✅ ‌强烈推荐‌符合现代 CMake “以目标为中心”的设计哲学。✅ ‌推荐‌用于管理非编译标志类的目标属性。‌典型参数示例‌-Wall, -O2, -stdc17-Wall, -Werror,-gVERSION, SOVERSION, OUTPUT_NAME, POSITION_INDEPENDENT_CODE4、搜索文件4.1 方式公式aux_source_directory(dir var)dir 要搜索的路径var 将从dir目录下搜索到的源文件列表存储到该变量中cmake_minimum_required(VERSION 3.0) project(CALC) set(HOME /home/pcf) set(EXECUTABLE_OUTPUT_PATH ${HOME}/bin) include_directories(${PROJECT_SOURCE_DIR}/include) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src SRC_LIST) add_executable(app ${SRC_LIST})4.2 方式2公式file(GLOB/GLOB_RECURSE 变量名 要搜索的文件路径和文件类型)GLOB: 只在指定目录下搜索GLOB_RECURSE递归搜索指定目录变量存储搜索结果要搜索的文件路径和文件类型file(GLOB_RECURSE CPP_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) file(GLOB_RECURSE C_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.c) set(SRC_LIST CPP_SRC C_SRC) #组合 file(GLOB MAIN_HEAD ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h)cmake_minimum_required(VERSION 3.0) project(CALC) set(HOME /home/pcf) set(EXECUTABLE_OUTPUT_PATH ${HOME}/bin) include_directories(${PROJECT_SOURCE_DIR}/include) file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) add_executable(app ${SRC_LIST})5、包含头文件include_directories(头文件路径)6、制作库文件6.1 制作静态库在cmake中如果要制作静态库需要使用的命令如下cmake_minimum_required(VERSION 3.1) project(test) file(GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) include_directories(${PROJECT_SOURCE_DIR}/include) add_library(rcp STATIC ${SRC}) #制作后生成的静态库名字为 librcp.a6.2 制作动态库cmake_minimum_required(VERSION 3.1) project(test) file(GLOB SRC ${PROJECT_SOURCE_DIR}/src) include_directories(${PROJECT_SOURCE_DIR}/include) add_library(rcp SHARED ${SRC})6.3 指定动态库生成路径set(LIBRARY_OUTPUT_PATH /home/liuzhenguang/lib)7、链接静态库:::warning链接静态库指定静态库路径:::cmake_minimum_required(VERSION 3.0) project(test) include_directories(${PROJECT_SOURCE_DIR}/include)#指定头文件路径 link_directories(${PROJECT_SOURCE_DIR}/lib)#指定静态库路径 link_libraries(rcp clac)#链接静态库 add_executable(app ${SRC_LIST})8、链接动态库target_link_libraries( target PRIVATE|PUBLIC|INTERFACE items PRIVATE|PUBLIC|INTERFACE items ... )**target:**指定要加载的动态库文件的名字该文件可能是一个源文件该文件可能是一个动态库该文件可能是一个可执行文件:::warning应该将链接动态库的地方放在最后:::cmake_minimum_required(VERSION 3.0) project(test) file(GLOB SRC ${PROJECT_SRC_DIR}/src) include_directories(${PROJECT_SRC_DIR}/include) link_directories(${PROJECT_SRC_DIR}/lib) add_executable(app ${SRC}) target_link_libraries(app PUBLIC calc PUBLIC add)9、日志10、list操作添加list(APPEND tmp xxx1 xxx2 ${SRC})添加xxx1、xxx2和SRC到tmp中删除指定元素_ITEM SRC ${PROJECT_SOURCE_DIR}/src/main.cpp)从SRC中删除main.cpp删除时要使用绝对路径获取 list 的长度。list(LENGTH )LENGTH子命令LENGTH用于读取列表长度当前操作的列表新创建的变量用于存储列表的长度。读取列表中指定索引的的元素可以指定多个索引list(GET [ …] )当前操作的列表列表元素的索引从0开始编号索引也可以是负数-1表示列表的最后一个元素-2表示列表倒数第二个元素以此类推。新创建的变量存储指定索引元素的返回结果也是一个列表。将列表中的元素用连接符字符串连接起来组成一个字符串list (JOIN )当前操作的列表指定的连接符字符串新创建的变量存储返回的字符串查找列表是否存在指定的元素若果未找到返回-1list(FIND )当前操作的列表要搜索的元素新创建的变量如果列表中存在那么返回在列表中的索引如果未找到则返回-1。在list中指定的位置插入若干元素list(INSERT element_index [ …])将元素插入到列表的0索引位置list (PREPEND [ …])将列表中最后元素移除list (POP_BACK […])将列表中第一个元素移除list (POP_FRONT […])将指定索引的元素从列表中移除list (REMOVE_AT [ …])移除列表中的重复元素list (REMOVE_DUPLICATES )列表翻转list(REVERSE )列表排序list (SORT [COMPARE ] [CASE ] [ORDER ])COMPARE指定排序方法。有如下几种值可选STRING:按照字母顺序进行排序为默认的排序方法FILE_BASENAME如果是一系列路径名会使用basename进行排序NATURAL使用自然数顺序排序CASE指明是否大小写敏感。有如下几种值可选SENSITIVE: 按照大小写敏感的方式进行排序为默认值INSENSITIVE按照大小写不敏感方式进行排序ORDER指明排序的顺序。有如下几种值可选ASCENDING:按照升序排列为默认值DESCENDING按照降序排11、编译宏在CmakeLists.txt中可以定义一些宏名而不是在源文件或头文件中定义宏来使得某些代码是否生效add_definations(-D宏名称)12、嵌套的Cmake12.1 一些原则根节点CmakeLists.txt中变量全局有效父节点CmakeLists.txt中变量可以在子节点中使用子节点CmakeLists.txt中变量只能在当前子节点中使用12.2 添加子目录我们还需要知道在 CMake 中父子节点之间的关系是如何建立的这里需要用到一个 CMake 命令add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])12.3 解决问题12.3.1 根目录cmake_minimum_required(VERSION 3.0) project(test) # 定义变量 # 静态库生成的路径 set(LIB_PATH ${CMAKE_CURRENT_SOURCE_DIR}/lib) # 测试程序生成的路径 set(EXEC_PATH ${CMAKE_CURRENT_SOURCE_DIR}/bin) # 头文件目录 set(HEAD_PATH ${CMAKE_CURRENT_SOURCE_DIR}/include) # 静态库的名字 set(CALC_LIB calc) set(SORT_LIB sort) # 可执行程序的名字 set(APP_NAME_1 test1) set(APP_NAME_2 test2) # 添加子目录 add_subdirectory(calc) add_subdirectory(sort) add_subdirectory(test1) add_subdirectory(test2)12.3.2 calc目录cmake_minimum_required(VERSION 3.0) project(CALCLIB) aux_source_directory(./ SRC) include_directories(${HEAD_PATH}) set(LIBRARY_OUTPUT_PATH ${LIB_PATH}) add_library(${CALC_LIB} STATIC ${SRC})12.3.4 testcmake_minimum_required(VERSION 3.0) project(CALCTEST) aux_source_directory(./ SRC) include_directories(${HEAD_PATH}) link_directories(${LIBPATH}) link_libraries(${CALC_LIB}) set(EXECUTABLE_OUTPUT_PATH ${EXEC_PATH}) add_executable(${APP_NAME_1} ${SRC})13 库中链接库13.1 库中链接静态库在库中链接静态库和可执行文件中链接静态库无异13.2 库中链接动态库在库中链接动态库和可执行文件中链接动态库无异附录宏功能PROJECT_SOURCE_DIRCMakeLists.txt所在路径CMAKE_CURRENT_SOURCE_DIRCMakeLists.txt所在路径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目录进行的构建那么得到的就是这个目录的路径
返回列表