From: Joel Rosdahl Date: Sat, 5 Dec 2020 18:17:32 +0000 (+0100) Subject: Reintroduce dev mode and disable problematic build flags in user mode X-Git-Tag: v4.2~81 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=533393e6ea0e31df161ab0eddccffc26b97c50fa;p=thirdparty%2Fccache.git Reintroduce dev mode and disable problematic build flags in user mode In version 3.x, ccache was in “user mode” when building from release archive sources and “dev mode” otherwise. In “dev mode”, additional compiler flags like “-Wextra -Wpedantic -Werror” were added, but they were not present in “user mode” in order not to break end users’ builds. This behavior was partially lost in the conversion to CMake. This commit tries to imitate the previous behavior by introducing a CCACHE_DEV_MODE CMake variable and only enable potentially problematic compiler flags when it’s set to ON. Related to #730. --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 39126a93b..b4a0ddcb9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,15 @@ endif() # # Settings # +include(CcacheVersion) + +if("${CCACHE_VERSION_ORIGIN}" STREQUAL git OR DEFINED ENV{CI}) + set(CCACHE_DEV_MODE ON) +else() + set(CCACHE_DEV_MODE OFF) +endif() +message(STATUS "Ccache dev mode: ${CCACHE_DEV_MODE}") + include(StandardSettings) include(StandardWarnings) include(CIBuildType) diff --git a/ci/build-and-verify-source-package b/ci/build-and-verify-source-package index 5a212c2f4..d74bc152c 100755 --- a/ci/build-and-verify-source-package +++ b/ci/build-and-verify-source-package @@ -5,6 +5,9 @@ set -eu +# Unset CI variable to trigger ccache user build mode. +unset CI + # Ninja builds with relative paths so that ccache can be used to cache the build # without resorting to setting base_dir. export CMAKE_GENERATOR=Ninja diff --git a/cmake/CcachePackConfig.cmake b/cmake/CcachePackConfig.cmake index daaca306d..a35949da5 100644 --- a/cmake/CcachePackConfig.cmake +++ b/cmake/CcachePackConfig.cmake @@ -6,7 +6,7 @@ if(${CMAKE_VERSION} VERSION_LESS "3.9") endif() # From CcacheVersion.cmake. -set(CPACK_PACKAGE_VERSION ${VERSION}) +set(CPACK_PACKAGE_VERSION ${CCACHE_VERSION}) set(CPACK_VERBATIM_VARIABLES ON) @@ -18,7 +18,7 @@ endif() set( CPACK_PACKAGE_FILE_NAME - "ccache-${VERSION}-${CMAKE_HOST_SYSTEM_NAME}-${CMAKE_HOST_SYSTEM_PROCESSOR}" + "ccache-${CCACHE_VERSION}-${CMAKE_HOST_SYSTEM_NAME}-${CMAKE_HOST_SYSTEM_PROCESSOR}" ) include(CPack) diff --git a/cmake/CcacheVersion.cmake b/cmake/CcacheVersion.cmake index e1cf88cab..25fd71620 100644 --- a/cmake/CcacheVersion.cmake +++ b/cmake/CcacheVersion.cmake @@ -1,3 +1,8 @@ +# This script sets two variables: +# +# - CCACHE_VERSION (version string) +# - CCACHE_VERSION_ORIGIN (archive or git) +# # There are three main scenarios: # # 1. Building from a source code archive generated by "git archive", e.g. the @@ -13,25 +18,32 @@ # 3. Building from a Git repository. In this case the version will be a proper # version if building a tagged commit, otherwise "branch.hash(+dirty)". In # case Git is not available, the version will be "unknown". +# +# CCACHE_VERSION_ORIGIN is set to "archive" in scenario 1 and "git" in scenario +# 3. set(version_info "$Format:%H %D$") if(version_info MATCHES "^([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f])[0-9a-f]* (.*)") # Scenario 1. + set(CCACHE_VERSION_ORIGIN archive) + set(hash "${CMAKE_MATCH_1}") set(ref_names "${CMAKE_MATCH_2}") if(ref_names MATCHES "tag: v([^,]+)") # Tagged commit. - set(VERSION "${CMAKE_MATCH_1}") + set(CCACHE_VERSION "${CMAKE_MATCH_1}") else() # Untagged commit. - set(VERSION "${hash}") + set(CCACHE_VERSION "${hash}") endif() elseif(EXISTS "${CMAKE_SOURCE_DIR}/.git") # Scenario 3. + set(CCACHE_VERSION_ORIGIN git) + find_package(Git QUIET) if(NOT GIT_FOUND) - set(VERSION "unknown") + set(CCACHE_VERSION "unknown") message(WARNING "Could not find git") else() macro(git) @@ -43,9 +55,9 @@ elseif(EXISTS "${CMAKE_SOURCE_DIR}/.git") git(describe --abbrev=8 --dirty) if(git_stdout MATCHES "^v([^-]+)(-dirty)?$") - set(VERSION "${CMAKE_MATCH_1}") + set(CCACHE_VERSION "${CMAKE_MATCH_1}") if(NOT "${CMAKE_MATCH_2}" STREQUAL "") - set(VERSION "${VERSION}+dirty") + set(CCACHE_VERSION "${CCACHE_VERSION}+dirty") endif() elseif(git_stdout MATCHES "^v[^-]+-[0-9]+-g([0-9a-f]+)(-dirty)?$") set(hash "${CMAKE_MATCH_1}") @@ -55,12 +67,14 @@ elseif(EXISTS "${CMAKE_SOURCE_DIR}/.git") git(rev-parse --abbrev-ref HEAD) set(branch "${git_stdout}") - set(VERSION "${branch}.${hash}${dirty}") + set(CCACHE_VERSION "${branch}.${hash}${dirty}") endif() # else: fail below endif() endif() -if(VERSION STREQUAL "") +if(CCACHE_VERSION STREQUAL "") # Scenario 2 or unexpected error. message(SEND_ERROR "Cannot determine Ccache version") endif() + +message(STATUS "Ccache version: ${CCACHE_VERSION}") diff --git a/cmake/DefaultBuildType.cmake b/cmake/DefaultBuildType.cmake index 87b764745..630ecfb8c 100644 --- a/cmake/DefaultBuildType.cmake +++ b/cmake/DefaultBuildType.cmake @@ -6,7 +6,7 @@ endif() # Default to Release for end user builds (from source archive) and Debug for # development builds (in a Git repository). -if(EXISTS "${CMAKE_SOURCE_DIR}/.git") +if(CCACHE_DEV_MODE) set( CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build." FORCE) diff --git a/cmake/DevModeWarnings.cmake b/cmake/DevModeWarnings.cmake new file mode 100644 index 000000000..1e3f22368 --- /dev/null +++ b/cmake/DevModeWarnings.cmake @@ -0,0 +1,158 @@ +include(CheckCXXCompilerFlag) + +# check_cxx_compiler_flag caches the result, so a unique variable name is +# required for every flag to be checked. +# +# Parameters: +# +# * flag [in], e.g. FLAG +# * var_name_of_var_name [in], e.g. "TEMP". This is the variable that "HAS_FLAG" +# will be written to. +function(generate_unique_has_flag_var_name flag var_name_of_var_name) + string(REGEX REPLACE "[=-]" "_" var_name "${flag}") + string(TOUPPER "${var_name}" var_name) + set(${var_name_of_var_name} "HAS_${var_name}" PARENT_SCOPE) +endfunction() + +macro(add_compile_flag_if_supported_ex varname flag alternative_flag) + # has_flag will contain "HAS_$flag" so each flag gets a unique HAS variable. + generate_unique_has_flag_var_name("${flag}" "has_flag") + + # Instead of passing "has_flag" this passes the content of has_flag. + check_cxx_compiler_flag("${flag}" "${has_flag}") + + if(${${has_flag}}) + list(APPEND "${varname}" "${flag}") + elseif("${alternative_flag}") + add_compile_flag_if_supported_ex("${varname}" ${alternative_flag} "") + endif() +endmacro() + +macro(add_compile_flag_if_supported varname flag) + add_compile_flag_if_supported_ex("${varname}" "${flag}" "") +endmacro() + +set( + _clang_gcc_warnings + -Wextra + -Wnon-virtual-dtor + -Wcast-align + -Wunused + -Woverloaded-virtual + -Wpedantic + + # Candidates for enabling in the future: + # -Wshadow + # -Wold-style-cast + # -Wconversion + # -Wsign-conversion + # -Wnull-dereference + # -Wformat=2 +) + +# Tested separately as this is not supported by Clang 3.4. +add_compile_flag_if_supported(_clang_gcc_warnings "-Wdouble-promotion") + +if(WARNINGS_AS_ERRORS) + list(APPEND _clang_gcc_warnings -Werror) +endif() + +if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + list(APPEND CCACHE_COMPILER_WARNINGS ${_clang_gcc_warnings}) + + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.0) + list( + APPEND + CCACHE_COMPILER_WARNINGS + -Qunused-arguments + -Wno-error=unreachable-code + ) + endif() + + list( + APPEND + CCACHE_COMPILER_WARNINGS + -Weverything + -Wno-c++98-compat + -Wno-c++98-compat-pedantic + -Wno-constexpr-not-const + -Wno-conversion + -Wno-disabled-macro-expansion + -Wno-documentation-unknown-command + -Wno-exit-time-destructors + -Wno-format-nonliteral + -Wno-global-constructors + -Wno-implicit-fallthrough + -Wno-old-style-cast + -Wno-padded + -Wno-shadow # Warnings in fmtlib + -Wno-shorten-64-to-32 + -Wno-sign-conversion + -Wno-signed-enum-bitfield # Warnings in fmtlib + -Wno-weak-vtables + ) + + # If compiler supports -Wshadow-field-in-constructor, disable only that. + # Otherwise disable shadow. + add_compile_flag_if_supported_ex( + CCACHE_COMPILER_WARNINGS "-Wno-shadow-field-in-constructor" "-Wno-shadow") + + # Disable C++20 compatibility for now. + add_compile_flag_if_supported(CCACHE_COMPILER_WARNINGS "-Wno-c++2a-compat") + + # If compiler supports these warnings they have to be disabled for now. + add_compile_flag_if_supported( + CCACHE_COMPILER_WARNINGS "-Wno-zero-as-null-pointer-constant") + add_compile_flag_if_supported( + CCACHE_COMPILER_WARNINGS "-Wno-undefined-func-template") + add_compile_flag_if_supported( + CCACHE_COMPILER_WARNINGS "-Wno-return-std-move-in-c++11") +elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + list( + APPEND + CCACHE_COMPILER_WARNINGS + ${_clang_gcc_warnings} + + # Warn about logical operations being used where bitwise were probably + # wanted. + -Wlogical-op + + # Candidates for enabling in the future: + # -Wduplicated-cond + # -Wduplicated-branches + # -Wuseless-cast + ) + + # TODO: Exact version or reason unknown, discovered in Ubuntu 14 Docker test + # with GCC 4.8.4 + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8.5) + add_compile_flag_if_supported( + CCACHE_COMPILER_WARNINGS "-Wno-missing-field-initializers") + add_compile_flag_if_supported( + CCACHE_COMPILER_WARNINGS "-Wno-unused-variable") + endif() +elseif(MSVC) + # Remove any warning level flags added by CMake. + string(REGEX REPLACE "/W[0-4]" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + string(REGEX REPLACE "/W[0-4]" "" CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS}") + string(REGEX REPLACE "/W[0-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + + if(WARNINGS_AS_ERRORS) + list(APPEND CCACHE_COMPILER_WARNINGS /WE) + endif() + + list( + APPEND + CCACHE_COMPILER_WARNINGS + /W4 + # Ignore bad macro in winbase.h triggered by /Zc:preprocessor: + /wd5105 + # Conversion warnings: + /wd4244 + /wd4267 + # Assignment in conditional: + /wd4706 + # Non-underscore-prefixed POSIX functions: + /wd4996 + ) +endif() diff --git a/cmake/GenerateVersionFile.cmake b/cmake/GenerateVersionFile.cmake index 1517d440b..7b2ad0cd4 100644 --- a/cmake/GenerateVersionFile.cmake +++ b/cmake/GenerateVersionFile.cmake @@ -1,6 +1,4 @@ -include(CcacheVersion) configure_file( ${CMAKE_SOURCE_DIR}/cmake/version.cpp.in ${CMAKE_BINARY_DIR}/src/version.cpp @ONLY) -message(STATUS "Ccache version: ${VERSION}") diff --git a/cmake/StandardWarnings.cmake b/cmake/StandardWarnings.cmake index 350773767..6a0ca71b5 100644 --- a/cmake/StandardWarnings.cmake +++ b/cmake/StandardWarnings.cmake @@ -2,161 +2,21 @@ # be linked privately by all product and test code, but not by third party code. add_library(standard_warnings INTERFACE) -if(IS_DIRECTORY "${CMAKE_SOURCE_DIR}/.git" OR DEFINED ENV{"CI"}) - # Enabled by default for development builds and CI builds. +if(CCACHE_DEV_MODE) + # Enabled by default for developer builds. option(WARNINGS_AS_ERRORS "Treat compiler warnings as errors" TRUE) else() - # Disabled by default for end user builds so compilation doesn't fail with new + # Disabled by default for user builds so compilation doesn't fail with new # compilers that may emit new warnings. option(WARNINGS_AS_ERRORS "Treat compiler warnings as errors" FALSE) endif() -include(CheckCXXCompilerFlag) - -# check_cxx_compiler_flag caches the result, so a unique variable name is -# required for every flag to be checked. -# -# Parameters: -# -# * flag [in], e.g. FLAG -# * var_name_of_var_name [in], e.g. "TEMP". This is the variable that "HAS_FLAG" -# will be written to. -function(generate_unique_has_flag_var_name flag var_name_of_var_name) - string(REGEX REPLACE "[=-]" "_" var_name "${flag}") - string(TOUPPER "${var_name}" var_name) - set(${var_name_of_var_name} "HAS_${var_name}" PARENT_SCOPE) -endfunction() - -function(add_target_compile_flag_if_supported_ex target flag alternative_flag) - # has_flag will contain "HAS_$flag" so each flag gets a unique HAS variable. - generate_unique_has_flag_var_name("${flag}" "has_flag") - - # Instead of passing "has_flag" this passes the content of has_flag. - check_cxx_compiler_flag("${flag}" "${has_flag}") - - if(${${has_flag}}) - target_compile_options(${target} INTERFACE "${flag}") - elseif("${alternative_flag}") - add_target_compile_flag_if_supported_ex(${target} ${alternative_flag} "") - endif() -endfunction() - -# TODO: Is there a better way to provide an optional third argument? -macro(add_target_compile_flag_if_supported target flag) - add_target_compile_flag_if_supported_ex("${target}" "${flag}" "") -endmacro() - -set(CLANG_GCC_WARNINGS - -Wall - -Wextra - -Wnon-virtual-dtor - -Wcast-align - -Wunused - -Woverloaded-virtual - -Wpedantic - - # Candidates for enabling in the future: - # -Wshadow - # -Wold-style-cast - # -Wconversion - # -Wsign-conversion - # -Wnull-dereference - # -Wformat=2 -) -# Tested separately as this is not supported by Clang 3.4. -add_target_compile_flag_if_supported(standard_warnings "-Wdouble-promotion") - -if(WARNINGS_AS_ERRORS) - set(CLANG_GCC_WARNINGS ${CLANG_GCC_WARNINGS} -Werror) +if(NOT MSVC) + set(CCACHE_COMPILER_WARNINGS -Wall) endif() -if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.0) - set( - CLANG_GCC_WARNINGS - ${CLANG_GCC_WARNINGS} - -Qunused-arguments - -Wno-error=unreachable-code) - endif() - - target_compile_options( - standard_warnings - INTERFACE - ${CLANG_GCC_WARNINGS} - -Weverything - -Wno-c++98-compat-pedantic - -Wno-c++98-compat - -Wno-constexpr-not-const - -Wno-conversion - -Wno-disabled-macro-expansion - -Wno-documentation-unknown-command - -Wno-exit-time-destructors - -Wno-format-nonliteral - -Wno-global-constructors - -Wno-implicit-fallthrough - -Wno-padded - -Wno-shadow # Warnings in fmtlib - -Wno-shorten-64-to-32 - -Wno-sign-conversion - -Wno-signed-enum-bitfield # Warnings in fmtlib - -Wno-weak-vtables - -Wno-old-style-cast) - - # If compiler supports -Wshadow-field-in-constructor, disable only that. - # Otherwise disable shadow. - add_target_compile_flag_if_supported_ex( - standard_warnings "-Wno-shadow-field-in-constructor" "-Wno-shadow") - - # Disable C++20 compatibility for now. - add_target_compile_flag_if_supported(standard_warnings "-Wno-c++2a-compat") - - # If compiler supports these warnings they have to be disabled for now. - add_target_compile_flag_if_supported( - standard_warnings "-Wno-zero-as-null-pointer-constant") - add_target_compile_flag_if_supported( - standard_warnings "-Wno-undefined-func-template") - add_target_compile_flag_if_supported( - standard_warnings "-Wno-return-std-move-in-c++11") -elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - target_compile_options( - standard_warnings - INTERFACE ${CLANG_GCC_WARNINGS} - # Warn about logical operations being used where bitwise were probably - # wanted. - -Wlogical-op - - # Candidates for enabling in the future: - # -Wduplicated-cond - # -Wduplicated-branches - # -Wuseless-cast - ) - - # TODO: Exact version or reason unknown, discovered in Ubuntu 14 Docker test - # with GCC 4.8.4 - if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8.5) - add_target_compile_flag_if_supported( - standard_warnings "-Wno-missing-field-initializers") - add_target_compile_flag_if_supported( - standard_warnings "-Wno-unused-variable") - endif() -elseif(MSVC) - # Remove any warning level flags added by CMake. - string(REGEX REPLACE "/W[0-4]" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") - string(REGEX REPLACE "/W[0-4]" "" CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS}") - string(REGEX REPLACE "/W[0-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - - target_compile_options( - standard_warnings - INTERFACE - /W4 - # Ignore bad macro in winbase.h triggered by /Zc:preprocessor - /wd5105 - # Conversion warnings. - /wd4244 - /wd4267 - # Assignment in conditional. - /wd4706 - # Non-underscore-prefixed POSIX functions. - /wd4996 - ) +if(CCACHE_DEV_MODE) + include(DevModeWarnings) endif() + +target_compile_options(standard_warnings INTERFACE ${CCACHE_COMPILER_WARNINGS}) diff --git a/cmake/version.cpp.in b/cmake/version.cpp.in index 291f04964..3b877464c 100644 --- a/cmake/version.cpp.in +++ b/cmake/version.cpp.in @@ -1,2 +1,2 @@ extern const char CCACHE_VERSION[]; -const char CCACHE_VERSION[] = "@VERSION@"; +const char CCACHE_VERSION[] = "@CCACHE_VERSION@"; diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 8f866b881..c5ce224d9 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -15,7 +15,7 @@ else() COMMAND ${ASCIIDOC_EXE} -o "${html_file}" - -a revnumber="${VERSION}" + -a revnumber="${CCACHE_VERSION}" -a toc -b xhtml11 "${CMAKE_SOURCE_DIR}/${adoc_file}" @@ -46,7 +46,7 @@ else() COMMAND ${ASCIIDOC_EXE} -o - - -a revnumber=${VERSION} + -a revnumber=${CCACHE_VERSION} -d manpage -b docbook "${CMAKE_SOURCE_DIR}/doc/MANUAL.adoc" | perl -pe 's!\(.*?\)!\\1!g'