xref: /aosp_15_r20/build/bazel/toolchains/clang/host/linux-x86/cc_toolchain_config.bzl (revision 7594170e27e0732bc44b93d1440d87a54b6ffe7c)
1# Copyright (C) 2023 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15load("@bazel_skylib//lib:paths.bzl", "paths")
16load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
17load(
18    "@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl",
19    "action_config",
20    "tool",
21    "tool_path",
22)
23load("//build/bazel/platforms/arch/variants:constants.bzl", _arch_constants = "constants")
24load(
25    ":cc_toolchain_constants.bzl",
26    "arch_to_variants",
27    "variant_constraints",
28    "variant_name",
29    "x86_64_host_toolchains",
30    "x86_64_musl_host_toolchains",
31    "x86_host_toolchains",
32    "x86_musl_host_toolchains",
33    _actions = "actions",
34    _enabled_features = "enabled_features",
35    _generated_config_constants = "generated_config_constants",
36    _generated_sanitizer_constants = "generated_sanitizer_constants",
37)
38load(
39    ":cc_toolchain_features.bzl",
40    "get_features",
41    "int_overflow_ignorelist_filename",
42    "int_overflow_ignorelist_path",
43)
44
45# Clang-specific configuration.
46_ClangVersionInfo = provider(fields = ["clang_version", "includes"])
47
48CLANG_TOOLS = [
49    "llvm-ar",
50    "llvm-dwarfdump",
51    "llvm-nm",
52    "llvm-objcopy",
53    "llvm-objdump",
54    "llvm-readelf",
55    "llvm-strip",
56    "clang-tidy",
57    "clang-tidy.sh",
58    "clang-tidy.real",
59]
60
61CLANG_TEST_TOOLS = [
62    "llvm-readelf",
63    "llvm-nm",
64]
65
66def clang_tool_output_group(tool_name):
67    return tool_name.replace("-", "_").replace(".", "_")
68
69_libclang_rt_prebuilt_map = {
70    "android_arm": "libclang_rt.builtins-arm-android.a",
71    "android_arm64": "libclang_rt.builtins-aarch64-android.a",
72    "android_x86": "libclang_rt.builtins-i686-android.a",
73    "android_x86_64": "libclang_rt.builtins-x86_64-android.a",
74    "linux_bionic_x86_64": "libclang_rt.builtins-x86_64-android.a",
75    "linux_glibc_x86": "libclang_rt.builtins-i386.a",
76    "linux_glibc_x86_64": "libclang_rt.builtins-x86_64.a",
77    "linux_musl_x86": "i686-unknown-linux-musl/lib/linux/libclang_rt.builtins-i386.a",
78    "linux_musl_x86_64": "x86_64-unknown-linux-musl/lib/linux/libclang_rt.builtins-x86_64.a",
79}
80
81_libclang_rt_ubsan_minimal_prebuilt_map = {
82    "android_arm": "libclang_rt.ubsan_minimal-arm-android.a",
83    "android_arm64": "libclang_rt.ubsan_minimal-aarch64-android.a",
84    "android_x86": "libclang_rt.ubsan_minimal-i686-android.a",
85    "android_x86_64": "libclang_rt.ubsan_minimal-x86_64-android.a",
86    "linux_bionic_x86_64": "libclang_rt.ubsan_minimal-x86_64-android.a",
87    "linux_glibc_x86": "libclang_rt.ubsan_minimal-i386.a",
88    "linux_glibc_x86_64": "libclang_rt.ubsan_minimal-x86_64.a",
89    "linux_musl_x86": "i686-unknown-linux-musl/lib/linux/libclang_rt.ubsan_minimal-i386.a",
90    "linux_musl_x86_64": "x86_64-unknown-linux-musl/lib/linux/libclang_rt.ubsan_minimal-x86_64.a",
91}
92
93def _clang_version_info_impl(ctx):
94    clang_version = ctx.attr.clang_version[BuildSettingInfo].value
95    clang_version_directory = paths.join(ctx.label.package, clang_version)
96    clang_version_dir_prefix = clang_version_directory + "/"
97    clang_short_version = ctx.attr.clang_short_version[BuildSettingInfo].value
98
99    all_files = {}  # a set to do fast prebuilt lookups later
100    output_groups = {
101        "compiler_clang_includes": [],
102        "compiler_binaries": [],
103        "linker_binaries": [],
104        "ar_files": [],
105        "clang_test_tools": [],
106    }
107
108    for file in ctx.files.clang_files:
109        if not file.short_path.startswith(clang_version_dir_prefix):
110            continue
111        file_path = file.short_path.removeprefix(clang_version_dir_prefix)
112        all_files[file_path] = file
113
114        file_path_parts = file_path.split("/")
115        if file_path_parts[:2] == ["lib", "clang"] and file_path_parts[4] == "include":
116            output_groups["compiler_clang_includes"].append(file)  # /lib/clang/*/include/**
117        if file_path_parts[0] == "bin" and len(file_path_parts) == 2:
118            output_groups["linker_binaries"].append(file)  # /bin/*
119            if file.basename.startswith("clang"):
120                output_groups["compiler_binaries"].append(file)  # /bin/clang*
121            if file.basename == "llvm-ar":
122                output_groups["ar_files"].append(file)  # /bin/llvm-ar
123            if file.basename in CLANG_TEST_TOOLS:
124                output_groups["clang_test_tools"].append(file)
125            if file.basename in CLANG_TOOLS:
126                output_groups[clang_tool_output_group(file.basename)] = [file]
127
128    libclang_rt_prefix = "lib/clang/%s/lib/linux" % clang_short_version
129    for arch, path in _libclang_rt_prebuilt_map.items():
130        file_path = paths.join(libclang_rt_prefix, path)
131        if file_path in all_files:
132            output_groups["libclang_rt_builtins_" + arch] = [all_files[file_path]]
133        else:
134            fail("could not find libclang_rt_builtin for `%s` at path `%s`" % (arch, file_path))
135    for arch, path in _libclang_rt_ubsan_minimal_prebuilt_map.items():
136        file_path = paths.join(libclang_rt_prefix, path)
137        if file_path in all_files:
138            output_groups["libclang_rt_ubsan_minimal_" + arch] = [all_files[file_path]]
139        else:
140            fail("could not find libclang_rt_ubsan_minimal for `%s` at path `%s`" % (arch, file_path))
141
142    return [
143        _ClangVersionInfo(
144            clang_version = clang_version,
145            includes = [
146                paths.join(clang_version_directory, "lib", "clang", clang_short_version, "include"),
147            ],
148        ),
149        OutputGroupInfo(
150            **output_groups
151        ),
152    ]
153
154clang_version_info = rule(
155    implementation = _clang_version_info_impl,
156    attrs = {
157        "clang_version": attr.label(mandatory = True),
158        "clang_short_version": attr.label(mandatory = True),
159        "clang_files": attr.label_list(
160            allow_files = True,
161        ),
162    },
163)
164
165def _tool_paths(clang_version_info):
166    return [
167        tool_path(
168            name = "gcc",
169            path = clang_version_info.clang_version + "/bin/clang",
170        ),
171        tool_path(
172            name = "ld",
173            path = clang_version_info.clang_version + "/bin/ld.lld",
174        ),
175        tool_path(
176            name = "ar",
177            path = clang_version_info.clang_version + "/bin/llvm-ar",
178        ),
179        tool_path(
180            name = "cpp",
181            path = "/bin/false",
182        ),
183        tool_path(
184            name = "gcov",
185            path = clang_version_info.clang_version + "/bin/llvm-profdata",
186        ),
187        tool_path(
188            name = "llvm-cov",
189            path = clang_version_info.clang_version + "/bin/llvm-cov",
190        ),
191        tool_path(
192            name = "nm",
193            path = clang_version_info.clang_version + "/bin/llvm-nm",
194        ),
195        tool_path(
196            name = "objcopy",
197            path = clang_version_info.clang_version + "/bin/llvm-objcopy",
198        ),
199        tool_path(
200            name = "objdump",
201            path = clang_version_info.clang_version + "/bin/llvm-objdump",
202        ),
203        # Soong has a wrapper around strip.
204        # https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/strip.go;l=62;drc=master
205        # https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/builder.go;l=991-1025;drc=master
206        tool_path(
207            name = "strip",
208            path = clang_version_info.clang_version + "/bin/llvm-strip",
209        ),
210        tool_path(
211            name = "clang++",
212            path = clang_version_info.clang_version + "/bin/clang++",
213        ),
214    ]
215
216# Set tools used for all actions in Android's C++ builds.
217def _create_action_configs(tool_paths, target_os):
218    action_configs = []
219
220    tool_name_to_tool = {}
221    for tool_path in tool_paths:
222        tool_name_to_tool[tool_path.name] = tool(path = tool_path.path)
223
224    # use clang for assembler actions
225    # https://cs.android.com/android/_/android/platform/build/soong/+/a14b18fb31eada7b8b58ecd469691c20dcb371b3:cc/builder.go;l=616;drc=769a51cc6aa9402c1c55e978e72f528c26b6a48f
226    for action_name in _actions.assemble:
227        action_configs.append(action_config(
228            action_name = action_name,
229            enabled = True,
230            tools = [tool_name_to_tool["gcc"]],
231            implies = [
232                "user_compile_flags",
233                "compiler_input_flags",
234                "compiler_output_flags",
235            ],
236        ))
237
238    # use clang++ for compiling C++
239    # https://cs.android.com/android/_/android/platform/build/soong/+/a14b18fb31eada7b8b58ecd469691c20dcb371b3:cc/builder.go;l=627;drc=769a51cc6aa9402c1c55e978e72f528c26b6a48f
240    action_configs.append(action_config(
241        action_name = _actions.cpp_compile,
242        enabled = True,
243        tools = [tool_name_to_tool["clang++"]],
244        implies = [
245            "user_compile_flags",
246            "compiler_input_flags",
247            "compiler_output_flags",
248        ],
249    ))
250
251    # use clang for compiling C
252    # https://cs.android.com/android/_/android/platform/build/soong/+/a14b18fb31eada7b8b58ecd469691c20dcb371b3:cc/builder.go;l=623;drc=769a51cc6aa9402c1c55e978e72f528c26b6a48f
253    action_configs.append(action_config(
254        action_name = _actions.c_compile,
255        enabled = True,
256        # this is clang, but needs to be called gcc for legacy reasons.
257        # to avoid this, we need to set `no_legacy_features`: b/201257475
258        # http://google3/third_party/bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java;l=1106-1122;rcl=398974497
259        # http://google3/third_party/bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java;l=1185-1187;rcl=398974497
260        tools = [tool_name_to_tool["gcc"]],
261        implies = [
262            "user_compile_flags",
263            "compiler_input_flags",
264            "compiler_output_flags",
265        ],
266    ))
267
268    rpath_features = []
269    if target_os not in ("android", "windows"):
270        rpath_features.append("runtime_library_search_directories")
271
272    # use clang++ for dynamic linking
273    # https://cs.android.com/android/_/android/platform/build/soong/+/a14b18fb31eada7b8b58ecd469691c20dcb371b3:cc/builder.go;l=790;drc=769a51cc6aa9402c1c55e978e72f528c26b6a48f
274    for action_name in [_actions.cpp_link_dynamic_library, _actions.cpp_link_nodeps_dynamic_library]:
275        action_configs.append(action_config(
276            action_name = action_name,
277            enabled = True,
278            tools = [tool_name_to_tool["clang++"]],
279            implies = [
280                "shared_flag",
281                "linkstamps",
282                "output_execpath_flags",
283                "library_search_directories",
284                "libraries_to_link",
285                "user_link_flags",
286                "linker_param_file",
287            ] + rpath_features,
288        ))
289
290    # use clang++ for linking cc executables
291    action_configs.append(action_config(
292        action_name = _actions.cpp_link_executable,
293        enabled = True,
294        tools = [tool_name_to_tool["clang++"]],
295        implies = [
296            "linkstamps",
297            "output_execpath_flags",
298            "library_search_directories",
299            "libraries_to_link",
300            "user_link_flags",
301            "linker_param_file",
302        ] + rpath_features,
303    ))
304
305    # use llvm-ar for creating static archives
306    action_configs.append(action_config(
307        action_name = _actions.cpp_link_static_library,
308        enabled = True,
309        tools = [tool_name_to_tool["ar"]],
310        implies = [
311            "linker_param_file",
312        ],
313    ))
314
315    # unused, but Bazel complains if there isn't an action config for strip
316    action_configs.append(action_config(
317        action_name = _actions.strip,
318        enabled = True,
319        tools = [tool_name_to_tool["strip"]],
320        # This doesn't imply any feature, because Bazel currently mimics
321        # Soong by running strip actions in a rule (stripped_shared_library).
322    ))
323
324    # use llvm-objcopy to remove addrsig sections from partially linked objects
325    action_configs.append(action_config(
326        action_name = "objcopy",
327        enabled = True,
328        tools = [tool_name_to_tool["objcopy"]],
329    ))
330
331    return action_configs
332
333def _cc_toolchain_config_impl(ctx):
334    clang_version_info = ctx.attr.clang_version[_ClangVersionInfo]
335    tool_paths = _tool_paths(clang_version_info)
336
337    action_configs = _create_action_configs(tool_paths, ctx.attr.target_os)
338
339    builtin_include_dirs = []
340    builtin_include_dirs.extend(clang_version_info.includes)
341
342    # b/186035856: Do not add anything to this list.
343    builtin_include_dirs.extend(_generated_config_constants.CommonGlobalIncludes)
344
345    crt_files = struct(
346        shared_library_crtbegin = ctx.file.shared_library_crtbegin,
347        shared_library_crtend = ctx.file.shared_library_crtend,
348        shared_binary_crtbegin = ctx.file.shared_binary_crtbegin,
349        static_binary_crtbegin = ctx.file.static_binary_crtbegin,
350        binary_crtend = ctx.file.binary_crtend,
351    )
352
353    features = get_features(
354        ctx,
355        builtin_include_dirs,
356        crt_files,
357    )
358
359    # This is so that Bazel doesn't validate .d files against the set of headers
360    # declared in BUILD files (Blueprint files don't contain that data). %workspace%/
361    # will be replaced with the empty string by Bazel (essentially making it relative
362    # to the build directory), so Bazel will skip the validations of all the headers
363    # in .d files. For details please see CppCompileAction.validateInclude. We add
364    # %workspace% after calling get_features so it won't be exposed as an -isystem flag.
365    builtin_include_dirs.append("%workspace%/")
366
367    return cc_common.create_cc_toolchain_config_info(
368        ctx = ctx,
369        toolchain_identifier = ctx.attr.toolchain_identifier,
370        tool_paths = tool_paths,
371        features = features,
372        action_configs = action_configs,
373        cxx_builtin_include_directories = builtin_include_dirs,
374        target_cpu = "_".join([ctx.attr.target_os, ctx.attr.target_arch]),
375        # The attributes below are required by the constructor, but don't
376        # affect actions at all.
377        host_system_name = "__toolchain_host_system_name__",
378        target_system_name = "__toolchain_target_system_name__",
379        target_libc = "__toolchain_target_libc__",
380        compiler = "__toolchain_compiler__",
381        abi_version = "__toolchain_abi_version__",
382        abi_libc_version = "__toolchain_abi_libc_version__",
383    )
384
385_cc_toolchain_config = rule(
386    implementation = _cc_toolchain_config_impl,
387    attrs = {
388        "target_os": attr.string(mandatory = True),
389        "target_arch": attr.string(mandatory = True),
390        "toolchain_identifier": attr.string(mandatory = True),
391        "clang_version": attr.label(mandatory = True, providers = [_ClangVersionInfo]),
392        "target_flags": attr.string_list(default = []),
393        "compiler_flags": attr.string_list(default = []),
394        "linker_flags": attr.string_list(default = []),
395        "libclang_rt_builtin": attr.label(allow_single_file = True),
396        "libclang_rt_ubsan_minimal": attr.label(allow_single_file = True),
397        # crtbegin and crtend libraries for compiling cc_library_shared and
398        # cc_binary against the Bionic runtime
399        "shared_library_crtbegin": attr.label(allow_single_file = True, cfg = "target"),
400        "shared_library_crtend": attr.label(allow_single_file = True, cfg = "target"),
401        "shared_binary_crtbegin": attr.label(allow_single_file = True, cfg = "target"),
402        "static_binary_crtbegin": attr.label(allow_single_file = True, cfg = "target"),
403        "binary_crtend": attr.label(allow_single_file = True, cfg = "target"),
404        "rtti_toggle": attr.bool(default = True),
405        "_auto_zero_initialize": attr.label(
406            default = "//build/bazel/toolchains/clang/host/linux-x86:auto_zero_initialize_env",
407        ),
408        "_auto_pattern_initialize": attr.label(
409            default = "//build/bazel/toolchains/clang/host/linux-x86:auto_pattern_initialize_env",
410        ),
411        "_auto_uninitialize": attr.label(
412            default = "//build/bazel/toolchains/clang/host/linux-x86:auto_uninitialize_env",
413        ),
414        "_use_ccache": attr.label(
415            default = "//build/bazel/toolchains/clang/host/linux-x86:use_ccache_env",
416        ),
417        "_llvm_next": attr.label(
418            default = "//build/bazel/toolchains/clang/host/linux-x86:llvm_next_env",
419        ),
420        "_allow_unknown_warning_option": attr.label(
421            default = "//build/bazel/toolchains/clang/host/linux-x86:allow_unknown_warning_option_env",
422        ),
423        "_device_max_page_size_supported": attr.label(
424            default = "//build/bazel/product_config:device_max_page_size_supported",
425        ),
426        "_device_no_bionic_page_size_macro": attr.label(
427            default = "//build/bazel/product_config:device_no_bionic_page_size_macro",
428        ),
429        "_clang_default_debug_level": attr.label(
430            default = "//build/bazel/toolchains/clang/host/linux-x86:clang_default_debug_level",
431        ),
432    },
433    provides = [CcToolchainConfigInfo],
434)
435
436# macro to expand feature flags for a toolchain
437# we do not pass these directly to the toolchain so the order can
438# be specified per toolchain
439def expand_feature_flags(arch_variant, arch_variant_to_features = {}, flag_map = {}):
440    flags = []
441    features = _enabled_features(arch_variant, arch_variant_to_features)
442    for feature in features:
443        flags.extend(flag_map.get(feature, []))
444    return flags
445
446# Macro to set up both the toolchain and the config.
447def android_cc_toolchain(
448        name,
449        target_os = None,
450        target_arch = None,
451        clang_version = None,
452        gcc_toolchain = None,
453        # If false, the crt version and "normal" version of this toolchain are identical.
454        crt = None,
455        libclang_rt_builtin = None,
456        libclang_rt_ubsan_minimal = None,
457        target_flags = [],
458        compiler_flags = [],
459        linker_flags = [],
460        toolchain_identifier = None,
461        rtti_toggle = True):
462    extra_linker_paths = []
463    libclang_rt_path = None
464    if libclang_rt_builtin:
465        libclang_rt_path = libclang_rt_builtin
466        extra_linker_paths.append(libclang_rt_path)
467    libclang_rt_ubsan_minimal_path = None
468    if libclang_rt_ubsan_minimal:
469        libclang_rt_ubsan_minimal_path = libclang_rt_ubsan_minimal
470    if gcc_toolchain:
471        gcc_toolchain_path = "//%s:tools" % gcc_toolchain
472        extra_linker_paths.append(gcc_toolchain_path)
473    extra_linker_paths.append("//%s:%s" % (
474        _generated_sanitizer_constants.CfiExportsMapPath,
475        _generated_sanitizer_constants.CfiExportsMapFilename,
476    ))
477    extra_linker_paths.append("//%s:%s" % (
478        _generated_sanitizer_constants.CfiBlocklistPath,
479        _generated_sanitizer_constants.CfiBlocklistFilename,
480    ))
481
482    common_toolchain_config = dict(
483        [
484            ("target_os", target_os),
485            ("target_arch", target_arch),
486            ("clang_version", clang_version),
487            ("libclang_rt_builtin", libclang_rt_path),
488            ("libclang_rt_ubsan_minimal", libclang_rt_ubsan_minimal_path),
489            ("target_flags", target_flags),
490            ("compiler_flags", compiler_flags),
491            ("linker_flags", linker_flags),
492            ("rtti_toggle", rtti_toggle),
493        ],
494    )
495
496    _cc_toolchain_config(
497        name = "%s_nocrt_config" % name,
498        toolchain_identifier = toolchain_identifier + "_nocrt",
499        **common_toolchain_config
500    )
501
502    # Create the filegroups needed for sandboxing toolchain inputs to C++ actions.
503    native.filegroup(
504        name = "%s_compiler_clang_includes" % name,
505        srcs = [clang_version],
506        output_group = "compiler_clang_includes",
507    )
508
509    native.filegroup(
510        name = "%s_compiler_binaries" % name,
511        srcs = [clang_version],
512        output_group = "compiler_binaries",
513    )
514
515    native.filegroup(
516        name = "%s_linker_binaries" % name,
517        srcs = [clang_version],
518        output_group = "linker_binaries",
519    )
520
521    native.filegroup(
522        name = "%s_ar_files" % name,
523        srcs = [clang_version],
524        output_group = "ar_files",
525    )
526
527    native.filegroup(
528        name = "%s_compiler_files" % name,
529        srcs = [
530            "%s_compiler_binaries" % name,
531            "%s_compiler_clang_includes" % name,
532            "@//%s:%s" % (int_overflow_ignorelist_path, int_overflow_ignorelist_filename),
533        ],
534    )
535
536    native.filegroup(
537        name = "%s_linker_files" % name,
538        srcs = ["%s_linker_binaries" % name] + extra_linker_paths,
539    )
540
541    native.filegroup(
542        name = "%s_all_files" % name,
543        srcs = [
544            "%s_compiler_files" % name,
545            "%s_linker_files" % name,
546            "%s_ar_files" % name,
547        ],
548    )
549
550    native.cc_toolchain(
551        name = name + "_nocrt",
552        all_files = "%s_all_files" % name,
553        as_files = "//:empty",  # Note the "//" prefix, see comment above
554        ar_files = "%s_ar_files" % name,
555        compiler_files = "%s_compiler_files" % name,
556        dwp_files = ":empty",
557        linker_files = "%s_linker_files" % name,
558        objcopy_files = ":empty",
559        strip_files = ":empty",
560        supports_param_files = 0,
561        toolchain_config = ":%s_nocrt_config" % name,
562        toolchain_identifier = toolchain_identifier + "_nocrt",
563    )
564
565    if crt:
566        # Write the toolchain config.
567        _cc_toolchain_config(
568            name = "%s_config" % name,
569            toolchain_identifier = toolchain_identifier,
570            shared_library_crtbegin = crt.shared_library_crtbegin,
571            shared_library_crtend = crt.shared_library_crtend,
572            shared_binary_crtbegin = crt.shared_binary_crtbegin,
573            static_binary_crtbegin = crt.static_binary_crtbegin,
574            binary_crtend = crt.binary_crtend,
575            **common_toolchain_config
576        )
577
578        native.filegroup(
579            name = "%s_crt_libs" % name,
580            srcs = [
581                crt.shared_library_crtbegin,
582                crt.shared_library_crtend,
583                crt.shared_binary_crtbegin,
584                crt.static_binary_crtbegin,
585                crt.binary_crtend,
586            ],
587        )
588
589        native.filegroup(
590            name = "%s_linker_files_with_crt" % name,
591            srcs = [
592                "%s_linker_files" % name,
593                "%s_crt_libs" % name,
594            ],
595        )
596
597        # Create the actual cc_toolchain.
598        # The dependency on //:empty is intentional; it's necessary so that Bazel
599        # can parse .d files correctly (see the comment in $TOP/BUILD)
600        native.cc_toolchain(
601            name = name,
602            all_files = "%s_all_files" % name,
603            as_files = "//:empty",  # Note the "//" prefix, see comment above
604            ar_files = "%s_ar_files" % name,
605            compiler_files = "%s_compiler_files" % name,
606            dwp_files = ":empty",
607            linker_files = "%s_linker_files_with_crt" % name,
608            objcopy_files = ":empty",
609            strip_files = ":empty",
610            supports_param_files = 0,
611            toolchain_config = ":%s_config" % name,
612            toolchain_identifier = toolchain_identifier,
613            exec_transition_for_inputs = False,
614        )
615    else:
616        _cc_toolchain_config(
617            name = "%s_config" % name,
618            toolchain_identifier = toolchain_identifier,
619            **common_toolchain_config
620        )
621
622        native.alias(
623            name = name,
624            actual = name + "_nocrt",
625        )
626
627def _toolchain_name(arch, variant, nocrt = False):
628    return "cc_toolchain_{arch}{variant}{nocrt}_def".format(
629        arch = arch,
630        variant = variant_name(variant),
631        nocrt = "_nocrt" if nocrt else "",
632    )
633
634def toolchain_definition(arch, variant, nocrt = False):
635    """Macro to create a toolchain with a standardized name
636
637    The name used here must match that used in cc_register_toolchains.
638    """
639    name = _toolchain_name(arch, variant, nocrt)
640    native.toolchain(
641        name = name,
642        exec_compatible_with = [
643            "//build/bazel_common_rules/platforms/arch:x86_64",
644            "//build/bazel_common_rules/platforms/os:linux",
645        ],
646        target_compatible_with = [
647            "//build/bazel_common_rules/platforms/arch:%s" % arch,
648            "//build/bazel_common_rules/platforms/os:android",
649        ] + variant_constraints(
650            variant,
651            _arch_constants.AndroidArchToVariantToFeatures[arch],
652        ),
653        toolchain = ":cc_toolchain_{arch}{variant}{nocrt}".format(
654            arch = arch,
655            variant = variant_name(variant),
656            nocrt = "_nocrt" if nocrt else "",
657        ),
658        toolchain_type = (
659            ":nocrt_toolchain" if nocrt else "@bazel_tools//tools/cpp:toolchain_type"
660        ),
661    )
662
663def cc_register_toolchains():
664    """Register cc_toolchains for device and host platforms.
665
666    This function ensures that generic (non-variant) device toolchains are
667    registered last.
668    """
669
670    generic_toolchains = []
671    arch_variant_toolchains = []
672    cpu_variant_toolchains = []
673    for arch, variants in arch_to_variants.items():
674        for variant in variants:
675            if not variant.arch_variant:
676                generic_toolchains.append((arch, variant))
677            elif not variant.cpu_variant:
678                arch_variant_toolchains.append((arch, variant))
679            else:
680                cpu_variant_toolchains.append((arch, variant))
681
682    target_toolchains = [
683        _toolchain_name(arch, variant, nocrt = nocrt)
684        for nocrt in [False, True]
685        for arch, variant in (
686            # Ordering is important here: more specific toolchains must be
687            # registered before more generic toolchains
688            cpu_variant_toolchains +
689            arch_variant_toolchains +
690            generic_toolchains
691        )
692    ]
693
694    host_toolchains = [
695        tc[0] + "_def"
696        for tc in x86_64_host_toolchains + x86_host_toolchains +
697                  x86_64_musl_host_toolchains + x86_musl_host_toolchains
698    ]
699
700    native.register_toolchains(*[
701        "//prebuilts/clang/host/linux-x86:" + tc
702        for tc in host_toolchains + target_toolchains
703    ])
704