Skip to content

Commit

Permalink
[#558] Add clang-format tool to check C++ runtime sources
Browse files Browse the repository at this point in the history
  • Loading branch information
mikir committed Jan 3, 2024
1 parent 0254b80 commit b746ef0
Show file tree
Hide file tree
Showing 8 changed files with 255 additions and 53 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/build_linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ jobs:
run: |
if [ -f "`which clang-tidy-14`" ] ; then
export CLANG_TIDY_BIN=clang-tidy-14
export CLANG_FORMAT_BIN=clang-format-14
fi
# gcovr works only for default gcc version
if [[ `gcc --version` == *" ${{matrix.gcc-version}}."* ]] ; then
Expand Down Expand Up @@ -154,6 +155,7 @@ jobs:
run: |
if [ -f "`which clang-tidy-14`" ] ; then
export CLANG_TIDY_BIN=clang-tidy-14
export CLANG_FORMAT_BIN=clang-format-14
fi
scripts/test.sh cpp-linux32-gcc cpp-linux64-gcc cpp-linux64-clang
env:
Expand Down
30 changes: 30 additions & 0 deletions cmake/clang_format_tool.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Script called from clang_format_utils.cmake to run clang-format and preserve it's output.
#
# Expected definitions:
# CLANG_FORMAT_BIN Clang format binary.
# SOURCE Source to check by clang-format.
# CONFIG_FILE Path to the clang-format config file.
# WERROR Ends with an error in case of any format violation.
cmake_minimum_required(VERSION 3.6.0)

foreach (ARG CLANG_FORMAT_BIN SOURCE CONFIG_FILE WERROR)
if (NOT DEFINED ${ARG})
message(FATAL_ERROR "Argument '${ARG}' not defined!")
endif ()
endforeach ()

if (WERROR)
set(WERROR_OPTION --Werror)
endif ()

execute_process(
COMMAND ${CLANG_FORMAT_BIN} --style=file:${CONFIG_FILE} --dry-run ${WERROR_OPTION} ${SOURCE}
RESULT_VARIABLE CLANG_FORMAT_RESULT
)

if (NOT ${CLANG_FORMAT_RESULT} EQUAL 0)
message(NOTICE "Command hints to reformat source using clang-format tool:")
message(NOTICE " git clang-format")
message(NOTICE " clang-format --style=file -i ${SOURCE}")
message(FATAL_ERROR "Clang Format Tool failed!")
endif ()
65 changes: 65 additions & 0 deletions cmake/clang_format_utils.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# A function to create clang-format target.
#
# Usage clang_format_add_custom_target
# DEPENDS List of dependencies.
# SOURCES List of source directories for clang-format.
# SOURCES_GLOBS List of sources globbing expressions which will be searched using GLOG_RECURSE.
# CONFIG_FILE Path to .clang-format config file.
# WERROR Ends with an error in case of any format violation. Default is ON.
function(clang_format_add_custom_target CLANG_FORMAT_TARGET)
if (CLANG_FORMAT_BIN)
cmake_parse_arguments(CLANG_FORMAT
""
"CONFIG_FILE;WERROR"
"DEPENDS;SOURCES;SOURCES_GLOBS"
${ARGN}
)

# check required arguments
foreach (ARG TARGET CONFIG_FILE)
if (NOT DEFINED CLANG_FORMAT_${ARG})
message(FATAL_ERROR "No value defined for required argument ${ARG}!")
endif ()
endforeach ()

if (NOT DEFINED CLANG_FORMAT_SOURCES AND NOT DEFINED CLANG_FORMAT_SOURCES_GLOBS)
message(FATAL_ERROR "No value defined neither for SOURCES nor SOURCES_GLOBS!")
endif ()

# process optional arguments
if (NOT DEFINED CLANG_FORMAT_WERROR)
set(CLANG_FORMAT_WERROR ON)
endif ()

# process sources
list(APPEND CLANG_FORMAT_SOURCES_LIST ${CLANG_FORMAT_SOURCES})
foreach (SOURCE_EXPRESSION ${CLANG_FORMAT_SOURCES_GLOBS})
file(GLOB_RECURSE MATCHING_SOURCES "${SOURCE_EXPRESSION}")
list(APPEND CLANG_FORMAT_SOURCES_LIST ${MATCHING_SOURCES})
endforeach ()
list(REMOVE_DUPLICATES CLANG_FORMAT_SOURCES_LIST)

# run clang format for each source
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/clang-format")
set(INDEX 0)
foreach (SOURCE_FILE ${CLANG_FORMAT_SOURCES_LIST})
get_filename_component(SOURCE_FILE_NAME ${SOURCE_FILE} NAME)
set(CLANG_FORMAT_FILE_STAMP "clang-format/${INDEX}_${SOURCE_FILE_NAME}")
add_custom_command(
OUTPUT "${CLANG_FORMAT_FILE_STAMP}"
COMMAND "${CMAKE_COMMAND}"
-DCLANG_FORMAT_BIN="${CLANG_FORMAT_BIN}"
-DSOURCE="${SOURCE_FILE}"
-DCONFIG_FILE="${CLANG_FORMAT_CONFIG_FILE}"
-DWERROR="${CLANG_FORMAT_WERROR}"
-P ${CMAKE_MODULE_PATH}/clang_format_tool.cmake
COMMAND "${CMAKE_COMMAND}" -E touch "${CLANG_FORMAT_FILE_STAMP}"
DEPENDS ${SOURCE_FILE}
COMMENT "Running clang-format on ${SOURCE_FILE}")
list(APPEND CLANG_FORMAT_FILE_STAMPS "${CLANG_FORMAT_FILE_STAMP}")
math(EXPR INDEX "${INDEX} + 1")
endforeach ()
add_custom_target(${CLANG_FORMAT_TARGET} ALL
DEPENDS ${CLANG_FORMAT_DEPENDS} ${CLANG_FORMAT_FILE_STAMPS})
endif ()
endfunction()
91 changes: 46 additions & 45 deletions cmake/clang_tidy_utils.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -21,57 +21,57 @@
# Fires an error in case of unused suppressions. Default is OFF.
# Note that only implementation files ('*.cpp') are used as sources.
function(clang_tidy_add_custom_target CLANG_TIDY_TARGET)
cmake_parse_arguments(CLANG_TIDY
""
"BUILD_PATH;CONFIG_FILE;HEADER_FILTER;OUTPUT_FILE;SUPPRESSIONS_FILE;WERROR;WERROR_UNUSED_SUPPRESSIONS"
"DEPENDS;SOURCES;SOURCES_GLOBS"
${ARGN}
)
if (CLANG_TIDY_BIN)
cmake_parse_arguments(CLANG_TIDY
""
"BUILD_PATH;CONFIG_FILE;HEADER_FILTER;OUTPUT_FILE;SUPPRESSIONS_FILE;WERROR;WERROR_UNUSED_SUPPRESSIONS"
"DEPENDS;SOURCES;SOURCES_GLOBS"
${ARGN}
)

# check required arguments
foreach (ARG TARGET BUILD_PATH CONFIG_FILE)
if (NOT DEFINED CLANG_TIDY_${ARG})
message(FATAL_ERROR "No value defined for required argument ${ARG}!")
endif ()
endforeach ()
# check required arguments
foreach (ARG TARGET BUILD_PATH CONFIG_FILE)
if (NOT DEFINED CLANG_TIDY_${ARG})
message(FATAL_ERROR "No value defined for required argument ${ARG}!")
endif ()
endforeach ()

if (NOT DEFINED CLANG_TIDY_SOURCES AND NOT DEFINED CLANG_TIDY_SOURCES_GLOBS)
message(FATAL_ERROR "No value defined neither for SOURCES nor SOURCES_GLOBS!")
endif ()
if (NOT DEFINED CLANG_TIDY_SOURCES AND NOT DEFINED CLANG_TIDY_SOURCES_GLOBS)
message(FATAL_ERROR "No value defined neither for SOURCES nor SOURCES_GLOBS!")
endif ()

# process optional arguments
if (NOT DEFINED CLANG_TIDY_HEADER_FILTER)
set(CLANG_TIDY_HEADER_FILTER ".*")
endif ()
# process optional arguments
if (NOT DEFINED CLANG_TIDY_HEADER_FILTER)
set(CLANG_TIDY_HEADER_FILTER ".*")
endif ()

if (NOT DEFINED CLANG_TIDY_OUTPUT_FILE)
set(CLANG_TIDY_OUTPUT_FILE "clang-tidy-report.txt")
endif ()
if (NOT DEFINED CLANG_TIDY_OUTPUT_FILE)
set(CLANG_TIDY_OUTPUT_FILE "clang-tidy-report.txt")
endif ()

if (NOT DEFINED CLANG_TIDY_SUPPRESSIONS_FILE)
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/ClangTidySuppressions.txt")
set(CLANG_TIDY_SUPPRESSIONS_FILE "${CMAKE_CURRENT_SOURCE_DIR}/ClangTidySuppressions.txt")
if (NOT DEFINED CLANG_TIDY_SUPPRESSIONS_FILE)
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/ClangTidySuppressions.txt")
set(CLANG_TIDY_SUPPRESSIONS_FILE "${CMAKE_CURRENT_SOURCE_DIR}/ClangTidySuppressions.txt")
endif ()
endif ()
endif ()

if (NOT DEFINED CLANG_TIDY_WERROR)
set(CLANG_TIDY_WERROR ON)
endif ()
if (NOT DEFINED CLANG_TIDY_WERROR)
set(CLANG_TIDY_WERROR ON)
endif ()

if (NOT DEFINED CLANG_TIDY_WERROR_UNUSED_SUPPRESSIONS)
set(CLANG_TIDY_WERROR_UNUSED_SUPPRESSIONS OFF)
endif ()
if (NOT DEFINED CLANG_TIDY_WERROR_UNUSED_SUPPRESSIONS)
set(CLANG_TIDY_WERROR_UNUSED_SUPPRESSIONS OFF)
endif ()

# process sources
list(APPEND CLANG_TIDY_SOURCES_LIST ${CLANG_TIDY_SOURCES})
foreach (SOURCE_EXPRESSION ${CLANG_TIDY_SOURCES_GLOBS})
file(GLOB_RECURSE MATCHING_SOURCES "${SOURCE_EXPRESSION}")
list(APPEND CLANG_TIDY_SOURCES_LIST ${MATCHING_SOURCES})
endforeach ()
list(REMOVE_DUPLICATES CLANG_TIDY_SOURCES_LIST)
list(FILTER CLANG_TIDY_SOURCES_LIST INCLUDE REGEX ".*\.c(pp)?$")
# process sources
list(APPEND CLANG_TIDY_SOURCES_LIST ${CLANG_TIDY_SOURCES})
foreach (SOURCE_EXPRESSION ${CLANG_TIDY_SOURCES_GLOBS})
file(GLOB_RECURSE MATCHING_SOURCES "${SOURCE_EXPRESSION}")
list(APPEND CLANG_TIDY_SOURCES_LIST ${MATCHING_SOURCES})
endforeach ()
list(REMOVE_DUPLICATES CLANG_TIDY_SOURCES_LIST)
list(FILTER CLANG_TIDY_SOURCES_LIST INCLUDE REGEX ".*\.c(pp)?$")

if (CLANG_TIDY_BIN)
set(CLANG_TIDY_TIMESTAMP_FILE "clang-tidy/${CLANG_TIDY_TARGET}-timestamp")
add_custom_command(
OUTPUT "${CLANG_TIDY_TIMESTAMP_FILE}" "${CLANG_TIDY_OUTPUT_FILE}"
Expand All @@ -85,7 +85,8 @@ function(clang_tidy_add_custom_target CLANG_TIDY_TARGET)

set(INDEX 0)
foreach (SOURCE_FILE ${CLANG_TIDY_SOURCES_LIST})
set(CLANG_TIDY_FILE_STAMP "clang-tidy/${CLANG_TIDY_TARGET}-${INDEX}")
get_filename_component(SOURCE_FILE_NAME ${SOURCE_FILE} NAME)
set(CLANG_TIDY_FILE_STAMP "clang-tidy/${INDEX}_${SOURCE_FILE_NAME}")
add_custom_command(
OUTPUT "${CLANG_TIDY_FILE_STAMP}"
COMMAND "${CMAKE_COMMAND}"
Expand All @@ -97,8 +98,8 @@ function(clang_tidy_add_custom_target CLANG_TIDY_TARGET)
-DOUTPUT_FILE="${CLANG_TIDY_OUTPUT_FILE}"
-P ${CMAKE_MODULE_PATH}/clang_tidy_tool.cmake
COMMAND "${CMAKE_COMMAND}" -E touch "${CLANG_TIDY_FILE_STAMP}"
DEPENDS "${CLANG_TIDY_TIMESTAMP_FILE}"
COMMENT "Running clang-tidy on ${SOURCE_FILE}(${INDEX})"
DEPENDS "${SOURCE_FILE}" "${CLANG_TIDY_TIMESTAMP_FILE}"
COMMENT "Running clang-tidy on ${SOURCE_FILE}"
)
list(APPEND CLANG_TIDY_FILE_STAMPS "${CLANG_TIDY_FILE_STAMP}")
math(EXPR INDEX "${INDEX} + 1")
Expand All @@ -115,7 +116,7 @@ function(clang_tidy_add_custom_target CLANG_TIDY_TARGET)
-P ${CMAKE_MODULE_PATH}/clang_tidy_check.cmake
COMMAND "${CMAKE_COMMAND}" -E touch "${CLANG_TIDY_CHECK_FILE}"
DEPENDS "${CLANG_TIDY_FILE_STAMPS}" "${CLANG_TIDY_SUPPRESSIONS_FILE}"
COMMENT "Checking clang-tidy warnigns in ${CLANG_TIDY_TARGET}"
COMMENT "Checking clang-tidy warnings in ${CLANG_TIDY_TARGET}"
)

add_custom_target(${CLANG_TIDY_TARGET} ALL DEPENDS ${CLANG_TIDY_CHECK_FILE})
Expand Down
76 changes: 76 additions & 0 deletions compiler/extensions/cpp/runtime/.clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
BasedOnStyle: Microsoft
---
Language: Cpp

# Access modifier should be aligned to braces.
AccessModifierOffset: -4

# Always break before braces.
BreakBeforeBraces: Allman

# Align pointer to the left (to the type).
PointerAlignment: Left

# The column limit for Zserio.
ColumnLimit: 112

# Always break after template declaration.
AlwaysBreakTemplateDeclarations: Yes

# Indent width for line continuations.
ContinuationIndentWidth: 8

# Settings for constructor initializers.
BreakConstructorInitializers: AfterColon
ConstructorInitializerIndentWidth: 8
PackConstructorInitializers: Never

# Don’t align, instead use ContinuationIndentWidth.
AlignAfterOpenBracket: DontAlign

# Don't align trailing comments.
AlignTrailingComments: false

# Don't align operands.
AlignOperands: DontAlign

# Indent preprocessor directives.
IndentPPDirectives: BeforeHash

# Improve indentation of chained method calls.
PenaltyIndentedWhitespace: 10

# Allow brace wrapping for unions .
# Allow empty braces on the same line for functions, records and namespaces.
BreakBeforeBraces: Custom
BraceWrapping:
AfterUnion: true
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false

# Regroup and sort includes.
IncludeBlocks: Regroup
IncludeCategories:
# System headers in <>.
- Regex: '<.*>'
Priority: -2
CaseSensitive: false
# Headers in "" in current directory.
- Regex: '"[^/\]+"'
Priority: 0
CaseSensitive: false
# Headers in "" in different directory.
- Regex: '".*"'
Priority: -1
CaseSensitive: false
# All other headers.
- Regex: '.*'
Priority: 1
CaseSensitive: false

# Indent case blocks.
IndentCaseBlocks: true
...

13 changes: 13 additions & 0 deletions compiler/extensions/cpp/runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ enable_testing()
set(CPPCHECK_HOME "" CACHE PATH "Home directory of cppcheck tool. If empty, cppcheck tool is not called.")
set(SANITIZERS_ENABLED OFF CACHE BOOL "Whether the compiler sanitizers are enabled.")
set(CLANG_TIDY_BIN "" CACHE STRING "Name of clang-tidy binary. If empty, clang-tidy tool is not called.")
set(CLANG_FORMAT_BIN "" CACHE STRING "Name of clang-format binary. If empty, clang-format tool is not called.")

set(ZSERIO_PROJECT_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../../..")
set(CMAKE_MODULE_PATH "${ZSERIO_PROJECT_ROOT}/cmake")
Expand Down Expand Up @@ -91,6 +92,18 @@ clang_tidy_add_custom_target(ZserioCppRuntime-clang-tidy
SUPPRESSIONS_FILE "${CMAKE_CURRENT_SOURCE_DIR}/ClangTidySuppressions.txt"
WERROR_UNUSED_SUPPRESSIONS ON)

# add clang-format custom target
include(clang_format_utils)
clang_format_add_custom_target(ZserioCppRuntime-clang-format
DEPENDS ZserioCppRuntime ZserioCppRuntimeTest
SOURCES_GLOBS
"${CMAKE_CURRENT_SOURCE_DIR}/src/zserio/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/zserio/*.h"
"${CMAKE_CURRENT_SOURCE_DIR}/test/zserio/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/test/zserio/*.h"
CONFIG_FILE "${CMAKE_CURRENT_SOURCE_DIR}/.clang-format"
WERROR ON)

# add cppcheck custom command
include(cppcheck_utils)
cppcheck_add_custom_command(TARGET ZserioCppRuntime
Expand Down
16 changes: 8 additions & 8 deletions compiler/extensions/cpp/runtime/ClangTidySuppressions.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ cppcoreguidelines-pro-bounds-constant-array-index:src/zserio/StringConvertUtil.h
cppcoreguidelines-pro-bounds-constant-array-index:src/zserio/StringConvertUtil.h:43
cppcoreguidelines-pro-bounds-constant-array-index:src/zserio/StringConvertUtil.h:53
cppcoreguidelines-pro-bounds-constant-array-index:src/zserio/StringConvertUtil.h:54
cppcoreguidelines-pro-bounds-constant-array-index:src/zserio/BitStreamReader.cpp:294
cppcoreguidelines-pro-bounds-constant-array-index:src/zserio/BitStreamReader.cpp:306
cppcoreguidelines-pro-bounds-constant-array-index:src/zserio/BitStreamReader.cpp:295
cppcoreguidelines-pro-bounds-constant-array-index:src/zserio/BitStreamReader.cpp:307
cppcoreguidelines-pro-bounds-constant-array-index:src/zserio/BitStreamWriter.cpp:356
cppcoreguidelines-pro-bounds-constant-array-index:src/zserio/BitStreamWriter.cpp:367
cppcoreguidelines-pro-bounds-constant-array-index:src/zserio/BitStreamWriter.cpp:378
Expand Down Expand Up @@ -92,6 +92,12 @@ cppcoreguidelines-pro-type-reinterpret-cast:src/zserio/ValidationSqliteUtil.h:10
fuchsia-multiple-inheritance:src/zserio/Reflectable.h:1999

# This is necessary for implementation of low level implementation to mimic standard C++17 abstractions.
google-explicit-constructor:src/zserio/OptionalHolder.h:222
google-explicit-constructor:src/zserio/OptionalHolder.h:232
google-explicit-constructor:src/zserio/OptionalHolder.h:242
google-explicit-constructor:src/zserio/OptionalHolder.h:669
google-explicit-constructor:src/zserio/OptionalHolder.h:677
google-explicit-constructor:src/zserio/OptionalHolder.h:688
google-explicit-constructor:src/zserio/pmr/PolymorphicAllocator.h:47
google-explicit-constructor:src/zserio/pmr/PolymorphicAllocator.h:72
google-explicit-constructor:src/zserio/Span.h:112
Expand All @@ -104,12 +110,6 @@ google-explicit-constructor:src/zserio/StringView.h:54
google-explicit-constructor:src/zserio/StringView.h:76
google-explicit-constructor:src/zserio/UniquePtr.h:57
google-explicit-constructor:src/zserio/UniquePtr.h:68
google-explicit-constructor:src/zserio/OptionalHolder.h:222
google-explicit-constructor:src/zserio/OptionalHolder.h:232
google-explicit-constructor:src/zserio/OptionalHolder.h:242
google-explicit-constructor:src/zserio/OptionalHolder.h:669
google-explicit-constructor:src/zserio/OptionalHolder.h:677
google-explicit-constructor:src/zserio/OptionalHolder.h:688

# This is necessary because of implementation. Zserio naturally supports recursion.
misc-no-recursion:src/zserio/JsonParser.h:154
Expand Down
Loading

0 comments on commit b746ef0

Please sign in to comment.