blob: 8dd5f2044960d7175d6f29ecfcabdb9c83541c9f [file] [log] [blame]
# Copyright 2024 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Recipe for building Clang toolchain without any runtimes."""
from PB.go.chromium.org.luci.common.proto.srcman.manifest import Manifest
from PB.recipes.fuchsia.contrib.clang import InputProperties
DEPS = [
"fuchsia/cas_util",
"fuchsia/cipd_util",
"fuchsia/cmake",
"fuchsia/git_checkout",
"fuchsia/go",
"fuchsia/goma",
"fuchsia/ninja",
"fuchsia/platform_util",
"fuchsia/tensorflow",
"fuchsia/toolchain",
"fuchsia/toolchain_3p_libs",
"recipe_engine/buildbucket",
"recipe_engine/cipd",
"recipe_engine/context",
"recipe_engine/file",
"recipe_engine/path",
"recipe_engine/platform",
"recipe_engine/properties",
"recipe_engine/step",
]
PROPERTIES = InputProperties
CIPD_SERVER_HOST = "chrome-infra-packages.appspot.com"
def RunSteps(api, props):
# default values
if not props.repository:
props.repository = "https://llvm.googlesource.com/llvm-project"
if not props.revision:
props.revision = "refs/heads/main"
use_goma = (
not api.platform.arch == "arm" and api.platform.bits == 64
) and not api.platform.is_win
if use_goma:
ninja_jobs = api.goma.jobs
remote_build_context = api.goma()
host_platform = api.cipd_util.platform_name
target_platform = props.platform or host_platform
use_breakpad = host_platform == "linux-amd64"
enable_ml_inliner = target_platform not in ("linux-arm64", "mac-arm64")
manifest = Manifest()
staging_dir = api.path.start_dir
pkg_dir = staging_dir.joinpath("llvm_install")
api.file.ensure_directory("create pkg dir", pkg_dir)
cipd_dir = ensure_llvm_deps_prebuilts(
api,
target_platform,
use_breakpad=use_breakpad,
enable_ml_inliner=enable_ml_inliner,
manifest=manifest,
)
llvm_dir, revision = api.git_checkout(props.repository, fallback_ref=props.revision)
git_checkout = manifest.directories[str(llvm_dir)].git_checkout
git_checkout.repo_url = props.repository
git_checkout.revision = revision
env_prefixes = {"PATH": [cipd_dir.joinpath("bin")]}
target_triple = api.platform_util.platform(target_platform).triple
host_triple = api.platform_util.platform(host_platform).triple
linux_sysroot = cipd_dir.joinpath("linux")
with remote_build_context, api.context(env_prefixes=env_prefixes):
arguments = {
"target_triple": target_triple,
"host_triple": host_triple,
"target_sysroot": linux_sysroot,
"host_sysroot": linux_sysroot,
"linux_sysroot": linux_sysroot,
"llvm_repo": props.repository,
"lto_option": "False",
"ninja": api.ninja.path,
"install_prefix": "",
}
arguments.update(api.toolchain.toolchain_base_args(api.platform.name, cipd_dir))
options = api.toolchain.toolchain_base_flags(api.platform.name)
options.extend(api.toolchain.toolchain_repo_flags())
options.extend(api.toolchain.toolchain_lto_flags())
arguments.update({"cflags": "", "cxxflags": "", "ldflags": ""})
api.file.write_proto(
"source manifest",
pkg_dir.joinpath("source_manifest.json"),
manifest,
"JSONPB",
)
# build clang+llvm
build_dir = staging_dir.joinpath("llvm_build")
api.file.ensure_directory("create llvm build dir", build_dir)
options.extend(
[
# Unprefixed flags are used by the first stage compiler.
f"-DCMAKE_{mode}_LINKER_FLAGS=-static-libstdc++"
for mode in ["SHARED", "MODULE", "EXE"]
]
)
env = {
"CLANG_MODULE_CACHE_PATH": "",
}
compiler_wrapper = None
if use_goma:
compiler_wrapper = api.goma.goma_dir.joinpath("gomacc")
arguments["compiler_wrapper"] = compiler_wrapper
options.extend(api.toolchain.compiler_wrapper_flags())
with api.step.nest("build llvm dependencies"):
options.append("-DCMAKE_FIND_PACKAGE_PREFER_CONFIG=ON")
api.toolchain_3p_libs.set_toolchain_dir(cipd_dir)
api.toolchain_3p_libs.set_sysroot_dir(linux_sysroot)
api.toolchain_3p_libs.set_source_manifest(manifest)
api.toolchain_3p_libs.set_compiler_wrapper(compiler_wrapper)
zlib_install_dir = api.toolchain_3p_libs.zlib.build(host_triple)
options.extend(
api.toolchain.zlib_deps_flags(zlib_install_dir, api.platform.is_win)
)
zstd_install_dir = api.toolchain_3p_libs.zstd.build(host_triple)
options.extend(api.toolchain.zstd_deps_flags(zstd_install_dir))
libxml2_install_dir = api.toolchain_3p_libs.libxml2.build(host_triple)
options.extend(api.toolchain.libxml2_deps_flags(libxml2_install_dir))
boringssl_install_dir = api.toolchain_3p_libs.boringssl.build(
host_triple,
cmake_extra_args=[
"-DCMAKE_POSITION_INDEPENDENT_CODE=ON",
f"-DGO_EXECUTABLE={api.go.go_root.joinpath('bin', 'go')}",
],
)
options.extend(api.toolchain.openssl_deps_flags(boringssl_install_dir))
curl_install_dir = api.toolchain_3p_libs.curl.build(
host_triple,
ssl_install_dir=boringssl_install_dir,
zlib_install_dir=zlib_install_dir,
)
options.extend(api.toolchain.curl_deps_flags(curl_install_dir))
cpp_httplib_install_dir = api.toolchain_3p_libs.cpp_httplib.build(
host_triple, zlib_install_dir=zlib_install_dir
)
options.extend(api.toolchain.httplib_deps_flags(cpp_httplib_install_dir))
if enable_ml_inliner:
options.extend(
[
f"-DTENSORFLOW_AOT_PATH={api.tensorflow.path}",
f"-DLLVM_OVERRIDE_MODEL_HEADER_INLINERSIZEMODEL={cipd_dir.joinpath('model', 'InlinerSizeModel.h')}",
f"-DLLVM_OVERRIDE_MODEL_OBJECT_INLINERSIZEMODEL={cipd_dir.joinpath('model', 'InlinerSizeModel.o')}",
"-DLLVM_RAEVICT_MODEL_PATH=none",
]
)
with api.step.nest("clang"), api.context(env=env):
api.cmake(
step_name="configure",
src_dir=llvm_dir.joinpath("llvm"),
build_dir=build_dir,
extra_args=[option.format(**arguments) for option in options]
+ ["-C", api.resource("Fuchsia-toolchain.cmake")],
)
api.file.read_text(
"read CMakeConfigureLog.yaml",
build_dir.joinpath("CMakeFiles", "CMakeConfigureLog.yaml"),
)
# Build the toolchain distribution.
api.ninja(
"build",
["toolchain-distribution", "libc-hdrgen"],
ninja_jobs=ninja_jobs,
build_dir=build_dir,
)
# Pack the toolchain distribution
with api.context(env={"DESTDIR": pkg_dir}):
api.ninja(
"install",
["install-toolchain-distribution"],
ninja_jobs=ninja_jobs,
build_dir=build_dir,
)
hdrgen = "libc-hdrgen.exe" if api.platform.is_win else "libc-hdrgen"
api.file.copy(
"copy libc-hdrgen",
build_dir.joinpath("bin", hdrgen),
pkg_dir.joinpath("bin", hdrgen),
)
api.cas_util.upload(pkg_dir, output_property="isolated")
api.ninja(
"tests",
[
"check-clang",
"check-llvm",
"check-lld",
],
ninja_jobs=ninja_jobs,
build_dir=build_dir,
)
def ensure_llvm_deps_prebuilts(
api, target_platform, use_breakpad=False, enable_ml_inliner=False, manifest=None
):
with api.step.nest("ensure packages"):
cipd_dir = api.path.start_dir.joinpath("cipd")
pkgs = api.cipd.EnsureFile()
# Use Linux x64 SDK on all platforms. We only need the sysroot, we
# don't use any tools so the host architecture is irrelevant.
pkgs.add_package("fuchsia/third_party/clang/${platform}", "integration")
pkgs.add_package(
"fuchsia/third_party/sysroot/linux",
"integration",
"linux",
)
pkgs.add_package(
"fuchsia/third_party/sysroot/focal",
"git_revision:fa7a5a9710540f30ff98ae48b62f2cdf72ed2acd",
"focal",
)
if enable_ml_inliner:
pkgs.add_package(
f"fuchsia/model/inlining/{target_platform}",
"git_revision:0ee1ce61a844b8fd285ff1a2c47c4b8690fd2b7d",
"model",
)
if use_breakpad:
pkgs.add_package(
"fuchsia/tools/breakpad/${platform}", "integration", "breakpad"
)
ensured = api.cipd.ensure(cipd_dir, pkgs)
for subdir, pins in ensured.items():
directory = manifest.directories[str(cipd_dir.joinpath(subdir))]
directory.cipd_server_host = CIPD_SERVER_HOST
for pin in pins:
directory.cipd_package[pin.package].instance_id = pin.instance_id
return cipd_dir
def GenTests(api):
yield (
api.test("ci_linux_x64")
+ api.buildbucket.ci_build(
project="fuchsia",
bucket="ci",
git_repo="https://fuchsia.googlesource.com/third_party/llvm-project",
revision="a" * 40,
)
+ api.platform.name("linux")
+ api.properties()
)