Bug 1324315 - Add support for building clang-tidy with Mozilla static analysis checks to build-clang.py; r=mystor
authorEhsan Akhgari <ehsan@mozilla.com>
Sun, 18 Dec 2016 01:03:10 -0500
changeset 327509 409bdaed6b9f41f001db03eb5a5469e5ad5685e5
parent 327508 8222951c9369ca13c6358bc32c9d5da6c6c2289b
child 327510 7d0b2be362337907af5b11f038900a0bf28b5c67
push id31135
push userkwierso@gmail.com
push dateThu, 29 Dec 2016 20:04:00 +0000
treeherdermozilla-central@79ef93672445 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmystor
bugs1324315
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1324315 - Add support for building clang-tidy with Mozilla static analysis checks to build-clang.py; r=mystor
build/build-clang/README
build/build-clang/build-clang.py
--- a/build/build-clang/README
+++ b/build/build-clang/README
@@ -37,9 +37,10 @@ build-clang.py accepts a JSON config for
 * libcxxabi_repo: SVN path to the libcxxabi repo.
 * python_path: Path to the Python 2.7 installation on the machine building clang.
 * gcc_dir: Path to the gcc toolchain installation, only required on Linux.
 * cc: Path to the bootsraping C Compiler.
 * cxx: Path to the bootsraping C++ Compiler.
 * patches: Optional list of patches to apply per platform.  Supported platforms: macosx64, linux32, linux64.  The default is Release.
 * build_type: The type of build to make.  Supported types: Release, Debug, RelWithDebInfo or MinSizeRel.
 * build_libcxx: Whether to build with libcxx.  The default is false.
+* import_clang_tidy: Whether to import Mozilla checks into clang-tidy before building.  The default is false.
 * assertions: Whether to enable LLVM assertions.  The default is false.
--- a/build/build-clang/build-clang.py
+++ b/build/build-clang/build-clang.py
@@ -52,16 +52,26 @@ def run_in(path, args):
 
 
 def patch(patch, srcdir):
     patch = os.path.realpath(patch)
     check_run(['patch', '-d', srcdir, '-p1', '-i', patch, '--fuzz=0',
                '-s'])
 
 
+def do_import_clang_tidy(source_dir):
+    clang_plugin_path = os.path.join(os.path.dirname(sys.argv[0]),
+                                     '..', 'clang-plugin')
+    clang_tidy_path = os.path.join(source_dir,
+                                   'tools/clang/tools/extra/clang-tidy')
+    sys.path.append(clang_plugin_path)
+    from import_mozilla_checks import do_import
+    do_import(clang_plugin_path, clang_tidy_path)
+
+
 def build_package(package_build_dir, run_cmake, cmake_args):
     if not os.path.exists(package_build_dir):
         os.mkdir(package_build_dir)
     if run_cmake:
         run_in(package_build_dir, ["cmake"] + cmake_args)
     run_in(package_build_dir, ["ninja", "install"])
 
 
@@ -254,16 +264,17 @@ if __name__ == "__main__":
         # to the LLVM build to bring back reproducibility.
         base_dir = os.path.join(os.getcwd(), 'llvm-sources')
 
     source_dir = base_dir + "/src"
     build_dir = base_dir + "/build"
 
     llvm_source_dir = source_dir + "/llvm"
     clang_source_dir = source_dir + "/clang"
+    extra_source_dir = source_dir + "/extra"
     compiler_rt_source_dir = source_dir + "/compiler-rt"
     libcxx_source_dir = source_dir + "/libcxx"
     libcxxabi_source_dir = source_dir + "/libcxxabi"
 
     if is_darwin():
         os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.7'
 
     exe_ext = ""
@@ -289,16 +300,17 @@ if __name__ == "__main__":
 
     if args.clean:
         shutil.rmtree(build_dir)
         os.sys.exit(0)
 
     llvm_revision = config["llvm_revision"]
     llvm_repo = config["llvm_repo"]
     clang_repo = config["clang_repo"]
+    extra_repo = config.get("extra_repo")
     compiler_repo = config["compiler_repo"]
     libcxx_repo = config["libcxx_repo"]
     libcxxabi_repo = config.get("libcxxabi_repo")
     stages = 3
     if "stages" in config:
         stages = int(config["stages"])
         if stages not in (1, 2, 3):
             raise ValueError("We only know how to build 1, 2, or 3 stages")
@@ -307,16 +319,21 @@ if __name__ == "__main__":
         build_type = config["build_type"]
         if build_type not in ("Release", "Debug", "RelWithDebInfo", "MinSizeRel"):
             raise ValueError("We only know how to do Release, Debug, RelWithDebInfo or MinSizeRel builds")
     build_libcxx = False
     if "build_libcxx" in config:
         build_libcxx = config["build_libcxx"]
         if build_libcxx not in (True, False):
             raise ValueError("Only boolean values are accepted for build_libcxx.")
+    import_clang_tidy = False
+    if "import_clang_tidy" in config:
+        import_clang_tidy = config["import_clang_tidy"]
+        if import_clang_tidy not in (True, False):
+            raise ValueError("Only boolean values are accepted for import_clang_tidy.")
     assertions = False
     if "assertions" in config:
         assertions = config["assertions"]
         if assertions not in (True, False):
             raise ValueError("Only boolean values are accepted for assertions.")
     python_path = None
     if "python_path" not in config:
         raise ValueError("Config file needs to set python_path")
@@ -334,28 +351,34 @@ if __name__ == "__main__":
     if not os.path.exists(source_dir):
         os.makedirs(source_dir)
         svn_co(source_dir, llvm_repo, llvm_source_dir, llvm_revision)
         svn_co(source_dir, clang_repo, clang_source_dir, llvm_revision)
         svn_co(source_dir, compiler_repo, compiler_rt_source_dir, llvm_revision)
         svn_co(source_dir, libcxx_repo, libcxx_source_dir, llvm_revision)
         if libcxxabi_repo:
             svn_co(source_dir, libcxxabi_repo, libcxxabi_source_dir, llvm_revision)
+        if extra_repo:
+            svn_co(source_dir, extra_repo, extra_source_dir, llvm_revision)
         for p in config.get("patches", {}).get(get_platform(), []):
             patch(p, source_dir)
     else:
         svn_update(llvm_source_dir, llvm_revision)
         svn_update(clang_source_dir, llvm_revision)
         svn_update(compiler_rt_source_dir, llvm_revision)
         svn_update(libcxx_source_dir, llvm_revision)
         if libcxxabi_repo:
             svn_update(libcxxabi_source_dir, llvm_revision)
+        if extra_repo:
+            svn_update(extra_source_dir, llvm_revision)
 
     symlinks = [(source_dir + "/clang",
                  llvm_source_dir + "/tools/clang"),
+                (source_dir + "/extra",
+                 llvm_source_dir + "/tools/clang/tools/extra"),
                 (source_dir + "/compiler-rt",
                  llvm_source_dir + "/projects/compiler-rt"),
                 (source_dir + "/libcxx",
                  llvm_source_dir + "/projects/libcxx"),
                 (source_dir + "/libcxxabi",
                  llvm_source_dir + "/projects/libcxxabi")]
     for l in symlinks:
         # On Windows, we have to re-copy the whole directory every time.
@@ -363,16 +386,19 @@ if __name__ == "__main__":
             continue
         if os.path.isdir(l[1]):
             shutil.rmtree(l[1])
         elif os.path.exists(l[1]):
             os.unlink(l[1])
         if os.path.exists(l[0]):
             symlink(l[0], l[1])
 
+    if import_clang_tidy:
+        do_import_clang_tidy(llvm_source_dir)
+
     if not os.path.exists(build_dir):
         os.makedirs(build_dir)
 
     stage1_dir = build_dir + '/stage1'
     stage1_inst_dir = stage1_dir + '/clang'
 
     final_stage_dir = stage1_dir