步驟 8:加入自訂命令和產生檔案

假設為了本教學的目的,我們決定永遠不使用平台的 logexp 函數,而是希望產生一個預先計算的值的表格,以便在 mysqrt 函數中使用。在本節中,我們將在建置過程中建立表格,然後將該表格編譯到我們的應用程式中。

首先,讓我們移除 MathFunctions/CMakeLists.txt 中對 logexp 函數的檢查。然後從 mysqrt.cxx 中移除對 HAVE_LOGHAVE_EXP 的檢查。同時,我們可以移除 #include <cmath>

MathFunctions 子目錄中,已提供名為 MakeTable.cxx 的新原始程式檔來產生表格。

檢視該檔案後,我們可以發現該表格是以有效的 C++ 程式碼產生的,並且輸出檔案名稱是作為引數傳入的。

下一步是建立 MathFunctions/MakeTable.cmake。然後,將適當的命令新增至該檔案,以建置 MakeTable 可執行檔,然後將其作為建置過程的一部分執行。需要幾個命令才能完成此操作。

首先,我們為 MakeTable 新增一個可執行檔。

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

建立可執行檔後,我們使用 target_link_libraries()tutorial_compiler_flags 新增至我們的可執行檔。

然後,我們新增一個自訂命令,指定如何透過執行 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
  )

接下來,我們必須讓 CMake 知道 mysqrt.cxx 相依於產生的檔案 Table.h。這是透過將產生的 Table.h 新增至程式庫 SqrtLibrary 的原始檔清單來完成。

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

我們還必須將目前的二進位目錄新增至包含目錄的清單中,以便 mysqrt.cxx 可以找到並包含 Table.h

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

  # link SqrtLibrary to tutorial_compiler_flags

最後一步,我們需要在 MathFunctions/CMakeLists.txt 的頂部包含 MakeTable.cmake

MathFunctions/CMakeLists.txt
  include(MakeTable.cmake)

現在讓我們使用產生的表格。首先,修改 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;
}
}
}

執行 cmake 可執行檔或 cmake-gui 來設定專案,然後使用您選擇的建置工具來建置它。

當這個專案建置時,它會先建置 MakeTable 可執行檔。然後它將執行 MakeTable 來產生 Table.h。最後,它會編譯包含 Table.hmysqrt.cxx 以產生 MathFunctions 程式庫。

執行 Tutorial 可執行檔並驗證它正在使用表格。