跳到主要内容

基于 MSVC 的 Windows 开发

三元组

kmpkg 内置了用于通过 MSVC cl.exe 编译器构建 Windows 桌面应用的三元组

架构kmpkg 三元组社区维护
x64x64-windows
x64-windows-release
x64-windows-static
x64-windows-static-md
x64-windows-static-release
x86x86-windows
x86-windows-static
x86-windows-static-md
armarm-windows
arm-windows-static
arm64arm64-windows
arm64-windows-static
arm64-windows-static-md
arm64-windows-static-release
arm64ecarm64ec-windows

static 后缀的静态链接三元组配置为将 MSVC 运行时库作为静态库使用(即 KMPKG_CRT_LINKAGE static)。

static-md 后缀的三元组配置为将 MSVC 运行时库作为 DLL 使用(即 KMPKG_CRT_LINKAGE dynamic)。根据微软 Learn 文档的建议,这是分发 MSVC 运行时库的推荐方案。

选择 MSVC 工具集

默认情况下,kmpkg 会使用系统中安装的最新版本 Visual Studio 构建代码。若需指定特定版本,可创建自定义三元组或三元组覆盖层,设置 KMPKG_PLATFORM_TOOLSET 变量。

例如,以下配置会强制使用 Visual Studio 2017 工具集:

set(KMPKG_PLATFORM_TOOLSET v141)

维护者注意事项

为这些三元组构建 CMake 项目时,CMAKE_SYSTEM_NAME 会被设置为 "Windows"。

库作者注意事项

  • 通常可在库中禁用“仅我的代码(Just My Code)”调试功能,以节省代码体积:
if(MSVC)
target_compile_options(mytarget PRIVATE /JMC-)
endif()
  • MSBuild 会自动添加一些 MSVC 编译器默认未启用的构建标志。为确保 Ninja 或其他生成器也能实现相同行为,需手动添加以下构建配置:
if(MSVC)
target_compile_options(mytarget PRIVATE /Zc:inline)
endif()
  • 建议为新版 MSVC 启用以下构建配置,以提升代码安全性:
if(MSVC)
target_compile_options(mytarget PRIVATE "$<$<NOT:$<CONFIG:DEBUG>>:/guard:cf>")
target_link_options(mytarget PRIVATE /DYNAMICBASE /NXCOMPAT)

if((CMAKE_SIZEOF_VOID_P EQUAL 4)
AND (NOT (${KMPKG_TARGET_ARCHITECTURE} MATCHES "^arm")))
target_link_options(mytarget PRIVATE /SAFESEH)
endif()

if((MSVC_VERSION GREATER_EQUAL 1928)
AND (CMAKE_SIZEOF_VOID_P EQUAL 8)
AND ((NOT (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
OR (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 13.0)))
target_compile_options(mytarget PRIVATE "$<$<NOT:$<CONFIG:DEBUG>>:/guard:ehcont>")
target_link_options(mytarget PRIVATE "$<$<NOT:$<CONFIG:DEBUG>>:/guard:ehcont>")
endif()
endif()

if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
target_compile_options(mytarget PRIVATE /sdl)

if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.24)
target_compile_options(mytarget PRIVATE /ZH:SHA_256)
endif()

if((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.27)
AND (NOT (${KMPKG_TARGET_ARCHITECTURE} MATCHES "^arm")))
target_link_options(mytarget PRIVATE /CETCOMPAT)
endif()
endif()
  • 为提升标准 C/C++ 兼容性,建议启用最新的编译器开关:
if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
target_compile_options(mytarget PRIVATE /permissive- /Zc:__cplusplus /Zc:inline)

if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.26)
target_compile_options(mytarget PRIVATE /Zc:preprocessor)
endif()

if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.28)
target_compile_options(mytarget PRIVATE /Zc:lambda)
endif()

if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.35)
target_compile_options(mytarget PRIVATE /Zc:templateScope)
endif()
endif()
  • 若要支持全程序优化(WPO)/链接时代码生成(LTCG),推荐使用以下构建配置:
if((CMAKE_CXX_COMPILER_ID MATCHES "MSVC") AND CMAKE_INTERPROCEDURAL_OPTIMIZATION)
target_compile_options(${PROJECT_NAME} PRIVATE /Gy /Gw)

if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.35)
target_compile_options(mytarget PRIVATE /Zc:checkGwOdr)
endif()
endif()
  • 若需启用 Spectre 漏洞缓解措施,可使用以下条件编译:
if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
if((MSVC_VERSION GREATER_EQUAL 1913) AND (NOT WINDOWS_STORE))
target_compile_options(mytarget PRIVATE "/Qspectre")
endif()
endif()

注:你可能还需要提供一个显式的 CMake 构建选项来控制该功能的启用/禁用。