[libc] Add cmake target for linting libc.
authorPaula Toth <paulatoth@google.com>
Fri, 17 Apr 2020 00:40:36 +0000 (17:40 -0700)
committerPaula Toth <paulatoth@google.com>
Fri, 17 Apr 2020 00:41:03 +0000 (17:41 -0700)
Summary:
This patch implements running linting on llvm-libc using build rule targets.

1) adds a new target per entrypoint for linting with the naming convention `<qualified_target_name>.__lint__` e.g `libc.src.string.strlen.__lint__`.
2) makes the build target for each entrypoint depend on the linting targets so that they run along with compilation of each entrypoint.
3) adds a lint all target named `lint-libc`.  `check-libc` now depends on this new target.
4) linting creates a lot of additional targets from clang and clang-tidy that need to be built so an opt out flag can be passed to cmake: `LLVM_LIBC_ENABLE_LINTING`.

Reviewers: sivachandra, abrachet

Reviewed By: sivachandra

Subscribers: abrachet, mgorny, tschuett, libc-commits

Tags: #libc-project

Differential Revision: https://reviews.llvm.org/D77861

libc/CMakeLists.txt
libc/cmake/modules/LLVMLibCRules.cmake

index d646653..2e3ba5f 100644 (file)
@@ -19,6 +19,28 @@ string(TOLOWER ${LIBC_TARGET_OS} LIBC_TARGET_OS)
 
 set(LIBC_TARGET_MACHINE ${CMAKE_SYSTEM_PROCESSOR})
 
+option(LLVM_LIBC_ENABLE_LINTING "Enables linting of libc source files" ON)
+if(LLVM_LIBC_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_LIBC_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_LIBC_ENABLE_LINTING to OFF
+      (pass -DLLVM_LIBC_ENABLE_LINTING=OFF to cmake).")
+  endif()
+else()
+  message(WARNING "
+    Linting for libc is currently disabled.
+
+    This is not recommended, to enable set LLVM_LIBC_ENABLE_LINTING to ON
+    (pass -DLLVM_LIBC_ENABLE_LINTING=ON to cmake).")
+endif()
+
 include(CMakeParseArguments)
 include(LLVMLibCRules)
 include(LLVMLibCCheckCpuFeatures)
index d604da8..74e5343 100644 (file)
@@ -347,6 +347,41 @@ function(add_entrypoint_object target_name)
       "OBJECT_FILES" "${all_objects}"
       "OBJECT_FILES_RAW" "${all_objects_raw}"
   )
+
+  if(LLVM_LIBC_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 $<TARGET_FILE:clang-tidy> "--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 @@ function(add_libc_unittest target_name)
   if(NOT LLVM_INCLUDE_TESTS)
     return()
   endif()
-  
+
   cmake_parse_arguments(
     "LIBC_UNITTEST"
     "" # No optional arguments