From c8e961014de6308bf1d41271e76e2b2fbfcd1bd0 Mon Sep 17 00:00:00 2001 From: Miki Rozloznik Date: Thu, 21 Dec 2023 14:41:12 +0100 Subject: [PATCH] Add clang-format tool to check C++ runtime sources --- .github/workflows/build_linux.yml | 2 + cmake/clang_format_tool.cmake | 30 ++++++ cmake/clang_format_utils.cmake | 65 +++++++++++++ cmake/clang_tidy_utils.cmake | 91 ++++++++++--------- compiler/extensions/cpp/runtime/.clang-format | 76 ++++++++++++++++ .../extensions/cpp/runtime/CMakeLists.txt | 13 +++ .../cpp/runtime/ClangTidySuppressions.txt | 16 ++-- scripts/common_tools.sh | 15 +++ 8 files changed, 255 insertions(+), 53 deletions(-) create mode 100644 cmake/clang_format_tool.cmake create mode 100644 cmake/clang_format_utils.cmake create mode 100644 compiler/extensions/cpp/runtime/.clang-format diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index eaa708e66..f54985fd5 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -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 @@ -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: diff --git a/cmake/clang_format_tool.cmake b/cmake/clang_format_tool.cmake new file mode 100644 index 000000000..ec5027e85 --- /dev/null +++ b/cmake/clang_format_tool.cmake @@ -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 () diff --git a/cmake/clang_format_utils.cmake b/cmake/clang_format_utils.cmake new file mode 100644 index 000000000..d98a77c89 --- /dev/null +++ b/cmake/clang_format_utils.cmake @@ -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() diff --git a/cmake/clang_tidy_utils.cmake b/cmake/clang_tidy_utils.cmake index 0dea09746..5d91b15a4 100644 --- a/cmake/clang_tidy_utils.cmake +++ b/cmake/clang_tidy_utils.cmake @@ -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}" @@ -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}" @@ -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") @@ -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}) diff --git a/compiler/extensions/cpp/runtime/.clang-format b/compiler/extensions/cpp/runtime/.clang-format new file mode 100644 index 000000000..8e2d903ce --- /dev/null +++ b/compiler/extensions/cpp/runtime/.clang-format @@ -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 +... + diff --git a/compiler/extensions/cpp/runtime/CMakeLists.txt b/compiler/extensions/cpp/runtime/CMakeLists.txt index c277e81ab..67eab905a 100644 --- a/compiler/extensions/cpp/runtime/CMakeLists.txt +++ b/compiler/extensions/cpp/runtime/CMakeLists.txt @@ -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") @@ -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 diff --git a/compiler/extensions/cpp/runtime/ClangTidySuppressions.txt b/compiler/extensions/cpp/runtime/ClangTidySuppressions.txt index 1a703d6b8..ad22b48e2 100644 --- a/compiler/extensions/cpp/runtime/ClangTidySuppressions.txt +++ b/compiler/extensions/cpp/runtime/ClangTidySuppressions.txt @@ -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 @@ -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 @@ -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 diff --git a/scripts/common_tools.sh b/scripts/common_tools.sh index 80d433dd7..62527ae6e 100644 --- a/scripts/common_tools.sh +++ b/scripts/common_tools.sh @@ -129,6 +129,13 @@ set_global_cpp_variables() return 1 fi + # clang-format binary to use for formatting check, by default is empty + CLANG_FORMAT_BIN="${CLANG_FORMAT_BIN:-""}" + if [[ (! -z "${CLANG_FORMAT_BIN}" && ! -f "`which "${CLANG_FORMAT_BIN}"`") ]] ; then + stderr_echo "Provided CLANG_FORMAT_BIN=\"${CLANG_FORMAT_BIN}\" does not exist!" + return 1 + fi + return 0 } @@ -439,6 +446,8 @@ Uses the following environment variables for building: CPPCHECK_HOME Home directory of cppcheck tool where cppcheck binary is located. If set, cppcheck will be called. Default is empty string. + CLANG_TIDY_BIN Name of clang-tidy binary. If not set, clang-tidy tool is not called. + CLANG_FORMAT_BIN Name of clang-format binary. If not set, clang-format tool is not called. GCOVR_BIN Gcovr binary to use for coverage report generation (gcc). Default is empty string. LLVM_PROFDATA_BIN llvm-profdata binary to use for coverage report generation (clang). @@ -754,6 +763,12 @@ compile_cpp_for_target() CMAKE_ARGS=("${CMAKE_ARGS[@]}" "-UCLANG_TIDY_BIN") fi + if [ ! -z "${CLANG_FORMAT_BIN}" ] ; then + CMAKE_ARGS=("${CMAKE_ARGS[@]}" "-DCLANG_FORMAT_BIN=${CLANG_FORMAT_BIN}") + else + CMAKE_ARGS=("${CMAKE_ARGS[@]}" "-UCLANG_FORMAT_BIN") + fi + # detect build type local BUILD_TYPE="Release" local BUILD_TYPE_LOWER_CASE="release"