返回介绍

5.8 探究可执行命令

发布于 2025-05-06 21:45:56 字数 3479 浏览 0 评论 0 收藏

NOTE : 此示例代码可以在 https://github.com/dev-cafe/cmake-cookbook/tree/v1.0/chapter-5/recipe-08 中找到,其中包含一个 C/C++例子。该示例在 CMake 3.5 版(或更高版本) 中是有效的,并且已经在 GNU/Linux、macOS 和 Windows 上进行过测试。

目前为止,我们已经展示了如何检查给定的源代码,是否可以由所选的编译器编译,以及如何确保所需的编译器和链接器标志可用。此示例中,将显示如何检查是否可以在当前系统上编译、链接和运行代码。

准备工作

本示例的代码示例是复用第 3 章第 9 节的配置,并进行微小的改动。之前,我们展示了如何在您的系统上找到 ZeroMQ 库并将其链接到一个 C 程序中。本示例中,在生成实际的 C++程序之前,我们将检查一个使用 GNU/Linux 上的系统 UUID 库的小型 C 程序是否能够实际运行。

具体实施

开始构建 C++项目之前,我们希望检查 GNU/Linux 上的 UUID 系统库是否可以被链接。这可以通过以下一系列步骤来实现:

  1. 声明一个混合的 C 和 C++11 程序。这是必要的,因为我们要编译和运行的测试代码片段是使用 C 语言完成:
    cmake_minimum_required(VERSION 3.6 FATAL_ERROR)
    project(recipe-08 LANGUAGES CXX C)
    set(CMAKE_CXX_STANDARD 11)
    set(CMAKE_CXX_EXTENSIONS OFF)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
  2. 我们需要在系统上找到 UUID 库。这通过使用 pkg-config 实现的。要求搜索返回一个 CMake 导入目标使用 IMPORTED_TARGET 参数:
    find_package(PkgConfig REQUIRED QUIET)
    pkg_search_module(UUID REQUIRED uuid IMPORTED_TARGET)
    if(TARGET PkgConfig::UUID)
        message(STATUS "Found libuuid")
    endif()
  3. 接下来,需要使用 CheckCSourceRuns.cmake 模块。C++的是 CheckCXXSourceRuns.cmake 模块。但到 CMake 3.11 为止,Fortran 语言还没有这样的模块:
    include(CheckCSourceRuns)
  4. 我们声明一个 _test_uuid 变量,其中包含要编译和运行的 C 代码段:
    set(_test_uuid
    "
    #include <uuid/uuid.h>
    int main(int argc, char * argv[]) {
      uuid_t uuid;
      uuid_generate(uuid);
      return 0;
    }
    ")
  5. 我们声明 CMAKE_REQUIRED_LIBRARIES 变量后,对 check_c_source_runs 函数的调用。接下来,调用 check_c_source_runs ,其中测试代码作为第一个参数, _runs 变量作为第二个参数,以保存执行的检查结果。之后,取消 CMAKE_REQUIRED_LIBRARIES 变量的设置:
    set(CMAKE_REQUIRED_LIBRARIES PkgConfig::UUID)
    check_c_source_runs("${_test_uuid}" _runs)
    unset(CMAKE_REQUIRED_LIBRARIES)
  6. 如果检查没有成功,要么是代码段没有编译,要么是没有运行,我们会用致命的错误停止配置:
    if(NOT _runs)
        message(FATAL_ERROR "Cannot run a simple C executable using libuuid!")
    endif()
  7. 若成功,我们继续添加 C++可执行文件作为目标,并链接到 UUID:
    add_executable(use-uuid use-uuid.cpp)
    target_link_libraries(use-uuid
      PUBLIC
          PkgConfig::UUID
      )

工作原理

check_<lang>_source_runs 用于 C 和 C++的函数,与 check_<lang>_source_compile 相同,但在实际运行生成的可执行文件的地方需要添加一个步骤。对于 check_<lang>_source_compiles , check_<lang>_source_runs 的执行可以通过以下变量来进行:

  • CMAKE_REQUIRED_FLAGS:设置编译器标志。
  • CMAKE_REQUIRED_DEFINITIONS:设置预编译宏。
  • CMAKE_REQUIRED_INCLUDES:设置包含目录列表。
  • CMAKE_REQUIRED_LIBRARIES:设置可执行目标需要连接的库列表。

由于使用 pkg_search_module 生成的为导入目标,所以只需要将 CMAKE_REQUIRES_LIBRARIES 设置为 PkgConfig::UUID ,就可以正确设置包含目录。

正如 check_<lang>_source_compilestry_compile 的包装器, check_<lang>_source_runs 是 CMake 中另一个功能更强大的命令的包装器: try_run 。因此,可以编写一个 CheckFortranSourceRuns.cmake 模块,通过适当包装 try_run , 提供与 C 和 C++模块相同的功能。

NOTE : pkg_search_module 只能定义导入目标(CMake 3.6),但目前的示例可以使工作,3.6 之前版本的 CMake 可以通过手动设置所需的包括目录和库 check_c_source_runs 如下: set(CMAKE_REQUIRED_INCLUDES $ {UUID_INCLUDE_DIRS})set(CMAKE_REQUIRED_LIBRARIES $ {UUID_LIBRARIES})

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。