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. ...
随机推荐
- RabbitMQ学习之基于spring-rabbitmq的消息异步发送
spring-rabbitmq的源码到http://github.com/momania/spring-rabbitmq下载,并可以下载实例代码.由于我使用的rabbitmq版本是3.0.4,部分代码 ...
- CentOS6.6安装mysql-5.7.25二进制安装包简易教程
#####1,安装前首先确认系统版本 [root@bogon:~]# cat /etc/redhat-release CentOS release 6.6 (Final) [root@bogon:~] ...
- 关于配置websocket,nginx转发https至wss问题
在本地测试通过的socket,再放到现在的有nginx代理之后发现会报:failed: Error in connection establishment: net::ERR_NAME_NOT_RES ...
- css实现三栏水平布局双飞翼与圣杯布局
作为布局的入门级选手,网上也查看了很多信息和资源 双飞翼的html结构 <div class="container"> <div class="main ...
- Project Euler 47 Distinct primes factors( 筛法记录不同素因子个数 )
题意: 首次出现连续两个数均有两个不同的质因数是在: 14 = 2 × 715 = 3 × 5 首次出现连续三个数均有三个不同的质因数是在: 644 = 22 × 7 × 23645 = 3 × 5 ...
- 指针FHQTreap
不太友好的代码 题面依旧是普通平衡树 //Writer : Hsz %WJMZBMR%tourist%hzwer #include <bits/stdc++.h> #define LL l ...
- python基础:局部变量--全局变量的使用
局部变量: 使用原则:仅在本函数内部使用的变量,其他函数无法使用本函数的变量 代码: def function1(): a = 2 #定义一个局部变量 print(a) def function2() ...
- BA--湿球温度和干球温度的区别
关于湿球温度和干球温度的区别: 干湿球温度表:用一对并列装置的.形状完全相同的温度表,一支测气温,称干球温度表,另一支包有保持浸透蒸馏水的脱脂纱布,称湿球温度表.当空气未饱和时,湿球因表面蒸发需要消耗 ...
- Hibernate-原生SQL查询
HQL尽管容易使用,但是在一些复杂的数据操作上功能有限.特别是在实现复杂的报表统计与计算,以及多表连接查询上往往无能为力,这时可以使用SQL(Native SQL)实现HQL无法完成的任务. 1.使用 ...
- iterator遍历list理解
1.iterator的next()方法返回值,就是你指定的iiterator<>泛型.所以你再强制转换,就可以得到list里的item了,直接是item对象了. 2.list这东西,你ne ...