CMake使用教程

一 基本配置

1.1 单文件项目

首先使用CMake创建一个最简单的项目

项目结构如下:

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

其中main.cpp为源文件,build是用来构建项目的文件夹

cmake_minimum_required(VERSION 3.0) #设置cmake的最低版本

project(CMAKEEXAMPLE)   #设置项目名称

add_executable(app main.cpp)	#生成一个可执行程序 指定需要用到的源文件

项目的编译可以使用如下命令:

cd build	#进入到build文件夹,目的是在该文件夹中执行后续操作,后续操作产生的文件就会放在该文件夹下,项目结构更加清晰
cmake ..	#因为此时我们位于build/文件夹下,所是cmake参数使用.. 表示使用上一层的CMakeists.txt文件执行cmake命令
make		#cmake命令执行完毕后会生成makefile等文件,我们还需要再执行以下make命令才能完成项目的编译

1.2 多文件项目

通常情况下一个稍微完善点的项目会使用到许多头文件和源文件,项目结构如下:

├── build
├── CMakeLists.txt
├── include
│   ├── util1.h
│   └── util2.h
├── main.cpp
└── src
    ├── util1.cpp
    └── util2.cpp

include和src文件夹中分别存放头文件和源文件,假设这些文件在main.cpp中被使用。

在g++中我们需要使用 -I 指定头文件搜索路径,使用CMake构建项目也需要类似的操作:

include_directories(./include)	#指定头文件搜索路径

由于使用了新增的源文件,所需还需要进行如下的修改,文件路径可以使用绝对路径也可以使用相对路径。

add_executable(app main.cpp ./src/util1.cpp /src/util2.cpp)

项目的编译命令和1.1是一样的。

1.3 生成静态/动态库

有时候需要将项目编译为库,而不是可执行文件,假设有如下项目

├── build
├── CMakeLists.txt
├── include
│   └── util1.h
└── src
    └── util1.cpp

将其编译为静态库需要进行如下设置:

include_directories(./include)		#同样需要指定头文件

add_library(util1 ./src/util1.cpp)	#指定生成的库名以及需要用到的源文件

add_library的语法为:

add_library(libname [SHARED|STATIC|MODULE] [EXCLUDE_FROM_ALL] source1 source2...)如果不指定参数,默认会使用 STATIC 也就是打包为静态库。

进入build文件夹执行编译命令后可以在该文件夹下找到一个名为 libutil1.a 的文件即为生成的静态库文件,文件名是按照“lib+你指定的文件名+.a”格式自动生成的。

1.4 使用静态/动态库

使用方式很简单,只需要指定好库文件路径以及对应头文件路径即可。如果想使用 1.3 中生成的静态库,我们需要通过如下方式指定 util1.h 和 libutil1.a 的路径(为了方便,我们可以将这两个文件放在一个特定的路径下,这里我把头文件放在了了/usr/include/中,库文件放在了/usr/lib/中)

项目结构如下:

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

其中main.cpp中使用到了libutil1.a库,在我们的项目的 CMakeLists.txt 中添加如下设置:

include_directories(/usr/include)

link_directories(/usr/lib)		#指定库文件搜索路径

add_executable(app main.cpp)	#生成可执行文件

target_link_libraries(app util1)	#由于可执行文件中使用了库,需要将库链接到可执行文件

1.5 多目录管理

在编写大型项目时可能需要将整个项目划分为多个子项目,方便管理与组织,下面个出一个样例结构:

├── build
├── CMakeLists.txt
├── Alg
│   ├── CMakeLists.txt
│   ├── include
│   │   └── mymath.h
│   └── src
│       └── mymath.cpp
├── View
│   ├── CMakeLists.txt
|   ├── include
|   │   └── myprint.h
|   └── src
|       └── myprint.cpp
└── App
    ├── CMakeLists.txt
    └── main.cpp

Alg为计算模块、View为可视化模块、App为主模块

App中调用Alg完成计算,然后调用View进行可视化

/Alg/CMakeLists.txt内容如下:

cmake_minimum_required(VERSION 3.0)
project(ALG)
include_directories(./include)
add_library(alg ./src/mymath.cpp)

/View/CMakeLists.txt内容如下:

cmake_minimum_required(VERSION 3.0)
project(VIEW)
include_directories(./include)
add_library(view ./src/myprint.cpp)

/App/CMakeLists.txt内容如下:

cmake_minimum_required(VERSION 3.0)
project(APP)
include_directories(../Alg/include ../View/include)
link_directories(../build)
add_executable(APP main.cpp)
target_link_libraries(APP alg view)

最后在根目录下的CMakeLists.txt下添加如下内容:

cmake_minimum_required(VERSION 3.0)
project(MUL_PROJECT)

#添加子目录,会自动执行子目录下CMakeLists.txt中的内容
add_subdirectory(Alg)
add_subdirectory(View)
add_subdirectory(App)

二 更多配置

2.1 自定义编译选项

有时我们需要根据配置项设置软件版本或者控制代码的运行(根据编译选项改变程序流程),camke提供了configure_file命令可以实现这种功能。

configure_file 可以根据配置选项替换模板文件中的内容从而生成一个头文件,在源码中使用该头文件完成控制。语法为:

configure_file(<input> <output>
				[COPYONLY] [ESCAPE_QUOTES] [@ONLY]
				[NEWLINE_STYLE] [UNIX|DOS|WIN32|LF|CRLF])

本例项目结构如下:

├── build
├── CMakeLists.txt
├── main.cpp
└── myconfig.h.in

我们创建了一个模板文件myconfig.h.in ,内容如下:

#cmakedefine APP_VERSION_MAJOR @APP_VERSION_MAJOR@
#cmakedefine APP_VERSION_MINOR @APP_VERSION_MINOR@
#cmakedefine APP_AUTHOR "@APP_AUTHOR@"

这三句替换后就是三个宏定义。

其中 #cmakedefine 将会被替换为 #define,当然直接在这里写 #define 也是可以的。

而具体的值需要使用@@获取。

下面我们需要在CMakeLists.txt中配置对应的值,configure_file才知道要替换成什么,在CMakeLists.txt中添加如下内容

cmake_minimum_required(VERSION 3.0)
project(APP)

set(APP_VERSION_MAJOR 1)	#设置值
set(APP_VERSION_MINOR 1)	#设置值
set(APP_AUTHOR 诗如沿海)	 #设置值

configure_file(
    "myconfig.h.in"
    "${PROJECT_BINARY_DIR}/myconfig.h"
    )

include_directories(${PROJECT_BINARY_DIR})
add_executable(main main.cpp)

在main中按照如下方式使用即可:

#include <iostream>
#include "myconfig.h"
using namespace std;

int main()
{
    cout << "VERSION_MAJOR: " << APP_VERSION_MAJOR << endl;
    cout << "VERSION_MINOR: " << APP_VERSION_MINOR << endl;
    cout << "APP_AUTHOR: " << APP_AUTHOR << endl;

    return 0;
}

在CMakeLists.txt中除了使用set设置值,还可以使用option,他更适合用来控制编译流程。

其语法为:

option(<variable> "<help_text>" [value])

value定义选项的默认状态,一般是OFF或ON。

三 常用变量

CMake提供了一些常用的变量,我们可以对其进行设置或者使用他们

  • CMAKE_C_FLAGS: gcc编译选项

  • CMAKE_CXX_FLAGS: g++编译选项

    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")	#注意需要在g++编译选项后追加参数,不然会覆盖之前的全部内容
    
  • CMAKE_BUILD_TYPE: 编译类型,可以选择Debug Release

    set(CMAKE_BUILD_TYPE Debug)
    
  • 编译发生的目录:

    • CMAKE_BINARY_DIR:
    • PROJECT_BINARY_DIR:
    • _BINARY_DIR:
  • 工程顶层目录:

    • CMAKE_SOURCE_DIR:
    • PROJECT_SOURCE_DIR:
    • _SOURCE_DIR:
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值