CMake使用问题汇总

cmake 指定编译类型

主要用在vs这种支持多配置的集成开发环境中,可以在CMakeLists.txt中指定,也可以在CLI中指定。测试的时候发现在CMakeLists.txt定义时不能使用自定义类型,如Debug_T,只能使用系统规定的4种类型,使用CLI时,可以自定义类型,如:

cmake .. -G"Visual Studio 15 2017" -D CMAKE_CONFIGURATION_TYPES="Release;Debug_T"

但是生成出来的自定义配置Debug_T并不是调试版本,默认不开启调试,没啥意义。

命令查找

cmake --help可查找所有的cmake命令
cmake --help-command-list可查找常用的cmake命令

常用变量

CMAKE_BINARY_DIR, PROJECT_BINARY_DIR :这两个变量内容一致,如果是内部编译,就指的是工程的顶级目录,如果是外部编译,指的就是工程编译发生的目录。
CMAKE_SOURCE_DIR, PROJECT_SOURCE_DIR:这两个变量内容一致,都指的是工程的顶级目录。
CMAKE_CURRENT_BINARY_DIR:外部编译时,指的是target目录,内部编译时,指的是顶级目录
CMAKE_CURRENT_SOURCE_DIR:CMakeList.txt所在的目录
CMAKE_CURRENT_LIST_DIR:CMakeList.txt的完整路径
CMAKE_CURRENT_LIST_LINE:当前所在的行
CMAKE_MODULE_PATH:如果工程复杂,可能需要编写一些cmake模块,这里通过SET指定这个变量
LIBRARY_OUTPUT_DIR, BINARY_OUTPUT_DIR:库和可执行的最终存放目录
PROJECT_NAME, CMAKE_PROJECT_NAME:前者是当前CMakeList.txt里设置的project_name,后者是整个项目配置的project_name
BUILD_SHARED_LIBS: set the default value when using ADD_LIBRARY()
CMAKE_C_FLAGS: set compiler for c language
CMAKE_CXX_FLAGS: set compiler for c++ language
在工程build目录下执行 cmake .. -DCMAKE_BUILD_TYPE=DEBUG|RELEASE,再执行make, 或者在顶级CMakeList.txt里加入: set(CMAKE_BUILD_TYPE Debug|Release|MinSizeRel|RelWithDebInfo)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32") # 指定32位编译,不加则默认64位编译
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32")

# 附加库目录,要在add_executable之前调用,参考手册里
# The command will apply only to targets created after it is called.
link_directories(${LIB_PATH})
# 附加依赖项
target_link_libraries(${LIB_LIST})
# 附加包含目录
include_directories(${INC_PATH})
# 包含其他的.cmake
include(xx.cmake)
# 包含其他路径下的CMakeLists.txt
add_subdirectory(${SRC_DIR} ${BIN_DIR})
# 调试时打印
message(STATUS "xxxx - found!")
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)
# 指定生成目标
add_executable(Demo ${DIR_SRCS})

# 判断变量是否满足条件,一个常用的方式是使用STREQUAL
if(${CMAKE_BUILD_TYPE} STREQUAL "Debug")
    XXXX
else()
    XXXX
endif()

# 使用cmake直接编译
cmake -D BUILD_TYPE=Debug/Release ..
cmake --build .

通过cmake打印能获取到的所有系统环境变量

在CMakeList.txt中使用
execute_process(
  COMMAND ${CMAKE_COMMAND} -E environment
)

# 在终端中使用
cmake -E environment

更多参考CMake教程——常用变量和常用环境变量的引用

添加打印调试

include(CMakePrintHelpers)
cmake_print_variables(var1 var2 ...)

CMake Cookbook中文版

2.2 处理与平台相关的源代码

通过使用target_compile_definition在预处理阶段使用,实现宏定义。也可以使用add_definition来设置定义。但是后者的缺点是,会修改编译整个项目的定义,而前者给我们机会,将定义限制于一个特定的目标,以及通过PRIVATE|PUBLIC|INTERFACE限定符,限制这些定义可见性。

2.4 检测处理器体系结构

检查空指针类型的大小。CMake的CMAKE_SIZEOF_VOID_P变量会告诉我们CPU是32位还是64位。CMake中加入如下语句:

if(CMAKE_SIZEOF_VOID_P EQUAL 8)
    target_compile_definitions(arch-dependent PUBLIC "IS_64_ARCH")
    message(STATUS "Target is 64 bits")
else()
    target_compile_definitions(arch-dependent PUBLIC "IS_32_ARCH")
    message(STATUS "Target is 32 bits")
endif()

问题汇总

1.ARGC、ARGV、ARGN
转载自CMake中的ARGV,ARGN参数的理解

cmake_minimum_required (VERSION 3.5)

project(test)

macro( testarg var1 var2 )
	message(STATUS "ARGC=${ARGC}")
	message(STATUS "ARGV=${ARGV}")
	message(STATUS "ARGN=${ARGN}")
	message(STATUS "ARGV0=${ARGV0}")
	message(STATUS "ARGV1=${ARGV1}")
	message(STATUS "ARGV2=${ARGV2}")
	message(STATUS "ARGV3=${ARGV3}")
	message(STATUS "ARGV4=${ARGV4}")
endmacro()

message(STATUS "\n")
testarg( a b c d e )
message(STATUS "\n")
testarg( a b )

输出
CMake使用问题汇总_第1张图片
2.宏
macro
3.CMake指定 MT MD MTd,这里涉及变量的追加、替换、已存在的批量替换方法

# 追加CMAKE_CXX_FLAGS_Build Type
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")

# 替换CAMKE_FLAGS
set(CMAKE_CXX_FLAGS_RELEASE "/MT")
set(CMAKE_CXX_FLAGS_DEBUG "/MTd")

# 将已经存在的/MD、/MDd批量替换为/MT、/MTd
if (MSVC)
    set(CompilerFlags
        CMAKE_CXX_FLAGS
        CMAKE_CXX_FLAGS_DEBUG
        CMAKE_CXX_FLAGS_RELEASE
        CMAKE_C_FLAGS
        CMAKE_C_FLAGS_DEBUG
        CMAKE_C_FLAGS_RELEASE
        )
    foreach(CompilerFlag ${CompilerFlags})
        string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}")
    endforeach()
endif(MSVC)

4.CMake指定MT、MD、MTD等
参考CMake指定 MT MD MTd等
5.set的使用方法
参考【cmake命令】set

set( ... [PARENT_SCOPE])

说明:将变量variable设置为值…,变量variable的作用域为调用set命令的函数或者当前目录,如果使用了PARENT_SCOPE选项,意味着该变量的作用域会传递到上一层(也就是上一层目录或者当前函数的调用者,如果是函数则传递到函数的调用者,如果是目录则传递到上一层目录),并且在当前作用域该变量不受带PARENT_SCOPE选项的set命令的影响(如果变量之前没有定义,那么在当前作用域仍然是无定义的;如果之前有定义值,那么值和之前定义的值保持一致)。
关于变量的作用域:每一个新的目录或者函数都会创建一个新的作用域,普通变量的作用域,如果不使用PARENT_SCOPE选项,只能从外层往内层传递。

6.CMake MSBUILD : error MSB1009: Project file does not exist
参考CMake MSBUILD : error MSB1009: Project file does not exist

In contrast to other generators (like Makefiles or Ninja) CMake does not generate an all target for Visual Studio solution but an ALL_BUILD target.
So cmake --build build --target ALL_BUILD --config Release should succeed.

7.在windows平台的vsc终端上运行python程序报错,但是在cmd上运行同样的命令可以正常运行
这是因为vsc默认的windows的终端是powershell,而windows命令行的终端是command prompt。所以如果要在vsc的windows终端上正确运行,只需要把终端切换到command prompt即可。切换界面在vsc的终端界面的左边栏,如下图所示。
CMake使用问题汇总_第2张图片
一劳永逸的做法是直接把默认的终端改为command prompt。这样的话,配置tasks.json时,如果是运行python程序,也可以直接运行。
参考Terminal Profiles
8.CMake如何显示编译过程,比如包含了哪些头文件,链接了哪些库,使用了哪些编译命令?
增加verbose命令

cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON

你可能感兴趣的:(工具,cmake)