learn cmake
cmake简介
在cmake出现之前,在linuxiax下,大型软件系统一般使用make来控制编译过程,而在Windows下可能是用vs下一个project来构建。一个复杂的系统本身依赖关系就很麻烦,如果想把一个linux下的项目拿到Windows下编译,我们可能要重新建立vs工程,这将是一项乏味且令人讨厌的工作。
cmake就是为了解决这个问题而生,同时他也使得控制软件编译过程变得更简单。其基本原理就是开发人员使用cmake的语法规则编写CMakeLists.txt,cmake executable根据该文件在linux下生产Makefile,在Windows下可能生成vs工程。然后再通过make命令编译、安装。开发人员不再需要自己去写Makefile了。
cmake语法
cmake的语法应该不算难,在初学者看来,至少比make要更user friendly一些。具体的语法可以参见cmake document。下面贴出开源项目muduo的root directory下的CMakeLists.txt,我在该文件中加入了一些comment,可以对cmake command有初步的映像。
# for cmake version control, if cmake version lower than this,
# cmake failed. Also this will call cmake_policy(VERSION, 2.6)
# for bug control.
# I see most of projects set this to 2.6
cmake_minimum_required(VERSION 2.6)
#project(<PROJECT-NAME> [LANGUAGES] [<language-name>...])
#default C CXX
#this must call (explict or implict)
project(muduo C CXX)
#enable ctest
#will need add_test() command, may in subdirectory/CMakeList.txt
enable_testing()
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
endif()
#Signatures of this command that specify a <value>... placeholder expect zero or more arguments. Multiple arguments will be joined as a ;-list to form the actual variable value to be set. Zero arguments will cause normal variables to be unset. See the unset() command to unset variables explicitly.
set(CXX_FLAGS
-g
# -DVALGRIND
# -DMUDUO_STD_STRING
-DCHECK_PTHREAD_RETURN_VALUE
-D_FILE_OFFSET_BITS=64
-Wall
-Wextra
#-Werror
-Wconversion
-Wno-unused-parameter
-Wold-style-cast
-Woverloaded-virtual
-Wpointer-arith
-Wshadow
-Wwrite-strings
-march=native
# -MMD
# -std=c++0x
-rdynamic
)
#list(LENGTH <list> <output variable>)
#list(GET <list> <element index> [<element index> ...]
# <output variable>)
#list(APPEND <list> [<element> ...])
#list(FILTER <list> <INCLUDE|EXCLUDE> REGEX <regular_expression>)
#list(FIND <list> <value> <output variable>)
#list(INSERT <list> <element_index> <element> [<element> ...])
#list(REMOVE_ITEM <list> <value> [<value> ...])
#list(REMOVE_AT <list> <index> [<index> ...])
#list(REMOVE_DUPLICATES <list>)
#list(REVERSE <list>)
#list(SORT <list>)
if(CMAKE_BUILD_BITS EQUAL 32)
list(APPEND CXX_FLAGS "-m32")
endif()
#replace all ";" in CXX_FLAGS with " " and output to CMAKE_CXX_FLAGS
string(REPLACE ";" " " CMAKE_CXX_FLAGS "${CXX_FLAGS}")
set(CMAKE_CXX_COMPILER "g++")
set(CMAKE_CXX_FLAGS_DEBUG "-O0")
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -finline-limit=1000 -DNDEBUG")
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
# call /usr/share/cmake-3.5/Modules/FindBoost.cmake
find_package(Boost REQUIRED)
find_package(Protobuf)
find_package(CURL)
find_package(ZLIB)
# find the path where ares.h in
find_path(CARES_INCLUDE_DIR ares.h)
find_library(CARES_LIBRARY NAMES cares)
find_path(MHD_INCLUDE_DIR microhttpd.h)
find_library(MHD_LIBRARY NAMES microhttpd)
find_library(BOOSTTEST_LIBRARY NAMES boost_unit_test_framework)
find_library(BOOSTPO_LIBRARY NAMES boost_program_options)
find_path(TCMALLOC_INCLUDE_DIR gperftools/heap-profiler.h)
find_library(TCMALLOC_LIBRARY NAMES tcmalloc_and_profiler)
find_path(HIREDIS_INCLUDE_DIR hiredis/hiredis.h)
find_library(HIREDIS_LIBRARY NAMES hiredis)
find_path(GD_INCLUDE_DIR gd.h)
find_library(GD_LIBRARY NAMES gd)
find_program(THRIFT_COMPILER thrift)
find_path(THRIFT_INCLUDE_DIR thrift)
find_library(THRIFT_LIBRARY NAMES thrift)
if(CARES_INCLUDE_DIR AND CARES_LIBRARY)
message(STATUS "found cares")
endif()
if(CURL_FOUND)
message(STATUS "found curl")
endif()
if(PROTOBUF_FOUND)
message(STATUS "found protobuf")
endif()
if(TCMALLOC_INCLUDE_DIR AND TCMALLOC_LIBRARY)
message(STATUS "found tcmalloc")
endif()
if(ZLIB_FOUND)
message(STATUS "found zlib")
endif()
if(HIREDIS_INCLUDE_DIR AND HIREDIS_LIBRARY)
message(STATUS "found hiredis")
endif()
if(GD_INCLUDE_DIR AND GD_LIBRARY)
message(STATUS "found gd")
endif()
if(THRIFT_COMPILER AND THRIFT_INCLUDE_DIR AND THRIFT_LIBRARY)
message(STATUS "found thrift")
endif()
include_directories(${Boost_INCLUDE_DIRS})
include_directories(${PROJECT_SOURCE_DIR})
string(TOUPPER ${CMAKE_BUILD_TYPE} BUILD_TYPE)
message(STATUS "CXX_FLAGS = " ${CMAKE_CXX_FLAGS} " " ${CMAKE_CXX_FLAGS_${BUILD_TYPE}})
add_subdirectory(muduo/base)
add_subdirectory(muduo/net)
if(NOT CMAKE_BUILD_NO_EXAMPLES)
add_subdirectory(contrib)
add_subdirectory(examples)
else()
if(CARES_INCLUDE_DIR AND CARES_LIBRARY)
add_subdirectory(examples/cdns)
endif()
endif()
cmake示例
编译链接库
构建lib应该算是一个最常见的需求,现在假设我们新建一个简单库,只包含一个整数相加的函数。我们有两个文件add.h和add.cc。
//add.h
int add(int a, int b);
//add.cc
#include"add.h"
int add(int a, int b)
{
return a + b;
}
我们可以新建CMakeLists.txt如下
cmake_minimum_required(VERSION 2.6)
project(add)
set (add_SRCS
add.cc
)
add_library(add ${add_SRCS})
install(TARGETS add DESTINATION lib)
file(GLOB HEADERS "*.h")
install(FILES ${HEADERS} DESTINATION include/add)
这个命令不仅可以帮我们编译add这个lib,而且还可以将.a文件和.h文件安装到指令的目录下,这个由变量CMAKE_INSTALL_PREFIX控制,可用ccmake命令更改,default是/usr/local目录下。
编译可执行文件
现在假设我们要写一个程序,并且要使用上一步中的链接库,下面是程序代码及CMakeLists.txt
//test.cc
#include"add.h"
#include<iostream>
int main()
{
std::cout << add(1, 2) << std::endl;
}
cmake_minimum_required(VERSION 2.6)
project(main)
set (main_SRCS
test.cc
)
include_directories("/home/keviwu/add/include/add")
find_library(LIB_PATH add "/home/keviwu/add/lib")
if (NOT LIB_PATH)
message("libadd.a not find")
endif()
add_executable(main ${main_SRCS})
target_link_libraries(main ${LIB_PATH})
learn cmake的更多相关文章
- CMake速记
目录 CMake速记 我的demo 外部构建 基础语法 常用指令 环境变量 一些变量 参考文档 title: CMake速记 date: 2019/11/18 19:17:40 toc: true - ...
- vscode c++ cmake template project
VSCode configure C++ dev environment claim use CMake to build the project. For debugging, VSCode's C ...
- CMake 构建项目教程-简介
CMake 构建项目教程-简介 Linux 平台构建项目,选择了CLion作为C++的IDE,而CLion默认就是使用CMake构建项目,所以这里记录了CMake在构建项目过程的一些小知识. 1. 项 ...
- win10下VSCode+CMake+Clang+GCC环境搭建
win10下VSCode+CMake+Clang+GCC环境搭建 win10下VSCode+CMake+Clang+GCC环境搭建 安装软件 VSCode插件安装 新建文件夹, 开始撸代码 main. ...
- Reprint: CMake or Make
CMake vs Make https://prateekvjoshi.com/2014/02/01/cmake-vs-make/ Programmers have been using CMake ...
- 使用VSCode和CMake构建跨平台的C/C++开发环境
日前在学习制作LearnOpenGL教程的实战项目Breakout游戏时,希望能将这个小游戏开发成跨平台的,支持在多个平台运行.工欲善其事必先利其器,首先需要做的自然是搭建一个舒服的跨平台C/C++开 ...
- 使用cmake自动构建工程
公司引擎是用cmake根据目标平台来构建工程的,刚接触的时候深深体会到cmake的方便:如果目标平台是windows,它可以帮你自动构建出vs工程:如果是安卓,自动构建出eclipse工程,如果是IO ...
- CMake
使用CMake编译跨平台静态库 http://www.tuicool.com/articles/3uu2Yj cmake命令 安装.用法简介 https://fukun.org/archives/04 ...
- CMake学习笔记
C++开发者必备技能CMake 先简单介绍一下,CMake是一个跨平台的编译工具,它可以根据不用的平台,不同的编译环境,生成不同的MakeFile,从而控制编译的过程. 使用CMake的步骤: 1. ...
随机推荐
- iPhone Mach-O文件格式与代码签名
错误现象1) 直接运行/Applications/MobileFonex.app/MobileFonexKilled: 9 2)gdb调试Program received signal EXC_BAD ...
- Python中的多个装饰器装饰一个函数
def wrapper1(func1): def inner1(): print('w1 ,before') func1() print('w1 after') return inner1 def w ...
- github下载报错:Permission denied (publickey). fatal: Could not read from remote repository.
Permission denied (publickey). fatal: Could not read from remote repository. 博主在github上下载tiny face的的 ...
- mongodb 和 mongoose 初探
mongodb MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的. 1. 安装相关 1.1 下载 官网下载地址 :官网下载社区版 1.2 安 ...
- JavaScript 数字字符串比较大小
JavaScript中常用数字字符串比较 1.数字与数字之间直接比较 比较方式依据数学运算,没什么好说的. 2.数字与字符串数字之间直接比较 例如 数字5 与字符串数字'123',这种比较先将数字字符 ...
- UOJ #86 mx的组合数 (数位DP+NTT+原根优化)
题目传送门 matthew99神犇的题解讲得非常清楚明白,跪烂Orzzzzzzzzzzzzz 总结一下,本题有很多重要的突破口 1.Lucas定理 看到n,m特别大但模数特别小时,容易想到$lucas ...
- vue v-for下图片src显示失败,404错误
- 猫狗分类--Tensorflow实现
贴一张自己画的思维导图 数据集准备 kaggle猫狗大战数据集(训练),微软的不需要FQ 12500张cat 12500张dog 生成图片路径和标签的List step1:获取D:/Study/Py ...
- 通过腾讯地图api获取用户位置限制在指定位置区域
<!--在微信中获取用户位置--><script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js">& ...
- 【ACM-ICPC 2018 南京赛区网络预赛 A】An Olympian Math Problem
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 估计试几个就会发现答案总是n-1吧. 队友给的证明 [代码] #include <bits/stdc++.h> #def ...