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. ...
随机推荐
- RxSwift學習教程之基礎篇
前言 我們在 iOS 開發過程中,幾乎無時無刻都要面對異步事件的處理.例如,按鍵點擊.數據保存..音頻後臺播放.交互動畫展示.這些事件並不具備特定時序性,甚至它們可能同時發生. 雖然 Apple 提供 ...
- spring注解略解
@Scope("prototype") 如果ACTION中不@Scope("prototype"),有可能报找不到XXXACTION的错误!写上这个就表示每次请 ...
- vc++实例创建简单窗体
#include<windows.h>#include<stdio.h>LRESULT CALLBACK WinSunProc(HWND hwnd,UINT uMsg,WPAR ...
- 解决python3在sublim Text3中中文乱码的问题
在Tool >> BulidingSystem 中 新建 python3 写入如下代码 { "cmd": ["C:/python3/python.exe&q ...
- Hibernate Session操作
1.增加 @Test public void add(){ Configuration cfg=new Configuration().configure(); SessionFactory fact ...
- 判断n是否为质数
#include <iostream> #include <vector> #include <stdio.h> using namespace std; int ...
- docker 命令部分
本文只记录docker命令在大部分情境下的使用,如果想了解每一个选项的细节,请参考官方文档,这里只作为自己以后的备忘记录下来. 根据自己的理解,总的来说分为以下几种: 看一个变迁图 看一个变迁图 ...
- js实现本地的图片压缩上传预览
js在设计时考虑到安全的原因是不允许读写本地文件的,随着html5的出现提供了fileReader AP从而可以I实现本地图片的读取预览功能, 另外在移动端有的限制图片大小的需求,主要是考虑图片过大会 ...
- BeanPostProcessor bean 的后置处理器
一. 自定 bean 的后置处理器 MyBeanPostProcessor 类.当你在初始化容器中的 bean 之前和之后,都会调用该处理器中的方法 @Component //将该后后置处理器加入到容 ...
- python的range()函数使用方法
python的range()函数使用非常方便.它能返回一系列连续添加的整数,它的工作方式类似于分片.能够生成一个列表对象. range函数大多数时常出如今for循环中.在for循环中可做为索引使用.事 ...