# ============================================================================ # # Compiler setup # # ============================================================================ # # Get upper case system name string(TOUPPER ${CMAKE_SYSTEM_NAME} SYSTEM_NAME_UPPER) # Determine architecture (32/64 bit) set(X64 OFF) if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(X64 ON) endif() # Determine if we're building a shared (dynamic) library # And set appropriate suffixes for the executables if(BUILD_SHARED_LIBS) set(CMAKE_DEBUG_POSTFIX "_d") else() add_definitions(-DSTATIC_LIB) set(CMAKE_DEBUG_POSTFIX "_d_s") set(CMAKE_RELEASE_POSTFIX "_s") endif() # Enable position independent code property set(CMAKE_POSITION_INDEPENDENT_CODE ON) # Check if compiler support the c++17 standard include(CheckCXXCompilerFlag) CHECK_CXX_COMPILER_FLAG("-std=c++17" COMPILER_SUPPORTS_CXX17) if(COMPILER_SUPPORTS_CXX17) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) else(COMPILER_SUPPORTS_CXX17) if (MSVC_VERSION GREATER_EQUAL 1900) include(CheckCXXCompilerFlag) add_definitions(-DNOMINMAX) CHECK_CXX_COMPILER_FLAG("/std:c++latest" _cpp_latest_flag_supported) if (_cpp_latest_flag_supported) add_compile_options("/std:c++latest") endif() else() message(STATUS "The compiler '${CMAKE_CXX_COMPILER}' has no C++17 support. Please use a more recent C++ compiler!") endif() endif() # Check compiler version if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") # c++17 require at least gcc 5.0.0 if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0.0) message(FATAL_ERROR "GCC version must be at least 7.0.0!") endif() elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") # c++17 require at least clang 5.0 if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0) message(FATAL_ERROR "Clang version must be at least 5.0!") endif() elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") # c++17 require at least clang 3.4 if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10.0) message(FATAL_ERROR "AppleClang version must be at least 10.0!") endif() elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # c++17 require at least Microsoft Visual Studio 2017 if (MSVC_VERSION VERSION_LESS 1910) message(FATAL_ERROR "MSVC version must be at Visual Studio 2017!") endif() else() message(FATAL_ERROR "Unsupported compiler: ${CMAKE_CXX_COMPILER_ID}") endif() # Set optional build flags set(EXTRA_FLAGS "") # Increase max. template depth on GCC and Clang if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") # Increase maximum number of instantiations and # reduce the number of template instantiations shown in backtrace. set(EXTRA_FLAGS "-ftemplate-depth=512 -ftemplate-backtrace-limit=0") endif() # GCC compiles large C++ programs faster if you increase its GC limit if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") set(EXTRA_FLAGS "${EXTRA_FLAGS} --param ggc-min-heapsize=524288") endif() # MSVC compiler options if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "MSVC") set(WFLAGS ${WFLAGS} /MP # -> build with multiple processes /W4 # -> warning level 4 # /WX # -> treat warnings as errors /wd4251 # -> disable warning: 'identifier': class 'type' needs to have dll-interface to be used by clients of class 'type2' /wd4275 # -> disable warning: non dll-interface struct '...' used as base for dll-interface class '...' /wd4592 # -> disable warning: 'identifier': symbol will be dynamically initialized (implementation limitation) # /wd4201 # -> disable warning: nonstandard extension used: nameless struct/union (caused by GLM) /wd4127 # -> disable warning: conditional expression is constant (caused by Qt) # /Zm114 # -> Memory size for precompiled headers (insufficient for msvc 2013) /Zm200 # -> Memory size for precompiled headers /bigobj # (Increase Number of Sections in .Obj file) ) string(REPLACE ";" " " WFLAGS "${WFLAGS}") message("WFLAGS is ${WFLAGS}") endif () # clang compiler options : add some very useful warnings by default if ( ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang") ) set(CLANG_ADDITIONAL_FLAGS "${EXTRA_FLAGS} " "-Wshadow " # Variable shadowing "-Winvalid-source-encoding " "-Wconditional-uninitialized " # Variable used when uninitialized "-Wnon-virtual-dtor" # missing virtual dtor "-Winconsistent-missing-override " "-Wheader-hygiene " # "using namespace" in a header "-Wunused-variable -Wunused-private-field" "-Wignored-qualifiers" # ignored "const" qualifiers "-Wunreachable-code-return" "-Wmissing-field-initializers" # conversion issues : those should be enabled later! # "-Wfloat-equal " #"-Wsign-conversion " #"-Wconversion " ) # Those flags can safely be disabled set(CLANG_DISABLED_FLAGS_LEGIT # https://stackoverflow.com/questions/13905200/is-it-wise-to-ignore-gcc-clangs-wmissing-braces-warning/13905432 "-Wno-missing-braces" "-Wno-unused-command-line-argument" ) # Those flags should be activated later (they denote real issues) set(CLANG_DISABLED_FLAGS_DUBIOUS "-Wno-float-equal " # comparing floating point with == or != is unsafe [-Wfloat-equal] "-Wno-sign-conversion" "-Wno-conversion" ) set(EXTRA_FLAGS ${CLANG_ADDITIONAL_FLAGS} ${CLANG_DISABLED_FLAGS_LEGIT} ${CLANG_DISABLED_FLAGS_DUBIOUS}) string(REPLACE ";" " " EXTRA_FLAGS "${EXTRA_FLAGS}") endif() # GCC compiler options # Add "-Werror" flag if requested if(OPTION_CXX_WARNINGS_AS_ERRORS) set(EXTRA_FLAGS "${EXTRA_FLAGS} -Werror") endif() # Set -fno-exception if requested if(OPTION_FORCE_NO_EXCEPTIONS) set(EXTRA_FLAGS "${EXTRA_FLAGS} -fno-exceptions") endif() # Enable a ton of warnings if --more-clang-warnings is used if(OPTION_MORE_WARNINGS) if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") set(WFLAGS "-Weverything -Wno-c++98-compat -Wno-padded " "-Wno-documentation-unknown-command -Wno-exit-time-destructors " "-Wno-global-constructors -Wno-missing-prototypes " "-Wno-c++98-compat-pedantic -Wno-unused-member-function " "-Wno-unused-const-variable -Wno-switch-enum " "-Wno-missing-noreturn -Wno-covered-switch-default") elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") set(WFLAGS "-Waddress -Wall -Warray-bounds " "-Wattributes -Wbuiltin-macro-redefined -Wcast-align " "-Wcast-qual -Wchar-subscripts -Wclobbered -Wcomment " "-Wconversion -Wconversion-null -Wcoverage-mismatch " "-Wcpp -Wdelete-non-virtual-dtor -Wdeprecated " "-Wdeprecated-declarations -Wdiv-by-zero -Wdouble-promotion " "-Wempty-body -Wendif-labels -Wenum-compare -Wextra " "-Wfloat-equal -Wformat -Wfree-nonheap-object " "-Wignored-qualifiers -Winit-self " "-Winline -Wint-to-pointer-cast -Winvalid-memory-model " "-Winvalid-offsetof -Wlogical-op -Wmain -Wmaybe-uninitialized " "-Wmissing-braces -Wmissing-field-initializers -Wmultichar " "-Wnarrowing -Wnoexcept -Wnon-template-friend " "-Wnon-virtual-dtor -Wnonnull -Woverflow " "-Woverlength-strings -Wparentheses " "-Wpmf-conversions -Wpointer-arith -Wreorder " "-Wreturn-type -Wsequence-point -Wshadow " "-Wsign-compare -Wswitch -Wtype-limits -Wundef " "-Wuninitialized -Wunused -Wvla -Wwrite-strings") endif() # Convert CMake list to a single string, erasing the ";" separators string(REPLACE ";" "" WFLAGS_STR ${WFLAGS}) build_string("EXTRA_FLAGS" "${WFLAGS_STR}") endif() # Allow unused private fields when using clang if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") set(EXTRA_FLAGS "${EXTRA_FLAGS} -Wno-unused-private-field") endif() # Enable Position Independent Code (PIC) in shared libraries if(NOT MINGW AND NOT WIN32) set(EXTRA_FLAGS "${EXTRA_FLAGS} -fPIC") endif() # Use pthreads on mingw and linux if(NOT APPLE AND NOT WIN32) set(EXTRA_FLAGS "${EXTRA_FLAGS} -pthread") endif() # Performance if(NOT WIN32) # Check for the Apple iOS platform if (APPLE AND PLATFORM STREQUAL "OS64COMBINED") set(EXTRA_FLAGS "${EXTRA_FLAGS} -mpopcnt") else() set(EXTRA_FLAGS "${EXTRA_FLAGS} -march=native -mpopcnt") endif() endif() # Performance if (OPTION_ENABLE_ADDRESS_SANITIZER) set(CXXFLAGS_BACKUP "${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "-fsanitize=address -fno-omit-frame-pointer") try_run(program_result compilation_succeeded "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_MODULE_PATH}/get_compiler_version.cpp") set(CMAKE_CXX_FLAGS "${CXXFLAGS_BACKUP}") if(NOT compilation_succeeded) message(STATUS "Address Sanitizer not available on selected compiler") else() message(STATUS "Enabling Address Sanitizer") set(EXTRA_FLAGS "${EXTRA_FLAGS} -fsanitize=address -fno-omit-frame-pointer") set(ASAN_FOUND true) endif() endif(OPTION_ENABLE_ADDRESS_SANITIZER) if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "MSVC") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WFLAGS}") endif() if(NOT CMAKE_CXX_FLAGS) set(CMAKE_CXX_FLAGS "-Wextra -Wall -pedantic ${EXTRA_FLAGS}") endif() # Check if the user provided CXXFLAGS, set defaults otherwise #if(NOT CMAKE_CXX_FLAGS_DEBUG) # set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") #endif() #if(NOT CMAKE_CXX_FLAGS_MINSIZEREL) # set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os") #endif() #if(NOT CMAKE_CXX_FLAGS_RELEASE) # set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG") #endif() #if(NOT CMAKE_CXX_FLAGS_RELWITHDEBINFO) # set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g") #endif() if (EXTRA_LINKER_FLAGS) if(NOT CMAKE_EXE_LINKER_FLAGS) set(CMAKE_EXE_LINKER_FLAGS "${EXTRA_LINKER_FLAGS}") endif() if(NOT CMAKE_SHARED_LINKER_FLAGS) set(CMAKE_SHARED_LINKER_FLAGS "${EXTRA_LINKER_FLAGS}") endif() endif() # Set build default build type to RelWithDebInfo if not set if(NOT CMAKE_BUILD_TYPE) # set(CMAKE_BUILD_TYPE RelWithDebInfo) endif() # Needed by subprojects set(LD_FLAGS ${LD_FLAGS} ${CMAKE_LD_LIBS})