avatar

Catalog
CMake Cookbook Notes 5: Configure-time and Build-time Operations

Chapter 5 Configure-time and Build-time Operations

There are three important periods during the whole process of building with CMake:

  • configure time: processing the CMakeLists.txt
  • generation time: generating files for the native build tool
  • build time: invoking the native build tool to create the targets (executables and libraries)

5.1 Using platform-independent file operations

  • When we need to execute some commands during the build, we can use add_custom_target to bundle those commands as a target and then use add_dependencies to make it a dependency of our application target:

    cmake
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    add_custom_target(unpack-eigen
    ALL
    COMMAND
    ${CMAKE_COMMAND} -E tar xzf ${CMAKE_CURRENT_SOURCE_DIR}/eigen-eigen-5a0156e40feb.tar.gz
    COMMAND
    ${CMAKE_COMMAND} -E rename eigen-eigen-5a0156e40feb eigen-3.3.4
    WORKING_DIRECTORY
    ${CMAKE_CURRENT_BINARY_DIR}
    COMMENT
    "Unpacking Eigen3 in ${CMAKE_CURRENT_BINARY_DIR}/eigen-3.3.4"
    )

    add_dependencies(linear-algebra unpack-eigen)
  • Note the argument following COMMAND here:

    cmake
    1
    ${CMAKE_COMMAND} -E rename eigen-eigen-5a0156e40feb eigen-3.3.4

    Actually -E indicates the command mode of CMake, which is followed by the platform-independent command applied in CMake.

  • Use cmake -E to list all those platform-independent commands.

5.2 Running a custom command at configure time

  • Note that when using execute_process, we can specify many commands to execute, and the output of the last command will be passed as the input of the next one, which means only the last output can be picked out.
  • Remember commands in execute_process are executed in configure time.

5.3 Running a custom command at build time: I. Using add_custom_command

  • If we use add_custom_command with OUTPUT as the first argument, it will generate some files when any target in the same CMakeLists.txt or which uses any file generated by the custom command is built:

    cmake
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    add_custom_command(
    OUTPUT
    ${wrap_BLAS_LAPACK_sources}
    COMMAND
    ${CMAKE_COMMAND} -E tar xzf ${CMAKE_CURRENT_SOURCE_DIR}/wrap_BLAS_LAPACK.tar.gz
    COMMAND
    ${CMAKE_COMMAND} -E touch ${wrap_BLAS_LAPACK_sources}
    WORKING_DIRECTORY
    ${CMAKE_CURRENT_BINARY_DIR}
    DEPENDS
    ${CMAKE_CURRENT_SOURCE_DIR}/wrap_BLAS_LAPACK.tar.gz
    COMMENT
    "Unpacking C++ wrappers for BLAS/LAPACK"
    VERBATIM
    )

5.4 Running a custom command at build time: I. Using add_custom_target

  • To circumvent the limitation that only targets in the same CMakeLists.txt with the add_custom_command could trigger it, we can combine both add_custom_command and add_custom_target:

    cmake
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    add_custom_target(BLAS_LAPACK_wrappers
    WORKING_DIRECTORY
    ${CMAKE_CURRENT_BINARY_DIR}
    DEPENDS
    ${MATH_SRCS}
    COMMENT
    "Intermediate BLAS_LAPACK_wrappers target"
    VERBATIM
    )

    add_custom_command(
    OUTPUT
    ${MATH_SRCS}
    COMMAND
    ${CMAKE_COMMAND} -E tar xzf ${CMAKE_CURRENT_SOURCE_DIR}/wrap_BLAS_LAPACK.tar.gz
    WORKING_DIRECTORY
    ${CMAKE_CURRENT_BINARY_DIR}
    DEPENDS
    ${CMAKE_CURRENT_SOURCE_DIR}/wrap_BLAS_LAPACK.tar.gz
    COMMENT
    "Unpacking C++ wrappers for BLAS/LAPACK"
    )

    so that the custom commands will always be executed.

5.5 Running custom commands for specific targets at build time

  • If we use add_custom_command with TARGET as the first argument, it will register some, like, hooks to a target:

    cmake
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    add_custom_command(
    TARGET
    example
    POST_BUILD
    COMMAND
    ${PYTHON_EXECUTABLE}
    ${CMAKE_CURRENT_SOURCE_DIR}/static-size.py
    $<TARGET_FILE:example>
    COMMENT
    "static size of executable:"
    VERBATIM
    )
  • We can register the hook to two times: PRE_LINK (for Linux, PRE_BUILD has the same effect with PRE_LINK) and POST_BUILD, whose names are self-explanatory.

Author: Gusabary
Link: http://gusabary.cn/2020/10/20/CMake-CookBook-Notes/CMake-Cookbook-Notes-5/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.

Comment