• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2019 The Bazel Authors. All rights reserved.
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
15"""A Starlark cc_toolchain configuration rule"""
16
17load("@rules_cc//cc:action_names.bzl", "ACTION_NAMES")
18load(
19    "@rules_cc//cc:cc_toolchain_config_lib.bzl",
20    "action_config",
21    "artifact_name_pattern",
22    "env_entry",
23    "env_set",
24    "feature",
25    "feature_set",
26    "flag_group",
27    "flag_set",
28    "tool",
29    "tool_path",
30    "variable_with_value",
31    "with_feature_set",
32)
33
34def _target_os_version(ctx):
35    platform_type = ctx.fragments.apple.single_arch_platform.platform_type
36    xcode_config = ctx.attr._xcode_config[apple_common.XcodeVersionConfig]
37    return xcode_config.minimum_os_for_platform_type(platform_type)
38
39def layering_check_features(compiler, extra_flags_per_feature, is_macos):
40    if compiler != "clang":
41        return []
42    return [
43        feature(
44            name = "use_module_maps",
45            requires = [feature_set(features = ["module_maps"])],
46            flag_sets = [
47                flag_set(
48                    actions = [
49                        ACTION_NAMES.c_compile,
50                        ACTION_NAMES.cpp_compile,
51                        ACTION_NAMES.cpp_header_parsing,
52                        ACTION_NAMES.cpp_module_compile,
53                    ],
54                    flag_groups = [
55                        flag_group(
56                            # macOS requires -Xclang because of a bug in Apple Clang
57                            flags = (["-Xclang"] if is_macos else []) + [
58                                "-fmodule-name=%{module_name}",
59                            ] + (["-Xclang"] if is_macos else []) + [
60                                "-fmodule-map-file=%{module_map_file}",
61                            ] + extra_flags_per_feature.get("use_module_maps", []),
62                        ),
63                    ],
64                ),
65            ],
66        ),
67
68        # Tell blaze we support module maps in general, so they will be generated
69        # for all c/c++ rules.
70        # Note: not all C++ rules support module maps; thus, do not imply this
71        # feature from other features - instead, require it.
72        feature(name = "module_maps", enabled = True),
73        feature(
74            name = "layering_check",
75            implies = ["use_module_maps"],
76            flag_sets = [
77                flag_set(
78                    actions = [
79                        ACTION_NAMES.c_compile,
80                        ACTION_NAMES.cpp_compile,
81                        ACTION_NAMES.cpp_header_parsing,
82                        ACTION_NAMES.cpp_module_compile,
83                    ],
84                    flag_groups = [
85                        flag_group(flags = [
86                            "-fmodules-strict-decluse",
87                            "-Wprivate-header",
88                        ]),
89                        flag_group(
90                            iterate_over = "dependent_module_map_files",
91                            flags = (["-Xclang"] if is_macos else []) + [
92                                "-fmodule-map-file=%{dependent_module_map_files}",
93                            ],
94                        ),
95                    ],
96                ),
97            ],
98        ),
99    ]
100
101def parse_headers_support(parse_headers_tool_path):
102    """
103    Returns action configurations and features for parsing headers.
104
105    Args:
106        parse_headers_tool_path: The path to the tool used for parsing headers.
107
108    Returns:
109        A tuple containing a list of action configurations and a list of features.
110    """
111    if not parse_headers_tool_path:
112        return [], []
113    action_configs = [
114        action_config(
115            action_name = ACTION_NAMES.cpp_header_parsing,
116            tools = [
117                tool(path = parse_headers_tool_path),
118            ],
119            flag_sets = [
120                flag_set(
121                    flag_groups = [
122                        flag_group(
123                            flags = [
124                                # Note: This treats all headers as C++ headers, which may lead to
125                                # parsing failures for C headers that are not valid C++.
126                                # For such headers, use features = ["-parse_headers"] to selectively
127                                # disable parsing.
128                                "-xc++-header",
129                                "-fsyntax-only",
130                            ],
131                        ),
132                    ],
133                ),
134            ],
135            implies = [
136                # Copied from the legacy feature definition in CppActionConfigs.java.
137                "legacy_compile_flags",
138                "user_compile_flags",
139                "sysroot",
140                "unfiltered_compile_flags",
141                "compiler_input_flags",
142                "compiler_output_flags",
143            ],
144        ),
145    ]
146    features = [
147        feature(name = "parse_headers"),
148    ]
149    return action_configs, features
150
151all_compile_actions = [
152    ACTION_NAMES.c_compile,
153    ACTION_NAMES.cpp_compile,
154    ACTION_NAMES.linkstamp_compile,
155    ACTION_NAMES.assemble,
156    ACTION_NAMES.preprocess_assemble,
157    ACTION_NAMES.cpp_header_parsing,
158    ACTION_NAMES.cpp_module_compile,
159    ACTION_NAMES.cpp_module_codegen,
160    ACTION_NAMES.cpp_module_deps_scanning,
161    ACTION_NAMES.cpp20_module_compile,
162    ACTION_NAMES.cpp20_module_codegen,
163    ACTION_NAMES.clif_match,
164    ACTION_NAMES.lto_backend,
165]
166
167all_cpp_compile_actions = [
168    ACTION_NAMES.cpp_compile,
169    ACTION_NAMES.linkstamp_compile,
170    ACTION_NAMES.cpp_header_parsing,
171    ACTION_NAMES.cpp_module_compile,
172    ACTION_NAMES.cpp_module_codegen,
173    ACTION_NAMES.cpp_module_deps_scanning,
174    ACTION_NAMES.cpp20_module_compile,
175    ACTION_NAMES.cpp20_module_codegen,
176    ACTION_NAMES.clif_match,
177]
178
179preprocessor_compile_actions = [
180    ACTION_NAMES.c_compile,
181    ACTION_NAMES.cpp_compile,
182    ACTION_NAMES.linkstamp_compile,
183    ACTION_NAMES.preprocess_assemble,
184    ACTION_NAMES.cpp_header_parsing,
185    ACTION_NAMES.cpp_module_compile,
186    ACTION_NAMES.cpp_module_deps_scanning,
187    ACTION_NAMES.cpp20_module_compile,
188    ACTION_NAMES.clif_match,
189]
190
191codegen_compile_actions = [
192    ACTION_NAMES.c_compile,
193    ACTION_NAMES.cpp_compile,
194    ACTION_NAMES.linkstamp_compile,
195    ACTION_NAMES.assemble,
196    ACTION_NAMES.preprocess_assemble,
197    ACTION_NAMES.cpp_module_codegen,
198    ACTION_NAMES.cpp20_module_codegen,
199    ACTION_NAMES.lto_backend,
200]
201
202all_link_actions = [
203    ACTION_NAMES.cpp_link_executable,
204    ACTION_NAMES.cpp_link_dynamic_library,
205    ACTION_NAMES.cpp_link_nodeps_dynamic_library,
206]
207
208lto_index_actions = [
209    ACTION_NAMES.lto_index_for_executable,
210    ACTION_NAMES.lto_index_for_dynamic_library,
211    ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
212]
213
214def _sanitizer_feature(name = "", specific_compile_flags = [], specific_link_flags = []):
215    return feature(
216        name = name,
217        flag_sets = [
218            flag_set(
219                actions = all_compile_actions,
220                flag_groups = [
221                    flag_group(flags = [
222                        "-fno-omit-frame-pointer",
223                        "-fno-sanitize-recover=all",
224                    ] + specific_compile_flags),
225                ],
226            ),
227            flag_set(
228                actions = all_link_actions,
229                flag_groups = [
230                    flag_group(flags = specific_link_flags),
231                ],
232            ),
233        ],
234    )
235
236def _impl(ctx):
237    is_linux = ctx.attr.target_libc != "macosx"
238
239    tool_paths = [
240        tool_path(name = name, path = path)
241        for name, path in ctx.attr.tool_paths.items()
242    ]
243    action_configs = []
244
245    llvm_cov = ctx.attr.tool_paths.get("llvm-cov")
246    if llvm_cov:
247        llvm_cov_action = action_config(
248            action_name = ACTION_NAMES.llvm_cov,
249            tools = [
250                tool(
251                    path = llvm_cov,
252                ),
253            ],
254        )
255        action_configs.append(llvm_cov_action)
256
257    objcopy = ctx.attr.tool_paths.get("objcopy")
258    if objcopy:
259        objcopy_action = action_config(
260            action_name = ACTION_NAMES.objcopy_embed_data,
261            tools = [
262                tool(
263                    path = objcopy,
264                ),
265            ],
266        )
267        action_configs.append(objcopy_action)
268
269    validate_static_library = ctx.attr.tool_paths.get("validate_static_library")
270    if validate_static_library:
271        validate_static_library_action = action_config(
272            action_name = ACTION_NAMES.validate_static_library,
273            tools = [
274                tool(
275                    path = validate_static_library,
276                ),
277            ],
278        )
279        action_configs.append(validate_static_library_action)
280
281        symbol_check = feature(
282            name = "symbol_check",
283            implies = [ACTION_NAMES.validate_static_library],
284        )
285    else:
286        symbol_check = None
287
288    deps_scanner = "cpp-module-deps-scanner_not_found"
289    if "cpp-module-deps-scanner" in ctx.attr.tool_paths:
290        deps_scanner = ctx.attr.tool_paths["cpp-module-deps-scanner"]
291    cc = ctx.attr.tool_paths.get("gcc")
292    compile_implies = [
293        # keep same with c++-compile
294        "legacy_compile_flags",
295        "user_compile_flags",
296        "sysroot",
297        "unfiltered_compile_flags",
298        "compiler_input_flags",
299        "compiler_output_flags",
300    ]
301    cpp_module_scan_deps = action_config(
302        action_name = ACTION_NAMES.cpp_module_deps_scanning,
303        tools = [
304            tool(
305                path = deps_scanner,
306            ),
307        ],
308        implies = compile_implies,
309    )
310    action_configs.append(cpp_module_scan_deps)
311
312    cpp20_module_compile = action_config(
313        action_name = ACTION_NAMES.cpp20_module_compile,
314        tools = [
315            tool(
316                path = cc,
317            ),
318        ],
319        flag_sets = [
320            flag_set(
321                flag_groups = [
322                    flag_group(
323                        flags = [
324                            "-x",
325                            "c++-module" if ctx.attr.compiler == "clang" else "c++",
326                        ],
327                    ),
328                ],
329            ),
330        ],
331        implies = compile_implies,
332    )
333    action_configs.append(cpp20_module_compile)
334
335    cpp20_module_codegen = action_config(
336        action_name = ACTION_NAMES.cpp20_module_codegen,
337        tools = [
338            tool(
339                path = cc,
340            ),
341        ],
342        implies = compile_implies,
343    )
344    action_configs.append(cpp20_module_codegen)
345
346    supports_pic_feature = feature(
347        name = "supports_pic",
348        enabled = True,
349    )
350    supports_start_end_lib_feature = feature(
351        name = "supports_start_end_lib",
352        enabled = True,
353    )
354
355    gcc_quoting_for_param_files_feature = feature(
356        name = "gcc_quoting_for_param_files",
357        enabled = True,
358    )
359
360    static_link_cpp_runtimes_feature = feature(
361        name = "static_link_cpp_runtimes",
362        enabled = False,
363    )
364
365    default_compile_flags_feature = feature(
366        name = "default_compile_flags",
367        enabled = True,
368        flag_sets = [
369            flag_set(
370                actions = all_compile_actions,
371                flag_groups = [
372                    flag_group(
373                        # Security hardening requires optimization.
374                        # We need to undef it as some distributions now have it enabled by default.
375                        flags = ["-U_FORTIFY_SOURCE"],
376                    ),
377                ],
378                with_features = [
379                    with_feature_set(
380                        not_features = ["thin_lto"],
381                    ),
382                ],
383            ),
384            flag_set(
385                actions = all_compile_actions,
386                flag_groups = ([
387                    flag_group(
388                        flags = ctx.attr.compile_flags,
389                    ),
390                ] if ctx.attr.compile_flags else []),
391            ),
392            flag_set(
393                actions = all_compile_actions,
394                flag_groups = ([
395                    flag_group(
396                        flags = ctx.attr.dbg_compile_flags,
397                    ),
398                ] if ctx.attr.dbg_compile_flags else []),
399                with_features = [with_feature_set(features = ["dbg"])],
400            ),
401            flag_set(
402                actions = all_compile_actions,
403                flag_groups = ([
404                    flag_group(
405                        flags = ctx.attr.opt_compile_flags,
406                    ),
407                ] if ctx.attr.opt_compile_flags else []),
408                with_features = [with_feature_set(features = ["opt"])],
409            ),
410            flag_set(
411                actions = [ACTION_NAMES.c_compile],
412                flag_groups = ([
413                    flag_group(
414                        flags = ctx.attr.conly_flags,
415                    ),
416                ] if ctx.attr.conly_flags else []),
417            ),
418            flag_set(
419                actions = all_cpp_compile_actions + [ACTION_NAMES.lto_backend],
420                flag_groups = ([
421                    flag_group(
422                        flags = ctx.attr.cxx_flags,
423                    ),
424                ] if ctx.attr.cxx_flags else []),
425            ),
426        ],
427    )
428
429    default_link_flags_feature = feature(
430        name = "default_link_flags",
431        enabled = True,
432        flag_sets = [
433            flag_set(
434                actions = all_link_actions + lto_index_actions,
435                flag_groups = ([
436                    flag_group(
437                        flags = ctx.attr.link_flags,
438                    ),
439                ] if ctx.attr.link_flags else []),
440            ),
441            flag_set(
442                actions = all_link_actions + lto_index_actions,
443                flag_groups = ([
444                    flag_group(
445                        flags = ctx.attr.opt_link_flags,
446                    ),
447                ] if ctx.attr.opt_link_flags else []),
448                with_features = [with_feature_set(features = ["opt"])],
449            ),
450        ],
451        env_sets = [
452            env_set(
453                actions = all_link_actions + lto_index_actions + [ACTION_NAMES.cpp_link_static_library],
454                env_entries = ([
455                    env_entry(
456                        # Required for hermetic links on macOS
457                        key = "ZERO_AR_DATE",
458                        value = "1",
459                    ),
460                ]),
461            ),
462        ],
463    )
464
465    dbg_feature = feature(name = "dbg")
466
467    opt_feature = feature(name = "opt")
468
469    sysroot_feature = feature(
470        name = "sysroot",
471        enabled = True,
472        flag_sets = [
473            flag_set(
474                actions = [
475                    ACTION_NAMES.preprocess_assemble,
476                    ACTION_NAMES.linkstamp_compile,
477                    ACTION_NAMES.c_compile,
478                    ACTION_NAMES.cpp_compile,
479                    ACTION_NAMES.cpp_header_parsing,
480                    ACTION_NAMES.cpp_module_compile,
481                    ACTION_NAMES.cpp_module_codegen,
482                    ACTION_NAMES.cpp_module_deps_scanning,
483                    ACTION_NAMES.cpp20_module_compile,
484                    ACTION_NAMES.cpp20_module_codegen,
485                    ACTION_NAMES.lto_backend,
486                    ACTION_NAMES.clif_match,
487                ] + all_link_actions + lto_index_actions,
488                flag_groups = [
489                    flag_group(
490                        flags = ["--sysroot=%{sysroot}"],
491                        expand_if_available = "sysroot",
492                    ),
493                ],
494            ),
495        ],
496    )
497
498    compiler_input_flags_feature = feature(
499        name = "compiler_input_flags",
500        enabled = True,
501        flag_sets = [
502            flag_set(
503                actions = [
504                    ACTION_NAMES.assemble,
505                    ACTION_NAMES.preprocess_assemble,
506                    ACTION_NAMES.linkstamp_compile,
507                    ACTION_NAMES.c_compile,
508                    ACTION_NAMES.cpp_compile,
509                    ACTION_NAMES.cpp_header_parsing,
510                    ACTION_NAMES.cpp_module_compile,
511                    ACTION_NAMES.cpp_module_codegen,
512                    ACTION_NAMES.cpp_module_deps_scanning,
513                    ACTION_NAMES.cpp20_module_compile,
514                    ACTION_NAMES.cpp20_module_codegen,
515                    ACTION_NAMES.objc_compile,
516                    ACTION_NAMES.objcpp_compile,
517                    ACTION_NAMES.lto_backend,
518                ],
519                flag_groups = [
520                    flag_group(
521                        flags = ["-c", "%{source_file}"],
522                        expand_if_available = "source_file",
523                    ),
524                ],
525            ),
526        ],
527    )
528
529    compiler_output_flags_feature = feature(
530        name = "compiler_output_flags",
531        enabled = True,
532        flag_sets = [
533            flag_set(
534                actions = [
535                    ACTION_NAMES.assemble,
536                    ACTION_NAMES.preprocess_assemble,
537                    ACTION_NAMES.linkstamp_compile,
538                    ACTION_NAMES.c_compile,
539                    ACTION_NAMES.cpp_compile,
540                    ACTION_NAMES.cpp_header_parsing,
541                    ACTION_NAMES.cpp_module_compile,
542                    ACTION_NAMES.cpp_module_codegen,
543                    ACTION_NAMES.cpp_module_deps_scanning,
544                    ACTION_NAMES.cpp20_module_compile,
545                    ACTION_NAMES.cpp20_module_codegen,
546                    ACTION_NAMES.objc_compile,
547                    ACTION_NAMES.objcpp_compile,
548                    ACTION_NAMES.lto_backend,
549                ],
550                flag_groups = [
551                    flag_group(
552                        flags = ["-S"],
553                        expand_if_available = "output_assembly_file",
554                    ),
555                    flag_group(
556                        flags = ["-E"],
557                        expand_if_available = "output_preprocess_file",
558                    ),
559                    flag_group(
560                        flags = ["-o", "%{output_file}"],
561                        expand_if_available = "output_file",
562                    ),
563                ],
564            ),
565        ],
566    )
567
568    fdo_optimize_feature = feature(
569        name = "fdo_optimize",
570        flag_sets = [
571            flag_set(
572                actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
573                flag_groups = [
574                    flag_group(
575                        flags = [
576                            "-fprofile-use=%{fdo_profile_path}",
577                            "-fprofile-correction",
578                        ],
579                        expand_if_available = "fdo_profile_path",
580                    ),
581                ],
582            ),
583        ],
584        provides = ["profile"],
585    )
586
587    supports_dynamic_linker_feature = feature(name = "supports_dynamic_linker", enabled = True)
588
589    user_compile_flags_feature = feature(
590        name = "user_compile_flags",
591        enabled = True,
592        flag_sets = [
593            flag_set(
594                actions = all_compile_actions,
595                flag_groups = [
596                    flag_group(
597                        flags = ["%{user_compile_flags}"],
598                        iterate_over = "user_compile_flags",
599                        expand_if_available = "user_compile_flags",
600                    ),
601                ],
602            ),
603        ],
604    )
605
606    unfiltered_compile_flags_feature = feature(
607        name = "unfiltered_compile_flags",
608        enabled = True,
609        flag_sets = [
610            flag_set(
611                actions = all_compile_actions,
612                flag_groups = ([
613                    flag_group(
614                        flags = ctx.attr.unfiltered_compile_flags,
615                    ),
616                ] if ctx.attr.unfiltered_compile_flags else []),
617            ),
618        ],
619    )
620
621    library_search_directories_feature = feature(
622        name = "library_search_directories",
623        flag_sets = [
624            flag_set(
625                actions = all_link_actions + lto_index_actions,
626                flag_groups = [
627                    flag_group(
628                        flags = ["-L%{library_search_directories}"],
629                        iterate_over = "library_search_directories",
630                        expand_if_available = "library_search_directories",
631                    ),
632                ],
633            ),
634        ],
635    )
636
637    static_libgcc_feature = feature(
638        name = "static_libgcc",
639        enabled = True,
640        flag_sets = [
641            flag_set(
642                actions = [
643                    ACTION_NAMES.cpp_link_executable,
644                    ACTION_NAMES.cpp_link_dynamic_library,
645                    ACTION_NAMES.lto_index_for_executable,
646                    ACTION_NAMES.lto_index_for_dynamic_library,
647                ],
648                flag_groups = [flag_group(flags = ["-static-libgcc"])],
649                with_features = [
650                    with_feature_set(features = ["static_link_cpp_runtimes"]),
651                ],
652            ),
653        ],
654    )
655
656    pic_feature = feature(
657        name = "pic",
658        enabled = True,
659        flag_sets = [
660            flag_set(
661                actions = [
662                    ACTION_NAMES.assemble,
663                    ACTION_NAMES.preprocess_assemble,
664                    ACTION_NAMES.linkstamp_compile,
665                    ACTION_NAMES.c_compile,
666                    ACTION_NAMES.cpp_compile,
667                    ACTION_NAMES.cpp_module_codegen,
668                    ACTION_NAMES.cpp_module_compile,
669                    ACTION_NAMES.cpp20_module_compile,
670                    ACTION_NAMES.cpp20_module_codegen,
671                ],
672                flag_groups = [
673                    flag_group(flags = ["-fPIC"], expand_if_available = "pic"),
674                ],
675            ),
676        ],
677    )
678
679    per_object_debug_info_feature = feature(
680        name = "per_object_debug_info",
681        enabled = True,
682        flag_sets = [
683            flag_set(
684                actions = [
685                    ACTION_NAMES.assemble,
686                    ACTION_NAMES.preprocess_assemble,
687                    ACTION_NAMES.c_compile,
688                    ACTION_NAMES.cpp_compile,
689                    ACTION_NAMES.cpp_module_codegen,
690                    ACTION_NAMES.cpp20_module_codegen,
691                ],
692                flag_groups = [
693                    flag_group(
694                        flags = ["-gsplit-dwarf", "-g"],
695                        expand_if_available = "per_object_debug_info_file",
696                    ),
697                ],
698            ),
699        ],
700    )
701
702    preprocessor_defines_feature = feature(
703        name = "preprocessor_defines",
704        enabled = True,
705        flag_sets = [
706            flag_set(
707                actions = [
708                    ACTION_NAMES.preprocess_assemble,
709                    ACTION_NAMES.linkstamp_compile,
710                    ACTION_NAMES.c_compile,
711                    ACTION_NAMES.cpp_compile,
712                    ACTION_NAMES.cpp_header_parsing,
713                    ACTION_NAMES.cpp_module_compile,
714                    ACTION_NAMES.cpp_module_deps_scanning,
715                    ACTION_NAMES.cpp20_module_compile,
716                    ACTION_NAMES.cpp20_module_codegen,
717                    ACTION_NAMES.clif_match,
718                ],
719                flag_groups = [
720                    flag_group(
721                        flags = ["-D%{preprocessor_defines}"],
722                        iterate_over = "preprocessor_defines",
723                    ),
724                ],
725            ),
726        ],
727    )
728
729    cs_fdo_optimize_feature = feature(
730        name = "cs_fdo_optimize",
731        flag_sets = [
732            flag_set(
733                actions = [ACTION_NAMES.lto_backend],
734                flag_groups = [
735                    flag_group(
736                        flags = [
737                            "-fprofile-use=%{fdo_profile_path}",
738                            "-Wno-profile-instr-unprofiled",
739                            "-Wno-profile-instr-out-of-date",
740                            "-fprofile-correction",
741                        ],
742                        expand_if_available = "fdo_profile_path",
743                    ),
744                ],
745            ),
746        ],
747        provides = ["csprofile"],
748    )
749
750    autofdo_feature = feature(
751        name = "autofdo",
752        flag_sets = [
753            flag_set(
754                actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
755                flag_groups = [
756                    flag_group(
757                        flags = [
758                            "-fauto-profile=%{fdo_profile_path}",
759                            "-fprofile-correction",
760                        ],
761                        expand_if_available = "fdo_profile_path",
762                    ),
763                ],
764            ),
765        ],
766        provides = ["profile"],
767    )
768
769    if is_linux:
770        runtime_library_search_directories_feature = feature(
771            name = "runtime_library_search_directories",
772            flag_sets = [
773                flag_set(
774                    actions = all_link_actions + lto_index_actions,
775                    flag_groups = [
776                        flag_group(
777                            iterate_over = "runtime_library_search_directories",
778                            flag_groups = [
779                                flag_group(
780                                    flags = [
781                                        "-Xlinker",
782                                        "-rpath",
783                                        "-Xlinker",
784                                        "$EXEC_ORIGIN/%{runtime_library_search_directories}",
785                                    ],
786                                    expand_if_true = "is_cc_test",
787                                ),
788                                flag_group(
789                                    flags = [
790                                        "-Xlinker",
791                                        "-rpath",
792                                        "-Xlinker",
793                                        "$ORIGIN/%{runtime_library_search_directories}",
794                                    ],
795                                    expand_if_false = "is_cc_test",
796                                ),
797                            ],
798                            expand_if_available =
799                                "runtime_library_search_directories",
800                        ),
801                    ],
802                    with_features = [
803                        with_feature_set(features = ["static_link_cpp_runtimes"]),
804                    ],
805                ),
806                flag_set(
807                    actions = all_link_actions + lto_index_actions,
808                    flag_groups = [
809                        flag_group(
810                            iterate_over = "runtime_library_search_directories",
811                            flag_groups = [
812                                flag_group(
813                                    flags = [
814                                        "-Xlinker",
815                                        "-rpath",
816                                        "-Xlinker",
817                                        "$ORIGIN/%{runtime_library_search_directories}",
818                                    ],
819                                ),
820                            ],
821                            expand_if_available =
822                                "runtime_library_search_directories",
823                        ),
824                    ],
825                    with_features = [
826                        with_feature_set(
827                            not_features = ["static_link_cpp_runtimes"],
828                        ),
829                    ],
830                ),
831            ],
832        )
833        set_install_name_feature = feature(
834            name = "set_soname",
835            flag_sets = [
836                flag_set(
837                    actions = [
838                        ACTION_NAMES.cpp_link_dynamic_library,
839                        ACTION_NAMES.cpp_link_nodeps_dynamic_library,
840                    ],
841                    flag_groups = [
842                        flag_group(
843                            flags = [
844                                "-Wl,-soname,%{runtime_solib_name}",
845                            ],
846                            expand_if_available = "runtime_solib_name",
847                        ),
848                    ],
849                ),
850            ],
851        )
852    else:
853        runtime_library_search_directories_feature = feature(
854            name = "runtime_library_search_directories",
855            flag_sets = [
856                flag_set(
857                    actions = all_link_actions + lto_index_actions,
858                    flag_groups = [
859                        flag_group(
860                            iterate_over = "runtime_library_search_directories",
861                            flag_groups = [
862                                flag_group(
863                                    flags = [
864                                        "-Xlinker",
865                                        "-rpath",
866                                        "-Xlinker",
867                                        "@loader_path/%{runtime_library_search_directories}",
868                                    ],
869                                ),
870                            ],
871                            expand_if_available = "runtime_library_search_directories",
872                        ),
873                    ],
874                ),
875            ],
876        )
877        set_install_name_feature = feature(
878            name = "set_install_name",
879            enabled = ctx.fragments.cpp.do_not_use_macos_set_install_name,
880            flag_sets = [
881                flag_set(
882                    actions = [
883                        ACTION_NAMES.cpp_link_dynamic_library,
884                        ACTION_NAMES.cpp_link_nodeps_dynamic_library,
885                    ],
886                    flag_groups = [
887                        flag_group(
888                            flags = [
889                                "-Wl,-install_name,@rpath/%{runtime_solib_name}",
890                            ],
891                            expand_if_available = "runtime_solib_name",
892                        ),
893                    ],
894                ),
895            ],
896        )
897
898    fission_support_feature = feature(
899        name = "fission_support",
900        flag_sets = [
901            flag_set(
902                actions = all_link_actions + lto_index_actions,
903                flag_groups = [
904                    flag_group(
905                        flags = ["-Wl,--gdb-index"],
906                        expand_if_available = "is_using_fission",
907                    ),
908                ],
909            ),
910        ],
911    )
912
913    shared_flag_feature = feature(
914        name = "shared_flag",
915        flag_sets = [
916            flag_set(
917                actions = [
918                    ACTION_NAMES.cpp_link_dynamic_library,
919                    ACTION_NAMES.cpp_link_nodeps_dynamic_library,
920                    ACTION_NAMES.lto_index_for_dynamic_library,
921                    ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
922                ],
923                flag_groups = [flag_group(flags = ["-shared"])],
924            ),
925        ],
926    )
927
928    random_seed_feature = feature(
929        name = "random_seed",
930        enabled = True,
931        flag_sets = [
932            flag_set(
933                actions = [
934                    ACTION_NAMES.c_compile,
935                    ACTION_NAMES.cpp_compile,
936                    ACTION_NAMES.cpp_module_codegen,
937                    ACTION_NAMES.cpp_module_compile,
938                    ACTION_NAMES.cpp_module_deps_scanning,
939                    ACTION_NAMES.cpp20_module_compile,
940                    ACTION_NAMES.cpp20_module_codegen,
941                ],
942                flag_groups = [
943                    flag_group(
944                        flags = ["-frandom-seed=%{output_file}"],
945                        expand_if_available = "output_file",
946                    ),
947                ],
948            ),
949        ],
950    )
951
952    includes_feature = feature(
953        name = "includes",
954        enabled = True,
955        flag_sets = [
956            flag_set(
957                actions = [
958                    ACTION_NAMES.preprocess_assemble,
959                    ACTION_NAMES.linkstamp_compile,
960                    ACTION_NAMES.c_compile,
961                    ACTION_NAMES.cpp_compile,
962                    ACTION_NAMES.cpp_header_parsing,
963                    ACTION_NAMES.cpp_module_compile,
964                    ACTION_NAMES.cpp_module_deps_scanning,
965                    ACTION_NAMES.cpp20_module_compile,
966                    ACTION_NAMES.clif_match,
967                    ACTION_NAMES.objc_compile,
968                    ACTION_NAMES.objcpp_compile,
969                ],
970                flag_groups = [
971                    flag_group(
972                        flags = ["-include", "%{includes}"],
973                        iterate_over = "includes",
974                        expand_if_available = "includes",
975                    ),
976                ],
977            ),
978        ],
979    )
980
981    fdo_instrument_feature = feature(
982        name = "fdo_instrument",
983        flag_sets = [
984            flag_set(
985                actions = [
986                    ACTION_NAMES.c_compile,
987                    ACTION_NAMES.cpp_compile,
988                ] + all_link_actions + lto_index_actions,
989                flag_groups = [
990                    flag_group(
991                        flags = [
992                            "-fprofile-generate=%{fdo_instrument_path}",
993                            "-fno-data-sections",
994                        ],
995                        expand_if_available = "fdo_instrument_path",
996                    ),
997                ],
998            ),
999        ],
1000        provides = ["profile"],
1001    )
1002
1003    cs_fdo_instrument_feature = feature(
1004        name = "cs_fdo_instrument",
1005        flag_sets = [
1006            flag_set(
1007                actions = [
1008                    ACTION_NAMES.c_compile,
1009                    ACTION_NAMES.cpp_compile,
1010                    ACTION_NAMES.lto_backend,
1011                ] + all_link_actions + lto_index_actions,
1012                flag_groups = [
1013                    flag_group(
1014                        flags = [
1015                            "-fcs-profile-generate=%{cs_fdo_instrument_path}",
1016                        ],
1017                        expand_if_available = "cs_fdo_instrument_path",
1018                    ),
1019                ],
1020            ),
1021        ],
1022        provides = ["csprofile"],
1023    )
1024
1025    include_paths_feature = feature(
1026        name = "include_paths",
1027        enabled = True,
1028        flag_sets = [
1029            flag_set(
1030                actions = [
1031                    ACTION_NAMES.preprocess_assemble,
1032                    ACTION_NAMES.linkstamp_compile,
1033                    ACTION_NAMES.c_compile,
1034                    ACTION_NAMES.cpp_compile,
1035                    ACTION_NAMES.cpp_header_parsing,
1036                    ACTION_NAMES.cpp_module_compile,
1037                    ACTION_NAMES.cpp_module_deps_scanning,
1038                    ACTION_NAMES.cpp20_module_compile,
1039                    ACTION_NAMES.clif_match,
1040                    ACTION_NAMES.objc_compile,
1041                    ACTION_NAMES.objcpp_compile,
1042                ],
1043                flag_groups = [
1044                    flag_group(
1045                        flags = ["-iquote", "%{quote_include_paths}"],
1046                        iterate_over = "quote_include_paths",
1047                    ),
1048                    flag_group(
1049                        flags = ["-I%{include_paths}"],
1050                        iterate_over = "include_paths",
1051                    ),
1052                    flag_group(
1053                        flags = ["-isystem", "%{system_include_paths}"],
1054                        iterate_over = "system_include_paths",
1055                    ),
1056                ],
1057            ),
1058        ],
1059    )
1060
1061    external_include_paths_feature = feature(
1062        name = "external_include_paths",
1063        flag_sets = [
1064            flag_set(
1065                actions = [
1066                    ACTION_NAMES.preprocess_assemble,
1067                    ACTION_NAMES.linkstamp_compile,
1068                    ACTION_NAMES.c_compile,
1069                    ACTION_NAMES.cpp_compile,
1070                    ACTION_NAMES.cpp_header_parsing,
1071                    ACTION_NAMES.cpp_module_compile,
1072                    ACTION_NAMES.cpp_module_deps_scanning,
1073                    ACTION_NAMES.cpp20_module_compile,
1074                    ACTION_NAMES.cpp20_module_codegen,
1075                    ACTION_NAMES.clif_match,
1076                    ACTION_NAMES.objc_compile,
1077                    ACTION_NAMES.objcpp_compile,
1078                ],
1079                flag_groups = [
1080                    flag_group(
1081                        flags = ["-isystem", "%{external_include_paths}"],
1082                        iterate_over = "external_include_paths",
1083                        expand_if_available = "external_include_paths",
1084                    ),
1085                ],
1086            ),
1087        ],
1088    )
1089
1090    strip_debug_symbols_feature = feature(
1091        name = "strip_debug_symbols",
1092        flag_sets = [
1093            flag_set(
1094                actions = all_link_actions + lto_index_actions,
1095                flag_groups = [
1096                    flag_group(
1097                        flags = ["-Wl,-S"],
1098                        expand_if_available = "strip_debug_symbols",
1099                    ),
1100                ],
1101            ),
1102        ],
1103    )
1104
1105    build_interface_libraries_feature = feature(
1106        name = "build_interface_libraries",
1107        flag_sets = [
1108            flag_set(
1109                actions = [
1110                    ACTION_NAMES.cpp_link_dynamic_library,
1111                    ACTION_NAMES.cpp_link_nodeps_dynamic_library,
1112                    ACTION_NAMES.lto_index_for_dynamic_library,
1113                    ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
1114                ],
1115                flag_groups = [
1116                    flag_group(
1117                        flags = [
1118                            "%{generate_interface_library}",
1119                            "%{interface_library_builder_path}",
1120                            "%{interface_library_input_path}",
1121                            "%{interface_library_output_path}",
1122                        ],
1123                        expand_if_available = "generate_interface_library",
1124                    ),
1125                ],
1126                with_features = [
1127                    with_feature_set(
1128                        features = ["supports_interface_shared_libraries"],
1129                    ),
1130                ],
1131            ),
1132        ],
1133    )
1134
1135    libraries_to_link_common_flag_groups = [
1136        flag_group(
1137            flags = ["-Wl,-whole-archive"],
1138            expand_if_true =
1139                "libraries_to_link.is_whole_archive",
1140            expand_if_equal = variable_with_value(
1141                name = "libraries_to_link.type",
1142                value = "static_library",
1143            ),
1144        ),
1145        flag_group(
1146            flags = ["%{libraries_to_link.object_files}"],
1147            iterate_over = "libraries_to_link.object_files",
1148            expand_if_equal = variable_with_value(
1149                name = "libraries_to_link.type",
1150                value = "object_file_group",
1151            ),
1152        ),
1153        flag_group(
1154            flags = ["%{libraries_to_link.name}"],
1155            expand_if_equal = variable_with_value(
1156                name = "libraries_to_link.type",
1157                value = "object_file",
1158            ),
1159        ),
1160        flag_group(
1161            flags = ["%{libraries_to_link.name}"],
1162            expand_if_equal = variable_with_value(
1163                name = "libraries_to_link.type",
1164                value = "interface_library",
1165            ),
1166        ),
1167        flag_group(
1168            flags = ["%{libraries_to_link.name}"],
1169            expand_if_equal = variable_with_value(
1170                name = "libraries_to_link.type",
1171                value = "static_library",
1172            ),
1173        ),
1174        flag_group(
1175            flags = ["-l%{libraries_to_link.name}"],
1176            expand_if_equal = variable_with_value(
1177                name = "libraries_to_link.type",
1178                value = "dynamic_library",
1179            ),
1180        ),
1181        flag_group(
1182            flags = ["-l:%{libraries_to_link.name}"],
1183            expand_if_equal = variable_with_value(
1184                name = "libraries_to_link.type",
1185                value = "versioned_dynamic_library",
1186            ),
1187        ),
1188        flag_group(
1189            flags = ["-Wl,-no-whole-archive"],
1190            expand_if_true = "libraries_to_link.is_whole_archive",
1191            expand_if_equal = variable_with_value(
1192                name = "libraries_to_link.type",
1193                value = "static_library",
1194            ),
1195        ),
1196    ]
1197
1198    libraries_to_link_feature = feature(
1199        name = "libraries_to_link",
1200        flag_sets = [
1201            flag_set(
1202                actions = [
1203                    ACTION_NAMES.cpp_link_executable,
1204                    ACTION_NAMES.cpp_link_dynamic_library,
1205                ] + lto_index_actions,
1206                flag_groups = [
1207                    flag_group(
1208                        iterate_over = "libraries_to_link",
1209                        flag_groups = [
1210                            flag_group(
1211                                flags = ["-Wl,--start-lib"],
1212                                expand_if_equal = variable_with_value(
1213                                    name = "libraries_to_link.type",
1214                                    value = "object_file_group",
1215                                ),
1216                            ),
1217                        ] + libraries_to_link_common_flag_groups + [
1218                            flag_group(
1219                                flags = ["-Wl,--end-lib"],
1220                                expand_if_equal = variable_with_value(
1221                                    name = "libraries_to_link.type",
1222                                    value = "object_file_group",
1223                                ),
1224                            ),
1225                        ],
1226                        expand_if_available = "libraries_to_link",
1227                    ),
1228                    flag_group(
1229                        flags = ["-Wl,@%{thinlto_param_file}"],
1230                        expand_if_true = "thinlto_param_file",
1231                    ),
1232                ],
1233            ),
1234            # Object file groups may contain symbols that aren't referenced in the same target that
1235            # produces the object files and must thus not be wrapped in --start-lib/--end-lib when
1236            # linking a nodeps dynamic library.
1237            flag_set(
1238                actions = [ACTION_NAMES.cpp_link_nodeps_dynamic_library],
1239                flag_groups = [
1240                    flag_group(
1241                        iterate_over = "libraries_to_link",
1242                        flag_groups = libraries_to_link_common_flag_groups,
1243                    ),
1244                    flag_group(
1245                        flags = ["-Wl,@%{thinlto_param_file}"],
1246                        expand_if_true = "thinlto_param_file",
1247                    ),
1248                ],
1249            ),
1250        ],
1251    )
1252
1253    user_link_flags_feature = feature(
1254        name = "user_link_flags",
1255        flag_sets = [
1256            flag_set(
1257                actions = all_link_actions + lto_index_actions,
1258                flag_groups = [
1259                    flag_group(
1260                        flags = ["%{user_link_flags}"],
1261                        iterate_over = "user_link_flags",
1262                        expand_if_available = "user_link_flags",
1263                    ),
1264                ],
1265            ),
1266        ],
1267    )
1268
1269    default_link_libs_feature = feature(
1270        name = "default_link_libs",
1271        enabled = True,
1272        flag_sets = [
1273            flag_set(
1274                actions = all_link_actions + lto_index_actions,
1275                flag_groups = [flag_group(flags = ctx.attr.link_libs)] if ctx.attr.link_libs else [],
1276            ),
1277        ],
1278    )
1279
1280    fdo_prefetch_hints_feature = feature(
1281        name = "fdo_prefetch_hints",
1282        flag_sets = [
1283            flag_set(
1284                actions = [
1285                    ACTION_NAMES.c_compile,
1286                    ACTION_NAMES.cpp_compile,
1287                    ACTION_NAMES.lto_backend,
1288                ],
1289                flag_groups = [
1290                    flag_group(
1291                        flags = [
1292                            "-mllvm",
1293                            "-prefetch-hints-file=%{fdo_prefetch_hints_path}",
1294                        ],
1295                        expand_if_available = "fdo_prefetch_hints_path",
1296                    ),
1297                ],
1298            ),
1299        ],
1300    )
1301
1302    linkstamps_feature = feature(
1303        name = "linkstamps",
1304        flag_sets = [
1305            flag_set(
1306                actions = all_link_actions + lto_index_actions,
1307                flag_groups = [
1308                    flag_group(
1309                        flags = ["%{linkstamp_paths}"],
1310                        iterate_over = "linkstamp_paths",
1311                        expand_if_available = "linkstamp_paths",
1312                    ),
1313                ],
1314            ),
1315        ],
1316    )
1317
1318    libtool_feature = feature(
1319        name = "libtool",
1320        enabled = not is_linux,
1321    )
1322
1323    archiver_flags_feature = feature(
1324        name = "archiver_flags",
1325        flag_sets = [
1326            flag_set(
1327                actions = [ACTION_NAMES.cpp_link_static_library],
1328                flag_groups = [
1329                    flag_group(
1330                        flags = [
1331                            "rcsD" if is_linux else "rcs",
1332                            "%{output_execpath}",
1333                        ],
1334                        expand_if_available = "output_execpath",
1335                    ),
1336                ],
1337                with_features = [
1338                    with_feature_set(
1339                        not_features = ["libtool"],
1340                    ),
1341                ],
1342            ),
1343            flag_set(
1344                actions = [ACTION_NAMES.cpp_link_static_library],
1345                flag_groups = [
1346                    flag_group(
1347                        flags = [
1348                            "-static",
1349                            "-o",
1350                            "%{output_execpath}",
1351                        ],
1352                        expand_if_available = "output_execpath",
1353                    ),
1354                ],
1355                with_features = [
1356                    with_feature_set(
1357                        features = ["libtool"],
1358                    ),
1359                ],
1360            ),
1361            flag_set(
1362                actions = [ACTION_NAMES.cpp_link_static_library],
1363                flag_groups = [
1364                    flag_group(
1365                        iterate_over = "libraries_to_link",
1366                        flag_groups = [
1367                            flag_group(
1368                                flags = ["%{libraries_to_link.name}"],
1369                                expand_if_equal = variable_with_value(
1370                                    name = "libraries_to_link.type",
1371                                    value = "object_file",
1372                                ),
1373                            ),
1374                            flag_group(
1375                                flags = ["%{libraries_to_link.object_files}"],
1376                                iterate_over = "libraries_to_link.object_files",
1377                                expand_if_equal = variable_with_value(
1378                                    name = "libraries_to_link.type",
1379                                    value = "object_file_group",
1380                                ),
1381                            ),
1382                        ],
1383                        expand_if_available = "libraries_to_link",
1384                    ),
1385                ],
1386            ),
1387            flag_set(
1388                actions = [ACTION_NAMES.cpp_link_static_library],
1389                flag_groups = ([
1390                    flag_group(
1391                        flags = ctx.attr.archive_flags,
1392                    ),
1393                ] if ctx.attr.archive_flags else []),
1394            ),
1395            flag_set(
1396                actions = [ACTION_NAMES.cpp_link_static_library],
1397                flag_groups = [
1398                    flag_group(
1399                        flags = ["%{user_archiver_flags}"],
1400                        iterate_over = "user_archiver_flags",
1401                        expand_if_available = "user_archiver_flags",
1402                    ),
1403                ],
1404            ),
1405        ],
1406    )
1407
1408    force_pic_flags_feature = feature(
1409        name = "force_pic_flags",
1410        flag_sets = [
1411            flag_set(
1412                actions = [
1413                    ACTION_NAMES.cpp_link_executable,
1414                    ACTION_NAMES.lto_index_for_executable,
1415                ],
1416                flag_groups = [
1417                    flag_group(
1418                        flags = ["-pie"],
1419                        expand_if_available = "force_pic",
1420                    ),
1421                ],
1422            ),
1423        ],
1424    )
1425
1426    dependency_file_feature = feature(
1427        name = "dependency_file",
1428        enabled = True,
1429        flag_sets = [
1430            flag_set(
1431                actions = [
1432                    ACTION_NAMES.assemble,
1433                    ACTION_NAMES.preprocess_assemble,
1434                    ACTION_NAMES.c_compile,
1435                    ACTION_NAMES.cpp_compile,
1436                    ACTION_NAMES.cpp_module_compile,
1437                    ACTION_NAMES.objc_compile,
1438                    ACTION_NAMES.objcpp_compile,
1439                    ACTION_NAMES.cpp_header_parsing,
1440                    ACTION_NAMES.cpp_module_deps_scanning,
1441                    ACTION_NAMES.cpp20_module_compile,
1442                    ACTION_NAMES.clif_match,
1443                ],
1444                flag_groups = [
1445                    flag_group(
1446                        flags = ["-MD", "-MF", "%{dependency_file}"],
1447                        expand_if_available = "dependency_file",
1448                    ),
1449                ],
1450            ),
1451        ],
1452    )
1453
1454    serialized_diagnostics_file_feature = feature(
1455        name = "serialized_diagnostics_file",
1456        flag_sets = [
1457            flag_set(
1458                actions = [
1459                    ACTION_NAMES.assemble,
1460                    ACTION_NAMES.preprocess_assemble,
1461                    ACTION_NAMES.c_compile,
1462                    ACTION_NAMES.cpp_compile,
1463                    ACTION_NAMES.cpp_module_compile,
1464                    ACTION_NAMES.objc_compile,
1465                    ACTION_NAMES.objcpp_compile,
1466                    ACTION_NAMES.cpp_header_parsing,
1467                    ACTION_NAMES.cpp_module_deps_scanning,
1468                    ACTION_NAMES.clif_match,
1469                ],
1470                flag_groups = [
1471                    flag_group(
1472                        flags = ["--serialize-diagnostics", "%{serialized_diagnostics_file}"],
1473                        expand_if_available = "serialized_diagnostics_file",
1474                    ),
1475                ],
1476            ),
1477        ],
1478    )
1479
1480    dynamic_library_linker_tool_feature = feature(
1481        name = "dynamic_library_linker_tool",
1482        flag_sets = [
1483            flag_set(
1484                actions = [
1485                    ACTION_NAMES.cpp_link_dynamic_library,
1486                    ACTION_NAMES.cpp_link_nodeps_dynamic_library,
1487                    ACTION_NAMES.lto_index_for_dynamic_library,
1488                    ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
1489                ],
1490                flag_groups = [
1491                    flag_group(
1492                        flags = [" + cppLinkDynamicLibraryToolPath + "],
1493                        expand_if_available = "generate_interface_library",
1494                    ),
1495                ],
1496                with_features = [
1497                    with_feature_set(
1498                        features = ["supports_interface_shared_libraries"],
1499                    ),
1500                ],
1501            ),
1502        ],
1503    )
1504
1505    generate_linkmap_feature = feature(
1506        name = "generate_linkmap",
1507        flag_sets = [
1508            flag_set(
1509                actions = [
1510                    ACTION_NAMES.cpp_link_executable,
1511                ],
1512                flag_groups = [
1513                    flag_group(
1514                        flags = [
1515                            "-Wl,-Map=%{output_execpath}.map" if is_linux else "-Wl,-map,%{output_execpath}.map",
1516                        ],
1517                        expand_if_available = "output_execpath",
1518                    ),
1519                ],
1520            ),
1521        ],
1522    )
1523
1524    output_execpath_flags_feature = feature(
1525        name = "output_execpath_flags",
1526        flag_sets = [
1527            flag_set(
1528                actions = all_link_actions + lto_index_actions,
1529                flag_groups = [
1530                    flag_group(
1531                        flags = ["-o", "%{output_execpath}"],
1532                        expand_if_available = "output_execpath",
1533                    ),
1534                ],
1535            ),
1536        ],
1537    )
1538
1539    # Note that we also set --coverage for c++-link-nodeps-dynamic-library. The
1540    # generated code contains references to gcov symbols, and the dynamic linker
1541    # can't resolve them unless the library is linked against gcov.
1542    coverage_feature = feature(
1543        name = "coverage",
1544        provides = ["profile"],
1545        flag_sets = [
1546            flag_set(
1547                actions = [
1548                    ACTION_NAMES.preprocess_assemble,
1549                    ACTION_NAMES.c_compile,
1550                    ACTION_NAMES.cpp_compile,
1551                    ACTION_NAMES.cpp_header_parsing,
1552                    ACTION_NAMES.cpp_module_compile,
1553                ],
1554                flag_groups = ([
1555                    flag_group(flags = ctx.attr.coverage_compile_flags),
1556                ] if ctx.attr.coverage_compile_flags else []),
1557            ),
1558            flag_set(
1559                actions = all_link_actions + lto_index_actions,
1560                flag_groups = ([
1561                    flag_group(flags = ctx.attr.coverage_link_flags),
1562                ] if ctx.attr.coverage_link_flags else []),
1563            ),
1564        ],
1565    )
1566
1567    thinlto_feature = feature(
1568        name = "thin_lto",
1569        flag_sets = [
1570            flag_set(
1571                actions = [
1572                    ACTION_NAMES.c_compile,
1573                    ACTION_NAMES.cpp_compile,
1574                ] + all_link_actions + lto_index_actions,
1575                flag_groups = [
1576                    flag_group(flags = ["-flto=thin"]),
1577                    flag_group(
1578                        expand_if_available = "lto_indexing_bitcode_file",
1579                        flags = [
1580                            "-Xclang",
1581                            "-fthin-link-bitcode=%{lto_indexing_bitcode_file}",
1582                        ],
1583                    ),
1584                ],
1585            ),
1586            flag_set(
1587                actions = [ACTION_NAMES.linkstamp_compile],
1588                flag_groups = [flag_group(flags = ["-DBUILD_LTO_TYPE=thin"])],
1589            ),
1590            flag_set(
1591                actions = lto_index_actions,
1592                flag_groups = [
1593                    flag_group(flags = [
1594                        "-flto=thin",
1595                        "-Wl,-plugin-opt,thinlto-index-only%{thinlto_optional_params_file}",
1596                        "-Wl,-plugin-opt,thinlto-emit-imports-files",
1597                        "-Wl,-plugin-opt,thinlto-prefix-replace=%{thinlto_prefix_replace}",
1598                    ]),
1599                    flag_group(
1600                        expand_if_available = "thinlto_object_suffix_replace",
1601                        flags = [
1602                            "-Wl,-plugin-opt,thinlto-object-suffix-replace=%{thinlto_object_suffix_replace}",
1603                        ],
1604                    ),
1605                    flag_group(
1606                        expand_if_available = "thinlto_merged_object_file",
1607                        flags = [
1608                            "-Wl,-plugin-opt,obj-path=%{thinlto_merged_object_file}",
1609                        ],
1610                    ),
1611                ],
1612            ),
1613            flag_set(
1614                actions = [ACTION_NAMES.lto_backend],
1615                flag_groups = [
1616                    flag_group(flags = [
1617                        "-c",
1618                        "-fthinlto-index=%{thinlto_index}",
1619                        "-o",
1620                        "%{thinlto_output_object_file}",
1621                        "-x",
1622                        "ir",
1623                        "%{thinlto_input_bitcode_file}",
1624                    ]),
1625                ],
1626            ),
1627        ],
1628    )
1629
1630    treat_warnings_as_errors_feature = feature(
1631        name = "treat_warnings_as_errors",
1632        flag_sets = [
1633            flag_set(
1634                actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
1635                flag_groups = [flag_group(flags = ["-Werror"])],
1636            ),
1637            flag_set(
1638                actions = all_link_actions,
1639                flag_groups = [flag_group(
1640                    flags = ["-Wl,-fatal-warnings"] if is_linux else ["-Wl,-fatal_warnings"],
1641                )],
1642            ),
1643        ],
1644    )
1645
1646    archive_param_file_feature = feature(
1647        name = "archive_param_file",
1648        enabled = True,
1649    )
1650
1651    asan_feature = _sanitizer_feature(
1652        name = "asan",
1653        specific_compile_flags = [
1654            "-fsanitize=address",
1655            "-fno-common",
1656        ],
1657        specific_link_flags = [
1658            "-fsanitize=address",
1659        ],
1660    )
1661
1662    tsan_feature = _sanitizer_feature(
1663        name = "tsan",
1664        specific_compile_flags = [
1665            "-fsanitize=thread",
1666        ],
1667        specific_link_flags = [
1668            "-fsanitize=thread",
1669        ],
1670    )
1671
1672    ubsan_feature = _sanitizer_feature(
1673        name = "ubsan",
1674        specific_compile_flags = [
1675            "-fsanitize=undefined",
1676        ],
1677        specific_link_flags = [
1678            "-fsanitize=undefined",
1679        ],
1680    )
1681
1682    # If you have Xcode + the CLT installed the version defaults can be
1683    # too old for some standard C apis such as thread locals
1684    macos_minimum_os_feature = feature(
1685        name = "macos_minimum_os",
1686        enabled = True,
1687        flag_sets = [
1688            flag_set(
1689                actions = all_compile_actions + all_link_actions,
1690                flag_groups = [flag_group(flags = ["-mmacosx-version-min={}".format(_target_os_version(ctx))])],
1691            ),
1692        ],
1693    )
1694
1695    # Kept for backwards compatibility with the crosstool that moved. Without
1696    # linking the objc runtime binaries don't link CoreFoundation for free,
1697    # which breaks abseil.
1698    macos_default_link_flags_feature = feature(
1699        name = "macos_default_link_flags",
1700        enabled = True,
1701        flag_sets = [
1702            flag_set(
1703                actions = all_link_actions,
1704                flag_groups = [flag_group(flags = [
1705                    "-no-canonical-prefixes",
1706                    "-fobjc-link-runtime",
1707                ])],
1708            ),
1709        ],
1710    )
1711
1712    # Tell bazel we support C++ modules now
1713    cpp_modules_feature = feature(
1714        name = "cpp_modules",
1715        # set default value to False
1716        # to enable the feature
1717        # use --features=cpp_modules
1718        # or add cpp_modules to features attr
1719        enabled = False,
1720    )
1721
1722    cpp_module_modmap_file_feature = feature(
1723        name = "cpp_module_modmap_file",
1724        flag_sets = [
1725            flag_set(
1726                actions = [
1727                    ACTION_NAMES.cpp_compile,
1728                    ACTION_NAMES.cpp20_module_compile,
1729                    ACTION_NAMES.cpp20_module_codegen,
1730                ],
1731                flag_groups = [
1732                    flag_group(
1733                        flags = ["@%{cpp_module_modmap_file}" if ctx.attr.compiler == "clang" else "-fmodule-mapper=%{cpp_module_modmap_file}"],
1734                        expand_if_available = "cpp_module_modmap_file",
1735                    ),
1736                ],
1737            ),
1738        ],
1739        enabled = True,
1740    )
1741    if ctx.attr.compiler == "clang":
1742        flag_groups = [
1743            flag_group(
1744                flags = ["-fmodule-output=%{cpp_module_output_file}"],
1745                expand_if_available = "cpp_module_output_file",
1746            ),
1747        ]
1748    else:
1749        flag_groups = []
1750    cpp20_module_compile_flags_feature = feature(
1751        name = "cpp20_module_compile_flags",
1752        flag_sets = [
1753            flag_set(
1754                actions = [
1755                    ACTION_NAMES.cpp20_module_compile,
1756                ],
1757                flag_groups = flag_groups,
1758            ),
1759        ],
1760        enabled = True,
1761    )
1762
1763    # TODO(#8303): Mac crosstool should also declare every feature.
1764    if is_linux:
1765        # Linux artifact name patterns are the default.
1766        artifact_name_patterns = []
1767        features = [
1768            cpp_modules_feature,
1769            cpp_module_modmap_file_feature,
1770            cpp20_module_compile_flags_feature,
1771            dependency_file_feature,
1772            serialized_diagnostics_file_feature,
1773            random_seed_feature,
1774            pic_feature,
1775            per_object_debug_info_feature,
1776            preprocessor_defines_feature,
1777            includes_feature,
1778            include_paths_feature,
1779            external_include_paths_feature,
1780            fdo_instrument_feature,
1781            cs_fdo_instrument_feature,
1782            cs_fdo_optimize_feature,
1783            thinlto_feature,
1784            fdo_prefetch_hints_feature,
1785            autofdo_feature,
1786            build_interface_libraries_feature,
1787            dynamic_library_linker_tool_feature,
1788            generate_linkmap_feature,
1789            shared_flag_feature,
1790            linkstamps_feature,
1791            output_execpath_flags_feature,
1792            runtime_library_search_directories_feature,
1793            library_search_directories_feature,
1794            libtool_feature,
1795            archiver_flags_feature,
1796            force_pic_flags_feature,
1797            fission_support_feature,
1798            strip_debug_symbols_feature,
1799            coverage_feature,
1800            supports_pic_feature,
1801            asan_feature,
1802            tsan_feature,
1803            ubsan_feature,
1804            gcc_quoting_for_param_files_feature,
1805            static_link_cpp_runtimes_feature,
1806        ] + (
1807            [
1808                supports_start_end_lib_feature,
1809            ] if ctx.attr.supports_start_end_lib else []
1810        ) + [
1811            default_compile_flags_feature,
1812            default_link_flags_feature,
1813            libraries_to_link_feature,
1814            user_link_flags_feature,
1815            default_link_libs_feature,
1816            static_libgcc_feature,
1817            fdo_optimize_feature,
1818            supports_dynamic_linker_feature,
1819            dbg_feature,
1820            opt_feature,
1821            user_compile_flags_feature,
1822            sysroot_feature,
1823            compiler_input_flags_feature,
1824            compiler_output_flags_feature,
1825            unfiltered_compile_flags_feature,
1826            treat_warnings_as_errors_feature,
1827            archive_param_file_feature,
1828            set_install_name_feature,
1829        ] + layering_check_features(ctx.attr.compiler, ctx.attr.extra_flags_per_feature, is_macos = False)
1830    else:
1831        # macOS artifact name patterns differ from the defaults only for dynamic
1832        # libraries.
1833        artifact_name_patterns = [
1834            artifact_name_pattern(
1835                category_name = "dynamic_library",
1836                prefix = "lib",
1837                extension = ".dylib",
1838            ),
1839        ]
1840        features = [
1841            cpp_modules_feature,
1842            cpp_module_modmap_file_feature,
1843            cpp20_module_compile_flags_feature,
1844            macos_minimum_os_feature,
1845            macos_default_link_flags_feature,
1846            dependency_file_feature,
1847            runtime_library_search_directories_feature,
1848            set_install_name_feature,
1849            libtool_feature,
1850            archiver_flags_feature,
1851            asan_feature,
1852            tsan_feature,
1853            ubsan_feature,
1854            gcc_quoting_for_param_files_feature,
1855            static_link_cpp_runtimes_feature,
1856        ] + (
1857            [
1858                supports_start_end_lib_feature,
1859            ] if ctx.attr.supports_start_end_lib else []
1860        ) + [
1861            coverage_feature,
1862            default_compile_flags_feature,
1863            default_link_flags_feature,
1864            user_link_flags_feature,
1865            default_link_libs_feature,
1866            external_include_paths_feature,
1867            fdo_optimize_feature,
1868            dbg_feature,
1869            opt_feature,
1870            user_compile_flags_feature,
1871            sysroot_feature,
1872            compiler_input_flags_feature,
1873            compiler_output_flags_feature,
1874            unfiltered_compile_flags_feature,
1875            treat_warnings_as_errors_feature,
1876            archive_param_file_feature,
1877            generate_linkmap_feature,
1878        ] + layering_check_features(ctx.attr.compiler, ctx.attr.extra_flags_per_feature, is_macos = True)
1879
1880    parse_headers_action_configs, parse_headers_features = parse_headers_support(
1881        parse_headers_tool_path = ctx.attr.tool_paths.get("parse_headers"),
1882    )
1883    action_configs += parse_headers_action_configs
1884    features += parse_headers_features
1885
1886    if symbol_check:
1887        features.append(symbol_check)
1888
1889    return cc_common.create_cc_toolchain_config_info(
1890        ctx = ctx,
1891        features = features,
1892        action_configs = action_configs,
1893        artifact_name_patterns = artifact_name_patterns,
1894        cxx_builtin_include_directories = ctx.attr.cxx_builtin_include_directories,
1895        toolchain_identifier = ctx.attr.toolchain_identifier,
1896        host_system_name = ctx.attr.host_system_name,
1897        target_system_name = ctx.attr.target_system_name,
1898        target_cpu = ctx.attr.cpu,
1899        target_libc = ctx.attr.target_libc,
1900        compiler = ctx.attr.compiler,
1901        abi_version = ctx.attr.abi_version,
1902        abi_libc_version = ctx.attr.abi_libc_version,
1903        tool_paths = tool_paths,
1904        builtin_sysroot = ctx.attr.builtin_sysroot,
1905    )
1906
1907cc_toolchain_config = rule(
1908    implementation = _impl,
1909    attrs = {
1910        "abi_libc_version": attr.string(mandatory = True),
1911        "abi_version": attr.string(mandatory = True),
1912        "archive_flags": attr.string_list(),
1913        "builtin_sysroot": attr.string(),
1914        "compile_flags": attr.string_list(),
1915        "compiler": attr.string(mandatory = True),
1916        "conly_flags": attr.string_list(),
1917        "coverage_compile_flags": attr.string_list(),
1918        "coverage_link_flags": attr.string_list(),
1919        "cpu": attr.string(mandatory = True),
1920        "cxx_builtin_include_directories": attr.string_list(),
1921        "cxx_flags": attr.string_list(),
1922        "dbg_compile_flags": attr.string_list(),
1923        "extra_flags_per_feature": attr.string_list_dict(),
1924        "host_system_name": attr.string(mandatory = True),
1925        "link_flags": attr.string_list(),
1926        "link_libs": attr.string_list(),
1927        "opt_compile_flags": attr.string_list(),
1928        "opt_link_flags": attr.string_list(),
1929        "supports_start_end_lib": attr.bool(),
1930        "target_libc": attr.string(mandatory = True),
1931        "target_system_name": attr.string(mandatory = True),
1932        "tool_paths": attr.string_dict(),
1933        "toolchain_identifier": attr.string(mandatory = True),
1934        "unfiltered_compile_flags": attr.string_list(),
1935        "_xcode_config": attr.label(default = configuration_field(
1936            fragment = "apple",
1937            name = "xcode_config_label",
1938        )),
1939    },
1940    fragments = ["apple", "cpp"],
1941    provides = [CcToolchainConfigInfo],
1942)
1943