It is possible to use include guards but with some limitations as mentioned here:
Note that the type of the include guard variable should never be a CACHE variable, since this would cause the variable to persist across multiple CMake configure runs, thereby causing the bug of blocking any subsequent run from reading in the module file's content. A Non-CACHE variable is not fully appropriate either, however, since foreign scopes (which did not adopt that variable definition yet) will lead to (somewhat unnecessary and potentially problematic) re-reading of the file's content. Thus the best choice is implementing this check via a GLOBAL property setting, since such settings have all of the desired characteristics: they're both globally valid and single-session only.
Second, note that only module files that are supportive of such a construct (i.e., files declaring only functions or defining all their settings as CACHE variables) can make use of include guards without issues (Non-CACHE variables, while possibly being referenced within those functions, may suddenly end up being out of scope yet the function will remain reachable).
In my case I have IncludeGuard.cmake
file with the following content:
# Include this file and invoke cmake_include_guard to prevent the CMake script
# parse invoker file multiple times.
macro(cmake_include_guard)
get_property(INCLUDE_GUARD GLOBAL PROPERTY "INCLUDE_GUARD_${CMAKE_CURRENT_LIST_FILE}")
if(INCLUDE_GUARD)
return()
endif()
set_property(GLOBAL PROPERTY "INCLUDE_GUARD_${CMAKE_CURRENT_LIST_FILE}" TRUE)
endmacro()
In common cmake files I use the following snippet at the beggining:
include(IncludeGuard)
cmake_include_guard()
Macro cmake_include_guard
use return()
to stop further content processing.