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...
20 from contextlib
import contextmanager
21 from shutil
import which
26 "x86_64-unknown-linux-gnu": ("Linux", "x86_64"),
27 "x86_64-pc-windows-msvc": ("Windows", "AMD64"),
28 "x86_64-apple-darwin": ("Darwin", "x86_64"),
29 "aarch64-apple-darwin": ("Darwin", "arm64"),
33 def is_llvm_toolchain(cc
, cxx
):
34 return "clang" in cc
and "clang" in cxx
38 print(" ".join(args
), file=sys
.stderr
, flush
=True)
39 if args
[0] == "cmake":
40 # CMake `message(STATUS)` messages, as appearing in failed source code
41 # compiles, appear on stdout, so we only capture that.
42 p
= subprocess
.Popen(args
, stdout
=subprocess
.PIPE
)
46 sys
.stdout
.write(line
.decode())
49 if r
!= 0 and os
.environ
.get("UPLOAD_DIR"):
50 cmake_output_re
= re
.compile(b
'See also "(.*/CMakeOutput.log)"')
51 cmake_error_re
= re
.compile(b
'See also "(.*/CMakeError.log)"')
53 def find_first_match(re
):
59 output_match
= find_first_match(cmake_output_re
)
60 error_match
= find_first_match(cmake_error_re
)
62 upload_dir
= os
.environ
["UPLOAD_DIR"].encode("utf-8")
63 if output_match
or error_match
:
66 shutil
.copy2(output_match
.group(1), upload_dir
)
68 shutil
.copy2(error_match
.group(1), upload_dir
)
70 r
= subprocess
.call(args
)
74 def run_in(path
, args
):
82 print('cd "%s"' % path
, file=sys
.stderr
)
87 print('cd "%s"' % d
, file=sys
.stderr
)
91 def patch(patch
, srcdir
):
92 patch
= os
.path
.realpath(patch
)
93 check_run(["patch", "-d", srcdir
, "-p1", "-i", patch
, "--fuzz=0", "-s"])
96 def import_clang_tidy(source_dir
, build_clang_tidy_alpha
, build_clang_tidy_external
):
97 clang_plugin_path
= os
.path
.join(os
.path
.dirname(sys
.argv
[0]), "..", "clang-plugin")
98 clang_tidy_path
= os
.path
.join(source_dir
, "clang-tools-extra/clang-tidy")
99 sys
.path
.append(clang_plugin_path
)
100 from import_mozilla_checks
import do_import
103 "alpha": build_clang_tidy_alpha
,
104 "external": build_clang_tidy_external
,
106 do_import(clang_plugin_path
, clang_tidy_path
, import_options
)
109 def build_package(package_build_dir
, cmake_args
):
110 if not os
.path
.exists(package_build_dir
):
111 os
.mkdir(package_build_dir
)
112 # If CMake has already been run, it may have been run with different
113 # arguments, so we need to re-run it. Make sure the cached copy of the
114 # previous CMake run is cleared before running it again.
115 if os
.path
.exists(package_build_dir
+ "/CMakeCache.txt"):
116 os
.remove(package_build_dir
+ "/CMakeCache.txt")
117 if os
.path
.exists(package_build_dir
+ "/CMakeFiles"):
118 shutil
.rmtree(package_build_dir
+ "/CMakeFiles")
120 run_in(package_build_dir
, ["cmake"] + cmake_args
)
121 run_in(package_build_dir
, ["ninja", "install", "-v"])
125 def updated_env(env
):
126 old_env
= os
.environ
.copy()
127 os
.environ
.update(env
)
130 os
.environ
.update(old_env
)
133 def build_tar_package(name
, base
, directory
):
134 name
= os
.path
.realpath(name
)
135 print("tarring {} from {}/{}".format(name
, base
, directory
), file=sys
.stderr
)
136 assert name
.endswith(".tar.zst")
138 cctx
= zstandard
.ZstdCompressor()
139 with
open(name
, "wb") as f
, cctx
.stream_writer(f
) as z
:
140 with tarfile
.open(mode
="w|", fileobj
=z
) as tf
:
149 if e
.errno
!= errno
.EEXIST
or not os
.path
.isdir(path
):
154 if os
.path
.isdir(path
):
163 def install_import_library(build_dir
, clang_dir
):
165 os
.path
.join(build_dir
, "lib", "clang.lib"), os
.path
.join(clang_dir
, "lib")
169 def is_darwin(target
):
170 return "-apple-darwin" in target
173 def is_linux(target
):
174 return "-linux-gnu" in target
177 def is_windows(target
):
178 return "-windows-msvc" in target
181 def is_cross_compile(target
):
182 return SUPPORTED_TARGETS
[target
] != (platform
.system(), platform
.machine())
199 is_final_stage
=False,
202 if not os
.path
.exists(stage_dir
):
205 build_dir
= stage_dir
+ "/build"
206 inst_dir
= stage_dir
+ "/" + package_name
208 # cmake doesn't deal well with backslashes in paths.
209 def slashify_path(path
):
210 return path
.replace("\\", "/")
212 def cmake_base_args(cc
, cxx
, asm
, ar
, ranlib
, ldflags
, inst_dir
):
213 machine_targets
= targets
if is_final_stage
and targets
else "X86"
217 "-DCMAKE_C_COMPILER=%s" % slashify_path(cc
[0]),
218 "-DCMAKE_CXX_COMPILER=%s" % slashify_path(cxx
[0]),
219 "-DCMAKE_ASM_COMPILER=%s" % slashify_path(asm
[0]),
220 "-DCMAKE_AR=%s" % slashify_path(ar
),
221 "-DCMAKE_C_FLAGS=%s" % " ".join(cc
[1:]),
222 "-DCMAKE_CXX_FLAGS=%s" % " ".join(cxx
[1:]),
223 "-DCMAKE_ASM_FLAGS=%s" % " ".join(asm
[1:]),
224 "-DCMAKE_EXE_LINKER_FLAGS=%s" % " ".join(ldflags
),
225 "-DCMAKE_SHARED_LINKER_FLAGS=%s" % " ".join(ldflags
),
226 "-DCMAKE_BUILD_TYPE=%s" % build_type
,
227 "-DCMAKE_INSTALL_PREFIX=%s" % inst_dir
,
228 "-DLLVM_TARGETS_TO_BUILD=%s" % machine_targets
,
229 "-DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF",
230 "-DLLVM_ENABLE_ASSERTIONS=%s" % ("ON" if assertions
else "OFF"),
231 "-DLLVM_ENABLE_BINDINGS=OFF",
232 "-DLLVM_ENABLE_CURL=OFF",
233 "-DLLVM_INCLUDE_TESTS=OFF",
235 if is_llvm_toolchain(cc
[0], cxx
[0]):
236 cmake_args
+= ["-DLLVM_ENABLE_LLD=ON"]
237 elif is_windows(target
) and is_cross_compile(target
):
239 "Cannot cross-compile for Windows with a compiler that is not clang"
242 if "TASK_ID" in os
.environ
:
244 "-DCLANG_REPOSITORY_STRING=taskcluster-%s" % os
.environ
["TASK_ID"],
246 projects
= ["clang", "lld"]
248 projects
.append("clang-tools-extra")
250 cmake_args
.append("-DLLVM_TOOL_LLI_BUILD=OFF")
252 cmake_args
.append("-DLLVM_ENABLE_PROJECTS=%s" % ";".join(projects
))
254 # There is no libxml2 on Windows except if we build one ourselves.
255 # libxml2 is only necessary for llvm-mt, but Windows can just use the
257 if not is_windows(target
) and is_final_stage
:
258 cmake_args
+= ["-DLLVM_ENABLE_LIBXML2=FORCE_ON"]
259 if is_linux(target
) and is_final_stage
:
260 sysroot
= os
.path
.join(os
.environ
.get("MOZ_FETCHES_DIR", ""), "sysroot")
261 if os
.path
.exists(sysroot
):
262 cmake_args
+= ["-DLLVM_BINUTILS_INCDIR=/usr/include"]
263 cmake_args
+= ["-DCMAKE_SYSROOT=%s" % sysroot
]
264 # Work around the LLVM build system not building the i386 compiler-rt
265 # because it doesn't allow to use a sysroot for that during the cmake
267 cmake_args
+= ["-DCAN_TARGET_i386=1"]
268 cmake_args
+= ["-DLLVM_ENABLE_TERMINFO=OFF"]
269 if is_windows(target
):
270 cmake_args
.insert(-1, "-DLLVM_EXPORT_SYMBOLS_FOR_PLUGINS=ON")
271 cmake_args
.insert(-1, "-DLLVM_USE_CRT_RELEASE=MT")
272 if is_cross_compile(target
):
274 f
"-DCMAKE_TOOLCHAIN_FILE={src_dir}/cmake/platforms/WinMsvc.cmake",
275 f
"-DLLVM_NATIVE_TOOLCHAIN={os.path.dirname(os.path.dirname(cc[0]))}",
276 f
"-DHOST_ARCH={target[: -len('-pc-windows-msvc')]}",
277 f
"-DLLVM_WINSYSROOT={os.environ['VSINSTALLDIR']}",
278 "-DLLVM_DISABLE_ASSEMBLY_FILES=ON",
281 # libllvm as a shared library is not supported on Windows
282 cmake_args
+= ["-DLLVM_LINK_LLVM_DYLIB=ON"]
283 if ranlib
is not None:
284 cmake_args
+= ["-DCMAKE_RANLIB=%s" % slashify_path(ranlib
)]
285 if is_darwin(target
) and is_cross_compile(target
):
286 arch
= "arm64" if target
.startswith("aarch64") else "x86_64"
288 "-DCMAKE_SYSTEM_NAME=Darwin",
289 "-DCMAKE_SYSTEM_VERSION=%s" % os
.environ
["MACOSX_DEPLOYMENT_TARGET"],
290 "-DCMAKE_OSX_SYSROOT=%s" % slashify_path(os
.getenv("CROSS_SYSROOT")),
291 "-DCMAKE_FIND_ROOT_PATH=%s" % slashify_path(os
.getenv("CROSS_SYSROOT")),
292 "-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER",
293 "-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY",
294 "-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY",
295 "-DCMAKE_MACOSX_RPATH=ON",
296 "-DCMAKE_OSX_ARCHITECTURES=%s" % arch
,
297 "-DDARWIN_osx_ARCHS=%s" % arch
,
298 "-DDARWIN_osx_SYSROOT=%s" % slashify_path(os
.getenv("CROSS_SYSROOT")),
299 "-DLLVM_DEFAULT_TARGET_TRIPLE=%s" % target
,
300 "-DCMAKE_C_COMPILER_TARGET=%s" % target
,
301 "-DCMAKE_CXX_COMPILER_TARGET=%s" % target
,
302 "-DCMAKE_ASM_COMPILER_TARGET=%s" % target
,
306 "-DDARWIN_osx_BUILTIN_ARCHS=arm64",
308 # Starting in LLVM 11 (which requires SDK 10.12) the build tries to
309 # detect the SDK version by calling xcrun. Cross-compiles don't have
310 # an xcrun, so we have to set the version explicitly.
312 "-DDARWIN_macosx_OVERRIDE_SDK_VERSION=%s"
313 % os
.environ
["MACOSX_DEPLOYMENT_TARGET"],
317 # Per https://releases.llvm.org/10.0.0/docs/HowToBuildWithPGO.html
319 "-DLLVM_BUILD_INSTRUMENTED=IR",
320 "-DLLVM_BUILD_RUNTIME=No",
324 "-DLLVM_PROFDATA_FILE=%s" % profile
,
327 # Using LTO for both profile generation and usage to avoid most
328 # "function control flow change detected (hash mismatch)" error.
329 if profile
and not is_windows(target
):
330 cmake_args
.append("-DLLVM_ENABLE_LTO=Thin")
334 cmake_args
+= cmake_base_args(cc
, cxx
, asm
, ar
, ranlib
, ldflags
, inst_dir
)
335 cmake_args
+= [src_dir
]
336 build_package(build_dir
, cmake_args
)
338 # For some reasons the import library clang.lib of clang.exe is not
339 # installed, so we copy it by ourselves.
340 if is_windows(target
) and is_final_stage
:
341 install_import_library(build_dir
, inst_dir
)
344 # Return the absolute path of a build tool. We first look to see if the
345 # variable is defined in the config file, and if so we make sure it's an
346 # absolute path to an existing tool, otherwise we look for a program in
349 # This expects the name of the key in the config file to match the name of
350 # the tool in the default toolchain on the system (for example, "ld" on Unix
351 # and "link" on Windows).
352 def get_tool(config
, key
):
355 f
= config
[key
].format(**os
.environ
)
357 if not os
.path
.exists(f
):
358 raise ValueError("%s must point to an existing path" % key
)
361 # Assume that we have the name of some program that should be on PATH.
362 tool
= which(f
) if f
else which(key
)
364 raise ValueError("%s not found on PATH" % (f
or key
))
368 # This function is intended to be called on the final build directory when
369 # building clang-tidy. Also clang-format binaries are included that can be used
370 # in conjunction with clang-tidy.
371 # As a separate binary we also ship clangd for the language server protocol that
372 # can be used as a plugin in `vscode`.
373 # Its job is to remove all of the files which won't be used for clang-tidy or
374 # clang-format to reduce the download size. Currently when this function
375 # finishes its job, it will leave final_dir with a layout like this:
379 # clang-apply-replacements
385 # * (nothing will be deleted here)
390 # * (nothing will be deleted here)
393 # clang-format-diff.py
396 def prune_final_dir_for_clang_tidy(final_dir
, target
):
397 # Make sure we only have what we expect.
409 dirs
.append("x86_64-unknown-linux-gnu")
410 for f
in glob
.glob("%s/*" % final_dir
):
411 if os
.path
.basename(f
) not in dirs
:
412 raise Exception("Found unknown file %s in the final directory" % f
)
413 if not os
.path
.isdir(f
):
414 raise Exception("Expected %s to be a directory" % f
)
417 "clang-apply-replacements",
424 re_clang_tidy
= re
.compile(r
"^(" + "|".join(kept_binaries
) + r
")(\.exe)?$", re
.I
)
425 for f
in glob
.glob("%s/bin/*" % final_dir
):
426 if re_clang_tidy
.search(os
.path
.basename(f
)) is None:
429 # Keep include/ intact.
431 # Remove the target-specific files.
433 if os
.path
.exists(os
.path
.join(final_dir
, "x86_64-unknown-linux-gnu")):
434 shutil
.rmtree(os
.path
.join(final_dir
, "x86_64-unknown-linux-gnu"))
436 # In lib/, only keep lib/clang/N.M.O/include and the LLVM shared library.
437 re_ver_num
= re
.compile(r
"^\d+(?:\.\d+\.\d+)?$", re
.I
)
438 for f
in glob
.glob("%s/lib/*" % final_dir
):
439 name
= os
.path
.basename(f
)
442 if is_darwin(target
) and name
in ["libLLVM.dylib", "libclang-cpp.dylib"]:
444 if is_linux(target
) and (
445 fnmatch
.fnmatch(name
, "libLLVM*.so")
446 or fnmatch
.fnmatch(name
, "libclang-cpp.so*")
450 for f
in glob
.glob("%s/lib/clang/*" % final_dir
):
451 if re_ver_num
.search(os
.path
.basename(f
)) is None:
453 for f
in glob
.glob("%s/lib/clang/*/*" % final_dir
):
454 if os
.path
.basename(f
) != "include":
457 # Completely remove libexec/, msbuild-bin and tools, if it exists.
458 shutil
.rmtree(os
.path
.join(final_dir
, "libexec"))
459 for d
in ("msbuild-bin", "tools"):
460 d
= os
.path
.join(final_dir
, d
)
461 if os
.path
.exists(d
):
464 # In share/, only keep share/clang/*tidy*
465 re_clang_tidy
= re
.compile(r
"format|tidy", re
.I
)
466 for f
in glob
.glob("%s/share/*" % final_dir
):
467 if os
.path
.basename(f
) != "clang":
469 for f
in glob
.glob("%s/share/clang/*" % final_dir
):
470 if re_clang_tidy
.search(os
.path
.basename(f
)) is None:
475 parser
= argparse
.ArgumentParser()
481 type=argparse
.FileType("r"),
482 help="Clang configuration file",
485 "--clean", required
=False, action
="store_true", help="Clean the build directory"
491 help="Skip tar packaging stage",
497 help="Do not patch source",
500 args
= parser
.parse_args()
502 if not os
.path
.exists("llvm/README.txt"):
504 "The script must be run from the root directory of the llvm-project tree"
506 source_dir
= os
.getcwd()
507 build_dir
= source_dir
+ "/build"
510 shutil
.rmtree(build_dir
)
513 llvm_source_dir
= source_dir
+ "/llvm"
516 # Merge all the configs we got from the command line.
517 for c
in args
.config
:
518 this_config_dir
= os
.path
.dirname(c
.name
)
519 this_config
= json
.load(c
)
520 patches
= this_config
.get("patches")
522 this_config
["patches"] = [os
.path
.join(this_config_dir
, p
) for p
in patches
]
523 for key
, value
in this_config
.items():
524 old_value
= config
.get(key
)
525 if old_value
is None:
530 elif type(old_value
) != type(value
):
532 "{} is overriding `{}` with a value of the wrong type".format(
536 elif isinstance(old_value
, list):
538 if v
not in old_value
:
540 elif isinstance(old_value
, dict):
541 raise Exception("{} is setting `{}` to a dict?".format(c
.name
, key
))
546 if "stages" in config
:
547 stages
= int(config
["stages"])
548 if stages
not in (1, 2, 3, 4):
549 raise ValueError("We only know how to build 1, 2, 3, or 4 stages.")
551 if "skip_stages" in config
:
552 # The assumption here is that the compiler given in `cc` and other configs
553 # is the result of the last skip stage, built somewhere else.
554 skip_stages
= int(config
["skip_stages"])
555 if skip_stages
>= stages
:
556 raise ValueError("Cannot skip more stages than are built.")
560 if pgo
not in (True, False):
561 raise ValueError("Only boolean values are accepted for pgo.")
562 build_type
= "Release"
563 if "build_type" in config
:
564 build_type
= config
["build_type"]
565 if build_type
not in ("Release", "Debug", "RelWithDebInfo", "MinSizeRel"):
567 "We only know how to do Release, Debug, RelWithDebInfo or "
570 targets
= config
.get("targets")
571 build_clang_tidy
= False
572 if "build_clang_tidy" in config
:
573 build_clang_tidy
= config
["build_clang_tidy"]
574 if build_clang_tidy
not in (True, False):
575 raise ValueError("Only boolean values are accepted for build_clang_tidy.")
576 build_clang_tidy_alpha
= False
577 # check for build_clang_tidy_alpha only if build_clang_tidy is true
578 if build_clang_tidy
and "build_clang_tidy_alpha" in config
:
579 build_clang_tidy_alpha
= config
["build_clang_tidy_alpha"]
580 if build_clang_tidy_alpha
not in (True, False):
582 "Only boolean values are accepted for build_clang_tidy_alpha."
584 build_clang_tidy_external
= False
585 # check for build_clang_tidy_external only if build_clang_tidy is true
586 if build_clang_tidy
and "build_clang_tidy_external" in config
:
587 build_clang_tidy_external
= config
["build_clang_tidy_external"]
588 if build_clang_tidy_external
not in (True, False):
590 "Only boolean values are accepted for build_clang_tidy_external."
593 if "assertions" in config
:
594 assertions
= config
["assertions"]
595 if assertions
not in (True, False):
596 raise ValueError("Only boolean values are accepted for assertions.")
598 for t
in SUPPORTED_TARGETS
:
599 if not is_cross_compile(t
):
604 f
"Cannot use this script on {platform.system()} {platform.machine()}"
607 target
= config
.get("target", host
)
608 if target
not in SUPPORTED_TARGETS
:
609 raise ValueError(f
"{target} is not a supported target.")
611 if is_cross_compile(target
) and not is_linux(host
):
612 raise Exception("Cross-compilation is only supported on Linux")
614 if is_darwin(target
):
615 os
.environ
["MACOSX_DEPLOYMENT_TARGET"] = (
616 "11.0" if target
.startswith("aarch64") else "10.12"
619 if is_windows(target
):
622 cxx_name
= "clang-cl"
628 cc
= get_tool(config
, "cc")
629 cxx
= get_tool(config
, "cxx")
630 asm
= get_tool(config
, "ml" if is_windows(target
) else "as")
631 # Not using lld here as default here because it's not in PATH. But clang
632 # knows how to find it when they are installed alongside each others.
633 ar
= get_tool(config
, "lib" if is_windows(target
) else "ar")
634 ranlib
= None if is_windows(target
) else get_tool(config
, "ranlib")
636 if not os
.path
.exists(source_dir
):
637 os
.makedirs(source_dir
)
639 if not args
.skip_patch
:
640 for p
in config
.get("patches", []):
643 package_name
= "clang"
645 package_name
= "clang-tidy"
646 if not args
.skip_patch
:
648 source_dir
, build_clang_tidy_alpha
, build_clang_tidy_external
651 if not os
.path
.exists(build_dir
):
652 os
.makedirs(build_dir
)
654 stage1_dir
= build_dir
+ "/stage1"
655 stage1_inst_dir
= stage1_dir
+ "/" + package_name
657 final_stage_dir
= stage1_dir
659 if is_darwin(target
):
665 # It's unfortunately required to specify the linker used here because
666 # the linker flags are used in LLVM's configure step before
667 # -DLLVM_ENABLE_LLD is actually processed.
672 elif is_linux(target
):
675 extra_cflags2
= ["-fPIC"]
676 # Silence clang's warnings about arguments not being used in compilation.
679 "-Qunused-arguments",
682 # Avoid libLLVM internal function calls going through the PLT.
683 extra_ldflags
= ["-Wl,-Bsymbolic-functions"]
684 # For whatever reason, LLVM's build system will set things up to turn
685 # on -ffunction-sections and -fdata-sections, but won't turn on the
686 # corresponding option to strip unused sections. We do it explicitly
687 # here. LLVM's build system is also picky about turning on ICF, so
688 # we do that explicitly here, too.
690 # It's unfortunately required to specify the linker used here because
691 # the linker flags are used in LLVM's configure step before
692 # -DLLVM_ENABLE_LLD is actually processed.
693 if is_llvm_toolchain(cc
, cxx
):
694 extra_ldflags
+= ["-fuse-ld=lld", "-Wl,--icf=safe"]
695 extra_ldflags
+= ["-Wl,--gc-sections"]
696 elif is_windows(target
):
699 # clang-cl would like to figure out what it's supposed to be emulating
700 # by looking at an MSVC install, but we don't really have that here.
701 # Force things on based on WinMsvc.cmake.
702 # Ideally, we'd just use WinMsvc.cmake as a toolchain file, but it only
703 # really works for cross-compiles, which this is not.
704 with
open(os
.path
.join(llvm_source_dir
, "cmake/platforms/WinMsvc.cmake")) as f
:
708 for item
in line
.split()
709 if "-fms-compatibility-version=" in item
711 extra_cflags2
= [compat
]
712 extra_cxxflags2
= [compat
]
716 upload_dir
= os
.getenv("UPLOAD_DIR")
717 if assertions
and upload_dir
:
718 extra_cflags2
+= ["-fcrash-diagnostics-dir=%s" % upload_dir
]
719 extra_cxxflags2
+= ["-fcrash-diagnostics-dir=%s" % upload_dir
]
724 [cxx
] + extra_cxxflags
,
725 [asm
] + extra_asmflags
,
736 is_final_stage
=(stages
== 1),
739 if stages
>= 2 and skip_stages
< 2:
740 stage2_dir
= build_dir
+ "/stage2"
741 stage2_inst_dir
= stage2_dir
+ "/" + package_name
742 final_stage_dir
= stage2_dir
744 cc
= stage1_inst_dir
+ "/bin/%s%s" % (cc_name
, exe_ext
)
745 cxx
= stage1_inst_dir
+ "/bin/%s%s" % (cxx_name
, exe_ext
)
746 asm
= stage1_inst_dir
+ "/bin/%s%s" % (cc_name
, exe_ext
)
748 [cc
] + extra_cflags2
,
749 [cxx
] + extra_cxxflags2
,
750 [asm
] + extra_asmflags
,
761 is_final_stage
=(stages
== 2),
762 profile
="gen" if pgo
else None,
765 if stages
>= 3 and skip_stages
< 3:
766 stage3_dir
= build_dir
+ "/stage3"
767 stage3_inst_dir
= stage3_dir
+ "/" + package_name
768 final_stage_dir
= stage3_dir
770 cc
= stage2_inst_dir
+ "/bin/%s%s" % (cc_name
, exe_ext
)
771 cxx
= stage2_inst_dir
+ "/bin/%s%s" % (cxx_name
, exe_ext
)
772 asm
= stage2_inst_dir
+ "/bin/%s%s" % (cc_name
, exe_ext
)
774 [cc
] + extra_cflags2
,
775 [cxx
] + extra_cxxflags2
,
776 [asm
] + extra_asmflags
,
790 llvm_profdata
= stage2_inst_dir
+ "/bin/llvm-profdata%s" % exe_ext
791 merge_cmd
= [llvm_profdata
, "merge", "-o", "merged.profdata"]
792 profraw_files
= glob
.glob(
793 os
.path
.join(stage2_dir
, "build", "profiles", "*.profraw")
795 run_in(stage3_dir
, merge_cmd
+ profraw_files
)
798 shutil
.copy2(os
.path
.join(stage3_dir
, "merged.profdata"), upload_dir
)
801 if stages
>= 4 and skip_stages
< 4:
802 stage4_dir
= build_dir
+ "/stage4"
803 final_stage_dir
= stage4_dir
807 profile_dir
= os
.environ
.get("MOZ_FETCHES_DIR", "")
809 profile_dir
= stage3_dir
810 profile
= os
.path
.join(profile_dir
, "merged.profdata")
812 cc
= stage3_inst_dir
+ "/bin/%s%s" % (cc_name
, exe_ext
)
813 cxx
= stage3_inst_dir
+ "/bin/%s%s" % (cxx_name
, exe_ext
)
814 asm
= stage3_inst_dir
+ "/bin/%s%s" % (cc_name
, exe_ext
)
816 [cc
] + extra_cflags2
,
817 [cxx
] + extra_cxxflags2
,
818 [asm
] + extra_asmflags
,
834 prune_final_dir_for_clang_tidy(
835 os
.path
.join(final_stage_dir
, package_name
), target
838 if not args
.skip_tar
:
839 build_tar_package("%s.tar.zst" % package_name
, final_stage_dir
, package_name
)
842 if __name__
== "__main__":