cmake:msvc分别对不同的target使用不同的运行库选项(/MT或/MD)

本文介绍如何在CMakeLists.txt文件中为MSVC编译器设置/MT选项来连接C/C++静态库,并提供了针对不同目标使用不同选项的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

很久以前写过一篇关于cmake下为msvc设置/MT的文章:

cmake:msvc编译第三方库时使用/MT静态库连接c/c++ runtime library

当时是为了解决用msvc编译时使用/MT连接static c library的问题。CMakeLists.txt中添加如下的代码,即可以将所有默认的C,CXX编译选项中的/MD替换成/MT.

if(MSVC)     
    # Use the static C library for all build types
    foreach(var 
        CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
        CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
        CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
        CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO
      )
      if(${var} MATCHES "/MD")
        # 正则表达式替换/MD为/MT
        string(REGEX REPLACE "/MD" "/MT" ${var} "${${var}}")
      endif()
    endforeach()    
endif(MSVC)

如果你希望CMakeLists.txt中所有的target都使用c/c++静态库,那么上面的做法就完全满足需要。
但如果希望针对CMakeLists.txt中的不同target使用不同的/MT/MD选项,这个办法就不行了。如果希望针对特定的target设置/MT选项,该怎么办呢?

这里就用到了target_compile_options命令还用到了Generator expressions,以下为封装成function的实现代码

# Use the static C library for all build types to a target
# MSVC编译时对指定的target设置'/MT'选项连接static c/c++ library
function (with_mt_if_msvc target )
if(MSVC) 
  # Generator expressions
  set(_mt "/MT$<$<CONFIG:Debug>:d")
  get_target_property(_options ${target} COMPILE_OPTIONS)
  if(_options)
    # message(STATUS "${target} COMPILE_OPTIONS=${_options}")
    if(${_options} MATCHES "/MD")
      string(REGEX REPLACE "/MD" "/MT" _options "${_options}")
    else()
      set(_options "${_options} ${_mt}")
    endif()    
  else()
    set(_options "${_mt}")
  endif() 
  get_target_property(_type ${target} TYPE)
  # 判断 ${target}是否为静态库
  if(_type STREQUAL "STATIC_LIBRARY")
    # 静态库将/MT选项加入INTERFACE_COMPILE_OPTIONS
    target_compile_options( ${target} PUBLIC "${_options}")
  else()
    target_compile_options( ${target} PRIVATE "${_options}")
  endif()
  # Cleanup temporary variables.
  unset(_mt)
  unset(_options)
  message(STATUS "target ${target} use static runtime /MT")
endif(MSVC)
endfunction()

有了这个with_mt_if_msvc函数,你可以针对target设置/MT选项,而那些没有指定的target仍使用默认的/MD选项

参考资料

Is it possible, in the same CMakeLists.txt, to setup projects with /MT and others with /MD?
target_compile_options
cmake-generator-expressions

<think>嗯,用户想了解如何使用CMake来构建和编译QCefView-1.1.0工程。首先,我需要回忆一下QCefView的相关信息。QCefView是一个基于CEF(Chromium Embedded Framework)的Qt组件,用于在Qt应用中嵌入Web浏览器功能。构建这样的项目通常需要处理依赖项,特别是CEF和Qt的集成。 首先,用户可能需要安装必要的依赖项,比如CMake本身,Qt库,以及CEF的二进制分发版。CEF的版本需要和QCefView兼容,所以需要确认1.1.0版本对应的CEF版本。通常,QCefView的文档GitHub页面上会有说明,但用户可能没有提到这一点,所以我需要假设他们可能需要下载特定版本的CEF,比如可能推荐使用CEF 3.3396版本者类似的。 接下来,项目结构方面,用户需要将QCefView的源代码和CEF的二进制包放在正确的位置。可能的结构是QCefView的根目录下有一个third_party目录来存放CEF,者用户需要设置CMake变量来指向CEF的路径。这里可能需要指导用户如何组织目录结构,者通过CMake命令传递参数。 然后,生成构建系统文件,用户需要创建一个build目录,运行cmake命令,指定Qt的路径(如果Qt不在系统路径中),以及CEF的路径。例如,使用-DQt6_DIR指定Qt的安装位置,使用-DCEF_ROOT来指向CEF的目录。这里可能需要提醒用户注意CMake的变量是否正确设置,否则可能导致找不到依赖项的错误。 编译过程中,用户可能会遇到CEF的链接问题,者头文件找不到的情况。这时候需要检查CMake的输出,确认是否所有依赖都被正确找到。另外,编译模式(Debug/Release)需要与依赖库的版本匹配,否则可能导致运行时错误。可能需要提醒用户注意这一点,尤其是在Windows平台上,不同编译器的运行时库可能不兼容。 另外,可能需要处理平台特定的问题。例如,在Windows上,CEF需要多线程调试DLL运行时库(/MDd/MD),而Qt可能默认使用不同的设置,这可能导致冲突。用户可能需要调整编译选项者在CMake中设置相应的标志。此外,CEF的分发版通常包含Debug和Release版本的库,用户需要根据构建类型选择正确的版本。 还有,QCefView可能有子模块需要额外的工具,比如yasm其他构建工具,用户可能需要确保这些工具已安装并可用。例如,CEF可能依赖一些第三方库,如FFmpeg,需要正确配置。 最后,测试编译后的库是否可用,可能需要编写一个简单的Qt应用来测试QCefView组件是否正常工作。用户可能还需要配置运行时依赖,比如CEF的资源文件(如 locales 和 swiftshader 目录)需要放在可执行文件的旁边,否则应用可能无法启动。 总结一下,步骤大致是:安装依赖,准备源代码和CEF,配置CMake生成构建文件,处理可能的路径和变量设置,编译,处理错误,测试。需要详细说明每一步的具体操作,尤其是如何设置CMake变量,如何处理常见的依赖问题,以及不同平台的注意事项。以下是</think>使用 CMake 构建并编译 **QCefView-1.1.0** 的详细步骤: --- ### **1. 环境准备** #### **依赖项安装** - **CMake**: 版本 ≥ 3.15(推荐最新版) - **Qt**: 版本 ≥ 5.15(需与 CEF 兼容,建议 Qt 5.15 LTS) - **CEF 二进制包**: QCefView-1.1.0 要求特定 CEF 版本(如 `CEF 3.3396`),需从 [CEF 官网](https://cef-builds.spotifycdn.com/index.html) 下载对应平台的预编译包(如 `cef_binary_3.3396.1774.gd49d983_xxx.tar.bz2`)。 - **编译器**: - Windows: Visual Studio 2019/2022 - Linux: GCC ≥ 9 - macOS: Xcode ≥ 12 --- ### **2. 目录结构准备** 假设路径如下: ``` QCefView-1.1.0/ # QCefView 源码目录 third_party/ cef/ # 解压 CEF 二进制包至此 ``` --- ### **3. 配置 CMake** #### **生成构建文件** ```bash mkdir build && cd build # Windows(使用 Visual Studio 生成器) cmake .. -G "Visual Studio 16 2019" -A x64 \ -DQt6_DIR="C:/Qt/6.5.0/msvc2019_64/lib/cmake/Qt6" \ -DCEF_ROOT="../third_party/cef" # Linux/macOS(使用 Ninja Makefile) cmake .. -GNinja \ -DQt6_DIR="/opt/Qt/6.5.0/gcc_64/lib/cmake/Qt6" \ -DCEF_ROOT="../third_party/cef" ``` #### **关键 CMake 参数** | 参数名 | 说明 | |--------|------| | `Qt6_DIR` | 指向 Qt 安装路径下的 CMake 目录(如 `Qt/6.x.x/.../lib/cmake/Qt6`) | | `CEF_ROOT` | 指向 CEF 解压后的根目录(包含 `CMakeLists.txt` 的 CEF 目录) | --- ### **4. 编译代码** ```bash # Windows(使用 MSBuild) cmake --build . --config Release --target ALL_BUILD # Linux/macOS(使用 Ninja) cmake --build . --config Release ``` --- ### **5. 常见问题处理** #### **错误:找不到 CEF/Qt 路径** - **解决**: 确保 `CEF_ROOT` 和 `Qt6_DIR` 路径正确,且 CEF 包版本与 QCefView 兼容。 #### **错误:头文件/库文件缺失** - **解决**: 检查 CEF 包是否包含 `Release` 和 `Debug` 子目录,确认 CMake 能自动找到它们。 #### **Windows 运行时库冲突** - **解决**: 确保所有依赖项(Qt、CEF)使用相同的运行时(如 `/MD` `/MT`),在 CMake 中设置: ```cmake add_compile_options(/MD) # 与 CEF 的 Release 版本一致 ``` --- ### **6. 测试与部署** - **编译结果**: 生成的库文件(如 `QCefView.lib` `libQCefView.so`)位于 `build/bin` 目录。 - **部署 CEF 资源**: 将 CEF 的 `Resources` 目录(含 `locales`、`swiftshader` 等)复制到可执行文件同级目录。 --- ### **附:完整流程示例(Windows)** ```bash # 假设路径: # - QCefView 源码: D:/Projects/QCefView-1.1.0/third_party/cef # - Qt 安装路径: C:/Qt/6.5.0/msvc2019_64 cd D:/Projects/QCefView-1.1.0 mkdir build && cd build cmake .. -G "Visual Studio 16 2019" -A x64 ^ -DQt6_DIR="C:/Qt/6.5.0/msvc2019_64/lib/cmake/Qt6" ^ -DCEF_ROOT="../third_party/cef" cmake --build . --config Release ``` --- 通过以上步骤,您可以完成 QCefView-1.1.0 的构建与编译。若需进一步调试,建议在 CMake 配置时添加 `-DCMAKE_BUILD_TYPE=Debug`。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

10km

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值