文档章节

CMAKE使用总结

能东棍
 能东棍
发布于 2017/05/16 16:40
字数 1663
阅读 386
收藏 1

参考文档

CMake Practice.pdf

最简单的例子

目录结构

.
├── CMakeLists.txt
└── main.cpp

main.cpp

#include <iostream>
int main()
{
    std::cout <<"Hello World" << std::endl;
    return 0;
}

CMakeLists.txt

PROJECT (PRACTISE1)
SET(SRC_LIST main.cpp)
MESSAGE(STATUS "This is BINARY dir "${PRACTISE1_BINARY_DIR})
MESSAGE(STATUS "This is BINARY dir "${PROJECT_BINARY_DIR})
MESSAGE(STATUS "This is SOURCE dir "${PRACTISE1_SOURCE_DIR})
MESSAGE(STATUS "This is SOURCE dir "${PROJECT_SOURCE_DIR})
ADD_EXECUTABLE(practise1 ${SRC_LIST})

在目录执行cmake命令

$ cmake .

输出

...
-- This is BINARY dir xxx/practise1
-- This is BINARY dir xxx/practise1
-- This is SOURCE dir xxx/practise1
-- This is SOURCE dir xxx/practise1
...

总结

  • CMAKE语法中的指令关键字不分大小写,但是传入的参数是分大小写的, 如果传入的参数是列表可以用空格或者分号隔开, 参数也可以使用双引号传入(处理带有空格字符的参数的时候很有用)。
  • PROJECT用来设置工程名字,可以与后面ADD_EXECUTABLE中的目标文件名不一样。
  • SET用来定义一个变量,如果定义的是列表可以用空格或者分号隔开,定义的变量可以在后面用${变量名}来进行取值。
  • MESSAGE用来打印日志,分别有SEND_ERROR | STATUS | FATAL_ERROR三中类型,其中FATAL_ERROR会让构建程序终止。
  • ADD_EXECUTABLE根据设置生成指定的可执行文件。
  • 默认变量${PROJECT_BINARY_DIR}指的是目标make文件的生成目录。
  • 默认变量${PROJECT_SOURCE_DIR}指的是工程CMakeLists.txt所在目录。
  • <工程名>_BINARY_DIR和<工程名>_SOURCE_DIR是 PROJECT 指令隐式定义的两个变量, 等同于PROJECT_BINARY_DIR和PROJECT_SOURCE_DIR,一般推荐使用后面这两个,因为工程名会变动。
  • cmake之后如果运行make命令会发现目标文件生成在${PROJECT_BINARY_DIR}
  • 清理使用 make clean

工程化组织

目录结构

.
├── bin
├── build
├── CMakeLists.txt
└── src
    ├── CMakeLists.txt
    └── main.cpp

根目录下面的CMakeLists.txt

SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin
ADD_EXECUTABLE(practise2 main.cpp)

src目录下面的CMakeLists.txt

PROJECT(PRACTISE2)
MESSAGE(STATUS "PROJECT_BINARY_DIR= "${PROJECT_BINARY_DIR})
MESSAGE(STATUS "PROJECT_SOURCE_DIR= "${PROJECT_SOURCE_DIR})
ADD_SUBDIRECTORY(src)

到build目录下面进行cmake

$ cd build
$ cmake ..
$ make

输出

-- PROJECT_BINARY_DIR= xxx/practise2/build
-- PROJECT_SOURCE_DIR= xxx/practise2

practise2最后生成在bin目录中

总结

  • 运行cmake命令所在的目录将是目标make文件的生成目录,即${PROJECT_BINARY_DIR}。
  • ADD_SUBDIRECTORY指令第一个参数指的是需要添加的子目录, 子目录下面也因该有CMakeLists.txt, 第二个指make生成的最终文件存放目录,实际执行时文件被保存到了${PROJECT_BINARY_DIR}/bin下 第三个参数EXCLUDE_FROM_ALL,用来将这个目录排除
  • 通过改变变量EXECUTABLE_OUTPUT_PATH来修改可执行文件的生成目录,一般是结合ADD_EXECUTABLE指令使用, LIBRARY_OUTPUT_PATH修改库的生成目录,一般是结合ADD_LIBRARY指令使用。

生成动态库和静态库

基本指令

  • 生成库文件
ADD_LIBRARY(库名 SHARED 源文件列表)

把上面的ADD_EXECUTABLE修改为ADD_LIBRARY就可以生成库文件了, 第二个参数SHARED表示生成动态库,STATIC表示生成静态库

  • 指定库文件的生成目录
SET(LIBRARY_OUTPUT_PATH <路径>)
  • 修改输出名字
ADD_LIBRARY(hello_static STATIC hello.c)
SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")

原本会输出 libhello_static.a,加上后面这个后,库文件名变为libhello.a

  • 设置动态库的版本号
SET_TARGET_PROPERTIES(hello PROPERTIES VERSION 1.2 SOVERSION 1)

VERSION 指代动态库版本,SOVERSION 指代 API 版本。

  • 同时生成动态库和静态库的CMakeLists.txt
SET(LIBHELLO_SRC hello.cpp)
SET(LIBRARY_OUTPUT_PATH lib)  #目标文件生成目录设置为lib
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})
SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello") #对目标文件重命名
SET_TARGET_PROPERTIES(hello PROPERTIES CLEAN_DIRECT_OUTPUT 1)  #不清理上个版本的生成文件
SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1) #不清理上个版本的生成文件

make之后会同时生成两个文件

    ├── lib
    │   ├── libhello.a
    │   └── libhello.so

windows下DLL生成说明

由于windows调用dll一般是需要dll文件,带有symbol的lib文件,以及函数声明的头文件,因此需要做额外的配置,CMAKE在动态库编译的之前会预定义一个宏 {库名}_EXPORTS,判断这个宏来决定dll中的函数是不是导出函数,有了导出函数vs才会额外的生成lib文件。

以下代码兼容windows和linux dynamic.h

#ifndef __DYNAMIC_H_
#define __DYNAMIC_H_

#ifdef _WIN32
#ifdef dynamic_EXPORTS
#define __DLL_API __declspec(dllexport)
#else
#define __DLL_API __declspec(dllimport)
#endif
#endif //_WINDOWS

#ifdef  __linux__
#ifdef dynamic_EXPORTS
#define __DLL_API  __attribute__((visibility("default")))
#else
#define __DLL_API
#endif
#endif //__linux__

__DLL_API void fun_dynamic();

#endif

dynamic_EXPORTS这个宏是cmake自动根据库名生成的,正好可以用来作为是导出函数的判断

dynamic.cpp

#include "dynamic.h"
#include <iostream>

__DLL_API void fun_dynamic()
{
	std::cout << "msg from dynamic" << std::endl;
}

引用外部头文件和库文件

指令语法

  • 引用外部头文件
INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...)

这条指令可以用来向工程添加多个特定的头文件搜索路径,路径之间用空格分割,如果路径 中包含了空格,可以使用双引号将它括起来,默认的行为是追加到当前的头文件搜索路径的 后面,你可以通过两种方式来进行控制搜索路径添加的方式: 1,CMAKE_INCLUDE_DIRECTORIES_BEFORE,通过 SET 这个 cmake 变量为 on,可以 将添加的头文件搜索路径放在已有路径的前面。 2,通过 AFTER 或者 BEFORE 参数,也可以控制是追加还是置前。

  • 链接库文件

添加非标准的共享库搜索路径

LINK_DIRECTORIES(directory1 directory2 ...)

为 target 添加需要链接的库,target可以是可执行文件,也可以是库文件

TARGET_LINK_LIBRARIES(target library1
                     <debug | optimized> library2
                     ...)

目录结构

├── bin
├── build
├── CMakeLists.txt
├── libs
└── src
    ├── CMakeLists.txt
    ├── libdynamic
    │   ├── CMakeLists.txt
    │   ├── dynamic.cpp
    │   └── dynamic.h
    ├── libstatic
    │   ├── CMakeLists.txt
    │   ├── static.cpp
    │   └── static.h
    └── main
        ├── CMakeLists.txt
        └── main.cpp

本工程由一个可执行文件和一个静态库和一个动态库构成,可执行文件调用了这两个库文件,可执行文件和动态库最后生成在bin目录下,静态库生成在libs目录。

根目录的 CMakeLists.txt

PROJECT(PRACTISE3)
MESSAGE(STATUS "PROJECT_BINARY_DIR= "${PROJECT_BINARY_DIR})
MESSAGE(STATUS "PROJECT_SOURCE_DIR= "${PROJECT_SOURCE_DIR})
ADD_SUBDIRECTORY(src)

src目录的CMakeLists.txt

ADD_SUBDIRECTORY(libstatic)
ADD_SUBDIRECTORY(libdynamic)
ADD_SUBDIRECTORY(main)

动态库的CMakeLists.txt

SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
ADD_LIBRARY(dynamic SHARED dynamic.cpp)

设定生成目录为根目录下面的bin

静态库的CMakeLists.txt

SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/libs)
ADD_LIBRARY(static STATIC static.cpp)

设定生成目录为根目录下面的libs

可执行文件的CMakeLists.txt

INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/libstatic ${PROJECT_SOURCE_DIR}/src/libdynamic)
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
ADD_EXECUTABLE(practise3 main.cpp)
TARGET_LINK_LIBRARIES(practise3 static)
TARGET_LINK_LIBRARIES(practise3 dynamic)

设定了头文件的查找目录,并在最后指定了需要链接的动态库和静态库,库的名字应该与ADD_LIBRARY指令中使用的名字一致

make的输出

Scanning dependencies of target static
[ 33%] Building CXX object src/libstatic/CMakeFiles/static.dir/static.o
Linking CXX static library ../../../libs/libstatic.a
[ 33%] Built target static
Scanning dependencies of target dynamic
[ 66%] Building CXX object src/libdynamic/CMakeFiles/dynamic.dir/dynamic.o
Linking CXX shared library ../../../bin/libdynamic.so
[ 66%] Built target dynamic
Scanning dependencies of target practise3
[100%] Building CXX object src/main/CMakeFiles/practise3.dir/main.o
Linking CXX executable ../../../bin/practise3
[100%] Built target practise3

自动根据各个项目的包含关系决定构建的顺序

© 著作权归作者所有

能东棍
粉丝 7
博文 34
码字总数 25265
作品 0
南京
程序员
私信 提问
使用Cmake生成跨极速赛车平台出租平台项目编译解决方案

项目最近有需求在windows下面运行,我花了几周时间将linux的服务器移植到windows下面,目前已经能够正常运行服务器,目前又有了新需求,两边的代码结构和组织是分开的,因此为了两边能够同步...

inuuns
2018/07/10
0
0
Visual Studio 现已支持 CMake

Visual C++ 团队在他们的官方博客上宣布 Visual Studio 现已支持 CMake。 什么是CMake? CMake 是一个跨平台的开源工具,通过抽象本地构建环境和编译器以管理建立跨多平台程序。CMake解析一个...

局长
2016/10/08
14.4K
15
在TX2上安装VIINS-Mono——问题总结

1 ceres-solver 我们一般通过以下命令安装Eigen: 默认安装在。 在CMakeList.txt中一般用以下语句找到Eigen: 如果有时找不到,可以替换成: 在TX2上安装ceres-solver时,出现以下错误: – ...

W_Tortoise
2018/10/25
0
0
MySQL 5.5 编译安装

文章转自: http://www.orczhou.com/ 在5.5版本之后MySQL自动化建构工具从GUN Autotools换成了跨平台的Cmake系统,编译和配置和原来有些不同,这里做一个简单的小结。 1. 安装CMake Cmake是跨...

红薯
2011/07/06
970
3
Cmake 实现debug和release lib依赖项处理

一、说明 最近用cmake开发东西,编译vs时候,发现debug和release版本的lib库的依赖项问题,故此小结一下。若有不对之处,还请看官多多指教。 使用的工程有自己编写的工程,也有借用第三方库的...

shzwork
04/17
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Kernel DMA

为什么会有DMA(直接内存访问)?我们知道通常情况下,内存数据跟外设之间的通信是通过cpu来传递的。cpu运行io指令将数据从内存拷贝到外设的io端口,或者从外设的io端口拷贝到内存。由于外设...

yepanl
今天
3
0
hive

一、hive的定义: Hive是一个SQL解析引擎,将SQL语句转译成MR Job,然后再在Hadoop平台上运行,达到快速开发的目的 Hive中的表是纯逻辑表,就只是表的定义,即表的元数据。本质就是Hadoop的目...

霉男纸
今天
3
0
二、Spring Cloud—Eureka(Greenwich.SR1)

注:本系列文章所用工具及版本如下:开发工具(IDEA 2018.3.5),Spring Boot(2.1.3.RELEASE),Spring Cloud(Greenwich.SR1),Maven(3.6.0),JDK(1.8) Eureka: Eureka是Netflix开发...

倪伟伟
昨天
8
0
eclipse常用插件

amaterasUML https://takezoe.github.io/amateras-update-site/ https://github.com/takezoe/amateras-modeler modelGoon https://www.cnblogs.com/aademeng/articles/6890266.html......

大头鬼_yc
昨天
4
0
centos7修改命令行或图形界面启动模式

1.systemctl get-default命令获取当前模式 2.systemctl set-default graphical.target 修改启动模式(修改为图形界面,要是修改为命令行就multi-user.target) 2.systemctl set-default multi-...

大圣39
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部