步驟 7:新增系統內省¶
讓我們考慮在專案中加入一些程式碼,這些程式碼依賴於目標平台可能不具備的功能。在這個範例中,我們將加入一些程式碼,這些程式碼依賴於目標平台是否具有 log
和 exp
函數。當然,幾乎每個平台都有這些函數,但為了本教學,我們假設它們並不常見。
練習 1 - 評估依賴項可用性¶
目標¶
根據可用的系統依賴項更改實作。
有用的資源¶
要編輯的檔案¶
MathFunctions/CMakeLists.txt
MathFunctions/mysqrt.cxx
開始¶
起始程式碼在 Step7
目錄中提供。在本練習中,完成 TODO 1
到 TODO 5
。
首先編輯 MathFunctions/CMakeLists.txt
。包含 CheckCXXSourceCompiles
模組。然後,使用 check_cxx_source_compiles
來判斷 log
和 exp
是否可從 cmath
取得。如果它們可用,請使用 target_compile_definitions()
來指定 HAVE_LOG
和 HAVE_EXP
作為編譯定義。
在 MathFunctions/mysqrt.cxx
中,包含 cmath
。然後,如果系統具有 log
和 exp
,則使用它們來計算平方根。
建置和執行¶
建立一個名為 Step7_build
的新目錄。執行 cmake
可執行檔或 cmake-gui
來組態專案,然後使用您選擇的建置工具建置專案,並執行 Tutorial
可執行檔。
這看起來會像這樣
mkdir Step7_build
cd Step7_build
cmake ../Step7
cmake --build .
現在哪個函數給出更好的結果,sqrt
還是 mysqrt
?
解決方案¶
在本練習中,我們將使用 CheckCXXSourceCompiles
模組中的函數,因此首先我們必須將其包含在 MathFunctions/CMakeLists.txt
中。
TODO 1:按一下以顯示/隱藏答案
include(CheckCXXSourceCompiles)
然後使用 check_cxx_compiles_source
測試 log
和 exp
的可用性。此函數可讓我們在真正原始程式碼編譯之前,嘗試使用所需依賴項來編譯簡單的程式碼。產生的變數 HAVE_LOG
和 HAVE_EXP
表示這些依賴項是否可用。
TODO 2:按一下以顯示/隱藏答案
check_cxx_source_compiles("
#include <cmath>
int main() {
std::log(1.0);
return 0;
}
" HAVE_LOG)
check_cxx_source_compiles("
#include <cmath>
int main() {
std::exp(1.0);
return 0;
}
" HAVE_EXP)
接下來,我們需要將這些 CMake 變數傳遞到我們的原始程式碼。這樣,我們的原始程式碼才能知道哪些資源可用。如果 log
和 exp
都可用,則使用 target_compile_definitions()
來指定 HAVE_LOG
和 HAVE_EXP
作為 PRIVATE
編譯定義。
TODO 3:按一下以顯示/隱藏答案
if(HAVE_LOG AND HAVE_EXP)
target_compile_definitions(SqrtLibrary
PRIVATE "HAVE_LOG" "HAVE_EXP"
)
endif()
target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
endif()
由於我們可能會使用 log
和 exp
,因此我們需要修改 mysqrt.cxx
以包含 cmath
。
TODO 4:按一下以顯示/隱藏答案
#include <cmath>
如果系統上提供 log
和 exp
,則在 mysqrt
函數中使用它們來計算平方根。MathFunctions/mysqrt.cxx
中的 mysqrt
函數看起來會像這樣
TODO 5:按一下以顯示/隱藏答案
#if defined(HAVE_LOG) && defined(HAVE_EXP)
double result = std::exp(std::log(x) * 0.5);
std::cout << "Computing sqrt of " << x << " to be " << result
<< " using log and exp" << std::endl;
#else
double result = 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;
}
#endif