第四步,添加系統相關特性
相關代碼:4_system
下面,我們考慮爲我們的項目添加一些代碼,這些代碼所依賴的特性可能在目標平臺上是沒有的。
對於這個例子,我們將加入一些代碼,這些代碼依賴的是:目標平臺是否具有 log
和 exp
函數。當然,幾乎所有的平臺都有這些函數,但是在這個教程中,我們假設它們是不通用的。
如果平臺具有 log
和 exp
,那麼我們就在程序中使用 log
和 exp
。
編輯項目文件 CMakeLists.txt
我們首先通過在頂級 CMakeLists.txt
中使用 CheckSymbolExists
. cmake
宏檢測這些函數的可用性,如下:
# does this system provide the log and exp functions?
include(CheckSymbolExists)
set(CMAKE_REQUIRED_LIBRARIES "m")
check_symbol_exists(log "math.h" HAVE_LOG)
check_symbol_exists(exp "math.h" HAVE_EXP)
message("Begin!")
if (HAVE_LOG AND HAVE_EXP)
message("Have, have have!")
# add_definitions(-DHAVE_LOG)
# add_definitions(-DHAVE_EXP)
endif (HAVE_LOG AND HAVE_EXP)
message("End!")
注意
- 不知爲何,有時
#if(HAVE_LOG AND HAVE_EXP)
爲真,有時爲假,確保這個變量的話,可以用 "cmake -DHAVE_LOG=ON -DHAVE_EXP=ON tutorial" 來調試。 - 對
log
和exp
的測試要在用於TutorialConfig.h
的configure_file
命令之前進行。configure_file
命令會根據當前在CMake
中的設置立即對文件進行配置。 - 使用
set(CMAKE_REQUIRED_LIBRARIES "m")
設置後,再進行檢測否則可能會有問題。
編輯配置文件 TutorialConfig.h.in
接下來,我們修改 TutorialConfig.h.in
來定義哪些值以便 CMake
在平臺上查找,如下:
// does the platform provide exp and log functions?
#cmakedefine HAVE_LOG
#cmakedefine HAVE_EXP
注意:
- 前面
CMakeLists.txt
中的add_definitions(...)
與這裏的#cmakedefine ...
是相互衝突的,不能同時存在,保留一個即可。
編輯代碼文件 main.cpp
我們通過下述代碼,可以在 log
和 exp
在系統中可用的時候,基於這兩個函數提供一個可選的實現,如下:
// if we have both log and exp then use them
#if defined (HAVE_LOG) && defined (HAVE_EXP)
fprintf(stdout, "Result of exp(log(0.5))is:%ld\n", exp(log(0.5)));
#else // otherwise use an iterative approach
fprintf(stdout, "Don't support exp and log\n");
#endif
執行
$cmake -S tutorial -B build
$cmake --build build
$./build/Tutorial
./build/Tutorial Version 1.0
Usage: ./build/Tutorial number
$./build/Tutorial 25
Result of exp(log(0.5))is:4627730092099895296
custom square root.
The square root of 25 is 0
注意,第一條命令 -S
指定源碼目錄, -B
指定生成的編譯目錄。 第二條命令 --build
指明到 build
目錄中編譯,相當於 cd build && make
。