compiler.cmake 10 KB
include(CheckCXXCompilerFlag)

set(PLATFORM_RELEASE "")
function(platformRelease)
    set(PR, "")
    execute_process(COMMAND /bin/bash -c "if [ -e /etc/redhat-release ]; then cat /etc/redhat-release | tr -d '\n'; fi" OUTPUT_VARIABLE PR)
    message(STATUS "Platform is ${PR}")
    set(PLATFORM_RELEASE "${PR}" PARENT_SCOPE)
endfunction(platformRelease)

# The target architecture (-march, -mtune) is assumed to be the architecture that was used to build gcc.
#  If cross-compilation is required, this should be specified as cmake arguments.

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wshadow" )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Woverloaded-virtual -Winit-self -Wuninitialized -Wunused -Wcast-qual" )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-long-long" )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wold-style-cast" )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=return-type" )

if(CMAKE_SYSTEM_PROCESSOR MATCHES "^x86_64")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-noexcept-type" )
endif()

if(CMAKE_COMPILER_IS_GNUCC
   AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9
   AND NOT APPLE)
    # Mac OSX doesn't seem to honour -isystem, so not for Mac.
    # Also, GCC 4.8 complains about boost
    MESSAGE(STATUS "Don't treat warnings as errors")
else()
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror" )
endif()
if(BUILD_WITH_PROFILING)
    message(STATUS "Profiling enabled")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg" )
else()
    message(STATUS "Profiling disabled")
endif()

# Allow linking into a dynamic library
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC" )

# Use RelWithDebInfo as default build type
if (NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE "RelWithDebInfo")
endif()
message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")

if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
    set(NOASSERTS 1) # Disable asserts as well
    # -O3 causes weird crashes on win32 so we force -O2 for release builds also for linux builds
    string(REGEX REPLACE "-O3" "-O2" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
    string(REGEX REPLACE "-O3" "-O2" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
    if(MINGW)
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s")
    endif()
else()
    # Let Qt track the use of QSharedPointer
    set(CMAKE_CXX_CFLAGS "${CMAKE_CXX_FLAGS} -DQT_SHAREDPOINTER_TRACK_POINTERS")
    # If we're debugging, remove -O2 completely
    string(REGEX REPLACE "-O2" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
    string(REGEX REPLACE "-O2" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
    string(REGEX REPLACE "-O2" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
    string(REGEX REPLACE "-O2" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
endif()

# Disable asserts with -DNOASSERTS=1 as a CMake command-line parameter
if(NOASSERTS)
    add_definitions(-DQT_NO_DEBUG)
    add_definitions(-DNDEBUG)
    message(STATUS "Asserts have been disabled")
endif(NOASSERTS)

if(APPLE)
    # AVX instructions currently cause assembler errors, so disabling them
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w -mno-avx  -mmacosx-version-min=10.7 -stdlib=libc++ ")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w -mno-avx  -mmacosx-version-min=10.7")
endif(APPLE)

if(UNIX)
    if(BUILD_WITH_COVERAGE)
        # Specifically enable coverate info, since ccache can't cache with
        # profiling enabled, seriously hurting build-times in Debug-mode
        message(STATUS "Generate coverage info")
        set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage")
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
        if (NOT TARGET RemoveGCDA)
            add_custom_target(RemoveGCDA ALL
                              COMMAND find . -name "*.gcda" -delete
                              COMMENT "Removing gcda files")
        endif(NOT TARGET RemoveGCDA)

        if(NOT NOASSERTS)
            add_definitions(-DQT_SHAREDPOINTER_TRACK_POINTERS)
        endif(NOT NOASSERTS)
    else()
        message(STATUS "Building without coverage info")
    endif()
endif(UNIX)

if(UNIX AND NOT APPLE)
    # needed for making qwt happy
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lrt" )
endif(UNIX AND NOT APPLE)

if(MINGW)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mwindows" )
endif(MINGW)

CHECK_CXX_COMPILER_FLAG( -fstack-protector-all result )
if(result)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector-all")
endif(result)

CHECK_CXX_COMPILER_FLAG( -fthreadsafe-statics THREADSAFE_RESULT)
if( NOT THREADSAFE_RESULT)
    message(FATAL_ERROR, "Compiler does not support threadsafe statics variables in methods")
endif()
# We use static variables in method scope, they must be threadsafe, this is on by default since gcc 4 but this flag is a check
# If the compiler does not support this then build will fail.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fthreadsafe-statics")

if(CMAKE_COMPILER_IS_GNUCXX)
    # Check on which architecture we are. ARM doesn't support mfpmath
    if(CMAKE_SYSTEM_PROCESSOR MATCHES "^x86_64")
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpmath=sse" )
    endif()

    # Check which version of c++ we can use. We drill down from c++17 to c98
    CHECK_CXX_COMPILER_FLAG( -stdc++17 cxxresult )
    if( NOT cxxresult )
        CHECK_CXX_COMPILER_FLAG( -std=c++14 cxxresult )
        if( NOT cxxresult )
            CHECK_CXX_COMPILER_FLAG( -std=c++11 cxxresult )
            if( NOT cxxresult )
                set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
            else()
                set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
            endif()
        else()
            set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
        endif()
    else()
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
    endif()
    MESSAGE(STATUS "Compiling for ${CMAKE_CXX_FLAGS}")

    # -Wzero-as-null-pointer-constant is disabled for now, since the Qt 4.8.4
    # macro's produce a bucketload of these warnings. Might be useful later on.
#    CHECK_CXX_COMPILER_FLAG( -Wzero-as-null-pointer-constant cxxresult )
#    if(cxxresult)
#        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wzero-as-null-pointer-constant")
#    endif(cxxresult)
    # Leave out deprecation warnings, mostly generated by CppUnit
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Weffc++")

endif(CMAKE_COMPILER_IS_GNUCXX)

if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
    MESSAGE(STATUS "Enabling Clang flags")
    # We enable all warnings and disable what we don't need
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Weverything")
    # Warns if items need to be re-aligned to 4-byte boundaries. Since we use
    # booleans in our code, these warnings are all over the place. If
    # memory-usage becomes an issue, we can pack all booleans together using
    # this warning. However, it's currently not practical to eliminate them all.
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-padded")
    # We use a lot of static objects, which get cleaned up at exit by their destructors.
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-exit-time-destructors")
    # Static objects tend to have global constructors
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-global-constructors")
    # We mix int / unsigned int a lot, so disabled it for the moment
    #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-sign-conversion")
    # Warning caused by the Qt translations
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-missing-prototypes")
    # We standardize on C++11, so don't bother us with C++98
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-c++98-compat -Wno-c++98-compat-pedantic")
    # We explicitly want to use the switch(){default: break;} construction
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-switch-enum")
    # Q_OBJECT does an "int i = i;"...
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-self-assign")
    # Compile for C++11
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
    # Don't complain about unused arguments, since this also triggers warnings
    # about include-directories that are unused...
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments")
    # Don't complain about fall-throughs in switch/case statements
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-implicit-fallthrough")
    # Since "Q_ASSERT(false)" creates a not of noise, disable it when asserts are active
    if(NOT NOASSERTS)
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unreachable-code")
    endif(NOT NOASSERTS)
    # There is no way to avoid this warning right now, so we disable it
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-weak-template-vtables")
    # Warning caused by Qt resource files, so disabling it
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-missing-variable-declarations")
    # WORKAROUND: Somehow Qt forgets that Clang is a C++11 compiler
    ADD_DEFINITIONS("-DQ_COMPILER_INITIALIZER_LISTS")
    # Clang 3.3 doesn't know Doxygens' "\test" and "\retval" tags, so disabling
    # check for unknown tags for now
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-documentation-unknown-command")

    if(CMAKE_CXX_COMPILER_VERSION MATCHES "3\\.4\\.2")
        message(STATUS "compiler is clang version 3.4.2")
        platformRelease()
        if("${PLATFORM_RELEASE}" MATCHES "CentOS Linux release 7\\.2\\..+")
            # Override the gnu minor version only for this specific combination of platform and clang version
            set(CMAKE_CXX_FLAGS "-U__GNUC_MINOR__ -D__GNUC_MINOR__=3  ${CMAKE_CXX_FLAGS}")
            message(STATUS "Overriding clang gnu minor version to 3 so that several libstd c++11 features like tuple can be used")
        endif("${PLATFORM_RELEASE}" MATCHES "CentOS Linux release 7\\.2\\..+")
    endif(CMAKE_CXX_COMPILER_VERSION MATCHES "3\\.4\\.2")
endif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")

if(APPLE)
    set(WHOLE_ARCHIVE_ON "-all_load")
    set(WHOLE_ARCHIVE_OFF "")
else()
    set(WHOLE_ARCHIVE_ON "-Wl,-whole-archive")
    set(WHOLE_ARCHIVE_OFF "-Wl,-no-whole-archive")
endif()