diff --git a/build/unix/build-clang/README b/build/build-clang/README similarity index 88% rename from build/unix/build-clang/README rename to build/build-clang/README index 6cf1b05233ca..ea3a636f4b68 100644 --- a/build/unix/build-clang/README +++ b/build/build-clang/README @@ -13,6 +13,16 @@ optional arguments: --clean Clean the build directory ``` +Pre-requisites +-------------- +* Working build toolchain. +* Subversion +* CMake +* Ninja +* Python 2.7 + +Please use the latest available CMake for your platform to avoid surprises. + Config file format ------------------ diff --git a/build/unix/build-clang/build-clang.py b/build/build-clang/build-clang.py similarity index 75% rename from build/unix/build-clang/build-clang.py rename to build/build-clang/build-clang.py index 471f03063998..a33aaa0fe845 100755 --- a/build/unix/build-clang/build-clang.py +++ b/build/build-clang/build-clang.py @@ -18,6 +18,17 @@ import sys DEBUG = os.getenv("DEBUG") + +def symlink(source, link_name): + os_symlink = getattr(os, "symlink", None) + if callable(os_symlink): + os_symlink(source, link_name) + else: + if os.path.isdir(source): + # Fall back to copying the directory :( + copy_dir_contents(source, link_name) + + def check_run(args): global DEBUG if DEBUG: @@ -63,6 +74,10 @@ def updated_env(env): def build_tar_package(tar, name, base, directory): name = os.path.realpath(name) + # On Windows, we have to convert this into an msys path so that tar can + # understand it. + if is_windows(): + name = name.replace('\\', '/').replace('c:', '/c') run_in(base, [tar, "-c", "-%s" % ("J" if ".xz" in name else "j"), @@ -74,7 +89,10 @@ def copy_dir_contents(src, dest): for f in glob.glob("%s/*" % src): try: destname = "%s/%s" % (dest, os.path.basename(f)) - shutil.copytree(f, destname) + 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) @@ -121,19 +139,18 @@ def build_and_use_libgcc(env, clang_dir): shutil.rmtree(tempdir) -def svn_co(url, directory, revision): - check_run(["svn", "co", "-r", revision, url, directory]) +def svn_co(source_dir, url, directory, revision): + run_in(source_dir, ["svn", "co", "-r", revision, url, directory]) def svn_update(directory, revision): run_in(directory, ["svn", "update", "-r", revision]) -def build_one_stage(env, src_dir, stage_dir, build_libcxx, build_type, assertions, - python_path): - with updated_env(env): - build_one_stage_aux(src_dir, stage_dir, build_libcxx, build_type, - assertions, python_path) +def build_one_stage(cc, cxx, src_dir, stage_dir, build_libcxx, + build_type, assertions, python_path): + build_one_stage_aux(cc, cxx, src_dir, stage_dir, build_libcxx, + build_type, assertions, python_path) def get_platform(): @@ -141,10 +158,15 @@ def get_platform(): if p == "Darwin": return "macosx64" elif p == "Linux": - if platform.processor() == "x86_64": + if platform.architecture() == "AMD64": return "linux64" else: return "linux32" + elif p == "Windows": + if platform.architecture() == "AMD64": + return "win64" + else: + return "win32" else: raise NotImplementedError("Not supported platform") @@ -153,7 +175,15 @@ def is_darwin(): return platform.system() == "Darwin" -def build_one_stage_aux(src_dir, stage_dir, build_libcxx, +def is_linux(): + return platform.system() == "Linux" + + +def is_windows(): + return platform.system() == "Windows" + + +def build_one_stage_aux(cc, cxx, src_dir, stage_dir, build_libcxx, build_type, assertions, python_path): if not os.path.exists(stage_dir): os.mkdir(stage_dir) @@ -162,10 +192,12 @@ def build_one_stage_aux(src_dir, stage_dir, build_libcxx, inst_dir = stage_dir + "/clang" run_cmake = True - if os.path.exists(build_dir): + if os.path.exists(build_dir + "/build.ninja"): run_cmake = False cmake_args = ["-GNinja", + "-DCMAKE_C_COMPILER=%s" % cc, + "-DCMAKE_CXX_COMPILER=%s" % cxx, "-DCMAKE_BUILD_TYPE=%s" % build_type, "-DLLVM_TARGETS_TO_BUILD=X86;ARM", "-DLLVM_ENABLE_ASSERTIONS=%s" % ("ON" if assertions else "OFF"), @@ -182,6 +214,8 @@ if __name__ == "__main__": # We use a directory in /builds/slave because the mozilla infrastructure # cleans it up automatically. base_dir = "/builds/slave/moz-toolchain" + if is_windows(): + base_dir = "c:%s" % base_dir source_dir = base_dir + "/src" build_dir = base_dir + "/build" @@ -194,6 +228,16 @@ if __name__ == "__main__": if is_darwin(): os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.7' + exe_ext = "" + if is_windows(): + exe_ext = ".exe" + + cc_name = "clang" + cxx_name = "clang++" + if is_windows(): + cc_name = "clang-cl" + cxx_name = "clang-cl" + parser = argparse.ArgumentParser() parser.add_argument('-c', '--config', required=True, type=argparse.FileType('r'), @@ -243,7 +287,7 @@ if __name__ == "__main__": gcc_dir = config["gcc_dir"] if not os.path.exists(gcc_dir): raise ValueError("gcc_dir must point to an existing path") - if not is_darwin() and gcc_dir is None: + if is_linux() and gcc_dir is None: raise ValueError("Config file needs to set gcc_dir") cc = None if "cc" in config: @@ -262,15 +306,10 @@ if __name__ == "__main__": if not os.path.exists(source_dir): os.makedirs(source_dir) - svn_co(llvm_repo, llvm_source_dir, llvm_revision) - svn_co(clang_repo, clang_source_dir, llvm_revision) - svn_co(compiler_repo, compiler_rt_source_dir, llvm_revision) - svn_co(libcxx_repo, libcxx_source_dir, llvm_revision) - os.symlink("../../clang", llvm_source_dir + "/tools/clang") - os.symlink("../../compiler-rt", - llvm_source_dir + "/projects/compiler-rt") - os.symlink("../../libcxx", - llvm_source_dir + "/projects/libcxx") + 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) for p in config.get("patches", {}).get(get_platform(), []): patch(p, source_dir) else: @@ -279,6 +318,22 @@ if __name__ == "__main__": svn_update(compiler_rt_source_dir, llvm_revision) svn_update(libcxx_source_dir, llvm_revision) + symlinks = [(source_dir + "/clang", + llvm_source_dir + "/tools/clang"), + (source_dir + "/compiler-rt", + llvm_source_dir + "/projects/compiler-rt"), + (source_dir + "/libcxx", + llvm_source_dir + "/projects/libcxx")] + for l in symlinks: + # On Windows, we have to re-copy the whole directory every time. + if not is_windows() and os.path.islink(l[1]): + continue + if os.path.isdir(l[1]): + shutil.rmtree(l[1]) + elif os.path.exists(l[1]): + os.unlink(l[1]) + symlink(l[0], l[1]) + if not os.path.exists(build_dir): os.makedirs(build_dir) @@ -292,7 +347,7 @@ if __name__ == "__main__": extra_cxxflags = "-stdlib=libc++" extra_cflags2 = "" extra_cxxflags2 = "-stdlib=libc++" - else: + elif is_linux(): extra_cflags = "-static-libgcc" extra_cxxflags = "-static-libgcc -static-libstdc++" extra_cflags2 = "-fPIC --gcc-toolchain=%s" % gcc_dir @@ -302,10 +357,15 @@ if __name__ == "__main__": os.environ['LD_LIBRARY_PATH'] = '%s/lib64/:%s' % (gcc_dir, os.environ['LD_LIBRARY_PATH']); else: os.environ['LD_LIBRARY_PATH'] = '%s/lib64/' % gcc_dir + elif is_windows(): + extra_cflags = "" + extra_cxxflags = "" + extra_cflags2 = "" + extra_cxxflags2 = "" build_one_stage( - {"CC": cc + " %s" % extra_cflags, - "CXX": cxx + " %s" % extra_cxxflags}, + cc + " %s" % extra_cflags, + cxx + " %s" % extra_cxxflags, llvm_source_dir, stage1_dir, build_libcxx, build_type, assertions, python_path) @@ -314,8 +374,10 @@ if __name__ == "__main__": stage2_inst_dir = stage2_dir + '/clang' final_stage_dir = stage2_dir build_one_stage( - {"CC": stage1_inst_dir + "/bin/clang %s" % extra_cflags2, - "CXX": stage1_inst_dir + "/bin/clang++ %s" % extra_cxxflags2}, + stage1_inst_dir + "/bin/%s%s %s" % + (cc_name, exe_ext, extra_cflags2), + stage1_inst_dir + "/bin/%s%s %s" % + (cxx_name, exe_ext, extra_cxxflags2), llvm_source_dir, stage2_dir, build_libcxx, build_type, assertions, python_path) @@ -323,19 +385,21 @@ if __name__ == "__main__": stage3_dir = build_dir + '/stage3' final_stage_dir = stage3_dir build_one_stage( - {"CC": stage2_inst_dir + "/bin/clang %s" % extra_cflags2, - "CXX": stage2_inst_dir + "/bin/clang++ %s" % extra_cxxflags2}, + stage2_inst_dir + "/bin/%s%s %s" % + (cc_name, exe_ext, extra_cflags2), + stage2_inst_dir + "/bin/%s%s %s" % + (cxx_name, exe_ext, extra_cxxflags2), llvm_source_dir, stage3_dir, build_libcxx, build_type, assertions, python_path) - if not is_darwin(): + if is_linux(): final_stage_inst_dir = final_stage_dir + '/clang' build_and_use_libgcc( {"CC": cc + " %s" % extra_cflags, "CXX": cxx + " %s" % extra_cxxflags}, final_stage_inst_dir) - if is_darwin(): + if is_darwin() or is_windows(): build_tar_package("tar", "clang.tar.bz2", final_stage_dir, "clang") else: build_tar_package("tar", "clang.tar.xz", final_stage_dir, "clang") diff --git a/build/unix/build-clang/clang-static-analysis-linux64-centos6.json b/build/build-clang/clang-static-analysis-linux64-centos6.json similarity index 100% rename from build/unix/build-clang/clang-static-analysis-linux64-centos6.json rename to build/build-clang/clang-static-analysis-linux64-centos6.json diff --git a/build/unix/build-clang/clang-static-analysis-linux64.json b/build/build-clang/clang-static-analysis-linux64.json similarity index 100% rename from build/unix/build-clang/clang-static-analysis-linux64.json rename to build/build-clang/clang-static-analysis-linux64.json diff --git a/build/unix/build-clang/clang-static-analysis-macosx64.json b/build/build-clang/clang-static-analysis-macosx64.json similarity index 100% rename from build/unix/build-clang/clang-static-analysis-macosx64.json rename to build/build-clang/clang-static-analysis-macosx64.json diff --git a/build/build-clang/clang-static-analysis-win32.json b/build/build-clang/clang-static-analysis-win32.json new file mode 100644 index 000000000000..0e3ce2dd3fab --- /dev/null +++ b/build/build-clang/clang-static-analysis-win32.json @@ -0,0 +1,16 @@ +{ + "llvm_revision": "259916", + "stages": "3", + "build_libcxx": false, + "build_type": "Release", + "assertions": false, + "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/trunk", + "clang_repo": "https://llvm.org/svn/llvm-project/cfe/trunk", + "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/trunk", + "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/trunk", + "python_path": "c:/mozilla-build/python/python.exe", + "cc": "c:/Program Files (x86)/Microsoft Visual Studio 12.0/VC/BIN/amd64_x86/cl.exe", + "cxx": "c:/Program Files (x86)/Microsoft Visual Studio 12.0/VC/BIN/amd64_x86/cl.exe", + "patches": { + } +} diff --git a/build/build-clang/clang-static-analysis-win64.json b/build/build-clang/clang-static-analysis-win64.json new file mode 100644 index 000000000000..94343b671e89 --- /dev/null +++ b/build/build-clang/clang-static-analysis-win64.json @@ -0,0 +1,16 @@ +{ + "llvm_revision": "259916", + "stages": "3", + "build_libcxx": false, + "build_type": "Release", + "assertions": false, + "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/trunk", + "clang_repo": "https://llvm.org/svn/llvm-project/cfe/trunk", + "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/trunk", + "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/trunk", + "python_path": "c:/mozilla-build/python/python.exe", + "cc": "c:/Program Files (x86)/Microsoft Visual Studio 12.0/VC/BIN/amd64/cl.exe", + "cxx": "c:/Program Files (x86)/Microsoft Visual Studio 12.0/VC/BIN/amd64/cl.exe", + "patches": { + } +} diff --git a/build/unix/build-clang/llvm-debug-frame.patch b/build/build-clang/llvm-debug-frame.patch similarity index 100% rename from build/unix/build-clang/llvm-debug-frame.patch rename to build/build-clang/llvm-debug-frame.patch diff --git a/build/unix/build-clang/query-selector-visibility.patch b/build/build-clang/query-selector-visibility.patch similarity index 100% rename from build/unix/build-clang/query-selector-visibility.patch rename to build/build-clang/query-selector-visibility.patch diff --git a/build/unix/build-clang/return-empty-string-non-mangled.patch b/build/build-clang/return-empty-string-non-mangled.patch similarity index 100% rename from build/unix/build-clang/return-empty-string-non-mangled.patch rename to build/build-clang/return-empty-string-non-mangled.patch diff --git a/testing/taskcluster/scripts/misc/build-clang-linux.sh b/testing/taskcluster/scripts/misc/build-clang-linux.sh index 5e32a0e99f49..d3fc5eab08c0 100755 --- a/testing/taskcluster/scripts/misc/build-clang-linux.sh +++ b/testing/taskcluster/scripts/misc/build-clang-linux.sh @@ -19,7 +19,7 @@ $HOME_DIR/tooltool.py -m browser/config/tooltool-manifests/linux64/releng.manife # gets a bit too verbose here set +x -cd build/unix/build-clang +cd build/build-clang ./build-clang.py -c clang-static-analysis-linux64-centos6.json set -x