ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# 3.9 检测外部库:Ⅰ. 使用pkg-config **NOTE**:*此示例代码可以在 https://github.com/dev-cafe/cmake-cookbook/tree/v1.0/chapter-03/recipe-09 中找到,包含一个C的示例。该示例在CMake 3.6版(或更高版本)中是有效的,并且已经在GNU/Linux、macOS和Windows上进行过测试。https://github.com/dev-cafe/cmake-cookbook/tree/v1.0/chapter-03/recipe-09 中也有一个适用于CMake 3.5的示例。* 目前为止,我们已经讨论了两种检测外部依赖关系的方法: * 使用CMake自带的`find-module`,但并不是所有的包在CMake的`find`模块都找得到。 * 使用` <package>Config.cmake`, ` <package>ConfigVersion.cmake `和`<package>Targets.cmake`,这些文件由软件包供应商提供,并与软件包一起安装在标准位置的cmake文件夹下。 如果某个依赖项既不提供查找模块,也不提供供应商打包的CMake文件,该怎么办?在这种情况下,我们只有两个选择: * 依赖`pkg-config`程序,来找到系统上的包。这依赖于包供应商在`.pc`配置文件中,其中有关于发行包的元数据。 * 为依赖项编写自己的`find-package`模块。 本示例中,将展示如何利用CMake中的`pkg-config`来定位ZeroMQ消息库。下一个示例中,将编写一个find模块,展示如何为ZeroMQ编写属于自己`find`模块。 ## 准备工作 我们构建的代码来自ZeroMQ手册 http://zguide.zeromq.org/page:all 的示例。由两个源文件`hwserver.c`和`hwclient.c`组成,这两个源文件将构建为两个独立的可执行文件。执行时,它们将打印“Hello, World”。 ## 具体实施 这是一个C项目,我们将使用C99标准,逐步构建`CMakeLists.txt`文件: 1. 声明一个C项目,并要求符合C99标准: ```cmake cmake_minimum_required(VERSION 3.6 FATAL_ERROR) project(recipe-09 LANGUAGES C) set(CMAKE_C_STANDARD 99) set(CMAKE_C_EXTENSIONS OFF) set(CMAKE_C_STANDARD_REQUIRED ON) ``` 2. 使用CMake附带的find-module,查找`pkg-config`。这里在`find_package`中传递了`QUIET`参数。只有在没有找到`pkg-config`时,CMake才会报错: ```cmake find_package(PkgConfig REQUIRED QUIET) ``` 3. 找到`pkg-config`时,我们将使用`pkg_search_module`函数,以搜索任何附带包配置`.pc`文件的库或程序。该示例中,我们查找ZeroMQ库: ```cmake pkg_search_module( ZeroMQ REQUIRED libzeromq libzmq lib0mq IMPORTED_TARGET ) ``` 4. 如果找到ZeroMQ库,则打印状态消息: ```cmake if(TARGET PkgConfig::ZeroMQ) message(STATUS "Found ZeroMQ") endif() ``` 5. 然后,添加两个可执行目标,并链接到ZeroMQ。这将自动设置包括目录和链接库: ```cmake add_executable(hwserver hwserver.c) target_link_libraries(hwserver PkgConfig::ZeroMQ) add_executable(hwclient hwclient.c) target_link_libraries(hwclient PkgConfig::ZeroMQ) ``` 6. 现在,我们可以配置和构建示例: ```shell $ mkdir -p build $ cd build $ cmake .. $ cmake --build . ``` 7. 在终端中,启动服务器,启动时会输出类似于本例的消息: ```shell Current 0MQ version is 4.2.2 ``` 8. 然后,在另一个终端启动客户端,它将打印如下内容: ```shell Connecting to hello world server… Sending Hello 0… Received World 0 Sending Hello 1… Received World 1 Sending Hello 2… ... ``` ## 工作 当找到`pkg-config`时, CMake需要提供两个函数,来封装这个程序提供的功能: * `pkg_check_modules`,查找传递列表中的所有模块(库和/或程序) * `pkg_search_module`,要在传递的列表中找到第一个工作模块 与`find_package`一样,这些函数接受`REQUIRED`和`QUIET`参数。更详细地说,我们对`pkg_search_module`的调用如下: ```cmake pkg_search_module( ZeroMQ REQUIRED libzeromq libzmq lib0mq IMPORTED_TARGET ) ``` 这里,第一个参数是前缀,它将用于命名存储搜索ZeroMQ库结果的目标:`PkgConfig::ZeroMQ`。注意,我们需要为系统上的库名传递不同的选项:`libzeromq`、`libzmq`和`lib0mq`。这是因为不同的操作系统和包管理器,可为同一个包选择不同的名称。 **NOTE**:*`pkg_check_modules`和`pkg_search_module`函数添加了`IMPORTED_TARGET`选项,并在CMake 3.6中定义导入目标的功能。3.6之前的版本,只定义了变量`ZeroMQ_INCLUDE_DIRS`(用于include目录)和`ZeroMQ_LIBRARIES`(用于链接库),供后续使用。*