ModernCMake-Chinese
  • Introduction
  • Modern CMake 简介
    • 安装 CMake
    • 运行 CMake
    • Do's and Don'ts
    • CMake 中的新变化
  • 基础知识简介
    • 变量和 Cache
    • 在CMake 中编程
    • 与你的代码交互
    • 如何结构化你的工程
    • 运行其他程序
  • Adding Features
    • C++11 and Beyond
    • Small but common needs
    • Utilities
    • Useful modules
    • IDEs
    • Debugging
  • Including Projects
    • Submodule
    • DownloadProject
    • Fetch (CMake 3.11)
  • Testing
    • GoogleTest
    • Catch
  • Exporting and Installing
    • Installing
    • Exporting
    • Packaging
  • Looking for libraries
    • CUDA
    • OpenMP
    • Boost
    • MPI
    • ROOT
      • UseFile Example
      • Simple Example
      • Simple Example CMake 3.11+
      • Dictionary Example
    • Minuit2
Powered by GitBook
On this page
  • Running a command at configure time
  • Running a command at build time
  • Included common utilities

Was this helpful?

  1. 基础知识简介

运行其他程序

Previous如何结构化你的工程NextAdding Features

Last updated 6 years ago

Was this helpful?

Running a command at configure time

Running a command at configure time is relatively easy. Use to run a process and access the results. It is generally a good idea to avoid hard coding a program path into your CMake; you can use ${CMAKE_COMMAND}, find_package(Git), or find_program to get access to a command to run. Use RESULT_VARIABLE to check the return code and OUTPUT_VARIABLE to get the output.

Here is an example that updates all git submodules:

find_package(Git QUIET)

if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
    execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive
                    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
                    RESULT_VARIABLE GIT_SUBMOD_RESULT)
    if(NOT GIT_SUBMOD_RESULT EQUAL "0")
        message(FATAL_ERROR "git submodule update --init failed with ${GIT_SUBMOD_RESULT}, please checkout submodules")
    endif()
endif()

Running a command at build time

Build time commands are a bit tricker. The main complication comes from the target system; when do you want your command to run? Does it produce an output that another target needs? With this in mind, here is an example that calls a Python script to generate a header file:

find_package(PythonInterp REQUIRED)
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/include/Generated.hpp"
    COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/scripts/GenerateHeader.py" --argument
    DEPENDS some_target)

add_custom_target(generate_header ALL
    DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/include/Generated.hpp")

install(FILES ${CMAKE_CURRENT_BINARY_DIR}/include/Generated.hpp DESTINATION include)

Here, the generation happens after some_target is complete, and happens when you run make without a target (ALL). If you make this a dependency of another target with add_dependencies, you could avoid the ALL keyword. Or, you could require that a user explicitly builds the generate_header target when making.

Included common utilities

A useful tool in writing CMake builds that work cross-platform is cmake -E <mode> (seen in CMake files as ${CMAKE_COMMAND} -E). This mode allows CMake to do a variety of things without calling system tools explicitly, like copy, make_directory, and remove. It is mostly used for the build time commands. Note that the very useful create_symlink mode only works on Unix systems. .

execute_process
See the docs