CMake学习笔记1:一个简单示例


CMake用 CMakeLists.txt来描述代码间的组织关系。

一个最简单的CMakeLists.txt包含3部分内容:所需CMake版本、项目信息以及编译过程。

CMake版本

CMakeLists.txt中用cmake_minimum_required来指定所需CMake的最低版本,例如以下语句说明编译所需CMake最低版本为3.2:

cmake_minimum_required(VERSION 3.2)

项目信息

每一个CMake项目都需要一个project()语句来描述项目信息,通常项目信息出现在cmake_minimum_required语句之后。用来描述项目信息的语句遵循以下形式:

project(projectName
    [VERSION major[.minor[.patch[.tweak]]]]
    [LANGUAGES languageName ...]
)

其中,projectName是项目名称;[VERSION major[.minor[.patch[.tweak]]]]代表项目的版本号,包含主版本号(major)、子版本号(minor)、修正版本号(patch)和微调版本号(tweak),其中可以只写主版本号;[LANGUAGES languageName ...]表示项目所涉及的语言,CMake在配置时将会检查对应的语言编译器/解释器等信息,如果涉及多种语言,中间用空格隔开。

这里边必须写的是项目名称,而其它两个可以不写。如果没有写项目涉及的语言,CMake默认会寻找C和C++语言。以下为描述项目信息的一个示例,项目名称为MyApp,版本1.0,采用C++语言:

project(MyApp VERSION 1.0 LANGUAGES CXX)

编译过程

编译目标对象

CMakeLists.txt当然一定要包含编译目标。编译的目标对象实际上可以分为两类,一类是可执行文件,另一类是库文件。

可执行文件

下面是描述编译可执行文件语句的一般形式:

add_executable(targetName [WIN32] [MACOSX_BUNDLE]
    [EXCLUDE_FROM_ALL]
    source1 [source2 ...]
)

其中,

  • targetName是可执行文件的名称,例如在Windows系统下会生成targetName.exe
  • WIN32是在Windows平台会用到的一个参数,在其他平台这个参数会被忽略。这个参数表示这个目标可执行文件是一个Windows GUI程序,对应Visual Studio中将项目属性-链接器-系统中的子系统这一项设置成了窗口(/SUBSYSTEM:WINDOWS)。例如,使用库wxWidgets,生成GUI可执行文件时要加上这一参数,否则会报错。
  • MACOSX_BUNDLE参数表明在Apple平台上构建的是一个应用程序捆绑包(app bundle)。
  • EXCLUDE_FROM_ALL参数表明当不指明生成这一目标时,不会被默认生成。在不指明编译目标时,默认会编译ALL目标,也就是全部目标,该参数表明这个目标不在ALL目标中。除非显示指明要生成该目标,或者其它需要编译的目标依赖于这个目标,这个目标不会被编译。

库文件

在较大的项目中,除了需要构建可执行文件以外,还需要构建许多库文件。描述编译目标为库文件的一般形式如下:

add_library(targetName [STATIC | SHARED | MODULE]
    [EXCLUDE_FROM_ALL]
    source1 [source2 ...]
)

其中,

  • targetName为所编译库的名字。
  • STATIC | SHARED | MODULE对应不同的库种类,包含动态库、静态库以及模块库。这里建议省略这一参数,然后在运行cmake的时候视情况来加上-DBUILD_SHARED_LIBS=YES参数指明要编译动态库。
  • source1source2为编译库所需的源文件。

链接

在项目中,库与库、应用程序与库之间常常存在依赖关系,也就是说库会被链接到库或应用程序上。一般来讲,依赖关系可以分为以下三种:

  • PRIVATE(私有)
    私有依赖表示A库在自己的内部实现中用到了B库,任何用到A库的代码不需要知道B库。
  • PUBLIC(公共)
    公共依赖表示A库不光在内部实现中用到了B库,甚至还在其接口中用到了B库,这意味着没有B库,A库也用不了,所有用到A库的代码都直接依赖于B库。
  • INTERFACE(接口)
    接口依赖表示为了用A库,必须用到B库的一部分。接口依赖与公共依赖之间的不同之处在于,在接口依赖中,A库的内部实现中并没有用到B库,而仅在接口中用到了B库。

在CMake中,用target_link_libraries来描述依赖关系,其一般形式如下:

target_link_libraries(targetName
    <PRIVATE|PUBLIC|INTERFACE> item1 [item2 ...]
    [<PRIVATE|PUBLIC|INTERFACE> item3 [item4 ...]]
    ...
)

其中,

  • targetName是要链接的库/应用程序名称。
  • <PRIVATE|PUBLIC|INTERFACE>是可选参数,描述之间的依赖关系。
  • item1依赖的库的名称。

完整示例

假设项目目录中的文件如下所示:

project
    |-- func.h
    |-- func.cpp
    |-- main.cpp
    |-- CMakeLists.txt

func.h中的内容:

#ifndef __FUNC_H
#define __FUNC_H

int func();

#endif

func.cpp中的内容:

#include "func.h"

int func(){
    
    
    return 2;
}

main.cpp中的内容:

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

int main(){
    
    
    std::cout << func() << std::endl;
    return 0;
}

CMakeLists中的内容:

# 版本
cmake_minimum_required(VERSION 3.2)

# 项目信息
project(simple VERSION 1.0 LANGUAGES CXX)

# 编译目标
add_library(func func.cpp)
add_executable(main main.cpp)

# 依赖关系
target_link_libraries(main PRIVATE func)

CMake编译过程:

  1. 新建build目录并进入
  2. 命令行输入cmake ..
  3. CMake配置完成之后命令行输入cmake --build .
  4. Debug文件夹中找到可执行文件

相关链接

猜你喜欢

转载自blog.csdn.net/willian113/article/details/107917113
今日推荐