summaryrefslogtreecommitdiffstats
path: root/build/clang-plugin/import_mozilla_checks.py
diff options
context:
space:
mode:
Diffstat (limited to 'build/clang-plugin/import_mozilla_checks.py')
-rwxr-xr-xbuild/clang-plugin/import_mozilla_checks.py177
1 files changed, 177 insertions, 0 deletions
diff --git a/build/clang-plugin/import_mozilla_checks.py b/build/clang-plugin/import_mozilla_checks.py
new file mode 100755
index 0000000000..d573dafcf1
--- /dev/null
+++ b/build/clang-plugin/import_mozilla_checks.py
@@ -0,0 +1,177 @@
+#!/usr/bin/python3
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import errno
+import glob
+import os
+import shutil
+
+import ThirdPartyPaths
+import ThreadAllows
+
+
+def copy_dir_contents(src, dest):
+ for f in glob.glob("%s/*" % src):
+ try:
+ destname = "%s/%s" % (dest, os.path.basename(f))
+ if os.path.isdir(f):
+ shutil.copytree(f, destname)
+ else:
+ shutil.copy2(f, destname)
+ except OSError as e:
+ if e.errno == errno.ENOTDIR:
+ shutil.copy2(f, destname)
+ elif e.errno == errno.EEXIST:
+ if os.path.isdir(f):
+ copy_dir_contents(f, destname)
+ else:
+ os.remove(destname)
+ shutil.copy2(f, destname)
+ else:
+ raise Exception("Directory not copied. Error: %s" % e)
+
+
+def write_cmake(module_path, import_options):
+ names = [" " + os.path.basename(f) for f in glob.glob("%s/*.cpp" % module_path)]
+
+ if import_options["external"]:
+ names += [
+ " " + os.path.join("external", os.path.basename(f))
+ for f in glob.glob("%s/external/*.cpp" % (module_path))
+ ]
+
+ if import_options["alpha"]:
+ names += [
+ " " + os.path.join("alpha", os.path.basename(f))
+ for f in glob.glob("%s/alpha/*.cpp" % (module_path))
+ ]
+
+ with open(os.path.join(module_path, "CMakeLists.txt"), "w") as f:
+ f.write(
+ """set(LLVM_LINK_COMPONENTS support)
+
+add_definitions( -DCLANG_TIDY )
+
+add_clang_library(clangTidyMozillaModule
+ ThirdPartyPaths.cpp
+%(names)s
+
+ LINK_LIBS
+ clangTidy
+ clangTidyReadabilityModule
+ clangTidyUtils
+ clangTidyMPIModule
+ )
+
+clang_target_link_libraries(clangTidyMozillaModule
+ PRIVATE
+ clangAST
+ clangASTMatchers
+ clangBasic
+ clangLex
+ )"""
+ % {"names": "\n".join(names)}
+ )
+
+
+def add_moz_module(cmake_path):
+ with open(cmake_path, "r") as f:
+ lines = f.readlines()
+ f.close()
+
+ try:
+ idx = lines.index("set(ALL_CLANG_TIDY_CHECKS\n")
+ lines.insert(idx + 1, " clangTidyMozillaModule\n")
+
+ with open(cmake_path, "w") as f:
+ for line in lines:
+ f.write(line)
+ except ValueError:
+ raise Exception("Unable to find ALL_CLANG_TIDY_CHECKS in {}".format(cmake_path))
+
+
+def write_third_party_paths(mozilla_path, module_path):
+ tpp_txt = os.path.join(mozilla_path, "../../tools/rewriting/ThirdPartyPaths.txt")
+ generated_txt = os.path.join(mozilla_path, "../../tools/rewriting/Generated.txt")
+ with open(os.path.join(module_path, "ThirdPartyPaths.cpp"), "w") as f:
+ ThirdPartyPaths.generate(f, tpp_txt, generated_txt)
+
+
+def generate_thread_allows(mozilla_path, module_path):
+ names = os.path.join(mozilla_path, "../../build/clang-plugin/ThreadAllows.txt")
+ files = os.path.join(mozilla_path, "../../build/clang-plugin/ThreadFileAllows.txt")
+ with open(os.path.join(module_path, "ThreadAllows.h"), "w") as f:
+ f.write(
+ ThreadAllows.generate_allows(allowed_names=[names], allowed_files=[files])
+ )
+
+
+def do_import(mozilla_path, clang_tidy_path, import_options):
+ module = "mozilla"
+ module_path = os.path.join(clang_tidy_path, module)
+ try:
+ os.makedirs(module_path)
+ except OSError as e:
+ if e.errno != errno.EEXIST:
+ raise
+
+ copy_dir_contents(mozilla_path, module_path)
+ write_third_party_paths(mozilla_path, module_path)
+ generate_thread_allows(mozilla_path, module_path)
+ write_cmake(module_path, import_options)
+ add_moz_module(os.path.join(module_path, "..", "CMakeLists.txt"))
+ with open(os.path.join(module_path, "..", "CMakeLists.txt"), "a") as f:
+ f.write("add_subdirectory(%s)\n" % module)
+ # A better place for this would be in `ClangTidyForceLinker.h` but `ClangTidyMain.cpp`
+ # is also OK.
+ with open(os.path.join(module_path, "..", "tool", "ClangTidyMain.cpp"), "a") as f:
+ f.write(
+ """
+// This anchor is used to force the linker to link the MozillaModule.
+extern volatile int MozillaModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED MozillaModuleAnchorDestination =
+ MozillaModuleAnchorSource;
+"""
+ )
+
+
+def main():
+ import argparse
+
+ parser = argparse.ArgumentParser(
+ usage="import_mozilla_checks.py <mozilla-clang-plugin-path> <clang-tidy-path> [option]",
+ description="Imports the Mozilla static analysis checks into a clang-tidy source tree.",
+ )
+ parser.add_argument(
+ "mozilla_path", help="Full path to mozilla-central/build/clang-plugin"
+ )
+ parser.add_argument(
+ "clang_tidy_path", help="Full path to llvm-project/clang-tools-extra/clang-tidy"
+ )
+ parser.add_argument(
+ "--import-alpha",
+ help="Enable import of in-tree alpha checks",
+ action="store_true",
+ )
+ parser.add_argument(
+ "--import-external",
+ help="Enable import of in-tree external checks",
+ action="store_true",
+ )
+ args = parser.parse_args()
+
+ if not os.path.isdir(args.mozilla_path):
+ print("Invalid path to mozilla clang plugin")
+
+ if not os.path.isdir(args.clang_tidy_path):
+ print("Invalid path to clang-tidy source directory")
+
+ import_options = {"alpha": args.import_alpha, "external": args.import_external}
+
+ do_import(args.mozilla_path, args.clang_tidy_path, import_options)
+
+
+if __name__ == "__main__":
+ main()