[libc-commits] [libc] [libc] Fail configure if requested linting cannot run (PR #231001)

via libc-commits libc-commits at lists.llvm.org
Sun Oct 11 09:05:36 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

Author: Jeff Bailey (kaladron)

<details>
<summary>Changes</summary>

If linting was requested but could not run, CMake previously disabled it with a warning and generated an empty libc-lint target.

Change these conditions to FATAL_ERROR so misconfigurations fail early:
* Compiler is not Clang
* clang-tidy is not found
* Auto-discovered clang-tidy has a mismatched major version

If LLVM_LIBC_CLANG_TIDY is set explicitly, treat version mismatches as a warning instead of an error.

Document the configure requirements in code_style.md.

Assisted-by: Automated tooling, human reviewed.

---
Full diff: https://github.com/llvm/llvm-project/pull/231001.diff


2 Files Affected:

- (modified) libc/CMakeLists.txt (+72-36) 
- (modified) libc/docs/dev/code_style.md (+29) 


``````````diff
diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt
index 6a1e9ac9e8306..36d5e18966b14 100644
--- a/libc/CMakeLists.txt
+++ b/libc/CMakeLists.txt
@@ -417,49 +417,35 @@ endif()
 include(LLVMLibCCheckMPFR)
 include(LLVMLibCCheckMPC)
 
+# Linting is opt in.  Naming a clang-tidy binary with LLVM_LIBC_CLANG_TIDY
+# turns it on as well.  Once linting is requested, every problem below stops
+# the configure: an empty libc-lint target that always succeeds would hide a
+# misconfiguration behind a green build.
 if(LLVM_LIBC_CLANG_TIDY)
   set(LLVM_LIBC_ENABLE_LINTING ON)
+  set(LIBC_CLANG_TIDY_EXPLICIT TRUE)
+else()
+  set(LIBC_CLANG_TIDY_EXPLICIT FALSE)
 endif()
 
 if(LLVM_LIBC_ENABLE_LINTING)
   if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
-    set(LLVM_LIBC_ENABLE_LINTING OFF)
-    message(WARNING "C++ compiler is not clang++, linting with be disabled.")
-  else()
-    if(NOT LLVM_LIBC_CLANG_TIDY)
-      find_program(LLVM_LIBC_CLANG_TIDY NAMES clang-tidy)
-    endif()
+    message(FATAL_ERROR "
+      Linting needs clang++ as the C++ compiler so that clang-tidy can replay
+      the compile commands, but the configured compiler is
+      ${CMAKE_CXX_COMPILER_ID}.
 
-    if(LLVM_LIBC_CLANG_TIDY)
-      # Check clang-tidy major version.
-      execute_process(COMMAND ${LLVM_LIBC_CLANG_TIDY} "--version"
-        OUTPUT_VARIABLE CLANG_TIDY_OUTPUT
-        ERROR_VARIABLE CLANG_TIDY_ERROR
-        RESULT_VARIABLE CLANG_TIDY_RESULT)
-
-      if(CLANG_TIDY_RESULT AND NOT CLANG_TIDY_RESULT EQUAL 0)
-        message(FATAL_ERROR "Failed to execute '${LLVM_LIBC_CLANG_TIDY} --version'
-          output : '${CLANG_TIDY_OUTPUT}'
-          error  : '${CLANG_TIDY_ERROR}'
-          result : '${CLANG_TIDY_RESULT}'
-          ")
-      endif()
-      string(REGEX MATCH "[0-9]+" CLANG_TIDY_VERSION "${CLANG_TIDY_OUTPUT}")
-      string(REGEX MATCH "[0-9]+" CLANG_MAJOR_VERSION
-        "${CMAKE_CXX_COMPILER_VERSION}")
-
-      if(NOT CLANG_TIDY_VERSION EQUAL CLANG_MAJOR_VERSION)
-        set(LLVM_LIBC_ENABLE_LINTING OFF)
-        message(WARNING "
-          'clang-tidy' (version ${CLANG_TIDY_VERSION}) is not the same as
-          'clang' (version ${CLANG_MAJOR_VERSION}).  Linting will
-          be disabled.
-
-          The path to the clang-tidy binary can be set manually by passing
-          -DLLVM_LIBC_CLANG_TIDY=<path/to/clang-tidy> to CMake.")
-      endif()
-      add_custom_target(libc-lint)
-    else()
+      To disable linting set LLVM_LIBC_ENABLE_LINTING to OFF
+      (pass -DLLVM_LIBC_ENABLE_LINTING=OFF to cmake).")
+  endif()
+
+  if(NOT LIBC_CLANG_TIDY_EXPLICIT)
+    # Discover into a separate cache entry so that LLVM_LIBC_CLANG_TIDY keeps
+    # meaning "chosen by the user" on later reconfigures.  A bootstrapping
+    # build picks up the clang-tidy that was built next to the compiler.
+    find_program(LIBC_CLANG_TIDY_DISCOVERED NAMES clang-tidy
+      HINTS ${LLVM_TOOLS_BINARY_DIR})
+    if(NOT LIBC_CLANG_TIDY_DISCOVERED)
       message(FATAL_ERROR "
         Linting is enabled but 'clang-tidy' is not found!
 
@@ -469,7 +455,57 @@ if(LLVM_LIBC_ENABLE_LINTING)
         To disable linting set LLVM_LIBC_ENABLE_LINTING to OFF
         (pass -DLLVM_LIBC_ENABLE_LINTING=OFF to cmake).")
     endif()
+    set(LLVM_LIBC_CLANG_TIDY "${LIBC_CLANG_TIDY_DISCOVERED}")
   endif()
+
+  execute_process(COMMAND "${LLVM_LIBC_CLANG_TIDY}" --version
+    OUTPUT_VARIABLE CLANG_TIDY_OUTPUT
+    ERROR_VARIABLE CLANG_TIDY_ERROR
+    RESULT_VARIABLE CLANG_TIDY_RESULT)
+  if(NOT CLANG_TIDY_RESULT EQUAL 0)
+    message(FATAL_ERROR "Failed to execute '${LLVM_LIBC_CLANG_TIDY} --version'
+      output : '${CLANG_TIDY_OUTPUT}'
+      error  : '${CLANG_TIDY_ERROR}'
+      result : '${CLANG_TIDY_RESULT}'
+      ")
+  endif()
+
+  # clang-tidy carries its own clang front end.  A different major version
+  # than the compiler means different builtins, resource headers and warning
+  # flags, which shows up as spurious diagnostics rather than as a clear
+  # failure, so the majors have to agree unless the user chose the binary.
+  if(NOT CLANG_TIDY_OUTPUT MATCHES "LLVM version ([0-9]+)")
+    message(FATAL_ERROR "
+      Could not read a version from '${LLVM_LIBC_CLANG_TIDY} --version':
+      ${CLANG_TIDY_OUTPUT}")
+  endif()
+  set(CLANG_TIDY_VERSION ${CMAKE_MATCH_1})
+  string(REGEX MATCH "[0-9]+" CLANG_MAJOR_VERSION
+    "${CMAKE_CXX_COMPILER_VERSION}")
+
+  if(NOT CLANG_TIDY_VERSION EQUAL CLANG_MAJOR_VERSION)
+    if(LIBC_CLANG_TIDY_EXPLICIT)
+      message(WARNING "
+        'clang-tidy' (version ${CLANG_TIDY_VERSION}) is not the same as
+        'clang' (version ${CLANG_MAJOR_VERSION}).  Using
+        ${LLVM_LIBC_CLANG_TIDY} anyway because LLVM_LIBC_CLANG_TIDY was set
+        explicitly.  Expect spurious diagnostics where the two versions
+        disagree.")
+    else()
+      message(FATAL_ERROR "
+        'clang-tidy' (version ${CLANG_TIDY_VERSION}, found at
+        ${LLVM_LIBC_CLANG_TIDY}) is not the same as 'clang' (version
+        ${CLANG_MAJOR_VERSION}).
+
+        Pass -DLLVM_LIBC_CLANG_TIDY=<path/to/clang-tidy> to CMake to select a
+        matching clang-tidy, or to use this one regardless.
+
+        To disable linting set LLVM_LIBC_ENABLE_LINTING to OFF
+        (pass -DLLVM_LIBC_ENABLE_LINTING=OFF to cmake).")
+    endif()
+  endif()
+
+  add_custom_target(libc-lint)
 endif()
 
 option(LLVM_LIBC_INCLUDE_SCUDO "Include the SCUDO standalone as the allocator for LLVM libc" OFF)
diff --git a/libc/docs/dev/code_style.md b/libc/docs/dev/code_style.md
index 65cd094f8e5d4..2a91944f02f4b 100644
--- a/libc/docs/dev/code_style.md
+++ b/libc/docs/dev/code_style.md
@@ -344,6 +344,35 @@ LLVM libc uses layered `.clang-tidy` configuration files:
   `readability-identifier-naming` and `llvm-header-guard`. Diagnostics from
   `llvmlibc-*` checks are treated as errors.
 
+### Running the checks
+
+Configure with `-DLLVM_LIBC_ENABLE_LINTING=ON` and build the `libc-lint`
+target. CMake looks for `clang-tidy` in the LLVM tools directory first (the
+build tree in a bootstrapping build, so the freshly built `clang-tidy` wins)
+and then on `PATH`. The `clang-tidy` it finds must have the same major
+version as the compiler, because `clang-tidy` carries its own clang front end
+and a mismatch shows up as spurious diagnostics. To use a specific binary,
+pass `-DLLVM_LIBC_CLANG_TIDY=<path>`; this also turns linting on, and a
+version mismatch is then reported as a warning rather than an error.
+
+The `.clang-tidy` files and the `llvmlibc-*` checks live in the same
+repository and change together, so the configuration is written for the
+`clang-tidy` built from the same revision as the libc sources, not for the
+latest release. An older `clang-tidy` does not fail loudly on a newer
+configuration: it ignores checks and check options it does not know, and
+releases up to at least 21 react to an unknown top-level key by discarding
+the file and running their default checks, exiting 0 either way. Results
+from an older `clang-tidy` are therefore not comparable with a build at the
+same revision. To match, add `clang-tools-extra` to a bootstrapping build
+and point `LLVM_LIBC_CLANG_TIDY` at the `clang-tidy` it produces;
+`clang-tidy --verify-config --config-file=libc/src/.clang-tidy` reports
+anything your `clang-tidy` would silently skip.
+
+A configuration that asks for linting but cannot run it (no `clang-tidy`, a
+non-clang compiler, or a discovered `clang-tidy` of the wrong major version)
+fails to configure. There is no mode in which `libc-lint` exists but does
+nothing, so a green `libc-lint` build always means the checks ran.
+
 ### LLVM-libc checks
 
 ### restrict-system-libc-headers

``````````

</details>


https://github.com/llvm/llvm-project/pull/231001


More information about the libc-commits mailing list