CMake教程(二)——基本操作

通常情况下,使用CMake的目的是为了构建比较大一些的项目,有很多文件需要处理,还要引用一些第三方库,接下来我来讲解在CMakeLists.txt下的基本操作。
本文是我自己整理的,没有按照官方教程进行翻译。
如果想要学习官方教程,请点击这里

开始

一般使用

示例目录结构如图

helloworld
├── CMakeLists.txt
├── README.md
├── main.c
└── main.h

最基础最简单的CMakeLists.txt写法,应该像这样:

# 最低要求版本
cmake_minimum_required(VERSION 3.10)

# 设置项目名
project(HelloWorld)

# 添加可执行目标
add_executable(hello main.c main.h)

注意,CMake不区分大小写,但这里采用最流行现代的写法,小写为主,部分采用大写。

然后按照标准方式编译构建

mkdir build
cd build
cmake ..
cmake --build .

编译完成后,目录结构大概就成了这样

helloworld
├── CMakeLists.txt
├── build
│   ├── CMakeCache.txt
│   ├── CMakeFiles
│   ├── Makefile
│   ├── cmake_install.cmake
│   └── hello
├── main.c
└── main.h

这样,你就会在build目录下看到编译好的可执行文件

更好的例子

如果你不喜欢这样的工程模式,可以采用更科学的目录结构,例如:

helloworld
├── CMakeLists.txt
├── inc
│   └── hello.h
└── src
    ├── hello.c
    └── main.c

参考文件内容

  • main.c
#include "../inc/hello.h"

int main(void)
{
    hello();
    return 0;
}
  • hello.c
#include "../inc/hello.h"

void hello()
{
    printf("hello, world!\n");
}
  • hello.h
#include <stdio.h>
void hello();

只需要把CMakeLists.txt改为

# 最低要求版本
cmake_minimum_required(VERSION 3.10)

# 设置项目名
project(HelloWorld)

# 将目录下所有文件添加到变量
file(GLOB all_SRCS
        # C项目
        "${PROJECT_SOURCE_DIR}/inc/*.h"
        "${PROJECT_SOURCE_DIR}/src/*.c"
        # C++项目
        # "${PROJECT_SOURCE_DIR}/inc/*.hpp"
        # "${PROJECT_SOURCE_DIR}/src/*.cpp"
        )

# 添加可执行目标
add_executable(hello ${all_SRCS})

选择构建工具,配合IDE或编辑器

大多数时候,你可能需要和你的IDE一起工作,此时你只需要指定构建工具,在生成构建时添加-G <Generators>
查看当前系统所支持的IDE,你只需要

cmake --help

在输出最后类似是这样

Generators

The following generators are available on this platform (* marks default):
* Unix Makefiles               = Generates standard UNIX makefiles.
  Green Hills MULTI            = Generates Green Hills MULTI files
                                 (experimental, work-in-progress).
  Ninja                        = Generates build.ninja files.
  Watcom WMake                 = Generates Watcom WMake makefiles.
  CodeBlocks - Ninja           = Generates CodeBlocks project files.
  CodeBlocks - Unix Makefiles  = Generates CodeBlocks project files.
  CodeLite - Ninja             = Generates CodeLite project files.
  CodeLite - Unix Makefiles    = Generates CodeLite project files.
  Sublime Text 2 - Ninja       = Generates Sublime Text 2 project files.
  Sublime Text 2 - Unix Makefiles
                               = Generates Sublime Text 2 project files.
  Kate - Ninja                 = Generates Kate project files.
  Kate - Unix Makefiles        = Generates Kate project files.
  Eclipse CDT4 - Ninja         = Generates Eclipse CDT 4.0 project files.
  Eclipse CDT4 - Unix Makefiles= Generates Eclipse CDT 4.0 project files.

如果选择使用Ninja,你只需要在生成构建时添加选项,如:

cmake .. -G Ninja

引用第三方库

关于第三方库的使用,网上有很多过时的文章,这里根据最新的文档整理过来的。
引用第三方库主要有三种方法:

  • 使用Pkg查找第三方库(推荐)
  • 使用CMake自带的查找模块
  • 手动指定库目录(不推荐)

使用Pkg查找第三方库(推荐)

很多时候,自带的查找模块并不好用,经常找不到第三方库。因此,PkgConfig是个不错的选择。
通常情况下,pkgconfig的查找模块在/usr/lib/x86_64-linux-gnu/pkgconfig/下,你可以查看是否有你需要的库,这里以GTK为例

ls /usr/lib/x86_64-linux-gnu/pkgconfig/ | grep -i gtk

输出

gtk+-2.0.pc
gtk+-3.0.pc
gtk+-broadway-3.0.pc
gtkmm-3.0.pc
gtk+-unix-print-2.0.pc
gtk+-unix-print-3.0.pc
gtk+-wayland-3.0.pc
gtk+-x11-2.0.pc
gtk+-x11-3.0.pc

我们需要gtk3的库,因此,
你只需要在CMakeLists.txt需要库的语句前,添加

find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)

CMake会将查找到的库相关内容存储在相应的变量之中,我们只需要

include_directories(${GTK3_INCLUDE_DIRS})                   # 添加头文件目录
link_directories(${GTK3_LIBRARY_DIRS})                      # 添加链接目录

set(CMAKE_ENABLE_EXPORTS TRUE)                              # 允许CMake为你添加编译器选项
add_compile_options(${GTK3_CFLAGS_OTHER})                   # 添加编译器选项

add_executable(<可执行程序名> <头文件和源文件>)

target_link_libraries(<可执行程序名> ${GTK3_LIBRARIES})     # 链接到第三方库

这里到的GTK3是可以任意替换的,包括变量名,pkg_check_modules生成对应的变量名。

使用CMake自带的查找模块

如果你用的是arch或openSUSE的风滚草,软件源中就有额外的查找模块,安装和使用都十分方便。
如果你使用的是openSUSE,可以用以下命令安装额外的查找模块

sudo zypper install extra-cmake-modules

如果你是Ubuntu用户,应该优先考虑pkg查找。
你可以在/usr/share/cmake-<版本号>/Modules/中找到你需要的库的查找模块。
例如,我的cmake版本是3.22,可以这样查看Qt库。

ls /usr/share/cmake-3.22/Modules/ | grep -i Qt

输出

DeployQt4.cmake
FindosgQt.cmake
FindQt3.cmake
FindQt4.cmake
FindQt.cmake
Qt4ConfigDependentSettings.cmake
Qt4Macros.cmake
UseQt4.cmake

下面是我qtCaller的示例:

cmake_minimum_required(VERSION 3.10)

project(qt-caller)

find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets REQUIRED)          # 调用查找模块,查找Qt5或Qt6库
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets REQUIRED)     # 这句应该是确定当前系统Qt库的版本

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)                               # 允许CMake为你添加编译器选项

add_executable(qtCaller 
                main.cpp 
                widget.cpp 
                widget.h)

target_link_libraries(qtCaller 
                PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)             # 链接到第三方库

手动指定库目录(不推荐)

我是看了一些CSDN的文章,才了解到这个方法的。
如果你的系统是Windows,用CMake就是好奇想了解一下,这个方法比较适合你。

include_directories(<头文件路径>)
link_directories(<链接文件路径>)

add_executable(<可执行程序名> <头文件和源文件>)

target_link_libraries(<可执行程序名> <链接选项>)

没什么系统性,无法跨平台,直接去CSDN里找示例就可以了,但是会比较直观,容易理解。

还有其他需求的,推荐查看官方文档

如果还需要另外的功能,请查看下一篇CMake教程(三)——配置完善
点击这里返回目录

参考链接:

posted @ 2022-07-28 18:28  Leeds_Garden  阅读(401)  评论(0编辑  收藏  举报