diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt --- a/libc/CMakeLists.txt +++ b/libc/CMakeLists.txt @@ -19,6 +19,28 @@ set(LIBC_TARGET_MACHINE ${CMAKE_SYSTEM_PROCESSOR}) +option(LLVM_ENABLE_LINTING "Enables linting of libc source files" ON) +if(LLVM_ENABLE_LINTING) + if("clang-tools-extra" IN_LIST LLVM_ENABLE_PROJECTS + AND "clang" IN_LIST LLVM_ENABLE_PROJECTS) + add_custom_target(lint-libc) + else() + message(FATAL_ERROR " + 'clang' and 'clang-tools-extra' are required in LLVM_ENABLE_PROJECTS to + lint llvm-libc. The linting step performs important checks to help prevent + the introduction of subtle bugs, but it may increase build times. + + To disable linting set LLVM_ENABLE_LINTING to OFF + (pass -DLLVM_ENABLE_LINTING=OFF to cmake).") + endif() +else() + message(WARNING " + Linting for libc is currently disabled. + + This is not recommended, to enable set LLVM_ENABLE_LINTING to ON + (pass -DLLVM_ENABLE_LINTING=ON to cmake).") +endif() + include(CMakeParseArguments) include(LLVMLibCRules) include(LLVMLibCCheckCpuFeatures) diff --git a/libc/cmake/modules/LLVMLibCRules.cmake b/libc/cmake/modules/LLVMLibCRules.cmake --- a/libc/cmake/modules/LLVMLibCRules.cmake +++ b/libc/cmake/modules/LLVMLibCRules.cmake @@ -347,6 +347,41 @@ "OBJECT_FILES" "${all_objects}" "OBJECT_FILES_RAW" "${all_objects_raw}" ) + + if(LLVM_ENABLE_LINTING) + set(lint_timestamp "${CMAKE_CURRENT_BINARY_DIR}/.${target_name}.__lint_timestamp__") + + add_custom_command( + OUTPUT ${lint_timestamp} + # --quiet is used to surpress warning statistics from clang-tidy like: + # Suppressed X warnings (X in non-user code). + # There seems to be a bug in clang-tidy where by even with --quiet some + # messages from clang's own diagnostics engine leak through: + # X warnings generated. + # Until this is fixed upstream, we use -fno-caret-diagnostics to surpress + # these. + COMMAND $ "--extra-arg=-fno-caret-diagnostics" --quiet + # Path to directory containing compile_commands.json + -p ${PROJECT_BINARY_DIR} + ${ADD_ENTRYPOINT_OBJ_SRCS} + # We have two options for running commands, add_custom_command and + # add_custom_target. We don't want to run the linter unless source files + # have changed. add_custom_target explicitly runs everytime therefore we + # use add_custom_command. This function requires an output file and since + # linting doesn't produce a file, we create a dummy file using a + # crossplatform touch. + COMMAND "${CMAKE_COMMAND}" -E touch ${lint_timestamp} + COMMENT "Linting... ${target_name}" + DEPENDS ${clang-tidy} ${objects_target_name} ${ADD_ENTRYPOINT_OBJ_SRCS} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + ) + + add_custom_target(${fq_target_name}.__lint__ + DEPENDS ${lint_timestamp}) + add_dependencies(lint-libc ${fq_target_name}.__lint__) + add_dependencies(${fq_target_name} ${fq_target_name}.__lint__) + endif() + endfunction(add_entrypoint_object) # A rule to build a library from a collection of entrypoint objects. @@ -465,7 +500,7 @@ if(NOT LLVM_INCLUDE_TESTS) return() endif() - + cmake_parse_arguments( "LIBC_UNITTEST" "" # No optional arguments