CSears created this revision. CSears added a reviewer: jroelofs. Herald added a subscriber: carlosgalvezp. CSears requested review of this revision. Herald added a project: clang-tools-extra. Herald added a subscriber: cfe-commits.
Using clang-tidy on LLVM itself (the proverbial eating your own dogfood) is a little different from using a clang-tidy installation on another source tree. clang-tidy needs to know where to find include files within the LLVM source tree itself. This is a Python script, tidy-llvm, which finds the root of the llvm tree, verifies LLVM build requirements (LLVM_ENABLE_PROJECTS:STRING=clang;clang-tools-extra and CMAKE_EXPORT_COMPILE_COMMANDS:UNINITIALIZED=On), constructs llvm and current directory include paths, concatenates up an argument list and then runs clang-tidy on the .h and .cpp files on the command line. tidy-llvm XXAsmPrinter.cpp generates a clang-tidy command line that looks like: clang-tidy -checks="llvm-*" -p .../build XXAsmPrinter.cpp -- -I. -IAsmParser -IGISel -IDisassembler -ITargetInfo -IXX -IMCTargetDesc -I.../libcxx/include -I.../build/include -I.../llvm/include I'm pretty sure that the llvm include directories (-I.../libcxx/include -I.../build/include -I.../llvm/include others?) have to be enumerated rather than simply inheriting where clang-tidy thinks they are in the installation. Unless I manually specified them, clang-tidy wasn't finding them. I think someone more expert in the build machinery could improve it greatly. For example, it currently gets a strange error about __config_site (which doesn't prevent the rest of the clang-tidy checking): Error while processing path to XXAsmPrinter.cpp. path/libcxx/include/__config:13:10: error: '__config_site' file not found [clang-diagnostic-error] #include <__config_site> __config_site is indeed not in my build tree. There is a file libcxx/include/__config_site.in but that's it. Again, someone more knowledgable in the build machinery might understand why this is the case. clang-tidy still interprets its .clang_tidy file wherever it finds it. It's better to leave most of the -checks there. The tidy-llvm Python script itself is currently set to -checks=\"llvm-*\". I set modernize in the .clang_tidy file for my backend. I can imagine having a .clang-tidy file at the root of the llvm tree. Adding support for run-clang-tidy would be nice but for tidying individual files it really won't matter. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D115848 Files: clang-tools-extra/clang-tidy/tool/tidy-llvm.py
Index: clang-tools-extra/clang-tidy/tool/tidy-llvm.py =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/tool/tidy-llvm.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python +# +#===- tidy-llvm --------------------------------------------*- python -*--===# +# +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +#===-----------------------------------------------------------------------===# + + +""" +tidy-llvm +========================== + +Runs clang-tidy over named .cpp and .h files. +tidy-llvm must be run from inside an LLVM source tree. +But otherwise, it finds the root of the llvm tree, verifies build requirements, +constructs include paths, concatenates an argument list and then runs clang-tidy. +clang-tidy will in turn examine any .clang-tidy in the path +""" + +import os +import sys + +def fail(s): + print(s) + sys.exit(1) + +def file_exists(name): + if not os.path.isfile(name): + fail('Cannot find ' + name) + return name + +def dir_exists(name): + if not os.path.isdir(name): + fail('Cannot find ' + name) + return name + +def find_llvm_root(): + result = './' + while not os.path.isdir(os.path.join(result, "build")): + if os.path.realpath(result) == '/': + fail('Error: could not find llvm root.') + result += '../' + return os.path.realpath(result) + +# LLVM_ENABLE_PROJECTS:STRING=clang;clang-tools-extra +# CMAKE_EXPORT_COMPILE_COMMANDS:UNINITIALIZED=On + +def verify_config(root): + found = 0 + for line in open(file_exists(os.path.join(root, "build/CMakeCache.txt")), 'r'): + if "LLVM_ENABLE_PROJECTS:STRING=" in line: + if "clang;clang-tools-extra" not in line: + fail('Build needs clang;clang-tools-extra') + found = 1 + break + if not found: + fail('Build needs clang;clang-tools-extra') + for line in open(file_exists(os.path.join(root, "build/CMakeCache.txt")), 'r'): + if "CMAKE_EXPORT_COMPILE_COMMANDS:UNINITIALIZED=On" in line: + return + fail('Build needs CMAKE_EXPORT_COMPILE_COMMANDS:UNINITIALIZED=On') + +def construct_llvm_include_paths(root): + libcxx = dir_exists(os.path.join(root, "libcxx/include")) + build_include = dir_exists(os.path.join(root, "build/include")) + llvm_include = dir_exists(os.path.join(root, "llvm/include")) + return "-I" + libcxx + " -I" + build_include + " -I" + llvm_include + +def construct_current_include_paths(): + paths = "" + for e in os.listdir(): + if os.path.isdir(e): + paths += " -I" + e + return paths + +def process_args(root, cmd_args): + for name in cmd_args: + if not name.endswith(".h") and not name.endswith(".cpp"): + fail(name + " does not end with .h or .cpp") + file_exists(name) + return " ".join(str(f) for f in cmd_args) + +def main(): + root = find_llvm_root() + verify_config(root) + llvm_include_paths = construct_llvm_include_paths(root) + current_include_paths = construct_current_include_paths() + if len(sys.argv) == 1: + fail("tidy-llvm: [.cpp and .h files]") + args = process_args(root, sys.argv[1:]) + cmd = ("clang-tidy -checks=\"llvm-*\" -p " + + os.path.join(root, "build") + " " + args + " -- -I." + + current_include_paths + " " + llvm_include_paths) + os.system(cmd) + +if __name__ == '__main__': + main()
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits