【问题标题】:CMake - compile with /MT instead of /MDCMake - 使用 /MT 而不是 /MD 编译
【发布时间】:2013-12-27 11:46:51
【问题描述】:

我是 cmake (2.8.12.1) 的新手,我在 Windows 上使用它来生成项目文件,以使用 Visual Studio 2012 构建 cpp-netlib。

默认情况下,它使用 /MDd 编译器开关进行编译。我想更改它以使其使用 /MTd。

我遵循了https://stackoverflow.com/a/14172871 此处给出的建议,但它对我不起作用。

具体来说,我在 CmakeLists.txt 的 if 语句中添加了如下所示的第二行。

if (MSVC)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj")
    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
endif()

当我打开 Visual Studio sln 文件时,我可以看到 /MDd 选项仍然设置。此外,我在 CMakeCache.txt 中看到以下内容:

//Flags used by the compiler during debug builds.
CMAKE_CXX_FLAGS_DEBUG:STRING=/D_DEBUG /MDd /Zi /Ob0 /Od /RTC1

我也尝试过像这样从头开始设置标志:

set(CMAKE_CXX_FLAGS_DEBUG "/MTd")

但这也不起作用。

如果我像这样通过命令行传递选项:

-DCMAKE_CXX_FLAGS_DEBUG="/MTd"

该选项已在 Visual Studio 项目中成功设置。

谁能告诉我我做错了什么?

如果有人能告诉我缓存中的值来自我没有在命令行中指定或不在 CmakeLists.txt 中的值,我将不胜感激。

按要求添加 CMakeList.txt。如果我没有做对,我以前从未发布过如此抱歉。

# Original from cpp-netlib.org with my edits

cmake_minimum_required(VERSION 2.8)
project(CPP-NETLIB)
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_MULTI_THREADED ON)
find_package( Boost 1.45.0 REQUIRED unit_test_framework system regex date_time thread filesystem program_options chrono )
find_package( OpenSSL )
find_package( Threads )
set(CMAKE_VERBOSE_MAKEFILE true)

if (CMAKE_BUILD_TYPE MATCHES Debug)
    add_definitions(-DBOOST_NETWORK_DEBUG)
endif()

if (OPENSSL_FOUND)
    add_definitions(-DBOOST_NETWORK_ENABLE_HTTPS)
    include_directories(${OPENSSL_INCLUDE_DIR})
endif()

if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU)
  set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
endif()

if (Boost_FOUND)
    ################# added #################
    add_definitions(-DBOOST_ALL_NO_LIB)
    #########################################
    if (MSVC)
      add_definitions(-D_SCL_SECURE_NO_WARNINGS)
    endif(MSVC)
    if (WIN32)
      add_definitions(-D_WIN32_WINNT=0x0501)
    endif(WIN32)
    include_directories(${Boost_INCLUDE_DIRS})
    enable_testing()
    add_subdirectory(libs/network/src)
    add_subdirectory(libs/network/test)
    if (NOT MSVC)
      add_subdirectory(libs/mime/test)
    endif(NOT MSVC)
    add_subdirectory(libs/network/example)
endif(Boost_FOUND)

if (MSVC)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj")
    ################# added #################
    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
    #########################################
endif()

enable_testing()

【问题讨论】:

    标签: visual-studio-2012 cmake cpp-netlib


    【解决方案1】:

    if 块中添加代码应该可以正常工作。但是,由于它不会在您的 .sln 中产生所需的效果,因此 if 块内的代码不会被执行,或者稍后会在 CMakeLists.txt 中替换标志。

    关于这些标志的缓存值来自哪里; CMake 应用并缓存被认为对每个默认构建类型有用的默认值。

    您是否在project 调用之前添加了对标志的更改? project 设置了很多东西,包括编译器标志。如果您设置这些标志而不缓存它们(即如您所示调用set),project 将覆盖它们。如果您设置标志缓存它们(例如,使用set(... CACHE),或通过命令行参数-D 添加它们,如您所示),那么project 不会 覆盖它们。

    此外,由于调用set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj") 不使用CACHE option of set,因此对变量CMAKE_CXX_FLAGS 的更改不会出现在您的CMakeCache.txt 文件中。

    为了将它放入缓存中,您还必须使用setFORCE 选项,因为您会告诉 CMake 替换已缓存的值(CMake 本身会缓存这些标志变量默认)。但是我不推荐这个 - 我不明白你为什么需要这样做,你最好寻找一种比附加你想要的标志更好的方法,因为每次 CMake 运行附加的标志将被重新附加。

    如果这不能解决您的问题,也许您可​​以显示一个完整的(小)CMakeLists.txt 来显示问题?

    更新:

    好的 - 问题是范围问题。对编译器标志的更改将应用​​于该 CMakeLists.txt 中定义的所有目标(exes/libs),但仅应用于在修改标志之后添加的子目录目标

    add_subdirectory 命令引入了一个新的范围(尽管文档中没有提到),它继承了父级变量的副本。但是,随后对父作用域中变量的更改不会影响子副本,同样更改子副本也不会影响父副本的值(除非您使用 set(... PARENT_SCOPE) 强制它)。

    因此,要解决您的问题,只需将 if(MSVC) 块移动到所有 add_subdirectory 调用之前。

    【讨论】:

    • 按要求添加了 CMakeLists.txt。 if 块内的代码肯定正在执行。
    • 是的 - 发布完整的 CMakeLists.txt 有帮助 :-) 希望我的更新解决了这个问题。
    • 非常感谢@Fraser 的帮助。按照建议修改 CMakeLists.txt 后,我​​能够构建解决方案。
    猜你喜欢
    • 2012-12-19
    • 2010-10-19
    • 1970-01-01
    • 2011-03-29
    • 2016-12-18
    • 1970-01-01
    • 1970-01-01
    • 2015-04-10
    • 1970-01-01
    相关资源
    最近更新 更多