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/.
6 # Only necessary for flake8 to be happy...
7 from __future__
import print_function
22 from contextlib
import contextmanager
23 from distutils
.dir_util
import copy_tree
25 from shutil
import which
30 def symlink(source
, link_name
):
31 os_symlink
= getattr(os
, "symlink", None)
32 if callable(os_symlink
):
33 os_symlink(source
, link_name
)
35 if os
.path
.isdir(source
):
36 # Fall back to copying the directory :(
37 copy_tree(source
, link_name
)
41 print(" ".join(args
), file=sys
.stderr
, flush
=True)
42 if args
[0] == "cmake":
43 # CMake `message(STATUS)` messages, as appearing in failed source code
44 # compiles, appear on stdout, so we only capture that.
45 p
= subprocess
.Popen(args
, stdout
=subprocess
.PIPE
)
49 sys
.stdout
.write(line
.decode())
52 if r
!= 0 and os
.environ
.get("UPLOAD_DIR"):
53 cmake_output_re
= re
.compile(b
'See also "(.*/CMakeOutput.log)"')
54 cmake_error_re
= re
.compile(b
'See also "(.*/CMakeError.log)"')
56 def find_first_match(re
):
62 output_match
= find_first_match(cmake_output_re
)
63 error_match
= find_first_match(cmake_error_re
)
65 upload_dir
= os
.environ
["UPLOAD_DIR"].encode("utf-8")
66 if output_match
or error_match
:
69 shutil
.copy2(output_match
.group(1), upload_dir
)
71 shutil
.copy2(error_match
.group(1), upload_dir
)
73 r
= subprocess
.call(args
)
77 def run_in(path
, args
):
85 print('cd "%s"' % path
, file=sys
.stderr
)
90 print('cd "%s"' % d
, file=sys
.stderr
)
94 def patch(patch
, srcdir
):
95 patch
= os
.path
.realpath(patch
)
96 check_run(["patch", "-d", srcdir
, "-p1", "-i", patch
, "--fuzz=0", "-s"])
99 def import_clang_tidy(source_dir
, build_clang_tidy_alpha
, build_clang_tidy_external
):
100 clang_plugin_path
= os
.path
.join(os
.path
.dirname(sys
.argv
[0]), "..", "clang-plugin")
101 clang_tidy_path
= os
.path
.join(source_dir
, "clang-tools-extra/clang-tidy")
102 sys
.path
.append(clang_plugin_path
)
103 from import_mozilla_checks
import do_import
106 "alpha": build_clang_tidy_alpha
,
107 "external": build_clang_tidy_external
,
109 do_import(clang_plugin_path
, clang_tidy_path
, import_options
)
112 def build_package(package_build_dir
, cmake_args
):
113 if not os
.path
.exists(package_build_dir
):
114 os
.mkdir(package_build_dir
)
115 # If CMake has already been run, it may have been run with different
116 # arguments, so we need to re-run it. Make sure the cached copy of the
117 # previous CMake run is cleared before running it again.
118 if os
.path
.exists(package_build_dir
+ "/CMakeCache.txt"):
119 os
.remove(package_build_dir
+ "/CMakeCache.txt")
120 if os
.path
.exists(package_build_dir
+ "/CMakeFiles"):
121 shutil
.rmtree(package_build_dir
+ "/CMakeFiles")
123 run_in(package_build_dir
, ["cmake"] + cmake_args
)
124 run_in(package_build_dir
, ["ninja", "install", "-v"])
128 def updated_env(env
):
129 old_env
= os
.environ
.copy()
130 os
.environ
.update(env
)
133 os
.environ
.update(old_env
)
136 def build_tar_package(name
, base
, directory
):
137 name
= os
.path
.realpath(name
)
138 print("tarring {} from {}/{}".format(name
, base
, directory
), file=sys
.stderr
)
139 assert name
.endswith(".tar.zst")
141 cctx
= zstandard
.ZstdCompressor()
142 with
open(name
, "wb") as f
, cctx
.stream_writer(f
) as z
:
143 with tarfile
.open(mode
="w|", fileobj
=z
) as tf
:
152 if e
.errno
!= errno
.EEXIST
or not os
.path
.isdir(path
):
157 if os
.path
.isdir(path
):
166 def install_import_library(build_dir
, clang_dir
):
168 os
.path
.join(build_dir
, "lib", "clang.lib"), os
.path
.join(clang_dir
, "lib")
173 return platform
.system() == "Darwin"
177 return platform
.system() == "Linux"
181 return platform
.system() == "Windows"
201 is_final_stage
=False,
204 if not os
.path
.exists(stage_dir
):
207 build_dir
= stage_dir
+ "/build"
208 inst_dir
= stage_dir
+ "/" + package_name
210 # cmake doesn't deal well with backslashes in paths.
211 def slashify_path(path
):
212 return path
.replace("\\", "/")
214 def cmake_base_args(cc
, cxx
, asm
, ld
, ar
, ranlib
, libtool
, inst_dir
):
215 machine_targets
= "X86;ARM;AArch64" if is_final_stage
else "X86"
216 if build_wasm
and is_final_stage
:
217 machine_targets
+= ";WebAssembly"
221 "-DCMAKE_C_COMPILER=%s" % slashify_path(cc
[0]),
222 "-DCMAKE_CXX_COMPILER=%s" % slashify_path(cxx
[0]),
223 "-DCMAKE_ASM_COMPILER=%s" % slashify_path(asm
[0]),
224 "-DCMAKE_LINKER=%s" % slashify_path(ld
[0]),
225 "-DCMAKE_AR=%s" % slashify_path(ar
),
226 "-DCMAKE_C_FLAGS=%s" % " ".join(cc
[1:]),
227 "-DCMAKE_CXX_FLAGS=%s" % " ".join(cxx
[1:]),
228 "-DCMAKE_ASM_FLAGS=%s" % " ".join(asm
[1:]),
229 "-DCMAKE_EXE_LINKER_FLAGS=%s" % " ".join(ld
[1:]),
230 "-DCMAKE_SHARED_LINKER_FLAGS=%s" % " ".join(ld
[1:]),
231 "-DCMAKE_BUILD_TYPE=%s" % build_type
,
232 "-DCMAKE_INSTALL_PREFIX=%s" % inst_dir
,
233 "-DLLVM_TARGETS_TO_BUILD=%s" % machine_targets
,
234 "-DLLVM_ENABLE_ASSERTIONS=%s" % ("ON" if assertions
else "OFF"),
235 "-DLLVM_ENABLE_BINDINGS=OFF",
236 "-DLLVM_ENABLE_CURL=OFF",
237 "-DLLVM_INCLUDE_TESTS=OFF",
239 if "TASK_ID" in os
.environ
:
241 "-DCLANG_REPOSITORY_STRING=taskcluster-%s" % os
.environ
["TASK_ID"],
243 # libc++ doesn't build with MSVC because of the use of #include_next.
244 if is_final_stage
and os
.path
.basename(cc
[0]).lower() != "cl.exe":
246 "-DLLVM_TOOL_LIBCXX_BUILD=%s" % ("ON" if build_libcxx
else "OFF"),
247 # libc++abi has conflicting definitions between the shared and static
248 # library on Windows because of the import library for the dll having
249 # the same name as the static library. libc++abi is not necessary on
251 "-DLLVM_TOOL_LIBCXXABI_BUILD=%s" % ("OFF" if is_windows() else "ON"),
253 if not is_final_stage
:
255 "-DLLVM_ENABLE_PROJECTS=clang",
256 "-DLLVM_TOOL_LLI_BUILD=OFF",
259 # There is no libxml2 on Windows except if we build one ourselves.
260 # libxml2 is only necessary for llvm-mt, but Windows can just use the
262 if not is_windows() and is_final_stage
:
263 cmake_args
+= ["-DLLVM_ENABLE_LIBXML2=FORCE_ON"]
264 if is_linux() and not osx_cross_compile
and is_final_stage
:
265 sysroot
= os
.path
.join(os
.environ
.get("MOZ_FETCHES_DIR", ""), "sysroot")
266 if os
.path
.exists(sysroot
):
267 cmake_args
+= ["-DLLVM_BINUTILS_INCDIR=/usr/include"]
268 cmake_args
+= ["-DCMAKE_SYSROOT=%s" % sysroot
]
269 # Work around the LLVM build system not building the i386 compiler-rt
270 # because it doesn't allow to use a sysroot for that during the cmake
272 cmake_args
+= ["-DCAN_TARGET_i386=1"]
274 cmake_args
.insert(-1, "-DLLVM_EXPORT_SYMBOLS_FOR_PLUGINS=ON")
275 cmake_args
.insert(-1, "-DLLVM_USE_CRT_RELEASE=MT")
277 # libllvm as a shared library is not supported on Windows
278 cmake_args
+= ["-DLLVM_LINK_LLVM_DYLIB=ON"]
279 if ranlib
is not None:
280 cmake_args
+= ["-DCMAKE_RANLIB=%s" % slashify_path(ranlib
)]
281 if libtool
is not None:
282 cmake_args
+= ["-DCMAKE_LIBTOOL=%s" % slashify_path(libtool
)]
283 if osx_cross_compile
:
284 arch
= "arm64" if os
.environ
.get("OSX_ARCH") == "arm64" else "x86_64"
286 "aarch64" if os
.environ
.get("OSX_ARCH") == "arm64" else "x86_64"
289 "-DCMAKE_SYSTEM_NAME=Darwin",
290 "-DCMAKE_SYSTEM_VERSION=%s" % os
.environ
["MACOSX_DEPLOYMENT_TARGET"],
291 "-DLIBCXXABI_LIBCXX_INCLUDES=%s" % libcxx_include_dir
,
292 "-DCMAKE_OSX_SYSROOT=%s" % slashify_path(os
.getenv("CROSS_SYSROOT")),
293 "-DCMAKE_FIND_ROOT_PATH=%s" % slashify_path(os
.getenv("CROSS_SYSROOT")),
294 "-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER",
295 "-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY",
296 "-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY",
297 "-DCMAKE_MACOSX_RPATH=ON",
298 "-DCMAKE_OSX_ARCHITECTURES=%s" % arch
,
299 "-DDARWIN_osx_ARCHS=%s" % arch
,
300 "-DDARWIN_osx_SYSROOT=%s" % slashify_path(os
.getenv("CROSS_SYSROOT")),
301 "-DLLVM_DEFAULT_TARGET_TRIPLE=%s-apple-darwin" % target_cpu
,
303 if os
.environ
.get("OSX_ARCH") == "arm64":
305 "-DDARWIN_osx_BUILTIN_ARCHS=arm64",
307 # Starting in LLVM 11 (which requires SDK 10.12) the build tries to
308 # detect the SDK version by calling xcrun. Cross-compiles don't have
309 # an xcrun, so we have to set the version explicitly.
311 "-DDARWIN_macosx_OVERRIDE_SDK_VERSION=%s"
312 % os
.environ
["MACOSX_DEPLOYMENT_TARGET"],
315 # Per https://releases.llvm.org/10.0.0/docs/HowToBuildWithPGO.html
317 "-DLLVM_BUILD_INSTRUMENTED=IR",
318 "-DLLVM_BUILD_RUNTIME=No",
322 "-DLLVM_PROFDATA_FILE=%s" % profile
,
327 cmake_args
+= cmake_base_args(cc
, cxx
, asm
, ld
, ar
, ranlib
, libtool
, inst_dir
)
328 cmake_args
+= [src_dir
]
329 build_package(build_dir
, cmake_args
)
331 # For some reasons the import library clang.lib of clang.exe is not
332 # installed, so we copy it by ourselves.
333 if is_windows() and is_final_stage
:
334 install_import_library(build_dir
, inst_dir
)
337 # Return the absolute path of a build tool. We first look to see if the
338 # variable is defined in the config file, and if so we make sure it's an
339 # absolute path to an existing tool, otherwise we look for a program in
342 # This expects the name of the key in the config file to match the name of
343 # the tool in the default toolchain on the system (for example, "ld" on Unix
344 # and "link" on Windows).
345 def get_tool(config
, key
):
348 f
= config
[key
].format(**os
.environ
)
350 if not os
.path
.exists(f
):
351 raise ValueError("%s must point to an existing path" % key
)
354 # Assume that we have the name of some program that should be on PATH.
355 tool
= which(f
) if f
else which(key
)
357 raise ValueError("%s not found on PATH" % (f
or key
))
361 # This function is intended to be called on the final build directory when
362 # building clang-tidy. Also clang-format binaries are included that can be used
363 # in conjunction with clang-tidy.
364 # As a separate binary we also ship clangd for the language server protocol that
365 # can be used as a plugin in `vscode`.
366 # Its job is to remove all of the files which won't be used for clang-tidy or
367 # clang-format to reduce the download size. Currently when this function
368 # finishes its job, it will leave final_dir with a layout like this:
372 # clang-apply-replacements
378 # * (nothing will be deleted here)
383 # * (nothing will be deleted here)
386 # clang-format-diff.py
389 def prune_final_dir_for_clang_tidy(final_dir
, osx_cross_compile
):
390 # Make sure we only have what we expect.
402 dirs
.append("x86_64-unknown-linux-gnu")
403 for f
in glob
.glob("%s/*" % final_dir
):
404 if os
.path
.basename(f
) not in dirs
:
405 raise Exception("Found unknown file %s in the final directory" % f
)
406 if not os
.path
.isdir(f
):
407 raise Exception("Expected %s to be a directory" % f
)
410 "clang-apply-replacements",
417 re_clang_tidy
= re
.compile(r
"^(" + "|".join(kept_binaries
) + r
")(\.exe)?$", re
.I
)
418 for f
in glob
.glob("%s/bin/*" % final_dir
):
419 if re_clang_tidy
.search(os
.path
.basename(f
)) is None:
422 # Keep include/ intact.
424 # Remove the target-specific files.
426 if os
.path
.exists(os
.path
.join(final_dir
, "x86_64-unknown-linux-gnu")):
427 shutil
.rmtree(os
.path
.join(final_dir
, "x86_64-unknown-linux-gnu"))
429 # In lib/, only keep lib/clang/N.M.O/include and the LLVM shared library.
430 re_ver_num
= re
.compile(r
"^\d+\.\d+\.\d+$", re
.I
)
431 for f
in glob
.glob("%s/lib/*" % final_dir
):
432 name
= os
.path
.basename(f
)
435 if osx_cross_compile
and name
in ["libLLVM.dylib", "libclang-cpp.dylib"]:
438 fnmatch
.fnmatch(name
, "libLLVM*.so")
439 or fnmatch
.fnmatch(name
, "libclang-cpp.so*")
443 for f
in glob
.glob("%s/lib/clang/*" % final_dir
):
444 if re_ver_num
.search(os
.path
.basename(f
)) is None:
446 for f
in glob
.glob("%s/lib/clang/*/*" % final_dir
):
447 if os
.path
.basename(f
) != "include":
450 # Completely remove libexec/, msbuild-bin and tools, if it exists.
451 shutil
.rmtree(os
.path
.join(final_dir
, "libexec"))
452 for d
in ("msbuild-bin", "tools"):
453 d
= os
.path
.join(final_dir
, d
)
454 if os
.path
.exists(d
):
457 # In share/, only keep share/clang/*tidy*
458 re_clang_tidy
= re
.compile(r
"format|tidy", re
.I
)
459 for f
in glob
.glob("%s/share/*" % final_dir
):
460 if os
.path
.basename(f
) != "clang":
462 for f
in glob
.glob("%s/share/clang/*" % final_dir
):
463 if re_clang_tidy
.search(os
.path
.basename(f
)) is None:
468 parser
= argparse
.ArgumentParser()
474 type=argparse
.FileType("r"),
475 help="Clang configuration file",
478 "--clean", required
=False, action
="store_true", help="Clean the build directory"
484 help="Skip tar packaging stage",
490 help="Do not patch source",
493 args
= parser
.parse_args()
495 if not os
.path
.exists("llvm/README.txt"):
497 "The script must be run from the root directory of the llvm-project tree"
499 source_dir
= os
.getcwd()
500 build_dir
= source_dir
+ "/build"
503 shutil
.rmtree(build_dir
)
506 llvm_source_dir
= source_dir
+ "/llvm"
507 extra_source_dir
= source_dir
+ "/clang-tools-extra"
508 clang_source_dir
= source_dir
+ "/clang"
509 lld_source_dir
= source_dir
+ "/lld"
510 libcxx_source_dir
= source_dir
+ "/libcxx"
511 libcxxabi_source_dir
= source_dir
+ "/libcxxabi"
521 cxx_name
= "clang-cl"
524 # Merge all the configs we got from the command line.
525 for c
in args
.config
:
526 this_config_dir
= os
.path
.dirname(c
.name
)
527 this_config
= json
.load(c
)
528 patches
= this_config
.get("patches")
530 this_config
["patches"] = [os
.path
.join(this_config_dir
, p
) for p
in patches
]
531 for key
, value
in this_config
.items():
532 old_value
= config
.get(key
)
533 if old_value
is None:
538 elif type(old_value
) != type(value
):
540 "{} is overriding `{}` with a value of the wrong type".format(
544 elif isinstance(old_value
, list):
546 if v
not in old_value
:
548 elif isinstance(old_value
, dict):
549 raise Exception("{} is setting `{}` to a dict?".format(c
.name
, key
))
554 if "stages" in config
:
555 stages
= int(config
["stages"])
556 if stages
not in (1, 2, 3, 4):
557 raise ValueError("We only know how to build 1, 2, 3, or 4 stages.")
559 if "skip_stages" in config
:
560 # The assumption here is that the compiler given in `cc` and other configs
561 # is the result of the last skip stage, built somewhere else.
562 skip_stages
= int(config
["skip_stages"])
563 if skip_stages
>= stages
:
564 raise ValueError("Cannot skip more stages than are built.")
568 if pgo
not in (True, False):
569 raise ValueError("Only boolean values are accepted for pgo.")
570 build_type
= "Release"
571 if "build_type" in config
:
572 build_type
= config
["build_type"]
573 if build_type
not in ("Release", "Debug", "RelWithDebInfo", "MinSizeRel"):
575 "We only know how to do Release, Debug, RelWithDebInfo or "
579 if "build_libcxx" in config
:
580 build_libcxx
= config
["build_libcxx"]
581 if build_libcxx
not in (True, False):
582 raise ValueError("Only boolean values are accepted for build_libcxx.")
584 if "build_wasm" in config
:
585 build_wasm
= config
["build_wasm"]
586 if build_wasm
not in (True, False):
587 raise ValueError("Only boolean values are accepted for build_wasm.")
588 build_clang_tidy
= False
589 if "build_clang_tidy" in config
:
590 build_clang_tidy
= config
["build_clang_tidy"]
591 if build_clang_tidy
not in (True, False):
592 raise ValueError("Only boolean values are accepted for build_clang_tidy.")
593 build_clang_tidy_alpha
= False
594 # check for build_clang_tidy_alpha only if build_clang_tidy is true
595 if build_clang_tidy
and "build_clang_tidy_alpha" in config
:
596 build_clang_tidy_alpha
= config
["build_clang_tidy_alpha"]
597 if build_clang_tidy_alpha
not in (True, False):
599 "Only boolean values are accepted for build_clang_tidy_alpha."
601 build_clang_tidy_external
= False
602 # check for build_clang_tidy_external only if build_clang_tidy is true
603 if build_clang_tidy
and "build_clang_tidy_external" in config
:
604 build_clang_tidy_external
= config
["build_clang_tidy_external"]
605 if build_clang_tidy_external
not in (True, False):
607 "Only boolean values are accepted for build_clang_tidy_external."
609 osx_cross_compile
= False
610 if "osx_cross_compile" in config
:
611 osx_cross_compile
= config
["osx_cross_compile"]
612 if osx_cross_compile
not in (True, False):
613 raise ValueError("Only boolean values are accepted for osx_cross_compile.")
614 if osx_cross_compile
and not is_linux():
615 raise ValueError("osx_cross_compile can only be used on Linux.")
617 if "assertions" in config
:
618 assertions
= config
["assertions"]
619 if assertions
not in (True, False):
620 raise ValueError("Only boolean values are accepted for assertions.")
622 if is_darwin() or osx_cross_compile
:
623 os
.environ
["MACOSX_DEPLOYMENT_TARGET"] = (
624 "11.0" if os
.environ
.get("OSX_ARCH") == "arm64" else "10.12"
627 cc
= get_tool(config
, "cc")
628 cxx
= get_tool(config
, "cxx")
629 asm
= get_tool(config
, "ml" if is_windows() else "as")
630 ld
= get_tool(config
, "link" if is_windows() else "ld")
631 ar
= get_tool(config
, "lib" if is_windows() else "ar")
632 ranlib
= None if is_windows() else get_tool(config
, "ranlib")
634 if "libtool" in config
:
635 libtool
= get_tool(config
, "libtool")
637 if not os
.path
.exists(source_dir
):
638 os
.makedirs(source_dir
)
640 if not args
.skip_patch
:
641 for p
in config
.get("patches", []):
645 (clang_source_dir
, llvm_source_dir
+ "/tools/clang"),
646 (extra_source_dir
, llvm_source_dir
+ "/tools/clang/tools/extra"),
647 (lld_source_dir
, llvm_source_dir
+ "/tools/lld"),
648 (libcxx_source_dir
, llvm_source_dir
+ "/projects/libcxx"),
649 (libcxxabi_source_dir
, llvm_source_dir
+ "/projects/libcxxabi"),
650 (source_dir
+ "/cmake", llvm_source_dir
+ "/projects/cmake"),
653 # On Windows, we have to re-copy the whole directory every time.
654 if not is_windows() and os
.path
.islink(l
[1]):
657 if os
.path
.exists(l
[0]):
660 package_name
= "clang"
662 package_name
= "clang-tidy"
663 if not args
.skip_patch
:
665 source_dir
, build_clang_tidy_alpha
, build_clang_tidy_external
668 if not os
.path
.exists(build_dir
):
669 os
.makedirs(build_dir
)
671 libcxx_include_dir
= os
.path
.join(llvm_source_dir
, "projects", "libcxx", "include")
673 stage1_dir
= build_dir
+ "/stage1"
674 stage1_inst_dir
= stage1_dir
+ "/" + package_name
676 final_stage_dir
= stage1_dir
680 extra_cxxflags
= ["-stdlib=libc++"]
682 extra_cxxflags2
= ["-stdlib=libc++"]
688 extra_cflags2
= ["-fPIC"]
689 # Silence clang's warnings about arguments not being used in compilation.
692 "-Qunused-arguments",
695 # Avoid libLLVM internal function calls going through the PLT.
696 extra_ldflags
= ["-Wl,-Bsymbolic-functions"]
697 # For whatever reason, LLVM's build system will set things up to turn
698 # on -ffunction-sections and -fdata-sections, but won't turn on the
699 # corresponding option to strip unused sections. We do it explicitly
700 # here. LLVM's build system is also picky about turning on ICF, so
701 # we do that explicitly here, too.
702 extra_ldflags
+= ["-fuse-ld=gold", "-Wl,--gc-sections", "-Wl,--icf=safe"]
706 # clang-cl would like to figure out what it's supposed to be emulating
707 # by looking at an MSVC install, but we don't really have that here.
708 # Force things on based on WinMsvc.cmake.
709 # Ideally, we'd just use WinMsvc.cmake as a toolchain file, but it only
710 # really works for cross-compiles, which this is not.
711 with
open(os
.path
.join(llvm_source_dir
, "cmake/platforms/WinMsvc.cmake")) as f
:
715 for item
in line
.split()
716 if "-fms-compatibility-version=" in item
718 extra_cflags2
= [compat
]
719 extra_cxxflags2
= [compat
]
723 if osx_cross_compile
:
724 # undo the damage done in the is_linux() block above, and also simulate
725 # the is_darwin() block above.
727 extra_cxxflags
= ["-stdlib=libc++"]
728 extra_cxxflags2
= ["-stdlib=libc++"]
732 "x86_64-apple-darwin",
733 "-mlinker-version=137",
735 "%s/bin" % os
.getenv("CROSS_CCTOOLS_PATH"),
737 os
.getenv("CROSS_SYSROOT"),
738 # technically the sysroot flag there should be enough to deduce this,
739 # but clang needs some help to figure this out.
740 "-I%s/usr/include" % os
.getenv("CROSS_SYSROOT"),
742 "%s/System/Library/Frameworks" % os
.getenv("CROSS_SYSROOT"),
744 extra_cflags
+= extra_flags
745 extra_cxxflags
+= extra_flags
746 extra_cflags2
+= extra_flags
747 extra_cxxflags2
+= extra_flags
748 extra_asmflags
+= extra_flags
750 "-Wl,-syslibroot,%s" % os
.getenv("CROSS_SYSROOT"),
754 upload_dir
= os
.getenv("UPLOAD_DIR")
755 if assertions
and upload_dir
:
756 extra_cflags2
+= ["-fcrash-diagnostics-dir=%s" % upload_dir
]
757 extra_cxxflags2
+= ["-fcrash-diagnostics-dir=%s" % upload_dir
]
762 [cxx
] + extra_cxxflags
,
763 [asm
] + extra_asmflags
,
764 [ld
] + extra_ldflags
,
777 is_final_stage
=(stages
== 1),
780 if stages
>= 2 and skip_stages
< 2:
781 stage2_dir
= build_dir
+ "/stage2"
782 stage2_inst_dir
= stage2_dir
+ "/" + package_name
783 final_stage_dir
= stage2_dir
785 cc
= stage1_inst_dir
+ "/bin/%s%s" % (cc_name
, exe_ext
)
786 cxx
= stage1_inst_dir
+ "/bin/%s%s" % (cxx_name
, exe_ext
)
787 asm
= stage1_inst_dir
+ "/bin/%s%s" % (cc_name
, exe_ext
)
789 [cc
] + extra_cflags2
,
790 [cxx
] + extra_cxxflags2
,
791 [asm
] + extra_asmflags
,
792 [ld
] + extra_ldflags
,
805 is_final_stage
=(stages
== 2),
806 profile
="gen" if pgo
else None,
809 if stages
>= 3 and skip_stages
< 3:
810 stage3_dir
= build_dir
+ "/stage3"
811 stage3_inst_dir
= stage3_dir
+ "/" + package_name
812 final_stage_dir
= stage3_dir
814 cc
= stage2_inst_dir
+ "/bin/%s%s" % (cc_name
, exe_ext
)
815 cxx
= stage2_inst_dir
+ "/bin/%s%s" % (cxx_name
, exe_ext
)
816 asm
= stage2_inst_dir
+ "/bin/%s%s" % (cc_name
, exe_ext
)
818 [cc
] + extra_cflags2
,
819 [cxx
] + extra_cxxflags2
,
820 [asm
] + extra_asmflags
,
821 [ld
] + extra_ldflags
,
837 llvm_profdata
= stage2_inst_dir
+ "/bin/llvm-profdata%s" % exe_ext
838 merge_cmd
= [llvm_profdata
, "merge", "-o", "merged.profdata"]
839 profraw_files
= glob
.glob(
840 os
.path
.join(stage2_dir
, "build", "profiles", "*.profraw")
842 run_in(stage3_dir
, merge_cmd
+ profraw_files
)
845 shutil
.copy2(os
.path
.join(stage3_dir
, "merged.profdata"), upload_dir
)
848 if stages
>= 4 and skip_stages
< 4:
849 stage4_dir
= build_dir
+ "/stage4"
850 final_stage_dir
= stage4_dir
854 profile_dir
= os
.environ
.get("MOZ_FETCHES_DIR", "")
856 profile_dir
= stage3_dir
857 profile
= os
.path
.join(profile_dir
, "merged.profdata")
859 cc
= stage3_inst_dir
+ "/bin/%s%s" % (cc_name
, exe_ext
)
860 cxx
= stage3_inst_dir
+ "/bin/%s%s" % (cxx_name
, exe_ext
)
861 asm
= stage3_inst_dir
+ "/bin/%s%s" % (cc_name
, exe_ext
)
863 [cc
] + extra_cflags2
,
864 [cxx
] + extra_cxxflags2
,
865 [asm
] + extra_asmflags
,
866 [ld
] + extra_ldflags
,
884 prune_final_dir_for_clang_tidy(
885 os
.path
.join(final_stage_dir
, package_name
), osx_cross_compile
888 if not args
.skip_tar
:
889 build_tar_package("%s.tar.zst" % package_name
, final_stage_dir
, package_name
)
892 if __name__
== "__main__":