零、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
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

  • 查看环境变量

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

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

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

该存储库处于维护模式。 从OpenVDB AX 1.0.0和OpenVDB 8.0.0开始,此存储库已合并到。 OpenVDB AX的所有未来开发都将集中在此。 强烈建议您通过OpenVDB存储库使用OpenVDB AX,该存储库包含修复程序,改进功能和最新文档! OpenVDB AX是一个开源C ++库,它提供了一种与点和卷数据进行交互的强大而简便的方法。 这公开了一种表达语言,以允许使用一系列数学函数快速,自定义地操作点属性和体素值。 表达式可以快速进行JIT编译,并提供出色的性能,在许多情况下,它们可以与自定义C ++运算符匹敌。 它最初是由DNEG开发和维护的,它提供了一种灵活且可移植的方式来处理OpenVDB数据。 OpenVDB AX是根据发布的,该是由Mozilla Foundation开发和维护的免费,开源且详细的软件许可证 Generate a Project Buildsystem cmake [<options>] <path-to-source> cmake [<options>] <path-to-existing-build> cmake [<options>] -S <path-to-source> -B <path-to-build> Build a Project cmake --build <dir&gt 这里编译生成了可执行文件和静态库,可以通过指定COMPOENNT只安装需要的lib,RUNTIME没有安装。FILE_PERMISSIONS和DIRECTORY_PERMISSIONS 指定安装之后的权限。将由DIRECTORY 指定的一个或多个目录安装到DESTINATION指定的目录下。 TinyVDBIO,仅标头的C ++ OpenVDB IO库。 警告! 这仍是实验性项目,还在进行中。 还没工作 TinyVDBIO是仅标头的C ++ 11 OpenVDB IO库。 并非所有 OpenVDB 格式都受支持。 另外,TinyVDBIO不提供与非IO相关的功能(例如,体积运算,等值面生成)。 TinyVDBIO不仅适用于您的图形应用程序,还适用于HPC可视化工具。 无依赖 C++11 代码。 大端支持(例如 Power、SPARC) 跨平台(至少应该可以在 Linux、macOS 和 Windows 上编译) 有限支持加载OpenVDB数据(支持从220到223版本) ZIP压缩 BLOSC 压缩 简单保存OpenVDB数据。 TinyVDB仅功能 支持大型字节序计算机(例如SPARC,POWER)。 很快就会得到支持! 使用TinyVDB读取Ope 状态:正在建设中。 注意:该程序仅在Windows和Visual Studio 2012上进行了测试。 Linux和Mac OS不受官方支持,但是以下说明可能对在这些环境中进行安装很有帮助。 请安装以下必需的库。 对于OpenVDB OpenVDB OpenEXR IlmBase 对于图像OpenCV (2.4.9版或更高版本) 对于UI Qt (5.2.1版或更高版本) 要构建OpenVDB库,请遵循。 您可以使用CMake机制为外部库使用以下目录结构来构建示例项目。 EXT_LIB_ROOT boost include IlmBase include CMake 文章目录CMake1. 最简单的CMake2. 添加message信息3. 添加链接库4. 链接第三方库5. 变量与缓存6. 跨平台和编译器7. 分支和判断8. 变量和作用域 我们使用的cmake版本为3.x 以上。 首先我们熟悉基本的命令: cmake -B build // 在源码目录用 -B 直接创建 build 目录并生成 build/Makefile cmake --build build -j4 文章目录搭建基于Visual Studio的Qt项目,设置不弹控制台窗口 搭建基于Visual Studio的Qt项目,设置不弹控制台窗口 在CMakeLists.txt中,修改add_executable,添加WIN32项(标志该程序为窗口程序),例如: add_executable(test WIN32 ${src_files}) ............ CMAKE是一个开源、跨平台的编译、测试和打包工具,它使用比较简单的语言描述编译、安装的过程,输出Makefile或者project文件,再去执行构建。当多人协同开发一个较大的项目时,会产生较多的源代码文,因此需要说明编译的顺序,例如需要先编译什么,再编译什么,这个过程称之为构建(Build),在构建的过程中使用的工具是make,对应的定义构建过程的文件称为Makefile;但是编写Makefile文件的语法较为复杂,尤其是对于大型的复杂项目,编写Makefile的过程则更为困难。3.1介绍/*...... 对于 cmake ,一直理解为项目构建工具,知道遇到 --build 才发现,cmake 还统一了各个平台的编译阶段。下面摘抄知乎上大神的理解: 简单说一下cmake项目构建过程: 1、首先,使用命令行:‘cmake <source tree>’,比如:cmake .. ,在你的构建目录(外部构建方式)下生成了项目文件 project files,官方文档中又叫 build tree / binary tree,这其中就包括,比如:Makefile,还有一些其他相关文件 / 目录 / 子目 CMake简单指令1 只有main.c2 多个C文件在同一文件夹下3 多个不同目录下多个C文件4 正式的组织结构(build文件夹正确使用)4.1 文件结构4.2 CMakeLists.txt写法 1 只有main.c 2 多个C文件在同一文件夹下 3 多个不同目录下多个C文件 4 正式的组织结构(build文件夹正确使用) 4.1 文件结构 假设我有一个工程文件夹test,其组织结构如下: (b... 3. 最后,--build后面的那个‘.’,指的是生成好的build tree的路径. 一般来说,如果你明确知道,你的系统中使用的是哪种构建器(build generator), 比如:Unix Makefiles, 你完全可以直接使用make进行项目构建.为什么不直接 make,而是使用 cmake --build 形式的命令,主要是为了跨平台,使用这种形式后,不管你是使用的什么生成器,CMake 都能正确构建,否则如果使用的是 Ninja 或者其他生成器,那 make 就不生效了。 cmake_minimum_required - 指定CMake的最小版本要求。 # 语法:cmake_minimum_required(VERSION versionNumber [FATAL_ERROR]) cmake_minimum_required(VERSION 2.8.3) #CMake最小版本要求为2.8.3 project - 定义工程名称,并可指定工程支持的语言 #语法:project(projectname [CXX] [C] [Java]) Houdini工具包 这个Houdini文件演示了工具包中的许多节点,并说明了基本概念,例如OpenVDB树结构,图块和体素,窄带级别集和雾量。更重要的是,它为常见任务(如粒子表面处理,多边形转换,压裂,过滤,重采样等)提出了推荐的工作流程。 Houdini Examples zip-2017年6月1日 Maya工具包 OpenVDB包括少量Maya节点... OpenVDB是获得奥斯卡奖的开源C ++库,它包含新颖的分层数据结构和一套工具,用于有效存储和处理离散在三维网格上的稀疏体积数据。它是由DreamWorks Animation开发的,用于故事片制作中通常遇到的体积应用程序,现在由Academy Software Foundation(ASWF)进行维护。 CMake是一个跨平台的构建系统,可以从CMakeLists.txt生成不同类型的构建系统(比如Linux的make,Windows的MSBuild),从而让构建规则可以只写一份,跨平台使用。如何让CMAKE_BUILD_TYPE在用户没有指定的时候为Release,指定的时候保持用户指定的值不变呢。不建议用CMAKE_SOURCE_DIR,那样会让你的项目无法被人作为子模块使用。和子模块的关系PROJECT_x_DIR和CMAKE_CURRENT_x_DIR的区别,....................