CMake教程-第 8 步:添加自定义命令和生成文件

CMake教程-第 8 步:添加自定义命令和生成文件

  • 1 CMake教程介绍
  • 2 学习步骤
    • Step 1: A Basic Starting Point
    • Step 2: Adding a Library
    • Step 3: Adding Usage Requirements for a Library
    • Step 4: Adding Generator Expressions
    • Step 5: Installing and Testing
    • Step 6: Adding Support for a Testing Dashboard
    • Step 7: Adding System Introspection
    • Step 8: Adding a Custom Command and Generated File
    • Step 9: Packaging an Installer
    • Step 10: Selecting Static or Shared Libraries
    • Step 11: Adding Export Configuration
    • Step 12: Packaging Debug and Release
  • 3 Step 8: Adding a Custom Command and Generated File
    • 3.1 Step 8: Adding a Custom Command and Generated File
    • 3.2 MathFunctions/MakeTable.cmake
    • 3.3 MathFunctions/CMakeLists.txt
    • 3.4 MathFunctions/mysqrt.cxx
    • 3.5 编译
    • 3.6 运行结果

该文档是基于CMake的官方教程翻译而来,并稍微添加了自己的理解:

cmake的官方网站为:CMake Tutorial

1 CMake教程介绍

The CMake tutorial provides a step-by-step guide that covers common build system issues that CMake helps address. Seeing how various topics all work together in an example project can be very helpful.
CMake 教程提供了一个循序渐进的指南,涵盖了 CMake 可帮助解决的常见构建系统问题。在一个示例项目中了解各个主题是如何协同工作的,会非常有帮助。

2 学习步骤

The tutorial source code examples are available in this archive. Each step has its own subdirectory containing code that may be used as a starting point. The tutorial examples are progressive so that each step provides the complete solution for the previous step.
本文档中提供了教程源代码示例。每个步骤都有自己的子目录,其中包含可用作起点的代码。教程示例是循序渐进的,因此每一步都提供了前一步的完整解决方案。

Step 1: A Basic Starting Point

  • Exercise 1 - Building a Basic Project
  • Exercise 2 - Specifying the C++ Standard
  • Exercise 3 - Adding a Version Number and Configured Header File

Step 2: Adding a Library

  • Exercise 1 - Creating a Library
  • Exercise 2 - Adding an Option

Step 3: Adding Usage Requirements for a Library

  • Exercise 1 - Adding Usage Requirements for a Library
  • Exercise 2 - Setting the C++ Standard with Interface Libraries

Step 4: Adding Generator Expressions

  • Exercise 1 - Adding Compiler Warning Flags with Generator Expressions

Step 5: Installing and Testing

  • Exercise 1 - Install Rules
  • Exercise 2 - Testing Support

Step 6: Adding Support for a Testing Dashboard

  • Exercise 1 - Send Results to a Testing Dashboard

Step 7: Adding System Introspection

  • Exercise 1 - Assessing Dependency Availability

Step 8: Adding a Custom Command and Generated File

Step 9: Packaging an Installer

Step 10: Selecting Static or Shared Libraries

Step 11: Adding Export Configuration

Step 12: Packaging Debug and Release

3 Step 8: Adding a Custom Command and Generated File

3.1 Step 8: Adding a Custom Command and Generated File

Suppose, for the purpose of this tutorial, we decide that we never want to use the platform log and exp functions and instead would like to generate a table of precomputed values to use in the mysqrt function. In this section, we will create the table as part of the build process, and then compile that table into our application.
假设在本教程中,我们决定不再使用平台log和 exp 函数,而是想生成一个预计算值表,供 mysqrt 函数使用。在本节中,我们将在构建过程中创建表格,然后将表格编译到应用程序中。

First, let’s remove the check for the log and exp functions in MathFunctions/CMakeLists.txt. Then remove the check for HAVE_LOG and HAVE_EXP from mysqrt.cxx. At the same time, we can remove #include .
首先,删除 MathFunctions/CMakeLists.txt 中对 logexp 函数的检查。然后删除 mysqrt.cxx 中的 HAVE_LOGHAVE_EXP 检查。同时,我们可以删除 #include

In the MathFunctions subdirectory, a new source file named MakeTable.cxx has been provided to generate the table.
MathFunctions 子目录中,提供了一个名为 MakeTable.cxx 的新源文件,用于生成表格。

After reviewing the file, we can see that the table is produced as valid C++ code and that the output filename is passed in as an argument.
查看文件后,我们可以看到表格是以有效的 C++ 代码生成的,输出文件名是作为参数传递的。

The next step is to create MathFunctions/MakeTable.cmake. Then, add the appropriate commands to the file to build the MakeTable executable and then run it as part of the build process. A few commands are needed to accomplish this.
下一步是创建 MathFunctions/MakeTable.cmake。然后,在该文件中添加适当的命令来构建 MakeTable 可执行文件,并将其作为构建过程的一部分来运行。为此需要执行几条命令。

First, we add an executable for MakeTable.
首先,我们为 MakeTable 添加一个可执行程序。

MathFunctions/MakeTable.cmake
add_executable(MakeTable MakeTable.cxx)

After creating the executable, we add the tutorial_compiler_flags to our executable using target_link_libraries().
在创建可执行的,我们使用target_link_libraries()添加tutorial_compiler_flags我们的可执行程序.

MathFunctions/MakeTable.cmake
target_link_libraries(MakeTable PRIVATE tutorial_compiler_flags)

Then we add a custom command that specifies how to produce Table.h by running MakeTable.
然后,我们添加一条自定义命令,指定如何通过运行 MakeTable 生成 Table.h

MathFunctions/MakeTable.cmake
add_custom_command(
  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
  COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
  DEPENDS MakeTable
  )

Next we have to let CMake know that mysqrt.cxx depends on the generated file Table.h. This is done by adding the generated Table.h to the list of sources for the library SqrtLibrary.
接下来,我们必须让 CMake 知道 mysqrt.cxx 依赖于生成的 Table.h 文件。方法是将生成的 Table.h 添加到 SqrtLibrary 库的源代码列表中。

MathFunctions/CMakeLists.txt
  add_library(SqrtLibrary STATIC
              mysqrt.cxx
              ${CMAKE_CURRENT_BINARY_DIR}/Table.h
              )

We also have to add the current binary directory to the list of include directories so that Table.h can be found and included by mysqrt.cxx.
我们还必须将当前二进制目录添加到包含目录列表中,以便 mysqrt.cxx 可以找到并包含 Table.h

MathFunctions/CMakeLists.txt
  target_include_directories(SqrtLibrary PRIVATE
                             ${CMAKE_CURRENT_BINARY_DIR}
                             )

  # link SqrtLibrary to tutorial_compiler_flags

As the last step, we need to include MakeTable.cmake at the top of the MathFunctions/CMakeLists.txt.
最后一步,我们需要在 MathFunctions/CMakeLists.txt 文件的顶部加入 MakeTable.cmake

MathFunctions/CMakeLists.txt
  include(MakeTable.cmake)

Now let’s use the generated table. First, modify mysqrt.cxx to include Table.h. Next, we can rewrite the mysqrt function to use the table:
现在让我们使用生成的表。首先,修改 mysqrt.cxx 以包含 Table.h。接下来,我们可以重写 mysqrt 函数以使用表格:

MathFunctions/mysqrt.cxx
double mysqrt(double x)
{
  if (x <= 0) {
    return 0;
  }

  // use the table to help find an initial value
  double result = x;
  if (x >= 1 && x < 10) {
    std::cout << "Use the table to help find an initial value " << std::endl;
    result = sqrtTable[static_cast<int>(x)];
  }

  // do ten iterations
  for (int i = 0; i < 10; ++i) {
    if (result <= 0) {
      result = 0.1;
    }
    double delta = x - (result * result);
    result = result + 0.5 * delta / result;
    std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
  }

  return result;
}

Run the cmake executable or the cmake-gui to configure the project and then build it with your chosen build tool.
运行 cmake 可执行文件或 cmake-gui 配置项目,然后使用所选的构建工具构建项目。

When this project is built it will first build the MakeTable executable. It will then run MakeTable to produce Table.h. Finally, it will compile mysqrt.cxx which includes Table.h to produce the MathFunctions library.
当这个项目建成时,它将首先编译 MakeTable 可执行程序。然后运行 MakeTable 生成 Table.h。最后,它将编译包含 Table.hmysqrt.cxx 以生成 MathFunctions 库。

Run the Tutorial executable and verify that it is using the table.
运行 Tutorial 可执行文件并验证它是否使用了表格。

3.2 MathFunctions/MakeTable.cmake

# first we add the executable that generates the table
add_executable(MakeTable MakeTable.cxx)

target_link_libraries(MakeTable PRIVATE tutorial_compiler_flags)

# add the command to generate the source code
add_custom_command(
  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
  COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
  DEPENDS MakeTable
  )

3.3 MathFunctions/CMakeLists.txt

include(MakeTable.cmake)

add_library(MathFunctions MathFunctions.cxx)

# should we use our own math functions
option(USE_MYMATH "Use tutorial provided math implementation" ON)
if (USE_MYMATH)
  target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")

  # library that just does sqrt
  add_library(SqrtLibrary STATIC
              mysqrt.cxx
              ${CMAKE_CURRENT_BINARY_DIR}/Table.h
              )
  target_include_directories(SqrtLibrary PRIVATE
                             ${CMAKE_CURRENT_BINARY_DIR}
                             )

  target_link_libraries(SqrtLibrary PUBLIC tutorial_compiler_flags)

  target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
endif()

# state that anybody linking to us needs to include the current source dir
# to find MathFunctions.h, while we don't.
target_include_directories(MathFunctions
                           INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
                           )

# link our compiler flags interface library
target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)

# install libs
set(installable_libs MathFunctions tutorial_compiler_flags)
if(TARGET SqrtLibrary)
  list(APPEND installable_libs SqrtLibrary)
endif()
install(TARGETS ${installable_libs} DESTINATION lib)
# install include headers
install(FILES MathFunctions.h DESTINATION include)

3.4 MathFunctions/mysqrt.cxx

#include "mysqrt.h"
#include "Table.h"

#include 

namespace mathfunctions {
namespace detail {
// a hack square root calculation using simple operations

double mysqrt(double x)
{
  if (x <= 0) {
    return 0;
  }

  // use the table to help find an initial value
  double result = x;
  if (x >= 1 && x < 10) {
    std::cout << "Use the table to help find an initial value " << std::endl;
    result = sqrtTable[static_cast<int>(x)];
  }

  // do ten iterations
  for (int i = 0; i < 10; ++i) {
    if (result <= 0) {
      result = 0.1;
    }
    double delta = x - (result * result);
    result = result + 0.5 * delta / result;
    std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
  }

  return result;
}
}
}

3.5 编译

test@test:~/sda3/work/cmake/Step8_build$ cmake ../Step8
-- The C compiler identification is GNU 10.5.0
-- The CXX compiler identification is GNU 10.5.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/test/sda3/work/cmake/Step8_build
test@test:~/sda3/work/cmake/Step8_build$ 
test@test:~/sda3/work/cmake/Step8_build$ 
test@test:~/sda3/work/cmake/Step8_build$ cmake --build .
[ 11%] Building CXX object MathFunctions/CMakeFiles/MakeTable.dir/MakeTable.cxx.o
[ 22%] Linking CXX executable MakeTable
[ 22%] Built target MakeTable
[ 33%] Generating Table.h
[ 44%] Building CXX object MathFunctions/CMakeFiles/SqrtLibrary.dir/mysqrt.cxx.o
[ 55%] Linking CXX static library libSqrtLibrary.a
[ 55%] Built target SqrtLibrary
[ 66%] Building CXX object MathFunctions/CMakeFiles/MathFunctions.dir/MathFunctions.cxx.o
[ 77%] Linking CXX static library libMathFunctions.a
[ 77%] Built target MathFunctions
[ 88%] Building CXX object CMakeFiles/Tutorial.dir/tutorial.cxx.o
[100%] Linking CXX executable Tutorial
[100%] Built target Tutorial
test@test:~/sda3/work/cmake/Step8_build$

3.6 运行结果

test@test:~/sda3/work/cmake/Step8_build$ ./Tutorial 100
Computing sqrt of 100 to be 50.5
Computing sqrt of 100 to be 26.2401
Computing sqrt of 100 to be 15.0255
Computing sqrt of 100 to be 10.8404
Computing sqrt of 100 to be 10.0326
Computing sqrt of 100 to be 10.0001
Computing sqrt of 100 to be 10
Computing sqrt of 100 to be 10
Computing sqrt of 100 to be 10
Computing sqrt of 100 to be 10
The square root of 100 is 10
test@test:~/sda3/work/cmake/Step8_build$

你可能感兴趣的:(cmake,cmake,添加自定义命令和生成文件,CMake教程-第,8,步)