CMake - 用/ MT而不是/ MD编译

ksl*_*ksl 3 cmake cpp-netlib visual-studio-2012

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

默认情况下,它使用/ MDd编译器开关进行编译.我想改变它,以便它使用/ MTd.

我按照这里给出的建议/sf/answers/992101001/但它不适合我.

具体来说,我在if语句中添加了下面显示的第二行到CmakeLists.txt.

if (MSVC)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj")
    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
endif()
Run Code Online (Sandbox Code Playgroud)

当我打开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
Run Code Online (Sandbox Code Playgroud)

我也尝试过像这样设置标志:

set(CMAKE_CXX_FLAGS_DEBUG "/MTd")
Run Code Online (Sandbox Code Playgroud)

但这也不起作用.

如果我通过命令行传递选项,如下所示:

-DCMAKE_CXX_FLAGS_DEBUG="/MTd"
Run Code Online (Sandbox Code Playgroud)

该选项已在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()
Run Code Online (Sandbox Code Playgroud)

Fra*_*ser 8

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

至于这些标志的缓存值来自何处; CMake应用并缓存每个默认构建类型的有用默认值.

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

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

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

如果这不允许你解决你的问题,也许你可以展示一个完整的(小)CMakeLists.txt来展示问题?

更新:

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

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

因此,要解决您的问题,只需if(MSVC)在所有add_subdirectory调用之前移动块即可.