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

关于在cmake生成msvc工程时静态链接c/c++运行库的问题,很久以前写过一篇博客《cmake设置msvc的运行库(runtime library)塈指定openjpeg使用静态库》。当时的办法是在CMakeLists.txt中加一段代码将C_FLAGS_XXX,CXX_FLAGS_XXX等所有变量中的/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")
        string(REGEX REPLACE "/MD" "/MT" ${var} "${${var}}")
      endif()
    endforeach()    
endif(MSVC)

这个办法的确是解决了问题,但从工程角度也存在一些缺陷。 1.对于自己的项目,如果有多个独立项目要管理,就要对每个项目的CMakeLists.txt中都这样加一段代码,也是挺麻烦的。。。容易出错。 2.如果是编译第三方库,也要用这种办法,就得修改第三方库的cmake脚本,无疑就增加了工程管理的复杂度,更容易出错。

今天找到这篇文章《How can I build my MSVC application with a static runtime?》,才完全解决了我的问题: msvc默认就是使用/MD选项,在cmake中,这个/MD是在初始化时就被设置的。 CMAKE_C_FLAGS_XXXX,CMAKE_CXX_FLAGS_XXXX等系列变量每一个都对应一个后缀为_INIT的初始变量CMAKE_C_FLAGS_XXXX_INIT,CMAKE_CXX_FLAGS_XXXX_INIT,这些变量中保存的就是编译选项的初始值。 这篇文章虽然写的有些错误,但我明白了它的道理: 基本的原理就是利用CMAKE_USER_MAKE_RULES_OVERRIDE这个cmake变量,定义一个初始化脚本,通过这个初始化脚本可以修改上面所说的_INIT系列变量!!!

如下定义一个名为 compiler_flags_overrides.cmake的脚本,脚本中将_INIT后缀的所有编译器初始化变量中的/MD统统改为/MT

if(MSVC)     
  # Use the static C library for all build types
  MESSAGE(STATUS "link to static  C and C++ runtime lirbary(/MT /MTd)")
  foreach(var 
        CMAKE_C_FLAGS_DEBUG_INIT 
        CMAKE_C_FLAGS_RELEASE_INIT
        CMAKE_C_FLAGS_MINSIZEREL_INIT 
        CMAKE_C_FLAGS_RELWITHDEBINFO_INIT
        CMAKE_CXX_FLAGS_DEBUG_INIT 
        CMAKE_CXX_FLAGS_RELEASE_INIT
        CMAKE_CXX_FLAGS_MINSIZEREL_INIT 
        CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT
    )
    if(${var} MATCHES "/MD")
      string(REGEX REPLACE "/MD" "/MT" ${var} "${${var}}")
      MESSAGE(STATUS  "${var}:${${var}}")
    endif()    
  endforeach()    
endif(MSVC)

然后在调用cmake生成msvc工程的时候用CMAKE_USER_MAKE_RULES_OVERRIDE指定前面compiler_flags_overrides.cmake脚本的位置,就可以实现/MD/MT的切换了。 大致如下:

cmake .. -G "NMake Makefiles" -DCMAKE_USER_MAKE_RULES_OVERRIDE=$overrides_cmake_path

这样的好处显而易见,不需要修改原项目的CMakeLists.txt,在外部就能控制/MD/MT选项。

参考资料:

《How can I build my MSVC application with a static runtime?》 《CMAKE_USER_MAKE_RULES_OVERRIDE》

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏技术博客

一步一步学Linq to sql(十):多层架构MVC WCF Linq

 A,MVC网站项目 MvcOperation:留言簿表现层  B,类库项目 Contract:定义数据访问服务的契约  C,类库项目 Service:定义数据...

632
来自专栏.NET开发者社区

基于ASP.NET MVC(C#)和Quartz.Net组件实现的定时执行任务调度

在之前的文章《推荐一个简单、轻量、功能非常强大的C#/ASP.NET定时任务执行管理器组件–FluentScheduler》和《简单、轻量、功能非常强大的C#/...

33210
来自专栏飞扬的花生

Npoi导入导出Excel操作

    之前公司的一个物流商系统需要实现对订单的批量导入和导出,翻阅了一些资料,最后考虑使用NPOI实现这个需求。 在winform上面实现excel操作:ht...

1695
来自专栏magicsoar

基于windowsphone7的控制ppt播放 第一部分 服务器端

最近突然想起了一个学长的一个利用手机控制ppt播放的一个创意,并想将其在windows phone7上实现一下。 经过几天的努力已经可以控制ppt的播放,暂停,...

1967
来自专栏GreenLeaves

WCF系列教程之消息交换模式之请求与答复模式(Request/Reply)

1、使用WCF请求与答复模式须知 (1)、客户端调用WCF服务端需要等待服务端的返回,即使返回类型是void (2)、相比Duplex来讲,这种模式强调的是客户...

18510
来自专栏飞扬的花生

Npoi导入导出Excel操作

    之前公司的一个物流商系统需要实现对订单的批量导入和导出,翻阅了一些资料,最后考虑使用NPOI实现这个需求。 在winform上面实现excel操作:ht...

2459
来自专栏一个爱瞎折腾的程序猿

.net core建站踩坑记录

services.AddOptions(); services.Configure<AppSettings>(Configuration...

912
来自专栏偏前端工程师的驿站

网页优化系列三:使用压缩后置viewstate

  Asp.net中的服务器控件都启用了viewstate,虽然方便了开发人员,但页面大小及性能上确实有所影响,对于无需viewstate的控件及页面可以直接把...

1716
来自专栏微服务

C# 如何在Excel 动态生成PivotTable

Excel 中的透视表对于数据分析来说,非常的方便,而且很多业务人员对于Excel的操作也是非常熟悉的,因此用Excel作为分析数据的界面,不失为一种很好的选择...

27012
来自专栏偏前端工程师的驿站

网页优化系列三:使用压缩后置viewstate

  Asp.net中的服务器控件都启用了viewstate,虽然方便了开发人员,但页面大小及性能上确实有所影响,对于无需viewstate的控件及页面可以直接把...

1945

扫码关注云+社区