Skip to content

Commit 2732c3f

Browse files
committed
Add CMake functions
1 parent 4f08296 commit 2732c3f

File tree

5 files changed

+225
-0
lines changed

5 files changed

+225
-0
lines changed

cmake/functions.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
include(${CMAKE_CURRENT_LIST_DIR}/functions/project_flags.cmake)
2+
include(${CMAKE_CURRENT_LIST_DIR}/functions/sanitizers.cmake)
3+
include(${CMAKE_CURRENT_LIST_DIR}/functions/target_options.cmake)
4+
include(${CMAKE_CURRENT_LIST_DIR}/functions/link_external_libraries.cmake)

cmake/functions/project_flags.cmake

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# @brief Set variable indicating if this is a master project
2+
# - This is important to avoid building tests and examples when project is not master
3+
macro(set_master_project_booleans)
4+
if (${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_SOURCE_DIR})
5+
set(MASTER_PROJECT ON)
6+
else ()
7+
set(MASTER_PROJECT OFF)
8+
endif ()
9+
endmacro()
10+
11+
# @brief Set variables indicating if mode is Debug or Release
12+
# - The mode might be neither of them
13+
macro(set_debug_booleans)
14+
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
15+
set(DEBUG_MODE ON)
16+
set(NOT_DEBUG_MODE OFF)
17+
set(RELEASE_MODE OFF)
18+
set(NOT_RELEASE_MODE ON)
19+
else ()
20+
set(DEBUG_MODE OFF)
21+
set(NOT_DEBUG_MODE ON)
22+
set(RELEASE_MODE ON)
23+
set(NOT_RELEASE_MODE OFF)
24+
endif ()
25+
endmacro()
26+
27+
# @brief Create booleans GCC and CLANG to identify the compiler more easily
28+
# - A boolean for MSVC already exists by default
29+
macro(set_compiler_booleans)
30+
set(CLANG OFF)
31+
set(GCC OFF)
32+
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
33+
set(CLANG ON)
34+
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
35+
set(GCC ON)
36+
endif ()
37+
38+
# Check if we are using the "expected" compilers, which are usually
39+
# Win+MSVC, Linux+GCC, Mac+Clang
40+
set(EXPECTED_COMPILER OFF)
41+
if (WIN32 AND MSVC)
42+
set(EXPECTED_COMPILER ON)
43+
elseif (APPLE AND CLANG)
44+
set(EXPECTED_COMPILER ON)
45+
elseif (UNIX AND NOT APPLE AND GCC)
46+
set(EXPECTED_COMPILER ON)
47+
endif()
48+
endmacro()
49+
50+
# @brief Set the default optimization flags in case the user didn't
51+
# explicitly choose it with -DCMAKE_CXX_FLAGS
52+
macro(set_optimization_flags)
53+
if (NOT CMAKE_CXX_FLAGS)
54+
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
55+
if (EMSCRIPTEN)
56+
list(APPEND CMAKE_CXX_FLAGS "-O0 -g4")
57+
elseif (MSVC)
58+
list(APPEND CMAKE_CXX_FLAGS "/O0")
59+
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
60+
list(APPEND CMAKE_CXX_FLAGS "-O0")
61+
else()
62+
# https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
63+
list(APPEND CMAKE_CXX_FLAGS "-Og")
64+
endif()
65+
else()
66+
if (MSVC)
67+
list(APPEND CMAKE_CXX_FLAGS "/O2")
68+
else()
69+
list(APPEND CMAKE_CXX_FLAGS "-O2")
70+
endif()
71+
endif()
72+
message("Setting CXX flags to default for ${CMAKE_BUILD_TYPE} mode (${CMAKE_CXX_FLAGS})")
73+
else()
74+
message("CXX flags are already set to ${CMAKE_CXX_FLAGS}")
75+
endif()
76+
endmacro()

cmake/functions/sanitizers.cmake

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# @brief Add sanitizer flag for Clang and GCC to all targets
2+
# - You shouldn't use sanitizers in Release Mode
3+
# - It's usually best to do that per target
4+
macro(add_sanitizer flag)
5+
include(CheckCXXCompilerFlag)
6+
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
7+
message("Looking for -fsanitize=${flag}")
8+
set(CMAKE_REQUIRED_FLAGS "-Werror -fsanitize=${flag}")
9+
check_cxx_compiler_flag(-fsanitize=${flag} HAVE_FLAG_SANITIZER)
10+
if (HAVE_FLAG_SANITIZER)
11+
message("Adding -fsanitize=${flag}")
12+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=${flag} -fno-omit-frame-pointer")
13+
set(DCMAKE_C_FLAGS "${DCMAKE_C_FLAGS} -fsanitize=${flag} -fno-omit-frame-pointer")
14+
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=${flag}")
15+
set(DCMAKE_MODULE_LINKER_FLAGS "${DCMAKE_MODULE_LINKER_FLAGS} -fsanitize=${flag}")
16+
else ()
17+
message("-fsanitize=${flag} unavailable")
18+
endif ()
19+
endif ()
20+
endmacro()
21+
22+
# @brief Add address sanitizer to all targets
23+
# - You shouldn't use sanitizers in Release Mode
24+
# - It's usually best to do that per target
25+
macro(add_address_sanitizer)
26+
add_sanitizer("address")
27+
endmacro()
28+
29+
# @brief Add thread sanitizer to all targets
30+
# - You shouldn't use sanitizers in Release Mode
31+
# - It's usually best to do that per target
32+
macro(add_thread_sanitizer)
33+
add_sanitizer("thread")
34+
endmacro()
35+
36+
# @brief Add undefined sanitizer to all targets
37+
# - You shouldn't use sanitizers in Release Mode
38+
# - It's usually best to do that per target
39+
macro(add_undefined_sanitizer)
40+
add_sanitizer("undefined")
41+
endmacro()
42+
43+
# @brief Add memory sanitizer to all targets
44+
# - You shouldn't use sanitizers in Release Mode
45+
# - It's usually best to do that per target
46+
macro(add_memory_sanitizer)
47+
add_sanitizer("memory")
48+
endmacro()
49+
50+
# @brief @brief Add leak sanitizer to all targets
51+
# - You shouldn't use sanitizers in Release Mode
52+
# - It's usually best to do that per target
53+
macro(add_leak_sanitizer)
54+
add_sanitizer("leak")
55+
endmacro()
56+
57+
# @brief Add all sanitizers to all targets
58+
# - You shouldn't use sanitizers in Release Mode
59+
# - It's usually best to do that per target
60+
macro(add_sanitizers)
61+
add_address_sanitizer()
62+
add_leak_sanitizer()
63+
add_undefined_sanitizer()
64+
# not allowed with address sanitizer
65+
# add_thread_sanitizer()
66+
# not supported
67+
# add_memory_sanitizer()
68+
endmacro()

cmake/functions/target_options.cmake

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# @brief Enable pedantic warnings for a target
2+
# - This does not propagate to other targets
3+
function(target_pedantic_warnings TARGET_NAME)
4+
# Set warning levels to about the same level for MSVC, GCC, and Clang
5+
if (MSVC)
6+
target_compile_options(${TARGET_NAME} PRIVATE /W4 /WX)
7+
else ()
8+
target_compile_options(${TARGET_NAME} PRIVATE -Wall -Wextra -pedantic -Werror)
9+
endif ()
10+
endfunction()
11+
12+
# @brief Maybe enable pedantic warnings for a target
13+
function(maybe_target_pedantic_warnings TARGET_NAME)
14+
if (BUILD_WITH_PEDANTIC_WARNINGS)
15+
target_pedantic_warnings(${TARGET_NAME})
16+
endif ()
17+
endfunction ()
18+
19+
# @brief Sets pedantic compiler options for all targets
20+
# - In a more serious project, we would do that per target
21+
# - Setting it for all targets unfortunately affects
22+
# external libraries, which often lead to some warnings.
23+
macro(add_pedantic_warnings)
24+
if (MSVC)
25+
add_compile_options(/W4 /WX)
26+
else ()
27+
add_compile_options(-Wall -Wextra -pedantic -Werror)
28+
endif ()
29+
endmacro()
30+
31+
# @brief Maybe set pedantic compiler options for all targets
32+
macro(maybe_add_pedantic_warnings)
33+
if (BUILD_WITH_PEDANTIC_WARNINGS)
34+
add_pedantic_warnings()
35+
endif ()
36+
endmacro()
37+
38+
# @brief Enable compile options for MSVC only
39+
# - Adding special compile options to make your code work on MSVC
40+
# is unfortunately very common, so this pattern becomes useful.
41+
function(target_msvc_compile_options TARGET_NAME DEFINITION)
42+
if (MSVC)
43+
target_compile_options(${TARGET_NAME} PUBLIC ${DEFINITION})
44+
endif ()
45+
endfunction()
46+
47+
# Enable exceptions for the target
48+
function(target_exception_options TARGET_NAME)
49+
# MSVC requires this flag if the code uses C++ exception handling
50+
target_msvc_compile_options(${TARGET_NAME} PRIVATE /EHsc)
51+
endfunction()
52+
53+
54+
55+
# @brief Enable big object files for the target
56+
function(target_bigobj_options TARGET_NAME)
57+
# MSVC requires this flag if the file has a lot of code
58+
target_msvc_compile_options(${TARGET_NAME} PRIVATE /bigobj)
59+
endfunction()
60+
61+
# @brief Enable utf-8 for the target
62+
function(target_utf8_options TARGET_NAME)
63+
# MSVC requires this flag if the file has a lot of code
64+
target_msvc_compile_options(${TARGET_NAME} PRIVATE /utf-8)
65+
endfunction()
66+
67+
# @brief Enable utf-8 for the target
68+
function(target_disable_minmax TARGET_NAME)
69+
if (MSVC)
70+
# Another hack to check for min in Windows.h
71+
# http://www.suodenjoki.dk/us/archive/2010/min-max.htm
72+
check_symbol_exists(min "Windows.h" HAVE_WINDOWS_MINMAX)
73+
if (HAVE_WINDOWS_MINMAX)
74+
target_compile_definitions(${TARGET_NAME} PUBLIC NOMINMAX)
75+
endif()
76+
endif()
77+
endfunction()

0 commit comments

Comments
 (0)