tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

import_mozilla_checks.py (5650B)


      1 #!/usr/bin/python3
      2 # This Source Code Form is subject to the terms of the Mozilla Public
      3 # License, v. 2.0. If a copy of the MPL was not distributed with this
      4 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
      5 
      6 import errno
      7 import glob
      8 import os
      9 import shutil
     10 
     11 import ThirdPartyPaths
     12 import ThreadAllows
     13 
     14 
     15 def copy_dir_contents(src, dest):
     16    for f in glob.glob("%s/*" % src):
     17        try:
     18            destname = "%s/%s" % (dest, os.path.basename(f))
     19            if os.path.isdir(f):
     20                shutil.copytree(f, destname)
     21            else:
     22                shutil.copy2(f, destname)
     23        except OSError as e:
     24            if e.errno == errno.ENOTDIR:
     25                shutil.copy2(f, destname)
     26            elif e.errno == errno.EEXIST:
     27                if os.path.isdir(f):
     28                    copy_dir_contents(f, destname)
     29                else:
     30                    os.remove(destname)
     31                    shutil.copy2(f, destname)
     32            else:
     33                raise Exception("Directory not copied. Error: %s" % e)
     34 
     35 
     36 def write_cmake(module_path, import_options):
     37    names = ["  " + os.path.basename(f) for f in glob.glob("%s/*.cpp" % module_path)]
     38 
     39    if import_options["external"]:
     40        names += [
     41            "  " + os.path.join("external", os.path.basename(f))
     42            for f in glob.glob("%s/external/*.cpp" % (module_path))
     43        ]
     44 
     45    if import_options["alpha"]:
     46        names += [
     47            "  " + os.path.join("alpha", os.path.basename(f))
     48            for f in glob.glob("%s/alpha/*.cpp" % (module_path))
     49        ]
     50 
     51    with open(os.path.join(module_path, "CMakeLists.txt"), "w") as f:
     52        f.write(
     53            """set(LLVM_LINK_COMPONENTS support)
     54 
     55 add_definitions( -DCLANG_TIDY )
     56 
     57 add_clang_library(clangTidyMozillaModule
     58  ThirdPartyPaths.cpp
     59 %(names)s
     60 
     61  LINK_LIBS
     62  clangTidy
     63  clangTidyReadabilityModule
     64  clangTidyUtils
     65  clangTidyMPIModule
     66  )
     67 
     68 clang_target_link_libraries(clangTidyMozillaModule
     69  PRIVATE
     70  clangAST
     71  clangASTMatchers
     72  clangBasic
     73  clangLex
     74  )"""
     75            % {"names": "\n".join(names)}
     76        )
     77 
     78 
     79 def add_moz_module(cmake_path):
     80    with open(cmake_path) as f:
     81        lines = f.readlines()
     82    f.close()
     83 
     84    try:
     85        idx = lines.index("set(ALL_CLANG_TIDY_CHECKS\n")
     86        lines.insert(idx + 1, "  clangTidyMozillaModule\n")
     87 
     88        with open(cmake_path, "w") as f:
     89            for line in lines:
     90                f.write(line)
     91    except ValueError:
     92        raise Exception(f"Unable to find ALL_CLANG_TIDY_CHECKS in {cmake_path}")
     93 
     94 
     95 def write_third_party_paths(mozilla_path, module_path):
     96    tpp_txt = os.path.join(mozilla_path, "../../tools/rewriting/ThirdPartyPaths.txt")
     97    generated_txt = os.path.join(mozilla_path, "../../tools/rewriting/Generated.txt")
     98    with open(os.path.join(module_path, "ThirdPartyPaths.cpp"), "w") as f:
     99        ThirdPartyPaths.generate(f, tpp_txt, generated_txt)
    100 
    101 
    102 def generate_thread_allows(mozilla_path, module_path):
    103    names = os.path.join(mozilla_path, "../../build/clang-plugin/ThreadAllows.txt")
    104    files = os.path.join(mozilla_path, "../../build/clang-plugin/ThreadFileAllows.txt")
    105    with open(os.path.join(module_path, "ThreadAllows.h"), "w") as f:
    106        f.write(
    107            ThreadAllows.generate_allows(allowed_names=[names], allowed_files=[files])
    108        )
    109 
    110 
    111 def do_import(mozilla_path, clang_tidy_path, import_options):
    112    module = "mozilla"
    113    module_path = os.path.join(clang_tidy_path, module)
    114    try:
    115        os.makedirs(module_path)
    116    except OSError as e:
    117        if e.errno != errno.EEXIST:
    118            raise
    119 
    120    copy_dir_contents(mozilla_path, module_path)
    121    write_third_party_paths(mozilla_path, module_path)
    122    generate_thread_allows(mozilla_path, module_path)
    123    write_cmake(module_path, import_options)
    124    add_moz_module(os.path.join(module_path, "..", "CMakeLists.txt"))
    125    with open(os.path.join(module_path, "..", "CMakeLists.txt"), "a") as f:
    126        f.write("add_subdirectory(%s)\n" % module)
    127    # A better place for this would be in `ClangTidyForceLinker.h` but `ClangTidyMain.cpp`
    128    # is also OK.
    129    with open(os.path.join(module_path, "..", "tool", "ClangTidyMain.cpp"), "a") as f:
    130        f.write(
    131            """
    132 // This anchor is used to force the linker to link the MozillaModule.
    133 extern volatile int MozillaModuleAnchorSource;
    134 static int LLVM_ATTRIBUTE_UNUSED MozillaModuleAnchorDestination =
    135          MozillaModuleAnchorSource;
    136 """
    137        )
    138 
    139 
    140 def main():
    141    import argparse
    142 
    143    parser = argparse.ArgumentParser(
    144        usage="import_mozilla_checks.py <mozilla-clang-plugin-path> <clang-tidy-path> [option]",
    145        description="Imports the Mozilla static analysis checks into a clang-tidy source tree.",
    146    )
    147    parser.add_argument(
    148        "mozilla_path", help="Full path to mozilla-central/build/clang-plugin"
    149    )
    150    parser.add_argument(
    151        "clang_tidy_path", help="Full path to llvm-project/clang-tools-extra/clang-tidy"
    152    )
    153    parser.add_argument(
    154        "--import-alpha",
    155        help="Enable import of in-tree alpha checks",
    156        action="store_true",
    157    )
    158    parser.add_argument(
    159        "--import-external",
    160        help="Enable import of in-tree external checks",
    161        action="store_true",
    162    )
    163    args = parser.parse_args()
    164 
    165    if not os.path.isdir(args.mozilla_path):
    166        print("Invalid path to mozilla clang plugin")
    167 
    168    if not os.path.isdir(args.clang_tidy_path):
    169        print("Invalid path to clang-tidy source directory")
    170 
    171    import_options = {"alpha": args.import_alpha, "external": args.import_external}
    172 
    173    do_import(args.mozilla_path, args.clang_tidy_path, import_options)
    174 
    175 
    176 if __name__ == "__main__":
    177    main()