cmake: Improve checks for compiler flags
authorAndreas Schneider <asn@samba.org>
Thu, 17 Oct 2019 13:34:21 +0000 (15:34 +0200)
committerAndreas Schneider <asn@cryptomilk.org>
Sun, 20 Oct 2019 12:59:54 +0000 (14:59 +0200)
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
CMakeLists.txt
CompilerChecks.cmake [new file with mode: 0644]
DefineOptions.cmake
cmake/Modules/AddCCompilerFlag.cmake [new file with mode: 0644]
cmake/Modules/CheckCCompilerFlagSSP.cmake
cmake/Modules/DefineCompilerFlags.cmake [deleted file]
src/CMakeLists.txt
tests/CMakeLists.txt

index 911b9164c8f14276fad1be62395315c91a6bf0a1..3d17bcd2b5de1650ce80530e3c59bfbeb17b35e9 100644 (file)
@@ -28,6 +28,7 @@ include(DefinePlatformDefaults)
 include(DefineInstallationPaths)
 include(DefineOptions.cmake)
 include(CPackConfig.cmake)
+include(CompilerChecks.cmake)
 
 # disallow in-source build
 include(MacroEnsureOutOfSourceBuild)
@@ -41,9 +42,6 @@ find_package(Threads)
 include(ConfigureChecks.cmake)
 configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
 
-# Add compiler flags for the project now.
-include(DefineCompilerFlags)
-
 # check subdirectories
 add_subdirectory(src)
 
diff --git a/CompilerChecks.cmake b/CompilerChecks.cmake
new file mode 100644 (file)
index 0000000..4fa1a83
--- /dev/null
@@ -0,0 +1,114 @@
+include(AddCCompilerFlag)
+include(CheckCCompilerFlagSSP)
+
+if (UNIX)
+    #
+    # Check for -Werror turned on if possible
+    #
+    # This will prevent that compiler flags are detected incorrectly.
+    #
+    check_c_compiler_flag("-Werror" REQUIRED_FLAGS_WERROR)
+    if (REQUIRED_FLAGS_WERROR)
+        set(CMAKE_REQUIRED_FLAGS "-Werror")
+
+        if (PICKY_DEVELOPER)
+            list(APPEND SUPPORTED_COMPILER_FLAGS "-Werror")
+        endif()
+    endif()
+
+    add_c_compiler_flag("-std=gnu99" SUPPORTED_COMPILER_FLAGS)
+    #add_c_compiler_flag("-Wpedantic" SUPPORTED_COMPILER_FLAGS)
+    add_c_compiler_flag("-Wall" SUPPORTED_COMPILER_FLAGS)
+    add_c_compiler_flag("-Wshadow" SUPPORTED_COMPILER_FLAGS)
+    add_c_compiler_flag("-Wmissing-prototypes" SUPPORTED_COMPILER_FLAGS)
+    add_c_compiler_flag("-Wcast-align" SUPPORTED_COMPILER_FLAGS)
+    #add_c_compiler_flag("-Wcast-qual" SUPPORTED_COMPILER_FLAGS)
+    add_c_compiler_flag("-Werror=address" SUPPORTED_COMPILER_FLAGS)
+    add_c_compiler_flag("-Wstrict-prototypes" SUPPORTED_COMPILER_FLAGS)
+    add_c_compiler_flag("-Werror=strict-prototypes" SUPPORTED_COMPILER_FLAGS)
+    add_c_compiler_flag("-Wwrite-strings" SUPPORTED_COMPILER_FLAGS)
+    add_c_compiler_flag("-Werror=write-strings" SUPPORTED_COMPILER_FLAGS)
+    add_c_compiler_flag("-Werror-implicit-function-declaration" SUPPORTED_COMPILER_FLAGS)
+    add_c_compiler_flag("-Wpointer-arith" SUPPORTED_COMPILER_FLAGS)
+    add_c_compiler_flag("-Werror=pointer-arith" SUPPORTED_COMPILER_FLAGS)
+    add_c_compiler_flag("-Wdeclaration-after-statement" SUPPORTED_COMPILER_FLAGS)
+    add_c_compiler_flag("-Werror=declaration-after-statement" SUPPORTED_COMPILER_FLAGS)
+    add_c_compiler_flag("-Wreturn-type" SUPPORTED_COMPILER_FLAGS)
+    add_c_compiler_flag("-Werror=return-type" SUPPORTED_COMPILER_FLAGS)
+    add_c_compiler_flag("-Wuninitialized" SUPPORTED_COMPILER_FLAGS)
+    add_c_compiler_flag("-Werror=uninitialized" SUPPORTED_COMPILER_FLAGS)
+    add_c_compiler_flag("-Wimplicit-fallthrough" SUPPORTED_COMPILER_FLAGS)
+    add_c_compiler_flag("-Werror=strict-overflow" SUPPORTED_COMPILER_FLAGS)
+    add_c_compiler_flag("-Wstrict-overflow=2" SUPPORTED_COMPILER_FLAGS)
+    add_c_compiler_flag("-Wno-format-zero-length" SUPPORTED_COMPILER_FLAGS)
+
+    check_c_compiler_flag("-Wformat" REQUIRED_FLAGS_WFORMAT)
+    if (REQUIRED_FLAGS_WFORMAT)
+        list(APPEND SUPPORTED_COMPILER_FLAGS "-Wformat")
+        set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Wformat")
+    endif()
+    add_c_compiler_flag("-Wformat-security" SUPPORTED_COMPILER_FLAGS)
+    add_c_compiler_flag("-Werror=format-security" SUPPORTED_COMPILER_FLAGS)
+
+    # Allow zero for a variadic macro argument
+    string(TOLOWER "${CMAKE_C_COMPILER_ID}" _C_COMPILER_ID)
+    if ("${_C_COMPILER_ID}" STREQUAL "clang")
+        add_c_compiler_flag("-Wno-gnu-zero-variadic-macro-arguments" SUPPORTED_COMPILER_FLAGS)
+    endif()
+
+    add_c_compiler_flag("-fno-common" SUPPORTED_COMPILER_FLAGS)
+
+    if (CMAKE_BUILD_TYPE)
+        string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
+        if (CMAKE_BUILD_TYPE_LOWER MATCHES (release|relwithdebinfo|minsizerel))
+            add_c_compiler_flag("-Wp,-D_FORTIFY_SOURCE=2" SUPPORTED_COMPILER_FLAGS)
+        endif()
+    endif()
+
+    if (NOT SOLARIS)
+        check_c_compiler_flag_ssp("-fstack-protector-strong" WITH_STACK_PROTECTOR_STRONG)
+        if (WITH_STACK_PROTECTOR_STRONG)
+            list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-protector-strong")
+            # This is needed as Solaris has a seperate libssp
+            if (SOLARIS)
+                list(APPEND SUPPORTED_LINKER_FLAGS "-fstack-protector-strong")
+            endif()
+        else (WITH_STACK_PROTECTOR_STRONG)
+            check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR)
+            if (WITH_STACK_PROTECTOR)
+                list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-protector")
+                # This is needed as Solaris has a seperate libssp
+                if (SOLARIS)
+                    list(APPEND SUPPORTED_LINKER_FLAGS "-fstack-protector")
+                endif()
+            endif()
+        endif (WITH_STACK_PROTECTOR_STRONG)
+
+        check_c_compiler_flag_ssp("-fstack-clash-protection" WITH_STACK_CLASH_PROTECTION)
+        if (WITH_STACK_CLASH_PROTECTION)
+            list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-clash-protection")
+        endif()
+    endif()
+
+    if (PICKY_DEVELOPER)
+        add_c_compiler_flag("-Wno-error=deprecated-declarations" SUPPORTED_COMPILER_FLAGS)
+        add_c_compiler_flag("-Wno-error=tautological-compare" SUPPORTED_COMPILER_FLAGS)
+    endif()
+
+    # Unset CMAKE_REQUIRED_FLAGS
+    unset(CMAKE_REQUIRED_FLAGS)
+endif()
+
+if (MSVC)
+    add_c_compiler_flag("/D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1" SUPPORTED_COMPILER_FLAGS)
+    add_c_compiler_flag("/D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1" SUPPORTED_COMPILER_FLAGS)
+    add_c_compiler_flag("/D _CRT_NONSTDC_NO_WARNINGS=1" SUPPORTED_COMPILER_FLAGS)
+    add_c_compiler_flag("/D _CRT_SECURE_NO_WARNINGS=1" SUPPORTED_COMPILER_FLAGS)
+endif()
+
+if (SUPPORTED_COMPILER_FLAGS)
+    set(DEFAULT_C_COMPILE_FLAGS ${SUPPORTED_COMPILER_FLAGS} CACHE INTERNAL "Default C Compiler Flags" FORCE)
+endif()
+if (SUPPORTED_LINKER_FLAGS)
+    set(DEFAULT_LINK_FLAGS ${SUPPORTED_LINKER_FLAGS} CACHE INTERNAL "Default C Linker Flags" FORCE)
+endif()
index 6030e79e71d34c39619e48cc9ca5b67bedf6818a..8fc654dedf6f01becefd380c8c2137da3bb02560 100644 (file)
@@ -1 +1,2 @@
 option(UNIT_TESTING "Build with unit tests" OFF)
+option(PICKY_DEVELOPER "Build with picky developer flags" OFF)
diff --git a/cmake/Modules/AddCCompilerFlag.cmake b/cmake/Modules/AddCCompilerFlag.cmake
new file mode 100644 (file)
index 0000000..c24c215
--- /dev/null
@@ -0,0 +1,21 @@
+#
+# add_c_compiler_flag("-Werror" SUPPORTED_CFLAGS)
+#
+# Copyright (c) 2018      Andreas Schneider <asn@cryptomilk.org>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+include(CheckCCompilerFlag)
+
+macro(add_c_compiler_flag _COMPILER_FLAG _OUTPUT_VARIABLE)
+    string(TOUPPER ${_COMPILER_FLAG} _COMPILER_FLAG_NAME)
+    string(REGEX REPLACE "^-" "" _COMPILER_FLAG_NAME "${_COMPILER_FLAG_NAME}")
+    string(REGEX REPLACE "(-|=|\ )" "_" _COMPILER_FLAG_NAME "${_COMPILER_FLAG_NAME}")
+
+    check_c_compiler_flag("${_COMPILER_FLAG}" WITH_${_COMPILER_FLAG_NAME}_FLAG)
+    if (WITH_${_COMPILER_FLAG_NAME}_FLAG)
+        #string(APPEND ${_OUTPUT_VARIABLE} "${_COMPILER_FLAG} ")
+        list(APPEND ${_OUTPUT_VARIABLE} ${_COMPILER_FLAG})
+    endif()
+endmacro()
index 2fe43954a91a0eba4b758c50287ed8eeaa8c018a..eeaf4fca0964ad248706a41caa3ad1badf11f4f7 100644 (file)
 # Redistribution and use is allowed according to the terms of the BSD license.
 # For details see the accompanying COPYING-CMAKE-SCRIPTS file.
 
-
+# Requires cmake 3.10
+#include_guard(GLOBAL)
 include(CheckCSourceCompiles)
+include(CMakeCheckCompilerFlagCommonPatterns)
+
+macro(CHECK_C_COMPILER_FLAG_SSP _FLAG _RESULT)
+   set(SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
+   set(CMAKE_REQUIRED_FLAGS "${_FLAG}")
+
+   # Normalize locale during test compilation.
+   set(_CheckCCompilerFlag_LOCALE_VARS LC_ALL LC_MESSAGES LANG)
+   foreach(v ${_CheckCCompilerFlag_LOCALE_VARS})
+     set(_CheckCCompilerFlag_SAVED_${v} "$ENV{${v}}")
+     set(ENV{${v}} C)
+   endforeach()
+
+   CHECK_COMPILER_FLAG_COMMON_PATTERNS(_CheckCCompilerFlag_COMMON_PATTERNS)
+   check_c_source_compiles("int main(int argc, char **argv) { char buffer[256]; return buffer[argc]=0;}"
+                           ${_RESULT}
+                           # Some compilers do not fail with a bad flag
+                           FAIL_REGEX "command line option .* is valid for .* but not for C" # GNU
+                           ${_CheckCCompilerFlag_COMMON_PATTERNS})
+   foreach(v ${_CheckCCompilerFlag_LOCALE_VARS})
+     set(ENV{${v}} ${_CheckCCompilerFlag_SAVED_${v}})
+     unset(_CheckCCompilerFlag_SAVED_${v})
+   endforeach()
+   unset(_CheckCCompilerFlag_LOCALE_VARS)
+   unset(_CheckCCompilerFlag_COMMON_PATTERNS)
 
-function(CHECK_C_COMPILER_FLAG_SSP _FLAG _RESULT)
-   set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
-   set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
-   check_c_source_compiles("int main(int argc, char **argv) { char buffer[256]; return buffer[argc]=0;}" ${_RESULT})
-   set(CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
-endfunction(CHECK_C_COMPILER_FLAG_SSP)
+   set(CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}")
+endmacro(CHECK_C_COMPILER_FLAG_SSP)
diff --git a/cmake/Modules/DefineCompilerFlags.cmake b/cmake/Modules/DefineCompilerFlags.cmake
deleted file mode 100644 (file)
index 0ab8802..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-# define system dependent compiler flags
-
-include(CheckCCompilerFlag)
-include(CheckCCompilerFlagSSP)
-
-if (UNIX AND NOT WIN32)
-    #
-    # Define GNUCC compiler flags
-    #
-    if (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)")
-
-        # add -Wconversion ?
-        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -pedantic -pedantic-errors")
-        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wshadow -Wmissing-prototypes -Wdeclaration-after-statement")
-        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wunused -Wfloat-equal -Wpointer-arith -Wwrite-strings -Wformat-security")
-        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-format-attribute")
-
-        # with -fPIC
-        check_c_compiler_flag("-fPIC" WITH_FPIC)
-        if (WITH_FPIC)
-            set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
-        endif (WITH_FPIC)
-
-        check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR)
-        if (WITH_STACK_PROTECTOR)
-            set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector")
-        endif (WITH_STACK_PROTECTOR)
-
-        if (CMAKE_BUILD_TYPE)
-            string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
-            if (CMAKE_BUILD_TYPE_LOWER MATCHES (release|relwithdebinfo|minsizerel))
-                check_c_compiler_flag("-Wp,-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE)
-                if (WITH_FORTIFY_SOURCE)
-                    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wp,-D_FORTIFY_SOURCE=2")
-                endif (WITH_FORTIFY_SOURCE)
-            endif()
-        endif()
-    endif (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)")
-
-    #
-    # Check for large filesystem support
-    #
-    if (CMAKE_SIZEOF_VOID_P MATCHES "8")
-        # with large file support
-        execute_process(
-            COMMAND
-                getconf LFS64_CFLAGS
-            OUTPUT_VARIABLE
-                _lfs_CFLAGS
-            ERROR_QUIET
-            OUTPUT_STRIP_TRAILING_WHITESPACE
-        )
-    else (CMAKE_SIZEOF_VOID_P MATCHES "8")
-        # with large file support
-        execute_process(
-            COMMAND
-                getconf LFS_CFLAGS
-            OUTPUT_VARIABLE
-                _lfs_CFLAGS
-            ERROR_QUIET
-            OUTPUT_STRIP_TRAILING_WHITESPACE
-        )
-    endif (CMAKE_SIZEOF_VOID_P MATCHES "8")
-    if (_lfs_CFLAGS)
-        string(REGEX REPLACE "[\r\n]" " " "${_lfs_CFLAGS}" "${${_lfs_CFLAGS}}")
-        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_lfs_CFLAGS}")
-    endif (_lfs_CFLAGS)
-
-endif (UNIX AND NOT WIN32)
-
-if (MSVC)
-    # Use secure functions by defaualt and suppress warnings about
-    #"deprecated" functions
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1")
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1")
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1")
-endif (MSVC)
index e95903ff7a95bdf6ca01d8ba293f4bac5d7bcb10..d991df6cea986a66dba380e33650b8c558ad61d5 100644 (file)
@@ -4,6 +4,10 @@ include_directories(${CMAKE_BINARY_DIR})
 add_library(resolv_wrapper SHARED resolv_wrapper.c)
 target_link_libraries(resolv_wrapper ${RWRAP_REQUIRED_LIBRARIES})
 
+target_compile_options(resolv_wrapper
+                       PRIVATE
+                           ${DEFAULT_C_COMPILE_FLAGS})
+
 set_target_properties(
   resolv_wrapper
     PROPERTIES
index efb6c6dfc725986c19833dd97e98fc6a3ebb39f6..5996779f2d77fa403a33488997abe407f047bfb6 100644 (file)
@@ -11,14 +11,17 @@ set(TORTURE_LIBRARY torture)
 
 # A simple DNS server for testing
 add_executable(dns_srv dns_srv.c)
+target_compile_options(dns_srv PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
 target_link_libraries(dns_srv ${RWRAP_REQUIRED_LIBRARIES})
 
 add_executable(test_real_res_query test_real_res_query.c)
+target_compile_options(test_real_res_query PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
 target_link_libraries(test_real_res_query ${RWRAP_REQUIRED_LIBRARIES} ${CMOCKA_LIBRARY})
 
 configure_file(fake_hosts.in ${CMAKE_CURRENT_BINARY_DIR}/fake_hosts @ONLY)
 
 add_library(${TORTURE_LIBRARY} STATIC torture.c)
+target_compile_options(${TORTURE_LIBRARY} PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
 target_link_libraries(${TORTURE_LIBRARY}
     ${CMOCKA_LIBRARY}
     ${SWRAP_REQUIRED_LIBRARIES})