CMake与MSVC工程化实践

CMake基础

cmake无疑是最流行的c++跨平台构建工具之一,关于cmake入门指南这里不再赘述,官方文档是最好的参考,这里通过一个例子简述构建一个工程常用的函数和变量。

假设此项目有三个文件hello.h、hello.cpp、main.cpp,hello.h和hello.cpp导出一个void hello();的函数,在main.cpp中使用,CMakeList.txt如下:

# 指明当前CMake的版本不能小于指定版本
cmake_minimum_required (VERSION 3.4)
# 工程名称,如果生成msvc工程,这个同样是解决方案名称
project(MyProject) # 将hello.h、hello.cpp保存到${HELLO_SRC}变量中,作为文件列表
file(GLOB HELLO_SRC
hello.h
hello.cpp
)
file(GLOB MAIN_SRC
main.cpp
) # ${HELLO_SRC}生成为一个共享库,在windows系统自然是dll模块
add_library(hello SHARED ${HELLO_SRC}) # ${MAIN_SRC}生成一个可执行程序main.exe/main.out
add_executable(main ${MAIN_SRC}) # 生产目标main的时候指定链接器链接hello模块
target_link_libraries(main hello)

这样便完成了一个非常简单的CMake工程,同时它也包含了我们工程最关注的一些东西,包括生成库文件,生成可执行文件,如何链接库等等。

Debug与Release

有时候我们希望生成带调试信息的库或者可执行文件与正式发布的文件进行区分,最常见的就是把带调试信息的文件后缀加'd',同时为了目录结构的整齐,需要把它们的生成目录进行区分,那么可以参考以下的CMake命令:

# 取消CMake默认生成的工程选项,仅保留Debug与Release(只对msvc这样的多样化构建ide有效)
if(CMAKE_CONFIGURATION_TYPES)
set(CMAKE_CONFIGURATION_TYPES Debug Release)
set(CMAKE_CONFIGURATION_TYPES "${CMAKE_CONFIGURATION_TYPES}" CACHE STRING
"Reset the configurations to what we need"
FORCE)
endif() # 可执行文件生成目录
# ${PROJECT_BINARY_DIR}运行CMake命令的所在目录(用于CMake的分离式编译)
# ${PROJECT_SOURCE_DIR}是工程的根目录(根CMakeList.txt的所在路径)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/bin/Debug)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}/bin/Release) # 库文件生成目录
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}/lib) # 可执行文件后缀
set_target_properties(${TARGET_NAME} PROPERTIES DEBUG_POSTFIX "d") # 库文件后缀
set(CMAKE_DEBUG_POSTFIX "d")

这时候会发现一些有争议的地方,如果库文件带上了'd'后缀,那么target_link_libraries链接库的时候如何分别链接Debug的库和Release的库的呢。可以分两种情况来说明,如果是上文中类似hello库这种在工程内部'声明'的库,那么我们可以不用考虑,仍然链接hello即可,在生成实际的msvc工程时cmake会为我们自动进行区分;如果使用第三方库,就需要特别的选项去区分:

target_link_libraries(main
debug hello
optimized hellod
)

简单的理解debug选项后面表明带调试信息的库就去搜索hellod,而不带调试信息的库就去搜索hello,特别的对于第三方库,需要注意声明库目录,可以参考link_directories

生成MSVC工程

当编写好一个基本的CMake工程后如何与Visual Studio结合使用呢,可以参考cmake -G命令:

# 在执行CMake命令的地方生成visual studio 2017的解决方案(32位构建选项)
cmake -G 'Visual Studio 15 2017' ${PROJECT_SOURCE_DIR}
# 生成vs2015的64位构建方案
cmake -G 'Visual Studio 14 2015 Win64' ${PROJECT_SOURCE_DIR}
# 根据你计算机内最新的visual studio版本生成解决方案
cmake ${PROJECT_SOURCE_DIR}

打开生成的解决方案会发现除了所有的库的可执行文件对应一个project外,还有ALL_BUILD和一个ZERO_CHECK项目,ALL_BUILD顾名思义就是构建所有的项目了。而构建ZERO_CHECK会触发cmake重新检查CMakeList.txt并且重新加载解决方案,这样就避免了修改CMakeList.txt后重新执行命令生成msvc工程的麻烦了,同时还能保留设置的断点、书签等等。

设置Target Platform Version

有时需要指定winsdk的版本,例如设置为8.1:

set(CMAKE_SYSTEM_VERSION 8.1 CACHE TYPE INTERNAL FORCE)

设置Platform Toolset

有时需要指定工具集的版本,例如生成vs2017工程但是使用vs2015的编译链:

cmake -G "Visual Studio 15 2017" -T v140

结束语

上文所述的仅仅是CMake的冰山一角,还有许许多多的功能和选项可以方便我们进行工程文件的管理。

CMake不仅仅是跨平台构建工程的不二选择,就是仅仅使用它来构建windows工程也提供了许多便利,尤其是鉴于visual studio更新比较频繁,如果我们使用cmake管理我们的工程,同时使用标准的c++去开发,那么visual studio版本的迁移也不是一件头疼的事情了~

CMake与MSVC工程化实践的更多相关文章

  1. [vue]webpack&vue组件工程化实践

    [vue]全局组件和局部组件(嵌套+props引用父组件数据) [vue]组件篇 [vue]组件的创建(componet)和销毁(keep-alive缓存)和父子dom同步nextTick [vue] ...

  2. Vue项目架构设计与工程化实践

    摘自Berwin<Vue项目架构设计与工程化实践>github.com/berwin/Blog/issues/14 1.Vue依赖套件 vuex:项目复杂后,用vuex来管理状态 elem ...

  3. 基于 Vue.js 之 iView UI 框架非工程化实践记要 使用 Newtonsoft.Json 操作 JSON 字符串 基于.net core实现项目自动编译、并生成nuget包 webpack + vue 在dev和production模式下的小小区别 这样入门asp.net core 之 静态文件 这样入门asp.net core,如何

    基于 Vue.js 之 iView UI 框架非工程化实践记要   像我们平日里做惯了 Java 或者 .NET 这种后端程序员,对于前端的认识还常常停留在 jQuery 时代,包括其插件在需要时就引 ...

  4. Vue 项目架构设计与工程化实践

    来源 文中会讲述我从0~1搭建一个前后端分离的vue项目详细过程 Feature: 一套很实用的架构设计 通过 cli 工具生成新项目 通过 cli 工具初始化配置文件 编译源码与自动上传CDN Mo ...

  5. 基于 Vue.js 之 iView UI 框架非工程化实践记要

    像我们平日里做惯了 Java 或者 .NET 这种后端程序员,对于前端的认识还常常停留在 jQuery 时代,包括其插件在需要时就引用一下,不需要就删除.故观念使然,尽管 Nuget 和 Maven ...

  6. CMake区分MSVC版本

    MSVC++ 4.x _MSC_VER == 1000 MSVC++ 5.0 _MSC_VER == 1100 MSVC++ 6.0 _MSC_VER == 1200 MSVC++ 7.0 _MSC_ ...

  7. webpack + react 前端工程化实践和暂不极致优化

    技术结构 webpack + react + react-router 功能实现 关于打包 1.基于react-router的自定义打包code split.2.分包异步按需加载.3.CommonsC ...

  8. 《CMake实践》笔记一:PROJECT/MESSAGE/ADD_EXECUTABLE

    <CMake实践>笔记一:PROJECT/MESSAGE/ADD_EXECUTABLE <CMake实践>笔记二:INSTALL/CMAKE_INSTALL_PREFIX &l ...

  9. 《CMake实践》笔记一:PROJECT/MESSAGE/ADD_EXECUTABLE【转】

    本文转载自:http://www.cnblogs.com/52php/p/5681745.html 前言: 开发了5,6年的时间,如果没有KDE4,也许不会有人或者Linux发行版本重视cmake,因 ...

随机推荐

  1. 4种更快更简单实现Python数据可视化的方法

    数据可视化是数据分析或机器学习项目中十分重要的一环.通常,你需要在项目初期进行探索性的数据分析(EDA),从而对数据有一定的了解,而且创建可视化确实可以使分析的任务更清晰.更容易理解,特别是对于大规模 ...

  2. css基础内容

    css基础内容 CSS 指层叠样式表 (Cascading Style Sheets)样式定义如何显示 HTML 元素样式通常存储在样式表中把样式添加到 HTML 4.0 中,是为了解决内容与表现分离 ...

  3. selenium - pycharm三种案例运行模式

    1.unittest 运行单个用例 (1)将鼠标放到对应的用例,右键运行即可 2.unittest运行整个脚本案例 将鼠标放到if __name__ == "__main__": ...

  4. 开源作业调度框架 - Quartz.NET - ASP.NET部署

    经过这次使用实践,感觉Quartz.NET使用起来方便快捷 但是在发布部署时我们会遇到一个问题 那就是当Web应用程序经常没有按照预计的时间去执行. 那问题出在哪里了呢? 根据以往的经验很容易就可以找 ...

  5. APP性能测试,网易Emmagee工具

    APK地址:https://github.com/NetEase/Emmagee/releases/download/V1.2.1/Emmagee-1.2.1.apk 开源代码github地址:htt ...

  6. vue预渲染实践总结

    # 预渲染 ## 预渲染简介 SEO和首屏加载速度慢的问题,社区讨论最多的解决方案是同构 SSR,即首屏使用服务端渲染,之后的交互逻辑交给客户端处理,解决了单页应用带来的两个问题,但是也带来了服务器压 ...

  7. Python shutil.md

    shutil shutil模块包括高级文件操作,例如复制和归档. Copying Files shutil.copyfileobj(fsrc, fdst[, length]):将类似文件的对象fsrc ...

  8. C# ActiveX 网页打包验证自动升级

    原文地址:http://www.cnblogs.com/yilin/p/csharp-activex.html 注意事项:Win10下需要设置兼容模式,F12仿真切换到IE6-8(版本参考——BT90 ...

  9. leetcode717—1-bit and 2-bit Characters

    We have two special characters. The first character can be represented by one bit 0. The second char ...

  10. Vim2.1-Vim简明教程【CoolShell】【非原创】

    vim的学习曲线相当的大(参看各种文本编辑器的学习曲线),所以,如果你一开始看到的是一大堆VIM的命令分类,你一定会对这个编辑器失去兴趣的.下面的文章翻译自<Learn Vim Progress ...