CMake与MSVC工程化实践
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工程化实践的更多相关文章
- [vue]webpack&vue组件工程化实践
[vue]全局组件和局部组件(嵌套+props引用父组件数据) [vue]组件篇 [vue]组件的创建(componet)和销毁(keep-alive缓存)和父子dom同步nextTick [vue] ...
- Vue项目架构设计与工程化实践
摘自Berwin<Vue项目架构设计与工程化实践>github.com/berwin/Blog/issues/14 1.Vue依赖套件 vuex:项目复杂后,用vuex来管理状态 elem ...
- 基于 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 时代,包括其插件在需要时就引 ...
- Vue 项目架构设计与工程化实践
来源 文中会讲述我从0~1搭建一个前后端分离的vue项目详细过程 Feature: 一套很实用的架构设计 通过 cli 工具生成新项目 通过 cli 工具初始化配置文件 编译源码与自动上传CDN Mo ...
- 基于 Vue.js 之 iView UI 框架非工程化实践记要
像我们平日里做惯了 Java 或者 .NET 这种后端程序员,对于前端的认识还常常停留在 jQuery 时代,包括其插件在需要时就引用一下,不需要就删除.故观念使然,尽管 Nuget 和 Maven ...
- CMake区分MSVC版本
MSVC++ 4.x _MSC_VER == 1000 MSVC++ 5.0 _MSC_VER == 1100 MSVC++ 6.0 _MSC_VER == 1200 MSVC++ 7.0 _MSC_ ...
- webpack + react 前端工程化实践和暂不极致优化
技术结构 webpack + react + react-router 功能实现 关于打包 1.基于react-router的自定义打包code split.2.分包异步按需加载.3.CommonsC ...
- 《CMake实践》笔记一:PROJECT/MESSAGE/ADD_EXECUTABLE
<CMake实践>笔记一:PROJECT/MESSAGE/ADD_EXECUTABLE <CMake实践>笔记二:INSTALL/CMAKE_INSTALL_PREFIX &l ...
- 《CMake实践》笔记一:PROJECT/MESSAGE/ADD_EXECUTABLE【转】
本文转载自:http://www.cnblogs.com/52php/p/5681745.html 前言: 开发了5,6年的时间,如果没有KDE4,也许不会有人或者Linux发行版本重视cmake,因 ...
随机推荐
- 10分钟让你明白MySQL是如何利用索引的
一.前言 在MySQL中进行SQL优化的时候,经常会在一些情况下,对MySQL能否利用索引有一些迷惑. 譬如: MySQL 在遇到范围查询条件的时候就停止匹配了,那么到底是哪些范围条件? MySQL ...
- MySQL之UNDO及MVCC、崩溃恢复
UNDO特性:避免脏读.事务回滚.非阻塞读.MVCC.崩溃恢复 事务工作流程(图2) MVCC原理机制 崩溃恢复:redo前滚.undo回滚 长事务.大事务:危害.判断.处理 UNDO优化:实现u ...
- Git & GitHub 的安装配置
参考 教你免费搭建个人博客,Hexo&Github 安装Git 1. 注册 GitHub 注册.登录 https://github.com/ 2. 创建仓库 在 GitHub 的右上角 ...
- 进程控制编程——Linux编程
1.进程的创建 编写一段程序,使用系统调用fork( )创建两个子进程,在系统中有一个父进程和两个子进程活动.让每个进程在屏幕上显示一个字符:父进程显示字符“a”,子进程分别显示字符“b” 和“c”. ...
- CSS 居中大全(转)
引用:http://jinlong.github.io/blog/2013/08/13/centering-all-the-directions/ CSS 居中大全 AUG 13TH, 2013 | ...
- 前端aes解密实战小结
很多人对于AES加密并不是很了解,导致互相之间进行加密解密困难. 本文用简单的方式来介绍AES在使用上需要的知识,而不涉及内部算法.最后给出例子来帮助理解AES加密解密的使用方法. AES的麻烦 相比 ...
- 【转】IE内嵌google chrome frame解决浏览器兼容问题
参考文献: http://www.pseudowired.com/2012/12/04/tomcat-http-header-manipulation/(html中自动添加使用chrome的heade ...
- c++ 智能指针、函数指针和指针函数
智能指针: 1.内存泄漏memory leak :是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出. 2.内存溢出 out of me ...
- Android SDK4/5/6/7,相册、拍照及裁剪功能及遇见的坑
保存照片和视频到系统相册显示- http://blog.csdn.net/chendong_/article/details/52290329 Android 7.0 之拍照与图片裁剪适配-http: ...
- js 正则表达式验证密码、邮箱格式.....
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...