CMake系列:问题解决点滴记录
Posted 岬淢箫声
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CMake系列:问题解决点滴记录相关的知识,希望对你有一定的参考价值。
文章目录
- 1. CMake点滴记录
- 1.1. 如何理解、使用CMake多配置编译系统
- 1.2. 判断环境变量是否存在
- 1.3. VS调试不用windeployqt
- 1.4. Debug与Release输出不同名称的编译结果
- 1.5. CMake不用手动添加源代码
- 1.6. CMake在Windows上生成没有控制台的程序
- 1.7. CMake添加编译生成事件
- 1.8. VS项目设置UNICODE
- 1.9. 一个子项目的属性如何传递到另一个子项目
- 1.10. CMake使用Qt MOC、界面和资源文件
- 1.11. CMake多编译器支持
- 1.12 关闭链接警告
- 1.13 有空格的宏定义不是字符串类型
- 1.14 版本号转十六进制整数
- 1.15 CMake文件读写操作
1. CMake点滴记录
1.1. 如何理解、使用CMake多配置编译系统
-
常见错误
以Debug和Release配置有不同的宏定义为例,如下所示:
if(NOT DEFINED CMAKE_BUILD_TYPE) add_definitions(-DDEBUG) else() add_definitions(-DRELEASE) endif()
-
问题现象
- 按Debug运行Configure后Release配置没有
RELEASE
宏定义,按Release运行Configure后Debug配置没有DEBUG
宏定义。 - 每次运行
cmake -B
命令只能看到一个宏定义
- 按Debug运行Configure后Release配置没有
-
正确做法
add_definitions( $<$<CONFIG:DEBUG>:-DDEBUG> $<$<CONFIG:RELEASE>:-DRELEASE> )
或者
add_definitions($<IF:$<CONFIG:DEBUG>,-DDEBUG,-DRELEASE>)
-
CMake的最少Configure原则
以下典型的情况不运行Configure:
- 项目配置没有改变
- CMake运行环境没有改变:操作系统版本、编译器版本等等
- 不是准备版本发布
-
CMake统一原则
同一个项目只有同一步CMakeLists.txt,应对不同的编译器、不同的操作系统。
-
cmake if指令应该什么时候使用
- 不同的编译器有不同的编译选项,比如MSVC和GCC
- 不同的目标平台有不同的编译选项,比如Windows和Linux
-
活学活用
CI只需要验证Debug配置环境可运行:
cmake -B build -DCMAKE_BUILD_TYPE=Debug
,Release同理。
CI只需要验证Debug编译结果可运行:cmake --build build --config Debug -j 16
,Release同理。 -
CMake淘汰的用法
项目属性+配置名的做法已被逐步淘汰。举例如下:
set(COMPILE_DEFINITIONS_DEBUG DEBUG) # 3.23版本已不起作用 set(COMPILE_DEFINITIONS_RELEASE RELEASE) # 3.23版本已不起作用 set_target_properties($PROJECT_NAME PROPERTIES LIBRARY_OUTPUT_NAME_DEBUG testd LIBRARY_OUTPUT_NAME_RELEASE test )
1.2. 判断环境变量是否存在
方法1:
if(NOT DEFINED ENVQt5_DIR)
message(FATAL_ERROR "environment variable Qt5_DIR is required.")
else()
message("---- Qt5_DIR is set to " $ENVQt5_DIR)
endif()
方法2:
if("$ENVQt5_DIR" STREQUAL "")
message(FATAL_ERROR "environment variable Qt5_DIR is required.")
else()
message("---- Qt5_DIR is set to " $ENVQt5_DIR)
endif()
1.3. VS调试不用windeployqt
像Qt Creator一样调试
set_property(TARGET LTFocus PROPERTY VS_DEBUGGER_ENVIRONMENT "PATH=$ENVQt5_DIR/bin")
set_property(TARGET LTFocus PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "$EXECUTABLE_OUTPUT_PATH")
1.4. Debug与Release输出不同名称的编译结果
set_property(TARGET LTFocus PROPERTY DEBUG_POSTFIX "d")
1.5. CMake不用手动添加源代码
举例:
file(GLOB SRCS *.h *.cpp *.ui *.rc *.qrc)
add_executable($PROJECT_NAME $SRCS)
GLOB
换成 GLOB_RECURSE
,结果包含子目录下的代码文件。
1.6. CMake在Windows上生成没有控制台的程序
方法1:
if(MSVC)
add_executable($PROJECT_NAME WIN32 $SRCS)
endif()
方法2:
if(MSVC)
add_link_options(/SUBSYSTEM:WINDOWS)
endif()
1.7. CMake添加编译生成事件
set(EXE_DIR $CMAKE_SOURCE_DIR/$CMAKE_BUILD_TYPE/)
cmake_path(NATIVE_PATH EXE_DIR EXE_DIR)
add_custom_command(TARGET $PROJECT_NAME POST_BUILD
COMMAND copy test.* $EXE_DIR /Y
WORKING_DIRECTORY $CMAKE_BINARY_DIR/$CMAKE_BUILD_TYPE)
POST_BUILD
指编译成功后,PRE_BUILD
指编译成功前。EXE_DIR
最后面的杠是必须的,因为copy命令不判断复制来源是目录还是文件。如果末尾没有杠且复制目的地不存在同名目录,copy就会在目的地创建与目录同名的文件,然后复制失败。cmake_path
的作用是转换路径分隔符,copy命令不支持Linux风格的路径。
1.8. VS项目设置UNICODE
这里有个坑,常见错误的做法
add_compile_definitions(UNICODE _UNICODE)
正确的做法
add_definitions(-DUNICODE -D_UNICODE)
add_definitions
的每个宏定义须添加-D前缀,add_compile_definitions
的每个宏定义不需要前缀。最终执行的编译命令,所有的宏都有 -D
或 /D
前缀。
1.9. 一个子项目的属性如何传递到另一个子项目
CMake中变量的作用域是自上而下的,一个下层项目的属性传递给另一个子项目的属性,如果没有上下级关系,则需要通过 set_property
和 get_property
指令实现。对于整个CMake项目树结构,需先添加 set_property
的下级项目,后添加 get_property
的下级项目。
1.10. CMake使用Qt MOC、界面和资源文件
方法1:打开CMake支持Qt的自动化设置,把Qt资源以代码形式直接添加到项目
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
add_executable($PROJECT_NAME *.qrc *.ui)
方法2:按Qt资源命名规则生成代码,把生成代码添加到项目。下面代码以UI文件为例。
file(GLOB UI_SOURCES *.ui)
qt5_wrap_ui(UI_SOURCES $UI_GENERATED)
foreach(UI_SRC $UI_GENERATED)
cmake_path(GET UI_SRC PARENT_PATH UI_DIR)
include_directories($UI_DIR)
endforeach()
1.11. CMake多编译器支持
方法1:直接设置编译器路径
set(CMAKE_SYSTEM_NAME QNX)
set(arch gcc_ntoarmv7le)
set(CMAKE_C_COMPILER qcc)
set(CMAKE_C_COMPILER_TARGET $arch)
set(CMAKE_CXX_COMPILER QCC)
set(CMAKE_CXX_COMPILER_TARGET $arch)
set(CMAKE_SYSROOT $ENVQNX_TARGET)
方法2:利用CMake的探测机器。以VC为例,CMake运行环境存在 %VCINSTALLDIR%
,则CMake能自动找到 cl
编译器,进而确认编译器版本和特性。VCINSTALLDIR
环境变量是Visual Studio提供的 vcvarsall.bat
提供的。典型的环境初始化代码:
@echo off
title Visual Studio 2019 Development Kit
set WORKDIR=%cd%
set Qt5_DIR=C:\\Qt\\Qt5.14.0\\5.14.0\\msvc2017_64
set GENERATOR=Visual Studio 16 2019
call "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Auxiliary\\Build\\vcvarsall.bat" x64
call "%Qt5_DIR%\\bin\\qtenv2.bat"
set PATH=%PATH%;C:\\Qt\\qtcreator-7.0.2\\bin;C:\\Program Files\\CMake\\bin
cd /d "%WORKDIR%"
cmd /k echo OK!
CMake能探测以默认选项安装的开发工具,比如VS安装到C盘,则即使不设置环境变量,CMake也能找到VC编译器。
1.12 关闭链接警告
CMake v3.24.3
代码add_link_options(/IGNORE:4099,4098)
不起作用,
代码set_target_properties($PROJECT_NAME PRIVATE LINK_FLAGS "/IGNORE:4099,4098")
可正常关闭链接警告。
1.13 有空格的宏定义不是字符串类型
错误的做法:add_compile_definitions(GC_API="__host__ __device__")
。实际结果是代码多了一个字符串类型的宏定义,不能作用于NVIDIA GPU函数修饰符。正确做法是使用转义字符把空格转义,即:add_compile_definitions(GC_API=__host__\\ __device__)
1.14 版本号转十六进制整数
project(Test1DLL VERSION 2.1.3.1)
math(EXPR AOI_INT_VER "$PROJECT_VERSION_MAJOR<<24|$PROJECT_VERSION_MINOR<<16|$PROJECT_VERSION_PATCH<<8|$PROJECT_VERSION_TWEAK" OUTPUT_FORMAT HEXADECIMAL)
add_compile_definitions(Test1DLL_EXPORTS AOI_PF_VER="$PROJECT_VERSION" AOI_INT_VER=$AOI_INT_VER)
1.15 CMake文件读写操作
write_file($LIBRARY_OUTPUT_DIRECTORY/Test1/makelib.cmd "@echo off")
write_file($LIBRARY_OUTPUT_DIRECTORY/Test1/makelib.cmd "title libTest1 release tool by zhtqs8@163.com" APPEND)
write_file($LIBRARY_OUTPUT_DIRECTORY/Test1/makelib.cmd "set CA7ZIP=C:\\\\Program Files\\\\7-Zip\\\\7z.exe" APPEND)
write_file($LIBRARY_OUTPUT_DIRECTORY/Test1/makelib.cmd "set CVER=$PROJECT_VERSION" APPEND)
write_file($LIBRARY_OUTPUT_DIRECTORY/Test1/makelib.cmd "if not exist \\"%CA7ZIP%\\" echo 7-zip is required. && goto end" APPEND)
write_file($LIBRARY_OUTPUT_DIRECTORY/Test1/makelib.cmd "\\"%CA7ZIP%\\" a \\"libTest1%CVER%.zip\\" libTest12.0.dll libTest12.0.lib libTest12.0.pdb libTest12.0*.md ../../src/test1/Test1DevCommon.h ../../src/test2/Test1Dev.h ../../src/test3/Test1Common.h" APPEND)
write_file($LIBRARY_OUTPUT_DIRECTORY/Test1/makelib.cmd ":end" APPEND)
write_file($LIBRARY_OUTPUT_DIRECTORY/Test1/makelib.cmd "pause" APPEND)
作者: | 岬淢箫声 |
邮箱: | zhtqs8@163.com |
来源: | https://caowei.blog.csdn.net/article/details/129088446 |
以上是关于CMake系列:问题解决点滴记录的主要内容,如果未能解决你的问题,请参考以下文章
点滴记录——在Ubuntu 14.04中使SublimeText 3支持中文输入法