Linux c++ vim环境搭建系列(6)——CMakeLists.txt多文档多目录组织方法和编写示例
CMakeLists.txt学习
1. 概要
主要是关于cmakelists.txt的编写模板,和多文档多目录的组织方法详解, 涉及第三方库的添加使用方法.
这里主要介绍cmakelists.txt的编写, 完整项目示例参见: https://github.com/whuwzp/vim_config/blob/master/test/cmake_example
2. 完整案例
项目目录结构:(省略了build目录)
$ ~/test/cmake_example$ tree
.
├── bin # 生成可执行文件的文件夹
│ └── main
├── CMakeLists.txt # 根目录cmakelists.txt
├── hello1 # 子目录1
│ ├── CMakeLists.txt # 子目录1的cmakelists.txt
│ ├── hello1.cpp
│ └── hello1.h
├── hello2 # 子目录2
│ ├── CMakeLists.txt # 子目录2的cmakelists.txt
│ ├── hello2.cpp
│ └── hello2.h
├── main.cpp # main函数所在源文件, 需要调用hellofunc1和hellofunc2
└── mbedtls # 第三方库
├── include # 第三方库的头文件
│ └── mbedtls
│ ├── aes.h # 省略了mbedtls的其他头文件
│ └── xtea.h
└── lib # 第三方库的库文件
├── libmbedcrypto.a
├── libmbedtls.a
└── libmbedx509.a
整体思路就是:
- 对于我们自己的代码: 每个文件文件夹单独编译生成库文件, 最后链接. 这一步靠
add_subdirectory
,add_library
,target_link_libraries
三个函数配合完成 - 对于第三方的库文件: 包含其头文件和库文件, 最后链接. 这一步主要靠
include_directories
和target_link_libraries
实现.
3. cmakelists.txt编写及详细解释
一共有三个CMakeLists.txt.
这个是项目根目录的CMakeLists.txt
cmake_minimum_required(VERSION 2.6)
# 定义工程名称
project("main")
set(CMAKE_CXX_COMPILER "clang++")
set(targets main)
# main source files
aux_source_directory(. main_src_files)
# add sub dirs
set(subdirs hello1 hello2)
FOREACH(subdir ${subdirs})
add_subdirectory(${subdir})
ENDFOREACH(subdir)
# other header files
set(includes
${PROJECT_SOURCE_DIR}/mbedtls/include/
)
# other libs files
set(libs
${PROJECT_SOURCE_DIR}/mbedtls/lib/libmbedtls.a
${PROJECT_SOURCE_DIR}/mbedtls/lib/libmbedcrypto.a
${PROJECT_SOURCE_DIR}/mbedtls/lib/libmbedx509.a
)
set(CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libc++ -pthread -Werror -Weverything -Wno-documentation-unknown-command -Wno-sign-conversion -Wno-switch-enum -Wno-unused-variable -Wno-unused-macros -Wno-zero-as-null-pointer-constant -Wno-reserved-id-macro -Wno-documentation-deprecated-sync -Wno-implicit-int-conversion -Wno-deprecated-declarations -Wno-disabled-macro-expansion -Wno-float-equal -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-global-constructors -Wno-exit-time-destructors -Wno-missing-prototypes -Wno-padded -Wno-old-style-cast")
set(CMAKE_BUILD_TYPE Debug)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
set(CMAKE_EXE_LINKER_FLAGS "-lc++ -lc++abi")
include_directories(${includes})
add_executable(${targets} ${main_src_files})
target_link_libraries(${targets} ${libs} ${subdirs})
这个是hello1中的CMakeLists.txt:
aux_source_directory(. hello1_src_files)
add_library(hello1 ${hello1_src_files})
这个是hello2中的CMakeLists.txt:
aux_source_directory(. hello2_src_files)
add_library(hello2 ${hello2_src_files})
3.1 基本设置
# 这句可选, 不一定要
cmake_minimum_required(VERSION 2.6)
# 定义工程名称, 名字随意
project("main")
3.2 编译器选择
cmakelists.txt是用set设置变量的, CMAKE_CXX_COMPILER
应该是类似宏一样, 是预先设定好的, 这句是设置编译器为clang++. 我们也可以设置自定义的变量targets. 访问变量则用${targets}
.
# 也可以设置为g++或gcc
set(CMAKE_CXX_COMPILER "clang++")
# 设置一个变量名为targets, 变量值设置为main
set(targets main)
3.3 添加源文件
aux_source_directory(path filesname)
函数是把path中所有cpp和c的文件名集合赋值给filename (filesname就相当于是一个数组, 数组中每个元素是源文件的文件名).
这句是把当前目录(.
就是当前目录)中所有的cpp和c赋值给main_src_files.
# main source files
aux_source_directory(. main_src_files)
3.4 添加子目录
add_subdirectory(dirname)函数是添加子目录, 这样的话dirname子目录下的CMakeLists.txt也会被自动cmake.
以下是添加hello1和hello2子目录:(这个方法不太方便, 如果有很多子目录就得复制这个函数比较麻烦, 提倡用下面的循环方法)
add_subdirectory(hello1)
add_subdirectory(hello2)
3.5 循环添加子目录
循环语句样式如下, 编译array中的每个元素, 赋值给变量item, 然后分别添加进子目录.
FOREACH(item array)
add_subdirectory(${item})
ENDFOREACH(item)
这个语句块是:
- 新增(数组)变量subdirs, 并赋值为hello1, hello2(数组).
- 循环访问subdirs中的元素, 赋值给subdir
- 添加至子目录
# add sub dirs
set(subdirs hello1 hello2)
FOREACH(subdir ${subdirs})
add_subdirectory(${subdir})
ENDFOREACH(subdir)
3.6 子目录CMakeLists.txt编写
- aux_source_directory函数前面解释过.
add_library(output mode filesname)
函数是用filesname源文件, 以mode形式(可选STATIC或SHARED), 生成库文件output(默认应该是静态库). 这个生成的文件路径后面介绍, 文件名一般是静态库liboutput.a
或共享库liboutput.so
(也就是会自动加上lib的前缀)
aux_source_directory(. hello1_src_files)
# 这个默认是静态库
add_library(hello1 ${hello1_src_files})
# 用以下生成共享库
add_library(hello1 SHARED ${hello1_src_files})
生成了库文件后, 就可以在link阶段链接生成最终的可执行文件:(后面也会有)
# 以下是根目录中CMakeLists.txt, 其中libs变量后面会介绍, 是其他第三方的库文件, subdirs就是所有子目录生成的库文件, 这些库文件一起来链接生成targets
target_link_libraries(${targets} ${libs} ${subdirs})
3.7 添加其他第三方头文件和库文件
上面的子目录一般是我们自己编写的, 如果要用第三方的库文件例如本例中的mbedtls, 那么我们可以以下方式添加头文件和库文件.
- include_directories: 添加include头文件
- target_link_libraries: 链接的库文件
# other header files
set(includes
${PROJECT_SOURCE_DIR}/mbedtls/include/
)
# other libs files
set(libs
${PROJECT_SOURCE_DIR}/mbedtls/lib/libmbedtls.a
${PROJECT_SOURCE_DIR}/mbedtls/lib/libmbedcrypto.a
${PROJECT_SOURCE_DIR}/mbedtls/lib/libmbedx509.a
)
set(subdirs hello1 hello2)
include_directories(${includes})
target_link_libraries(${targets} ${libs} ${subdirs})
3.8 编译选项之warning设置
如果make时报错了(警告), 例如-Wreserved-id-macro
,, 而我们又觉得这类警告不碍事, 就可以添加-Wno-reserved-id-macro
在这里面, 意思是no warning xxx警告.
set(CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libc++ -pthread -Werror -Weverything -Wno-documentation-unknown-command -Wno-sign-conversion -Wno-switch-enum -Wno-unused-variable -Wno-unused-macros -Wno-zero-as-null-pointer-constant -Wno-reserved-id-macro -Wno-documentation-deprecated-sync -Wno-implicit-int-conversion -Wno-deprecated-declarations -Wno-disabled-macro-expansion -Wno-float-equal -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-global-constructors -Wno-exit-time-destructors -Wno-missing-prototypes -Wno-padded -Wno-old-style-cast")
注意: 很多时候我们要用pthread, 这时一定要加上
-pthread
3.9 编译选项之release debug设置
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_BUILD_TYPE Release)
3.10 编译选项之输出文件路径
PROJECT_SOURCE_DIR
也像是一个宏, 指的是项目源文件根目录
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
3.11 链接设置
- add_executable是生成可执行文件
- add_library是生成库文件
add_executable(${targets} ${main_src_files})
target_link_libraries(${targets} ${libs} ${subdirs})
注意: 一定要先add_executable, 再target_link_libraries, 原因是必须先知道要生成的可执行文件, 才能链接, 否则报错: CMake error: 'target is not built by this project', 见: https://stackoverflow.com/questions/43245425/cmake-error-target-is-not-built-by-this-project
参考网址
- cmakelists.txt基础1: http://www.cnblogs.com/52php/p/5681745.html
- cmakelists.txt基础2: http://www.cnblogs.com/52php/p/5681751.html
- cmakelists.txt基础3: http://www.cnblogs.com/52php/p/5681755.html
- cmakelists.txt多文档多目录组织方法: https://www.ibm.com/developerworks/cn/linux/l-cn-cmake/
Linux c++ vim环境搭建系列(6)——CMakeLists.txt多文档多目录组织方法和编写示例的更多相关文章
- Linux c++ vim环境搭建系列(5)——vim使用
5. 使用 5.1 快捷键及设置 5.1.1 光标移动 w : 正向移动到相邻单词的首字符 b : 逆向移动到相邻单词的首字符 e : 正向移动到相邻单词的尾字符 ge : 逆向移动到相邻单词的尾字符 ...
- Linux c++ vim环境搭建系列(4)——vim插件安装配置使用
4. 插件 主要是c++相关的. ~/.vimrc文件在GitHub上有:https://github.com/whuwzp/vim_config 以下内容参考: https://github.com ...
- Linux c++ vim环境搭建系列(3)——Ubuntu18.04.4编译安装youcompleteme
3. youcompleteme编译安装 参考网址: https://github.com/ycm-core/YouCompleteMe#linux-64-bit 建议不要用这个博客的方法: http ...
- Linux c++ vim环境搭建系列(0)——简介
vim 学习 简介: 源码编译使用vim及其插件. 内容包含: vim的编译安装, llvm clang的编译安装, 插件youcompleteme的编译安装使用, 以及vim其他插件的使用. 搭建环 ...
- Linux c++ vim环境搭建系列(1)——Ubuntu18.04.4编译安装vim8.2
1. vim源码编译安装 参考网址: https://github.com/ycm-core/YouCompleteMe/wiki/Building-Vim-from-source 安装各类依赖库 s ...
- Linux c++ vim环境搭建系列(2)——Ubuntu18.04.4编译安装llvm clang
2. 源码编译安装llvm clang 参考网址: https://llvhttps
- Ubuntu环境搭建系列—JavaEE篇
恩,其实我是一时兴起,所以就写了目前这几篇环境的博文,希望能给自己做一个笔记,同时也能够给一些新手带来一些帮助,不会在配置方面那么迷茫.本篇文章主要就是针对Java web开发进行环境搭建. 一.To ...
- Linux vagrant+virtualbox环境搭建步骤
Linux vagrant+virtualbox环境搭建步骤 Vagrant 是一款用来构建虚拟开发环境的工具,非常适合 php/python/ruby/java 这类语言开发 web 应用. 我们可 ...
- 服务器环境搭建系列(四)-mysql篇
1.按照上一篇服务器环境搭建系列(三)-JDK篇中的方法检查系统是否已经预装Mysql并卸载. 2.下载mysql,这里是MySQL-server-5.5.25-1.linux2.6.x86_64.r ...
随机推荐
- http详解和分析
1.http是什么? http 是一种超文本传输协议原名是这个Hypertext Transfer Protocol -- HTTP/1.1 可以百度查看http的RFC文档编号为RFC-2616 连 ...
- 软件工程作业0——The Road Not Taken
目录 第一部分:结缘计算机 缘起 四顾 思考 第二部分:在计算机系里学习 挑战 落差 第三部分:未来规划 向前 未来四个月的软工课 项目 内容 这个作业属于 2020春季计算机学院软件工程(罗杰 任健 ...
- Data-independent acquisition mass spectrometry in metaproteomics of gut microbiota - implementation and computational analysis DIA技术在肠道宏蛋白质组研究中的方法实现和数据分析 (解读人:闫克强)
文献名:Data-independent acquisition mass spectrometry in metaproteomics of gut microbiota - implementat ...
- 《前端之路》- TypeScript (四) class 中各类属性、方法,抽象类、多态
目录 一.TypeScript 中的类 二.TypeScript 中类的继承 三.TypeScript 中公共,私有与受保护的修饰符 3-1.属性的 public 3-2.属性的 private 3- ...
- 李宏毅老师机器学习课程笔记_ML Lecture 0-1: Introduction of Machine Learning
引言: 最近开始学习"机器学习",早就听说祖国宝岛的李宏毅老师的大名,一直没有时间看他的系列课程.今天听了一课,感觉非常棒,通俗易懂,而又能够抓住重点,中间还能加上一些很有趣的例子 ...
- 决战Leetcode: easy part(51-96)
本博客是个人原创的针对leetcode上的problem的解法,所有solution都基本通过了leetcode的官方Judging,个别未通过的例外情况会在相应部分作特别说明. 欢迎互相交流! em ...
- [Intervention] Ignored attempt to cancel a touchmove event with cancelable=false, for example because scrolling is in progress and cannot be interrupted
字面意思大概就是: [干预]忽略尝试取消带有cancelable = false的touchmove事件的尝试,例如,因为滚动正在进行并且无法中断. 解决方法: 1.添加样式更改 将滑动报错的标签样式 ...
- Jupyter Notebook自动补全
大多数程序员都非常熟悉不同的自动补全工具.然而,我注意到许多数据科学家还没有使用它.如果你是他们中的一员,是时候开始使用这个提高效率的工具了 什么是自动补全? 它是你的编程环境提供的一种功能,用于完成 ...
- Hive学习笔记六
目录 查询 一.基本查询 1.全表和特定列查询 2.列别名 3.算术运算符 4.常用函数 5.Limit语句 二.Where语句 1.比较运算符(Between/In/ Is Null) 2.Like ...
- POJ 1797 最短路变形所有路径最小边的最大值
题意:卡车从路上经过,给出顶点 n , 边数 m,然后是a点到b点的权值w(a到b路段的承重),求卡车最重的重量是多少可以从上面经过. 思路:求所有路径中的最小的边的最大值.可以用迪杰斯特拉算法,只需 ...