Let us consider adding some code to our project that depends on features the target platform may not have.
假设某代码运行平台不包含log和exp这两个模块,下面我们使用cmake来判断是否平台中是否存在这两个模块,如果不存在则运行其他的代码段。 我们需要在顶层的CMakeLists.txt 中包含CheckSymbolExists模块,去检查在本平台中这些功能模块是否是可用的。在顶层CMakeLists.txt 中包含的代码如下:
include(CheckSymbolExists) check_symbol_exists(log "math.h" HAVE_LOG) check_symbol_exists(exp "math.h" HAVE_EXP) if(NOT (HAVE_LOG AND HAVE_EXP)) unset(HAVE_LOG CACHE) unset(HAVE_EXP CACHE) set(CMAKE_REQUIRED_LIBRARIES "m") check_symbol_exists(log "math.h" HAVE_LOG) check_symbol_exists(exp "math.h" HAVE_EXP) if(HAVE_LOG AND HAVE_EXP) target_link_libraries(MathFunctions PRIVATE m) endif() endif()为了在cxx文件中也能够使用判断结果,我们需要在TutorialConfig.h.in中插入下面的定义,以便在cxx程序中使用这些标识变量。
// does the platform provide exp and log functions? #cmakedefine HAVE_LOG #cmakedefine HAVE_EXP所以接下来我们就可以在MathFunctions/mysqrt.cxx文件中,使用这两个标志了
#include <cmath> #include "TutorialConfig.h" #if defined(HAVE_LOG) && defined(HAVE_EXP) double result = exp(log(x) * 0.5); std::cout << "Computing sqrt of " << x << " to be " << result << " using log and exp" << std::endl; #else double result = x;然后我们还需要在MathFunctions/CMakeLists.txt中添加TutorialConfig.h的位置:
target_include_directories(MathFunctions INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_BINARY_DIR} )然后我们就可以编译运行了。
下面我们来尝试不使用TutorialConfig.h来存放宏定义,直接使用target_compile_definitions()功能。 首先把TutorialConfig.h.in中的定义删除,并且删除MathFunctions中cxx文件中的include和CMakeLists中的target_include_directories中TutorialConfig.h的路径。 然后我们就可以将顶层的对log和exp的检查转移到MathFunctions/CMakeLists.txt中。 然后增加target_compile_definitions
include(CheckSymbolExists) check_symbol_exists(log "math.h" HAVE_LOG) check_symbol_exists(exp "math.h" HAVE_EXP) if(NOT (HAVE_LOG AND HAVE_EXP)) unset(HAVE_LOG CACHE) unset(HAVE_EXP CACHE) set(CMAKE_REQUIRED_LIBRARIES "m") check_symbol_exists(log "math.h" HAVE_LOG) check_symbol_exists(exp "math.h" HAVE_EXP) if(HAVE_LOG AND HAVE_EXP) target_link_libraries(MathFunctions PRIVATE m) endif() endif() # add compile definitions if(HAVE_LOG AND HAVE_EXP) target_compile_definitions(MathFunctions PRIVATE "HAVE_LOG" "HAVE_EXP") endif()然后重新编译运行,这样的写法与上面的第一种写法,作用一样。