步驟 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