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 条评论
登录 后参与评论

相关文章

来自专栏CaiRui

Python 类

1、创建和使用类   使用类几乎可以模拟任何东西。 1.1创建Dog类   根据Dog类创建的每个实例都将存储名字和年龄。我们赋予了每条小狗蹲下sit()和打滚...

1906
来自专栏Danny的专栏

浅谈ADO.NET中的对象——Connection、Command、DataReader、DataAdapter、DataSet、DataTable

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/...

603
来自专栏锦小年的博客

python学习笔记8.1-异常处理

程序员最大的天敌就是bug,所谓bug就是按照特定的输入,却没有得到期望的相应,这个时候程序出了bug。bug是一定会存在的,有些是人为因素造成的,所以在编程的...

1636
来自专栏IMWeb前端团队

Zepto核心模块之工具方法拾遗

本文作者:IMWeb 谦龙 原文出处:IMWeb社区 未经同意,禁止转载 前言 平时开发过程中经常会用类似each、map、forEach之类的方法...

2716
来自专栏跟着阿笨一起玩NET

浅谈WebService开发(一)

       简单通俗来说,就是企业之间、网站之间通过Internet来访问并使用在线服务,一些数据,由于安全性问题,不能提供数据库给其他单位使用,这时候可以使...

573
来自专栏向治洪

解释器模式

解释器模式: 解释器模式是类的行为模式。给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器。客户端可以使用这个解释器来解释这个语言中的...

17810
来自专栏FreeBuf

小白都能看懂的JSON反序列化远程命令执行

前言 Fastjson是一个由阿里巴巴维护的一个json库。它采用一种“假定有序快速匹配”的算法,是号称Java中最快的json库。Fastjson接口简单易...

3674
来自专栏Python

二、爬虫基础库

request模块 安装 1 pip install requests 简单使用   import requests respo...

2339
来自专栏从零开始学自动化测试

python爬虫beautifulsoup4系列2

前言 本篇详细介绍beautifulsoup4的功能,从最基础的开始讲起,让小伙伴们都能入门 一、读取HTML页面 1.先写一个简单的html页面,把以下...

2836
来自专栏杂七杂八

BeautifulSoup使用

Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种: Tag , NavigableS...

993

扫码关注云+社区