补充番外14:cmake笔记

linux更新cmake版本(sudo pacman -S cmake)

零、cmake的构建步骤

  • 步骤

1)第一步是cmake -B build,成为配置阶段(configure),这时候只检测环境并生成构建规则,会在build目录下生成本地构建系统能识别的项目文件(Makefile或是.sln)

1)这个阶段可以通过-D设置缓存变量。第二次配置时,之前的-D添加任然会被保留

2)第二步是cmake --build build ,成为构建阶段(build),这时候才实际调用编译器来编译代码

1)cmake -B build -DCMAKE_INSTALL_PREFIX=/opt/openvdb-8.0
设置安装路径为/opt/openvdb-8.0(会安装到/opt/openvdb-8.0/lib/libopenvdb.so)
2)cmake -B build -DCMAKE_BUILD_TYPE = Release
设置构建模式为发布模式
3)cmake -B build  
第二次配置没有-D参数,但是之前-D设置的变量都会保存
(此时缓存里仍有之前定义的CMAKE_BUILD_TYPE和CMAKE_INSTALL_PREFIX)

一、Cmake -B和–build指令(跨平台兼容)

1)cmake -B build

在源码目录用-B直接创建build目录并生成build/Makefile,免去了先创建目录再切换进去制定源码目录的麻烦

2)cmake --build build -j4 (统一了不同平台,linux上会调用make,Windows会调用devenv.exe)

自动调用本地的构建系统在build里面构建,即 :

make -C build -j4

3)sudo cmake --build build --target install

调用本地的构建系统执行install这个目标,即安装

二、Cmake -D 选项:制定配置变量(又称缓存变量,前面有提到)

三、Cmake -G选项 制定要用的生成器

  • 说明
    1)linux默认cmake使用Unix Makefile生成器;windows默认是vs2019生成器;MacOS系统默认是Xcode生成器
    2)可以用-G参数改用别的生成器,例如cmake -GNinja -B build
    3)ninja是专为性能优化的构建系统,和cmake都是行业标准
    4)pip install ninja
    5)ninja是跨平台的
    6)MSBuild是单线程的,比较慢

四、正式开始

1)第一章 添加源文件(add_executable生成可执行文件)

add_executable( [WIN32] [MACOSX_BUNDLE][EXCLUDE_FROM_ALL] source1 [source2 …])
生成可执行文件
add_executable(bin_file_name ${SRC_LIST})

  • 法一
    main.cpp是文件,main是执行文件

add_executable(main  main.cpp)
  • 法二
add_executable(main)
target_sources(main PUBLIC main.cpp)

假如多个源文件

add_executable(main)
target_sources(main PUBLIC main.cpp opther.cpp)
  • 法三:使用变量来存储
add_executable(main)
set(source main.cpp other.cpp)
target_sources(main PUBLIC {sources})
  • 法四(对比法三是增加了批量获取当前目录的.h和.c文件)
add_executable(main)
file(GLOB source *.cpp *.h)
target_sources(main PUBLIC {sources})

备注
GLOB会自动遍历所有文件
CONFIGURE_DEPENDS 每次编译都会重新查找文件

2)第二章添加子目录的文件aux_source_directory

GLOB只能指定一个目录,这里指定了当前目录和当前目录下mylib目录的所有文件

aux_source_directory (dir VAR)
扫描一个目录下所有的源代码文件并将列表存储在一个变量中
aux_source_directory(. DIR_LIB_SRCS)

  • 法一
add_executable(main)
aux_source_directory(. sources)
aux_source_directory(mylib sources)
target_sources(main PUBLIC {sources})
  • 法二
add_executable(main)
file(GLOB_RECURSE sources CONFIGURE_DEPENDS *.cpp *.h)
target_sources(main PUBLIC {sources})

GLOB_RECURSE当前目录下递归搜索,但是这个会把build目录下生成的临时cpp文件也加进来

解决方法:
把源码统一放到src目录下

3)第三章 项目配置变量

(1)CMAKE_BUILD_TYPE 设置构建的类型,调试模式还是发布模式

模式区别:

1)Debug  调试模式,完全不优化,生成调试信息,方便调试系统
2)Release  发布模式,优化程度最高,性能最佳,但是编译比debug慢
3)MinSizeRel  最小体积发布,不完全优化,减少二进制体积
4)RelWithDeblnfo 带调试信息发布,生成的文件比Release更大,因为带有调试的符号信息
5)默认情况下CMAKE_BUILD_TYPE 为空字符串,这时相当于Debug

在这里插入图片描述

  • 补充:设置默认构建模式的默认值

在这里插入图片描述

(2)project 初始化项目信息,并把当前CMakeLists.txt所在位置作为根目录

对于MSVC,会在buile里面生成hellocmake.sln作为“”“IDE眼中的项目”。

在这里插入图片描述

在这里插入图片描述

(4)四个目录的区别

在这里插入图片描述

在这里插入图片描述

(5)其他相关变量

在这里插入图片描述
在这里插入图片描述

(6)projecet的初始化:LANGUAGES字段

在这里插入图片描述

在这里插入图片描述

  • 可以一开始就设置编译的文件语言
    在这里插入图片描述

  • 或者是一开始就声明为空,后面再启用这些语言

在这里插入图片描述

(7)CMAKE_CXX_STANDARD变量设置C++标准
  • CMAKE_CXX_STANDARD_REQUIRED是BOOL类型,可以为ON或OFF,默认OFF
    表示是否一定要支持你制定的C++标准,为ON则发现不支持就报错,用了ON更安全

  • CMAKE_CXX_EXTENSIONS也是BOOL类型,默认为ON。设为ON表示启动GCC特有的一些扩展功能;OFF则关闭GCC的扩展功能,只能用标准的C++

特别备注
1)要兼容其他编译器(如MSVC)的项目,都会设为OFF防止不小心用了GCC才有的特性。
2)用CMAKE_CXX_FLAGS来添加-std=c++17有个缺陷:
GCC用户指定了-std=C++17,不兼容MSVC

在这里插入图片描述
在这里插入图片描述

(8)project的初始化:VERSION字段(设置程序版本号)

在这里插入图片描述

  • 补充:获取任意一个分支项目的版本号
(9)可以嵌套的${}表达式

1)${PROJECT_NAME}求值的结果是hellocmake
2)所以${${PROJECT_NAME}_VERSION}相当于${hellocmake_VERSION}进一步求值的结果也就是刚刚指定的0.2.3了

在这里插入图片描述

(10)cmake_minimun_required指定最低所需的CMAKE版本

在这里插入图片描述

(11)add_dependencies

add_dependencies (target-name depend-target1 depend-target2 …)
定义target依赖的其他target,确保target在构建之前,其依赖的target已经构建完毕

(12)target_compile_options设置编译参数

这个命令是为某个需要编译的目标增加编译选项

target_compile_options(<target> [BEFORE]
  <INTERFACE|PUBLIC|PRIVATE> [items1...]
  [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])

arget_compile_options会增加选项(options)到COMPILE_OPTIONS或者INTERFACE_COMPILE_OPOTIONS目标属性(也就是增加编译选项的意思)。这些选项会在编译给定目标()时使用,给定目标必须已经通过add_executable()或者add_library()这种命令添加到项目中,并且不能是别名目标。

  • 使用举例
cmake_minimum_required(VERSION 3.10)
 
project(cmake_gcc_options_try_c C)
 
set(CMAKE_C_STANDARD 11)
 
set(CMAKE_C_STANDARD_REQUIRED ON)
 
add_executable(cmake_gcc_options_try_c main.c)
 
target_compile_options(cmake_gcc_options_try_c
                       PUBLIC -W -Wall -Wextra -pedantic -pedantic-errors)
备注:CMake选择编译器及设置编译器选项

(1)命令行选择编译器

cmake .. -DCMAKE_CXX_COMPILER=/usr/local/gcc/bin/g++
-wall表示要生成所有警告信息

(2)在配置文件tool.cmake中指定编译器

set (CMAKE_C_COMPILER "/usr/local/gcc/bin/gcc")
set (CMAKE_CXX_COMPILER "/usr/local/gcc/bin/g++")

注:这两条命令应该放在文件的开始位置(cmake_minimum_required命令之下,其他命令之上),否则可能无效。
(3)区别
在这里插入图片描述
综上,对于一些在整个项目中通用的编译选项可以使用add_compile_options命令来添加比较方便,对于各个模块中的独立选项则使用CMAKE_CXX_FLAGS变量更好。

这里用到的CMAKE_CXX_FLAGS变量是只针对C++编译器的选项,对于其他编程语言,只要替换部分就可以,在当前cmake版本(3.17.2)中支持如下语言:

CMAKE_C_FLAGS:C语言编译器选项,对应于环境变量CFLAGS
CMAKE_CXX_FLAGS:C++语言编译器选项,对应于环境变量CXXFLAGS
CMAKE_CUDA_FLAGS:CUDA语言编译器选项,对应于环境变量CUDAFLAGS
CMAKE_Fortran_FLAGS:Fortran语言编译器选项,对应于环境变量FFLAGS

(4)实用举例

# 判断编译器类型,如果是gcc编译器,则在编译选项中加入c++11支持
if(CMAKE_COMPILER_IS_GNUCXX)
    add_compile_options(-std=c++11)
    message(STATUS "optional:-std=c++11")   
endif(CMAKE_COMPILER_IS_GNUCXX)


cmake_minimum_required(VERSION 3.5)
project(eignface_demo)
 
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lstdc++ -lm")
set(OPENCV_LIB opencv_highgui opencv_objdetect opencv_core opencv_imgproc opencv_contrib)
set(SRC_CPP EigenFace.cpp)
set(GCC_PATH D:/code/mingw)
 
if (HISI)
    set(CMAKE_C_COMPILER $(GCC_PATH)/bin/gcc.exe)
    set(CMAKE_CXX_COMPILER $(GCC_PATH)/bin/g++.exe)
	set(TOOLCHAIN_DIR "/opt/hisi-linux-nptl/arm-hisiv100-linux/target")
	set(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN_DIR})
	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_CXX_COMPILER ${TOOLCHAIN_DIR}/bin/arm-hisiv100nptl-linux-g++)
    set(CMAKE_C_COMPILER ${TOOLCHAIN_DIR}/bin/arm-hisiv100nptl-linux-gcc)
    include_directories(./hisi_opencv/include/)
    link_directories(./hisi_opencv/lib/)
    message("-- Use hisi compile demo")
    add_executable(eignface_hisi  ${SRC_CPP})
    target_link_libraries(eignface_hisi ${OPENCV_LIB})
else()
    set(CMAKE_C_COMPILER "/usr/bin/gcc")
    include_directories(./gcc_opencv/include/)
    link_directories(./gcc_opencv/lib/)
    message("-- Use gcc compile demo")
    add_executable(eignface_gcc  ${SRC_CPP})
    target_link_libraries(eignface_gcc ${OPENCV_LIB})
endif()
(13)target_include_directories

该命令可以指定目标(exe或者so文件)需要包含的头文件路径。命名的<目标>必须是由add_executable()或add_library()之类的命令创建的,并且不能是ALIAS目标。通过显式地使用AFTER或BEFORE,就可以在附加和预挂之间进行选择,而不是依赖默认值。

  • 备注
需要INTERFACE、PUBLIC和PRIVATE关键字来指定以下参数的范围。PRIVATE和
PUBLIC项将填充<target>的INCLUDE_DIRECTORIES属性。PUBLIC和INTERFACE项将
填充<target>的INTERFACE_INCLUDE_DIRECTORIES属性

private,public,interface的使用

  • 例子
    有如下文件的目录,一个math库,main.cc文件来调用math库,math库实现了一个整数的幂运算
    在这里插入图片描述
    1)math目录的cmakelist
cmake_minimum_required (VERSION 2.8)
 
project(MathFunctions)
 
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_LIB_SRCS 变量
aux_source_directory(. DIR_LIB_SRCS)
 
# 指定生成 MathFunctions 链接库
add_library (MathFunctions ${DIR_LIB_SRCS})

2)主目录的cmakelist

# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
 
# 项目信息
project (Demo3)
 
# 添加 math 子目录,输出.a文件到output目录
add_subdirectory(math output)
 
# 指定生成目标
add_executable(Demo main.cc)
 
# 将子目录的头文件包含到目标中
target_include_directories(Demo PUBLIC math)
 
# 添加链接库
target_link_libraries(Demo MathFunctions)
(14)add_library(有对对象库的定义)

使用该命令可以生成(静态/动态)库so或者.a文件,它有两种命令格式

  • 用法一:
add_library(<name> [STATIC | SHARED | MODULE]
            [EXCLUDE_FROM_ALL]
            [<source>...])

生成一个名为 < name > 的library,在项目中必须是全局唯一的。

1.1、< name > 应该保证在一个项目中的唯一性。
1.2、实际的library文件名基于Native平台的约定规则,比如:lib< name >.a, < name >.lib等
1.3、STATIC,SHARED,MODULE用于指定创建的library类型。
STATIC库:是object文件的归档,用于链接其他targets。
SHARED库:是动态链接,并于运行时加载。
MODULE库:不能链接到其他targets,但是可以用dlopen之类的方法在运行时动态加载。
1.4、如果没有明确指定上述类型,那么如果BUILD_SHARED_LIBS变量值为ON,则默认是SHARED,否则默认STATIC。
1.5、对于SHARED和MODULE类型的库,POSITION_INDEPENDENT_CODE属性自动置为ON。
1.6、EXCLUDE_FROM_ALL:表明该target是否从默认构建target中排除。
1.7、source参数可以使用generator表达式($ <…>)。

  • 用法二:
add_library(<name> OBJECT [<source>...])

创建一个object对象库,该对象库只编译源文件,但不链接。

由add_library()或 add_executable()创建的目标可以使用$<TARGET_OBJECTS:name>这样的表达式作为源引用对象,其中,name是对象库的名称。格式如下:

add_library(... $<TARGET_OBJECTS:name> ...)
add_executable(... $<TARGET_OBJECTS:name> ...)
  • 使用举例
(大家习惯通过 $<TARGET_OBJECTS:name>引用object文件。其实object library与静态
库,动态库一样,都是可以设置PUBLIC/PRIVATE属性的,再通过target_link_library()命令
链接)

四个文件hello.h,hello.cpp,main.cpp,CMakelist.txt,目录如下
在这里插入图片描述

(1)第一种library格式

cmake_minimum_required (VERSION 3.12.1)
 
project (Demo)
 
# 生成对象库文件
add_library(hello hello.cpp)
 
# 添加头文件目录
target_include_directories(hello PUBLIC ${CMAKE_SOURCE_DIR}/public)
 
# 生成可执行文件
add_executable(Demo main.cpp)
 
# 链接对象库
target_link_libraries(Demo hello)

(2)第二种格式

cmake_minimum_required (VERSION 3.12.1)
 
project (Demo)
 
# 生成对象库文件
add_library(hello OBJECT hello.cpp)
 
# 添加头文件目录
target_include_directories(hello PUBLIC ${CMAKE_SOURCE_DIR}/public)
 
# 添加编译选项 -Wall
target_compile_options(hello PUBLIC -Wall)
 
# 生成可执行文件
add_executable(Demo main.cpp $<TARGET_OBJECTS:hello>)

# 添加头文件目录
target_include_directories(Demo PUBLIC ${CMAKE_SOURCE_DIR}/public)

(3)第三种写法

cmake_minimum_required (VERSION 3.12.1)
 
project (Demo)
 
# 生成对象库文件,不链接
add_library(hello OBJECT hello.cpp)
 
# 添加头文件目录
target_include_directories(hello PUBLIC ${CMAKE_SOURCE_DIR}/public)
 
# 添加编译选项 -Wall
target_compile_options(hello PUBLIC -Wall)
 
# 生成可执行文件
add_executable(Demo main.cpp)
 
# 链接对象库
target_link_libraries(Demo hello)
(15)cmake的-G 参数

CMake默认根据平台选择一个生成器。通常,默认生成器足以让用户继续构建软件。用户可以使用-G选项覆盖默认生成器:

$ cmake .. -G Ninja
or
cmake -G "Visual Studio 15 2017 Win64" ..
  • 补充:在类Unix系统(包括Mac OS X)上,默认情况下使用Unix Makefiles生成器。该生成器的一个变体也可以在Windows的各种环境中使用,比如NMake Makefiles和MinGW Makefiles生成器。这些生成器生成一个Makefile变量,可以用make、gmake、nmake或类似的工具执行而Visual Studio生成器可以针对不同的体系结构。可以使用-A选项指定目标架构:
cmake .. -G "Visual Studio 2019" -A x64
cmake .. -G "Visual Studio 16" -A ARM
cmake .. -G "Visual Studio 16 2019" -A ARM64
(16)cmake的macro宏定义
  • 定义
    定义一个名为的宏,它接受名为,…等一系列的参数。macro与endmacro之间列出的命令,在宏被调用之前不会执行
macro(<name> [<arg1> ...])
  <commands>
endmacro()
  • 使用
macro(bar)
  foreach(arg IN LISTS ARGN)
    <commands>
  endforeach()
endmacro()
  • 调用
foo()
Foo()
FOO()
cmake_language(CALL foo)
(17)foreach的用法

cmake命令之foreach添加链接描述

(18)set的用法

传送门

(19)list的用法

传送门

五、标准的CMakeLists.txt模板

#1、设置所需cmake版本
cmake_minimum_required(VERSION 3.21)

#2、设置cmake编译语言
set(CMAKE_CXX_STADARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

#3、设置项目名字
project(freshman LANGUAGES C CXX)

#4、如果源目录和输出目录是同一个目录就发出警告
if (PROJECT_BINARY_DIR STREQUAL PROJECT_SOURCE_DIR)
    message(WARNING "The binary directory of CMake Cannot be the same as source directory")
endif()

#5、如果没设置构建模式,就设置为发布模式
if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE Release)
endif()

#6、WIN特有的bug,windows.h会定义下面两个宏,导致std::min和std::max用不了,所以要添加
if(WIN32)
	#向C/C++编译器添加-D定义,参数之间用空格分隔
    add_definitions(-DNOMINMAX -D_USE_MATH_DEFINES)
endif()

#7、增加编译缓存,编译得更快
if(NOT MSVC)
    find_program(CCACHE_PROGRAM ccache)
    if(CCACHE_PROGRAM)
        message(STATUS "Found CCache: ${CCACHE_PROGRAM}")
        set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_PROGRAM})
        set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE_PROGRAM})
    endif()
endif()

六、链接库文件find_target()

1)链接静态库(动态库在win上有很多坑,建议用静态库)

在这里插入图片描述

在这里插入图片描述

2)链接动态库

在这里插入图片描述

3)对象库(优点:可以指定不同的编译选项)

在这里插入图片描述

  • 对象库优点

在这里插入图片描述

4)add_libray无参数(STATIC或SHARED),根据BUILD_SHARED_LIBS决定使用的是静态库还是动态库

  • BUILD_SHARED_LIBS默认值
    BUILD_SHARED_LIBS默认为STATIC,ON相当于SHARED,OFF相当于STATIC
    在这里插入图片描述

  • 设定BUILD_SHARED_LIBS的默认值
    在这里插入图片描述

5)常见坑点1:动态库无法链接静态库(因为动态库地址是变化的,静态库链接执行文件地址是不变的)

  • 错误展示

在这里插入图片描述

  • 解决方法
    .

1)静态库变成对象库

在这里插入图片描述

2)静态库也生成PIC的代码
这里设置otherlib静态库为ON,表示生成PIC代码
在这里插入图片描述

6)windows使用静态链接库

  • 在实现的地方加上xport
    在这里插入图片描述
  • 在声明的地方加上import
    在这里插入图片描述

7)windwos链接动态库坑2:dll和exe不在同一目录导致的

  • 原因
    windwos只会找当前exe所在目录的dll,找不到就报错
  • 解法1
    把dll所在位置加入到PATH环境变量里面去,一劳永逸
  • 解法2
    把这个dll,以及这个dll所依赖的其他dll,全部拷贝到exe文件同一目录下
  • 解法3(手动吧dll和exe放在同一目录很麻烦)
    在这里插入图片描述
    1)做法1
    在这里插入图片描述

2)做法2:不用微软系统,暗转Arch Linux系统
在这里插入图片描述

8)完整演示

find_package(TBB)
if((TBB_FOUND)
    message(STATUS "TBB found at:  ${TBB_DIR}")
    target_link_libraries(main PUBLIC TBB::tbb)           #找到就链接上
    target_compile_definitions(main PUBLIC WITHTBB)
else()
    message(WARNING "TBB not found: using serial for")
endif()
  • 若编译进去了
    在这里插入图片描述
  • 或找到TBB::tbb对象
    +

七、设置对象的属性

1)set_property一个一个的设置属性

在这里插入图片描述

2)set_target_properties设置多个属性

在这里插入图片描述
这个命令是设置目标的属性,该命令的语法是列出想要更改的所有目标,然后提供接下来想要设置的值。您可以使用该命令任何所需的键值对,然后使用get_property()或get_target_property()命令提取它。

  • 备注(以下区别是等价的)
    1)set_properties和set_target_properties
add_executable(myplay ${DIR_SRCS})
# set_property
set_property(TARGET myplay PROPERTY CXX_STANDARD 14)
# set_target_properties
set_target_properties(myplay PROPERTIES CXX_STANDARD 14)

2)使用举例
设置目标的属性值,例如设置输出库名为 static => libstatic.a

set_target_properties(static_demo PROPERTIES OUTPUT_NAME "static") 

八、链接第三方库

1)案例:链接tbb这个库

在这里插入图片描述

  • 这样直接指定tbb的缺点
    1)这样指定,CMake会让连接器在系统的库目录里查找tbb,他会找到/usr/lib/libtbb.so这个系统自带的,但对于没有一个固定库安装位置的Windows系统并不适用
    2)此外,还要求tbb的头文件就在/usr/include这个系统默认的头文件目录里面,才能include<tbb/parallel_for.h>不出错,如果tbb的头文件在其他地方就需要再增加一个target_invlude_directories设置额外的头文件查找目录

2)find_package不需要手动添加库目录

在这里插入图片描述

  • 对比现在和古代cmake
    在这里插入图片描述
  • 带CONFIG有什么区别?

在这里插入图片描述

  • 举例QT(QT需要制定用了哪个组件)()
  • 举例TBB
    在这里插入图片描述
  • 为Cmake找到QT5怎么办?(WINODWS) 在这里插入图片描述

1)法一(目录写死):
在这里插入图片描述
2)法二:设置QT5_DIR这个变量
在这里插入图片描述
3)法三(推荐,命令行指定):
在这里插入图片描述
4)设置环境变量
在这里插入图片描述

九、cmake的目录/与\的问题

cmake的目录的路径分隔符始终都是/,即使在windows上,也要把所有的/改成/,这是出于跨平台的考虑,CMake在调用MSVC的时候转换成\。可以放心的使用${X}/bin来实现和Python的os.path.join(x,‘bin’)一样的效果

十、message

1)简单打印message

message( "  123123456....")

2)带上状态信息 STATUS

message(STATUS   "  123123456....")   #status表示做了啥,check或detecting等等

在这里插入图片描述

3)WARNING 打印出警告信息

message(WARNING  "  123123456....")  

4)AUTHOR_WARNING 可以用-Wno-dev关闭

在这里插入图片描述

5)message(FATAL_ERROR “…”) 表示错误信息,直接终止CMAKE的运行

6)message(SEND_ERROR “…”) 表示是错误信息,但之后的语句任然执行但是最后也报错

7)message 可以打印变量

在这里插入图片描述
在这里插入图片描述

  • 补充没加引号
    在这里插入图片描述
  • message默认打印第一个参数,例如打印了第一个FATAL_ERROR
    在这里插入图片描述

十一、缓存和变量

1)cmake两次编译的原因和结果(第一次缓存,第二次直接开始编译)

在这里插入图片描述
在这里插入图片描述

2)二次编译的坑,百分之99的cmake错误可以用删build解决(或者说删除build/CMakeCache.txt就可以了)

rm -rf build
在这里插入图片描述
在这里插入图片描述

3)设置缓存变量(官方默认错误的方法)

在这里插入图片描述

4)设置缓存变量(正确方法)

在这里插入图片描述

5)命令行-D参数太硬核了,更有图形化的缓存编辑器

ccmake-gui -B build
在这里插入图片描述

6)可以指定FORCE强制set更新缓存

在这里插入图片描述

7)缓存变量类型(举例4种),并用案例说明BOOL类型的缓存变量使用

在这里插入图片描述

  • 案例(添加一个BOOL类型的缓存变量,用于控制要不要开启某特性)
    在这里插入图片描述

8)CMake中Option的坑,直接改option是错误的

  • 1)法一:

cmake -B build -DWITH_TBB:BOOL=OFF
在这里插入图片描述

  • 2)法二:
    在这里插入图片描述

  • 法三:使用普通变量,没有定义时就设为默认值
    在这里插入图片描述

十二、跨平台和编译器

1)CMake中给.cpp定义一个宏

定义了MY_MACRO等于233
在这里插入图片描述

2)判断当前系统的名字

在这里插入图片描述

3)其他简写变量:WIN32,APPLE,UNIX,ANDROID,IOS、MSVC\等

在这里插入图片描述

  • 其他简写判断
    在这里插入图片描述

4)使用生成器表达式,简化成一条指令

在这里插入图片描述

  • 补充,不同平台都支持,中间可以逗号分隔
    在这里插入图片描述

5)可以判断当前使用的C++编译器

在这里插入图片描述

  • 生成器表达式判断编译器
    在这里插入图片描述
  • 或者用生成器表达式做复杂的逻辑判断
    在这里插入图片描述

6)命令行指定编译器

在这里插入图片描述

  • 补充选择编译器的检测
    在这里插入图片描述

  • 补充cmake4vim插件
    在这里插入图片描述

十三、分支和判断

1)BOOL类型的值(ON和OFF)

在这里插入图片描述

2)if的特点,不需要加${}

(1)MATCHES 表示匹配

在这里插入图片描述

  • 若加了${},由于找不到Hello变量名的存在,所以这个变量会被字符串代替并查找(有缺陷)
    在这里插入图片描述

  • 解决办法(加括号防止被当做变量名字)
    在这里插入图片描述

3)Cmake指令部分大小写,${}内的变量名是分大小写的

两个x不一样,蓝颜色部分
在这里插入图片描述

十四、变量和作用域

1)父模块的变量会传给子模块

在这里插入图片描述

2)子模块变量不传给父模块

  • 但是如果需要网上传变量,那就需要用set的PARENT_SCOPE选项
    在这里插入图片描述

  • 不建议用缓存变量向外传变量,这样不光父模块可见了,父模块的父模块,到处可见了

下面是错误做法
在这里插入图片描述

3)除了父子模块有独立作用域的

在这里插入图片描述

4)环境变量的访问方式: $ENV{xx}

  • 举例$x
    在这里插入图片描述

  • 举例环境变量访问
    在这里插入图片描述

5)缓存变量的访问方式: $CACHE{xx}

在这里插入图片描述

  • 补充:当找不到局部变量,会自动去找缓存变量
    在这里插入图片描述

6)用if(DEFINEED XX) 判断某变量是否存在

在这里插入图片描述

  • 补充:空字符串不等于未定义,空字符串等价于false
    在这里插入图片描述
  • 判断某环境变量是否存在
    在这里插入图片描述
  • 设置环境变量

x = 3 env

  • 查看环境变量

env

7)启用CCache:编译加速缓存(第二次编译就很快)

在这里插入图片描述

8)添加一个run为目标,用于启动程序

在这里插入图片描述

9)再增加一个configure伪目标,用于可视化地修改缓存变量在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值