• 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(
18    "@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl",
19    "action_config",
20    "artifact_name_pattern",
21    "feature",
22    "feature_set",
23    "flag_group",
24    "flag_set",
25    "tool",
26    "tool_path",
27    "variable_with_value",
28    "with_feature_set",
29)
30load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES")
31
32def layering_check_features(compiler):
33    if compiler != "clang":
34        return []
35    return [
36        feature(
37            name = "use_module_maps",
38            requires = [feature_set(features = ["module_maps"])],
39            flag_sets = [
40                flag_set(
41                    actions = [
42                        ACTION_NAMES.c_compile,
43                        ACTION_NAMES.cpp_compile,
44                        ACTION_NAMES.cpp_header_parsing,
45                        ACTION_NAMES.cpp_module_compile,
46                    ],
47                    flag_groups = [
48                        flag_group(
49                            flags = [
50                                "-fmodule-name=%{module_name}",
51                                "-fmodule-map-file=%{module_map_file}",
52                            ],
53                        ),
54                    ],
55                ),
56            ],
57        ),
58
59        # Tell blaze we support module maps in general, so they will be generated
60        # for all c/c++ rules.
61        # Note: not all C++ rules support module maps; thus, do not imply this
62        # feature from other features - instead, require it.
63        feature(name = "module_maps", enabled = True),
64        feature(
65            name = "layering_check",
66            implies = ["use_module_maps"],
67            flag_sets = [
68                flag_set(
69                    actions = [
70                        ACTION_NAMES.c_compile,
71                        ACTION_NAMES.cpp_compile,
72                        ACTION_NAMES.cpp_header_parsing,
73                        ACTION_NAMES.cpp_module_compile,
74                    ],
75                    flag_groups = [
76                        flag_group(flags = [
77                            "-fmodules-strict-decluse",
78                            "-Wprivate-header",
79                        ]),
80                        flag_group(
81                            iterate_over = "dependent_module_map_files",
82                            flags = [
83                                "-fmodule-map-file=%{dependent_module_map_files}",
84                            ],
85                        ),
86                    ],
87                ),
88            ],
89        ),
90    ]
91
92all_compile_actions = [
93    ACTION_NAMES.c_compile,
94    ACTION_NAMES.cpp_compile,
95    ACTION_NAMES.linkstamp_compile,
96    ACTION_NAMES.assemble,
97    ACTION_NAMES.preprocess_assemble,
98    ACTION_NAMES.cpp_header_parsing,
99    ACTION_NAMES.cpp_module_compile,
100    ACTION_NAMES.cpp_module_codegen,
101    ACTION_NAMES.clif_match,
102    ACTION_NAMES.lto_backend,
103]
104
105all_cpp_compile_actions = [
106    ACTION_NAMES.cpp_compile,
107    ACTION_NAMES.linkstamp_compile,
108    ACTION_NAMES.cpp_header_parsing,
109    ACTION_NAMES.cpp_module_compile,
110    ACTION_NAMES.cpp_module_codegen,
111    ACTION_NAMES.clif_match,
112]
113
114preprocessor_compile_actions = [
115    ACTION_NAMES.c_compile,
116    ACTION_NAMES.cpp_compile,
117    ACTION_NAMES.linkstamp_compile,
118    ACTION_NAMES.preprocess_assemble,
119    ACTION_NAMES.cpp_header_parsing,
120    ACTION_NAMES.cpp_module_compile,
121    ACTION_NAMES.clif_match,
122]
123
124codegen_compile_actions = [
125    ACTION_NAMES.c_compile,
126    ACTION_NAMES.cpp_compile,
127    ACTION_NAMES.linkstamp_compile,
128    ACTION_NAMES.assemble,
129    ACTION_NAMES.preprocess_assemble,
130    ACTION_NAMES.cpp_module_codegen,
131    ACTION_NAMES.lto_backend,
132]
133
134all_link_actions = [
135    ACTION_NAMES.cpp_link_executable,
136    ACTION_NAMES.cpp_link_dynamic_library,
137    ACTION_NAMES.cpp_link_nodeps_dynamic_library,
138]
139
140lto_index_actions = [
141    ACTION_NAMES.lto_index_for_executable,
142    ACTION_NAMES.lto_index_for_dynamic_library,
143    ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
144]
145
146def _sanitizer_feature(name = "", specific_compile_flags = [], specific_link_flags = []):
147    return feature(
148        name = name,
149        flag_sets = [
150            flag_set(
151                actions = all_compile_actions,
152                flag_groups = [
153                    flag_group(flags = [
154                        "-fno-omit-frame-pointer",
155                        "-fno-sanitize-recover=all",
156                    ] + specific_compile_flags),
157                ],
158                with_features = [
159                    with_feature_set(features = [name]),
160                ],
161            ),
162            flag_set(
163                actions = all_link_actions,
164                flag_groups = [
165                    flag_group(flags = specific_link_flags),
166                ],
167                with_features = [
168                    with_feature_set(features = [name]),
169                ],
170            ),
171        ],
172    )
173
174def _impl(ctx):
175    tool_paths = [
176        tool_path(name = name, path = path)
177        for name, path in ctx.attr.tool_paths.items()
178    ]
179    action_configs = []
180
181    llvm_cov_action = action_config(
182        action_name = ACTION_NAMES.llvm_cov,
183        tools = [
184            tool(
185                path = ctx.attr.tool_paths["llvm-cov"],
186            ),
187        ],
188    )
189
190    action_configs.append(llvm_cov_action)
191
192    supports_pic_feature = feature(
193        name = "supports_pic",
194        enabled = True,
195    )
196    supports_start_end_lib_feature = feature(
197        name = "supports_start_end_lib",
198        enabled = True,
199    )
200
201    default_compile_flags_feature = feature(
202        name = "default_compile_flags",
203        enabled = True,
204        flag_sets = [
205            flag_set(
206                actions = all_compile_actions,
207                flag_groups = [
208                    flag_group(
209                        # Security hardening requires optimization.
210                        # We need to undef it as some distributions now have it enabled by default.
211                        flags = ["-U_FORTIFY_SOURCE"],
212                    ),
213                ],
214                with_features = [
215                    with_feature_set(
216                        not_features = ["thin_lto"],
217                    ),
218                ],
219            ),
220            flag_set(
221                actions = all_compile_actions,
222                flag_groups = ([
223                    flag_group(
224                        flags = ctx.attr.compile_flags,
225                    ),
226                ] if ctx.attr.compile_flags else []),
227            ),
228            flag_set(
229                actions = all_compile_actions,
230                flag_groups = ([
231                    flag_group(
232                        flags = ctx.attr.dbg_compile_flags,
233                    ),
234                ] if ctx.attr.dbg_compile_flags else []),
235                with_features = [with_feature_set(features = ["dbg"])],
236            ),
237            flag_set(
238                actions = all_compile_actions,
239                flag_groups = ([
240                    flag_group(
241                        flags = ctx.attr.opt_compile_flags,
242                    ),
243                ] if ctx.attr.opt_compile_flags else []),
244                with_features = [with_feature_set(features = ["opt"])],
245            ),
246            flag_set(
247                actions = all_cpp_compile_actions + [ACTION_NAMES.lto_backend],
248                flag_groups = ([
249                    flag_group(
250                        flags = ctx.attr.cxx_flags,
251                    ),
252                ] if ctx.attr.cxx_flags else []),
253            ),
254        ],
255    )
256
257    default_link_flags_feature = feature(
258        name = "default_link_flags",
259        enabled = True,
260        flag_sets = [
261            flag_set(
262                actions = all_link_actions + lto_index_actions,
263                flag_groups = ([
264                    flag_group(
265                        flags = ctx.attr.link_flags,
266                    ),
267                ] if ctx.attr.link_flags else []),
268            ),
269            flag_set(
270                actions = all_link_actions + lto_index_actions,
271                flag_groups = ([
272                    flag_group(
273                        flags = ctx.attr.opt_link_flags,
274                    ),
275                ] if ctx.attr.opt_link_flags else []),
276                with_features = [with_feature_set(features = ["opt"])],
277            ),
278        ],
279    )
280
281    dbg_feature = feature(name = "dbg")
282
283    opt_feature = feature(name = "opt")
284
285    sysroot_feature = feature(
286        name = "sysroot",
287        enabled = True,
288        flag_sets = [
289            flag_set(
290                actions = [
291                    ACTION_NAMES.preprocess_assemble,
292                    ACTION_NAMES.linkstamp_compile,
293                    ACTION_NAMES.c_compile,
294                    ACTION_NAMES.cpp_compile,
295                    ACTION_NAMES.cpp_header_parsing,
296                    ACTION_NAMES.cpp_module_compile,
297                    ACTION_NAMES.cpp_module_codegen,
298                    ACTION_NAMES.lto_backend,
299                    ACTION_NAMES.clif_match,
300                ] + all_link_actions + lto_index_actions,
301                flag_groups = [
302                    flag_group(
303                        flags = ["--sysroot=%{sysroot}"],
304                        expand_if_available = "sysroot",
305                    ),
306                ],
307            ),
308        ],
309    )
310
311    fdo_optimize_feature = feature(
312        name = "fdo_optimize",
313        flag_sets = [
314            flag_set(
315                actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
316                flag_groups = [
317                    flag_group(
318                        flags = [
319                            "-fprofile-use=%{fdo_profile_path}",
320                            "-fprofile-correction",
321                        ],
322                        expand_if_available = "fdo_profile_path",
323                    ),
324                ],
325            ),
326        ],
327        provides = ["profile"],
328    )
329
330    supports_dynamic_linker_feature = feature(name = "supports_dynamic_linker", enabled = True)
331
332    user_compile_flags_feature = feature(
333        name = "user_compile_flags",
334        enabled = True,
335        flag_sets = [
336            flag_set(
337                actions = all_compile_actions,
338                flag_groups = [
339                    flag_group(
340                        flags = ["%{user_compile_flags}"],
341                        iterate_over = "user_compile_flags",
342                        expand_if_available = "user_compile_flags",
343                    ),
344                ],
345            ),
346        ],
347    )
348
349    unfiltered_compile_flags_feature = feature(
350        name = "unfiltered_compile_flags",
351        enabled = True,
352        flag_sets = [
353            flag_set(
354                actions = all_compile_actions,
355                flag_groups = ([
356                    flag_group(
357                        flags = ctx.attr.unfiltered_compile_flags,
358                    ),
359                ] if ctx.attr.unfiltered_compile_flags else []),
360            ),
361        ],
362    )
363
364    library_search_directories_feature = feature(
365        name = "library_search_directories",
366        flag_sets = [
367            flag_set(
368                actions = all_link_actions + lto_index_actions,
369                flag_groups = [
370                    flag_group(
371                        flags = ["-L%{library_search_directories}"],
372                        iterate_over = "library_search_directories",
373                        expand_if_available = "library_search_directories",
374                    ),
375                ],
376            ),
377        ],
378    )
379
380    static_libgcc_feature = feature(
381        name = "static_libgcc",
382        enabled = True,
383        flag_sets = [
384            flag_set(
385                actions = [
386                    ACTION_NAMES.cpp_link_executable,
387                    ACTION_NAMES.cpp_link_dynamic_library,
388                    ACTION_NAMES.lto_index_for_executable,
389                    ACTION_NAMES.lto_index_for_dynamic_library,
390                ],
391                flag_groups = [flag_group(flags = ["-static-libgcc"])],
392                with_features = [
393                    with_feature_set(features = ["static_link_cpp_runtimes"]),
394                ],
395            ),
396        ],
397    )
398
399    pic_feature = feature(
400        name = "pic",
401        enabled = True,
402        flag_sets = [
403            flag_set(
404                actions = [
405                    ACTION_NAMES.assemble,
406                    ACTION_NAMES.preprocess_assemble,
407                    ACTION_NAMES.linkstamp_compile,
408                    ACTION_NAMES.c_compile,
409                    ACTION_NAMES.cpp_compile,
410                    ACTION_NAMES.cpp_module_codegen,
411                    ACTION_NAMES.cpp_module_compile,
412                ],
413                flag_groups = [
414                    flag_group(flags = ["-fPIC"], expand_if_available = "pic"),
415                ],
416            ),
417        ],
418    )
419
420    per_object_debug_info_feature = feature(
421        name = "per_object_debug_info",
422        enabled = True,
423        flag_sets = [
424            flag_set(
425                actions = [
426                    ACTION_NAMES.assemble,
427                    ACTION_NAMES.preprocess_assemble,
428                    ACTION_NAMES.c_compile,
429                    ACTION_NAMES.cpp_compile,
430                    ACTION_NAMES.cpp_module_codegen,
431                ],
432                flag_groups = [
433                    flag_group(
434                        flags = ["-gsplit-dwarf", "-g"],
435                        expand_if_available = "per_object_debug_info_file",
436                    ),
437                ],
438            ),
439        ],
440    )
441
442    preprocessor_defines_feature = feature(
443        name = "preprocessor_defines",
444        enabled = True,
445        flag_sets = [
446            flag_set(
447                actions = [
448                    ACTION_NAMES.preprocess_assemble,
449                    ACTION_NAMES.linkstamp_compile,
450                    ACTION_NAMES.c_compile,
451                    ACTION_NAMES.cpp_compile,
452                    ACTION_NAMES.cpp_header_parsing,
453                    ACTION_NAMES.cpp_module_compile,
454                    ACTION_NAMES.clif_match,
455                ],
456                flag_groups = [
457                    flag_group(
458                        flags = ["-D%{preprocessor_defines}"],
459                        iterate_over = "preprocessor_defines",
460                    ),
461                ],
462            ),
463        ],
464    )
465
466    cs_fdo_optimize_feature = feature(
467        name = "cs_fdo_optimize",
468        flag_sets = [
469            flag_set(
470                actions = [ACTION_NAMES.lto_backend],
471                flag_groups = [
472                    flag_group(
473                        flags = [
474                            "-fprofile-use=%{fdo_profile_path}",
475                            "-Wno-profile-instr-unprofiled",
476                            "-Wno-profile-instr-out-of-date",
477                            "-fprofile-correction",
478                        ],
479                        expand_if_available = "fdo_profile_path",
480                    ),
481                ],
482            ),
483        ],
484        provides = ["csprofile"],
485    )
486
487    autofdo_feature = feature(
488        name = "autofdo",
489        flag_sets = [
490            flag_set(
491                actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
492                flag_groups = [
493                    flag_group(
494                        flags = [
495                            "-fauto-profile=%{fdo_profile_path}",
496                            "-fprofile-correction",
497                        ],
498                        expand_if_available = "fdo_profile_path",
499                    ),
500                ],
501            ),
502        ],
503        provides = ["profile"],
504    )
505
506    runtime_library_search_directories_feature = feature(
507        name = "runtime_library_search_directories",
508        flag_sets = [
509            flag_set(
510                actions = all_link_actions + lto_index_actions,
511                flag_groups = [
512                    flag_group(
513                        iterate_over = "runtime_library_search_directories",
514                        flag_groups = [
515                            flag_group(
516                                flags = [
517                                    "-Xlinker",
518                                    "-rpath",
519                                    "-Xlinker",
520                                    "$EXEC_ORIGIN/%{runtime_library_search_directories}",
521                                ],
522                                expand_if_true = "is_cc_test",
523                            ),
524                            flag_group(
525                                flags = [
526                                    "-Xlinker",
527                                    "-rpath",
528                                    "-Xlinker",
529                                    "$ORIGIN/%{runtime_library_search_directories}",
530                                ],
531                                expand_if_false = "is_cc_test",
532                            ),
533                        ],
534                        expand_if_available =
535                            "runtime_library_search_directories",
536                    ),
537                ],
538                with_features = [
539                    with_feature_set(features = ["static_link_cpp_runtimes"]),
540                ],
541            ),
542            flag_set(
543                actions = all_link_actions + lto_index_actions,
544                flag_groups = [
545                    flag_group(
546                        iterate_over = "runtime_library_search_directories",
547                        flag_groups = [
548                            flag_group(
549                                flags = [
550                                    "-Xlinker",
551                                    "-rpath",
552                                    "-Xlinker",
553                                    "$ORIGIN/%{runtime_library_search_directories}",
554                                ],
555                            ),
556                        ],
557                        expand_if_available =
558                            "runtime_library_search_directories",
559                    ),
560                ],
561                with_features = [
562                    with_feature_set(
563                        not_features = ["static_link_cpp_runtimes"],
564                    ),
565                ],
566            ),
567        ],
568    )
569
570    fission_support_feature = feature(
571        name = "fission_support",
572        flag_sets = [
573            flag_set(
574                actions = all_link_actions + lto_index_actions,
575                flag_groups = [
576                    flag_group(
577                        flags = ["-Wl,--gdb-index"],
578                        expand_if_available = "is_using_fission",
579                    ),
580                ],
581            ),
582        ],
583    )
584
585    shared_flag_feature = feature(
586        name = "shared_flag",
587        flag_sets = [
588            flag_set(
589                actions = [
590                    ACTION_NAMES.cpp_link_dynamic_library,
591                    ACTION_NAMES.cpp_link_nodeps_dynamic_library,
592                    ACTION_NAMES.lto_index_for_dynamic_library,
593                    ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
594                ],
595                flag_groups = [flag_group(flags = ["-shared"])],
596            ),
597        ],
598    )
599
600    random_seed_feature = feature(
601        name = "random_seed",
602        enabled = True,
603        flag_sets = [
604            flag_set(
605                actions = [
606                    ACTION_NAMES.c_compile,
607                    ACTION_NAMES.cpp_compile,
608                    ACTION_NAMES.cpp_module_codegen,
609                    ACTION_NAMES.cpp_module_compile,
610                ],
611                flag_groups = [
612                    flag_group(
613                        flags = ["-frandom-seed=%{output_file}"],
614                        expand_if_available = "output_file",
615                    ),
616                ],
617            ),
618        ],
619    )
620
621    includes_feature = feature(
622        name = "includes",
623        enabled = True,
624        flag_sets = [
625            flag_set(
626                actions = [
627                    ACTION_NAMES.preprocess_assemble,
628                    ACTION_NAMES.linkstamp_compile,
629                    ACTION_NAMES.c_compile,
630                    ACTION_NAMES.cpp_compile,
631                    ACTION_NAMES.cpp_header_parsing,
632                    ACTION_NAMES.cpp_module_compile,
633                    ACTION_NAMES.clif_match,
634                    ACTION_NAMES.objc_compile,
635                    ACTION_NAMES.objcpp_compile,
636                ],
637                flag_groups = [
638                    flag_group(
639                        flags = ["-include", "%{includes}"],
640                        iterate_over = "includes",
641                        expand_if_available = "includes",
642                    ),
643                ],
644            ),
645        ],
646    )
647
648    fdo_instrument_feature = feature(
649        name = "fdo_instrument",
650        flag_sets = [
651            flag_set(
652                actions = [
653                    ACTION_NAMES.c_compile,
654                    ACTION_NAMES.cpp_compile,
655                ] + all_link_actions + lto_index_actions,
656                flag_groups = [
657                    flag_group(
658                        flags = [
659                            "-fprofile-generate=%{fdo_instrument_path}",
660                            "-fno-data-sections",
661                        ],
662                        expand_if_available = "fdo_instrument_path",
663                    ),
664                ],
665            ),
666        ],
667        provides = ["profile"],
668    )
669
670    cs_fdo_instrument_feature = feature(
671        name = "cs_fdo_instrument",
672        flag_sets = [
673            flag_set(
674                actions = [
675                    ACTION_NAMES.c_compile,
676                    ACTION_NAMES.cpp_compile,
677                    ACTION_NAMES.lto_backend,
678                ] + all_link_actions + lto_index_actions,
679                flag_groups = [
680                    flag_group(
681                        flags = [
682                            "-fcs-profile-generate=%{cs_fdo_instrument_path}",
683                        ],
684                        expand_if_available = "cs_fdo_instrument_path",
685                    ),
686                ],
687            ),
688        ],
689        provides = ["csprofile"],
690    )
691
692    include_paths_feature = feature(
693        name = "include_paths",
694        enabled = True,
695        flag_sets = [
696            flag_set(
697                actions = [
698                    ACTION_NAMES.preprocess_assemble,
699                    ACTION_NAMES.linkstamp_compile,
700                    ACTION_NAMES.c_compile,
701                    ACTION_NAMES.cpp_compile,
702                    ACTION_NAMES.cpp_header_parsing,
703                    ACTION_NAMES.cpp_module_compile,
704                    ACTION_NAMES.clif_match,
705                    ACTION_NAMES.objc_compile,
706                    ACTION_NAMES.objcpp_compile,
707                ],
708                flag_groups = [
709                    flag_group(
710                        flags = ["-iquote", "%{quote_include_paths}"],
711                        iterate_over = "quote_include_paths",
712                    ),
713                    flag_group(
714                        flags = ["-I%{include_paths}"],
715                        iterate_over = "include_paths",
716                    ),
717                    flag_group(
718                        flags = ["-isystem", "%{system_include_paths}"],
719                        iterate_over = "system_include_paths",
720                    ),
721                ],
722            ),
723        ],
724    )
725
726    external_include_paths_feature = feature(
727        name = "external_include_paths",
728        flag_sets = [
729            flag_set(
730                actions = [
731                    ACTION_NAMES.preprocess_assemble,
732                    ACTION_NAMES.linkstamp_compile,
733                    ACTION_NAMES.c_compile,
734                    ACTION_NAMES.cpp_compile,
735                    ACTION_NAMES.cpp_header_parsing,
736                    ACTION_NAMES.cpp_module_compile,
737                    ACTION_NAMES.clif_match,
738                    ACTION_NAMES.objc_compile,
739                    ACTION_NAMES.objcpp_compile,
740                ],
741                flag_groups = [
742                    flag_group(
743                        flags = ["-isystem", "%{external_include_paths}"],
744                        iterate_over = "external_include_paths",
745                        expand_if_available = "external_include_paths",
746                    ),
747                ],
748            ),
749        ],
750    )
751
752    symbol_counts_feature = feature(
753        name = "symbol_counts",
754        flag_sets = [
755            flag_set(
756                actions = all_link_actions + lto_index_actions,
757                flag_groups = [
758                    flag_group(
759                        flags = [
760                            "-Wl,--print-symbol-counts=%{symbol_counts_output}",
761                        ],
762                        expand_if_available = "symbol_counts_output",
763                    ),
764                ],
765            ),
766        ],
767    )
768
769    strip_debug_symbols_feature = feature(
770        name = "strip_debug_symbols",
771        flag_sets = [
772            flag_set(
773                actions = all_link_actions + lto_index_actions,
774                flag_groups = [
775                    flag_group(
776                        flags = ["-Wl,-S"],
777                        expand_if_available = "strip_debug_symbols",
778                    ),
779                ],
780            ),
781        ],
782    )
783
784    build_interface_libraries_feature = feature(
785        name = "build_interface_libraries",
786        flag_sets = [
787            flag_set(
788                actions = [
789                    ACTION_NAMES.cpp_link_dynamic_library,
790                    ACTION_NAMES.cpp_link_nodeps_dynamic_library,
791                    ACTION_NAMES.lto_index_for_dynamic_library,
792                    ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
793                ],
794                flag_groups = [
795                    flag_group(
796                        flags = [
797                            "%{generate_interface_library}",
798                            "%{interface_library_builder_path}",
799                            "%{interface_library_input_path}",
800                            "%{interface_library_output_path}",
801                        ],
802                        expand_if_available = "generate_interface_library",
803                    ),
804                ],
805                with_features = [
806                    with_feature_set(
807                        features = ["supports_interface_shared_libraries"],
808                    ),
809                ],
810            ),
811        ],
812    )
813
814    libraries_to_link_feature = feature(
815        name = "libraries_to_link",
816        flag_sets = [
817            flag_set(
818                actions = all_link_actions + lto_index_actions,
819                flag_groups = [
820                    flag_group(
821                        iterate_over = "libraries_to_link",
822                        flag_groups = [
823                            flag_group(
824                                flags = ["-Wl,--start-lib"],
825                                expand_if_equal = variable_with_value(
826                                    name = "libraries_to_link.type",
827                                    value = "object_file_group",
828                                ),
829                            ),
830                            flag_group(
831                                flags = ["-Wl,-whole-archive"],
832                                expand_if_true =
833                                    "libraries_to_link.is_whole_archive",
834                            ),
835                            flag_group(
836                                flags = ["%{libraries_to_link.object_files}"],
837                                iterate_over = "libraries_to_link.object_files",
838                                expand_if_equal = variable_with_value(
839                                    name = "libraries_to_link.type",
840                                    value = "object_file_group",
841                                ),
842                            ),
843                            flag_group(
844                                flags = ["%{libraries_to_link.name}"],
845                                expand_if_equal = variable_with_value(
846                                    name = "libraries_to_link.type",
847                                    value = "object_file",
848                                ),
849                            ),
850                            flag_group(
851                                flags = ["%{libraries_to_link.name}"],
852                                expand_if_equal = variable_with_value(
853                                    name = "libraries_to_link.type",
854                                    value = "interface_library",
855                                ),
856                            ),
857                            flag_group(
858                                flags = ["%{libraries_to_link.name}"],
859                                expand_if_equal = variable_with_value(
860                                    name = "libraries_to_link.type",
861                                    value = "static_library",
862                                ),
863                            ),
864                            flag_group(
865                                flags = ["-l%{libraries_to_link.name}"],
866                                expand_if_equal = variable_with_value(
867                                    name = "libraries_to_link.type",
868                                    value = "dynamic_library",
869                                ),
870                            ),
871                            flag_group(
872                                flags = ["-l:%{libraries_to_link.name}"],
873                                expand_if_equal = variable_with_value(
874                                    name = "libraries_to_link.type",
875                                    value = "versioned_dynamic_library",
876                                ),
877                            ),
878                            flag_group(
879                                flags = ["-Wl,-no-whole-archive"],
880                                expand_if_true = "libraries_to_link.is_whole_archive",
881                            ),
882                            flag_group(
883                                flags = ["-Wl,--end-lib"],
884                                expand_if_equal = variable_with_value(
885                                    name = "libraries_to_link.type",
886                                    value = "object_file_group",
887                                ),
888                            ),
889                        ],
890                        expand_if_available = "libraries_to_link",
891                    ),
892                    flag_group(
893                        flags = ["-Wl,@%{thinlto_param_file}"],
894                        expand_if_true = "thinlto_param_file",
895                    ),
896                ],
897            ),
898        ],
899    )
900
901    user_link_flags_feature = feature(
902        name = "user_link_flags",
903        flag_sets = [
904            flag_set(
905                actions = all_link_actions + lto_index_actions,
906                flag_groups = [
907                    flag_group(
908                        flags = ["%{user_link_flags}"],
909                        iterate_over = "user_link_flags",
910                        expand_if_available = "user_link_flags",
911                    ),
912                ],
913            ),
914        ],
915    )
916
917    default_link_libs_feature = feature(
918        name = "default_link_libs",
919        enabled = True,
920        flag_sets = [
921            flag_set(
922                actions = all_link_actions + lto_index_actions,
923                flag_groups = [flag_group(flags = ctx.attr.link_libs)] if ctx.attr.link_libs else [],
924            ),
925        ],
926    )
927
928    fdo_prefetch_hints_feature = feature(
929        name = "fdo_prefetch_hints",
930        flag_sets = [
931            flag_set(
932                actions = [
933                    ACTION_NAMES.c_compile,
934                    ACTION_NAMES.cpp_compile,
935                    ACTION_NAMES.lto_backend,
936                ],
937                flag_groups = [
938                    flag_group(
939                        flags = [
940                            "-mllvm",
941                            "-prefetch-hints-file=%{fdo_prefetch_hints_path}",
942                        ],
943                        expand_if_available = "fdo_prefetch_hints_path",
944                    ),
945                ],
946            ),
947        ],
948    )
949
950    linkstamps_feature = feature(
951        name = "linkstamps",
952        flag_sets = [
953            flag_set(
954                actions = all_link_actions + lto_index_actions,
955                flag_groups = [
956                    flag_group(
957                        flags = ["%{linkstamp_paths}"],
958                        iterate_over = "linkstamp_paths",
959                        expand_if_available = "linkstamp_paths",
960                    ),
961                ],
962            ),
963        ],
964    )
965
966    archiver_flags_feature = feature(
967        name = "archiver_flags",
968        flag_sets = [
969            flag_set(
970                actions = [ACTION_NAMES.cpp_link_static_library],
971                flag_groups = [
972                    flag_group(flags = ["rcsD"]),
973                    flag_group(
974                        flags = ["%{output_execpath}"],
975                        expand_if_available = "output_execpath",
976                    ),
977                ],
978                with_features = [
979                    with_feature_set(
980                        not_features = ["libtool"],
981                    ),
982                ],
983            ),
984            flag_set(
985                actions = [ACTION_NAMES.cpp_link_static_library],
986                flag_groups = [
987                    flag_group(flags = ["-static", "-s"]),
988                    flag_group(
989                        flags = ["-o", "%{output_execpath}"],
990                        expand_if_available = "output_execpath",
991                    ),
992                ],
993                with_features = [
994                    with_feature_set(
995                        features = ["libtool"],
996                    ),
997                ],
998            ),
999            flag_set(
1000                actions = [ACTION_NAMES.cpp_link_static_library],
1001                flag_groups = [
1002                    flag_group(
1003                        iterate_over = "libraries_to_link",
1004                        flag_groups = [
1005                            flag_group(
1006                                flags = ["%{libraries_to_link.name}"],
1007                                expand_if_equal = variable_with_value(
1008                                    name = "libraries_to_link.type",
1009                                    value = "object_file",
1010                                ),
1011                            ),
1012                            flag_group(
1013                                flags = ["%{libraries_to_link.object_files}"],
1014                                iterate_over = "libraries_to_link.object_files",
1015                                expand_if_equal = variable_with_value(
1016                                    name = "libraries_to_link.type",
1017                                    value = "object_file_group",
1018                                ),
1019                            ),
1020                        ],
1021                        expand_if_available = "libraries_to_link",
1022                    ),
1023                ],
1024            ),
1025            flag_set(
1026                actions = [ACTION_NAMES.cpp_link_static_library],
1027                flag_groups = ([
1028                    flag_group(
1029                        flags = ctx.attr.archive_flags,
1030                    ),
1031                ] if ctx.attr.archive_flags else []),
1032            ),
1033        ],
1034    )
1035
1036    force_pic_flags_feature = feature(
1037        name = "force_pic_flags",
1038        flag_sets = [
1039            flag_set(
1040                actions = [
1041                    ACTION_NAMES.cpp_link_executable,
1042                    ACTION_NAMES.lto_index_for_executable,
1043                ],
1044                flag_groups = [
1045                    flag_group(
1046                        flags = ["-pie"],
1047                        expand_if_available = "force_pic",
1048                    ),
1049                ],
1050            ),
1051        ],
1052    )
1053
1054    dependency_file_feature = feature(
1055        name = "dependency_file",
1056        enabled = True,
1057        flag_sets = [
1058            flag_set(
1059                actions = [
1060                    ACTION_NAMES.assemble,
1061                    ACTION_NAMES.preprocess_assemble,
1062                    ACTION_NAMES.c_compile,
1063                    ACTION_NAMES.cpp_compile,
1064                    ACTION_NAMES.cpp_module_compile,
1065                    ACTION_NAMES.objc_compile,
1066                    ACTION_NAMES.objcpp_compile,
1067                    ACTION_NAMES.cpp_header_parsing,
1068                    ACTION_NAMES.clif_match,
1069                ],
1070                flag_groups = [
1071                    flag_group(
1072                        flags = ["-MD", "-MF", "%{dependency_file}"],
1073                        expand_if_available = "dependency_file",
1074                    ),
1075                ],
1076            ),
1077        ],
1078    )
1079
1080    serialized_diagnostics_file_feature = feature(
1081        name = "serialized_diagnostics_file",
1082        flag_sets = [
1083            flag_set(
1084                actions = [
1085                    ACTION_NAMES.assemble,
1086                    ACTION_NAMES.preprocess_assemble,
1087                    ACTION_NAMES.c_compile,
1088                    ACTION_NAMES.cpp_compile,
1089                    ACTION_NAMES.cpp_module_compile,
1090                    ACTION_NAMES.objc_compile,
1091                    ACTION_NAMES.objcpp_compile,
1092                    ACTION_NAMES.cpp_header_parsing,
1093                    ACTION_NAMES.clif_match,
1094                ],
1095                flag_groups = [
1096                    flag_group(
1097                        flags = ["--serialize-diagnostics", "%{serialized_diagnostics_file}"],
1098                        expand_if_available = "serialized_diagnostics_file",
1099                    ),
1100                ],
1101            ),
1102        ],
1103    )
1104
1105    dynamic_library_linker_tool_feature = feature(
1106        name = "dynamic_library_linker_tool",
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 = [" + cppLinkDynamicLibraryToolPath + "],
1118                        expand_if_available = "generate_interface_library",
1119                    ),
1120                ],
1121                with_features = [
1122                    with_feature_set(
1123                        features = ["supports_interface_shared_libraries"],
1124                    ),
1125                ],
1126            ),
1127        ],
1128    )
1129
1130    output_execpath_flags_feature = feature(
1131        name = "output_execpath_flags",
1132        flag_sets = [
1133            flag_set(
1134                actions = all_link_actions + lto_index_actions,
1135                flag_groups = [
1136                    flag_group(
1137                        flags = ["-o", "%{output_execpath}"],
1138                        expand_if_available = "output_execpath",
1139                    ),
1140                ],
1141            ),
1142        ],
1143    )
1144
1145    # Note that we also set --coverage for c++-link-nodeps-dynamic-library. The
1146    # generated code contains references to gcov symbols, and the dynamic linker
1147    # can't resolve them unless the library is linked against gcov.
1148    coverage_feature = feature(
1149        name = "coverage",
1150        provides = ["profile"],
1151        flag_sets = [
1152            flag_set(
1153                actions = [
1154                    ACTION_NAMES.preprocess_assemble,
1155                    ACTION_NAMES.c_compile,
1156                    ACTION_NAMES.cpp_compile,
1157                    ACTION_NAMES.cpp_header_parsing,
1158                    ACTION_NAMES.cpp_module_compile,
1159                ],
1160                flag_groups = ([
1161                    flag_group(flags = ctx.attr.coverage_compile_flags),
1162                ] if ctx.attr.coverage_compile_flags else []),
1163            ),
1164            flag_set(
1165                actions = all_link_actions + lto_index_actions,
1166                flag_groups = ([
1167                    flag_group(flags = ctx.attr.coverage_link_flags),
1168                ] if ctx.attr.coverage_link_flags else []),
1169            ),
1170        ],
1171    )
1172
1173    thinlto_feature = feature(
1174        name = "thin_lto",
1175        flag_sets = [
1176            flag_set(
1177                actions = [
1178                    ACTION_NAMES.c_compile,
1179                    ACTION_NAMES.cpp_compile,
1180                ] + all_link_actions + lto_index_actions,
1181                flag_groups = [
1182                    flag_group(flags = ["-flto=thin"]),
1183                    flag_group(
1184                        expand_if_available = "lto_indexing_bitcode_file",
1185                        flags = [
1186                            "-Xclang",
1187                            "-fthin-link-bitcode=%{lto_indexing_bitcode_file}",
1188                        ],
1189                    ),
1190                ],
1191            ),
1192            flag_set(
1193                actions = [ACTION_NAMES.linkstamp_compile],
1194                flag_groups = [flag_group(flags = ["-DBUILD_LTO_TYPE=thin"])],
1195            ),
1196            flag_set(
1197                actions = lto_index_actions,
1198                flag_groups = [
1199                    flag_group(flags = [
1200                        "-flto=thin",
1201                        "-Wl,-plugin-opt,thinlto-index-only%{thinlto_optional_params_file}",
1202                        "-Wl,-plugin-opt,thinlto-emit-imports-files",
1203                        "-Wl,-plugin-opt,thinlto-prefix-replace=%{thinlto_prefix_replace}",
1204                    ]),
1205                    flag_group(
1206                        expand_if_available = "thinlto_object_suffix_replace",
1207                        flags = [
1208                            "-Wl,-plugin-opt,thinlto-object-suffix-replace=%{thinlto_object_suffix_replace}",
1209                        ],
1210                    ),
1211                    flag_group(
1212                        expand_if_available = "thinlto_merged_object_file",
1213                        flags = [
1214                            "-Wl,-plugin-opt,obj-path=%{thinlto_merged_object_file}",
1215                        ],
1216                    ),
1217                ],
1218            ),
1219            flag_set(
1220                actions = [ACTION_NAMES.lto_backend],
1221                flag_groups = [
1222                    flag_group(flags = [
1223                        "-c",
1224                        "-fthinlto-index=%{thinlto_index}",
1225                        "-o",
1226                        "%{thinlto_output_object_file}",
1227                        "-x",
1228                        "ir",
1229                        "%{thinlto_input_bitcode_file}",
1230                    ]),
1231                ],
1232            ),
1233        ],
1234    )
1235
1236    treat_warnings_as_errors_feature = feature(
1237        name = "treat_warnings_as_errors",
1238        flag_sets = [
1239            flag_set(
1240                actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
1241                flag_groups = [flag_group(flags = ["-Werror"])],
1242            ),
1243            flag_set(
1244                actions = all_link_actions,
1245                flag_groups = [flag_group(flags = ["-Wl,-fatal-warnings"])],
1246            ),
1247        ],
1248    )
1249
1250    archive_param_file_feature = feature(
1251        name = "archive_param_file",
1252        enabled = True,
1253    )
1254
1255    asan_feature = _sanitizer_feature(
1256        name = "asan",
1257        specific_compile_flags = [
1258            "-fsanitize=address",
1259            "-fno-common",
1260        ],
1261        specific_link_flags = [
1262            "-fsanitize=address",
1263        ],
1264    )
1265
1266    tsan_feature = _sanitizer_feature(
1267        name = "tsan",
1268        specific_compile_flags = [
1269            "-fsanitize=thread",
1270        ],
1271        specific_link_flags = [
1272            "-fsanitize=thread",
1273        ],
1274    )
1275
1276    ubsan_feature = _sanitizer_feature(
1277        name = "ubsan",
1278        specific_compile_flags = [
1279            "-fsanitize=undefined",
1280        ],
1281        specific_link_flags = [
1282            "-fsanitize=undefined",
1283        ],
1284    )
1285
1286    is_linux = ctx.attr.target_libc != "macosx"
1287    libtool_feature = feature(
1288        name = "libtool",
1289        enabled = not is_linux,
1290    )
1291
1292    # TODO(#8303): Mac crosstool should also declare every feature.
1293    if is_linux:
1294        # Linux artifact name patterns are the default.
1295        artifact_name_patterns = []
1296        features = [
1297            dependency_file_feature,
1298            serialized_diagnostics_file_feature,
1299            random_seed_feature,
1300            pic_feature,
1301            per_object_debug_info_feature,
1302            preprocessor_defines_feature,
1303            includes_feature,
1304            include_paths_feature,
1305            external_include_paths_feature,
1306            fdo_instrument_feature,
1307            cs_fdo_instrument_feature,
1308            cs_fdo_optimize_feature,
1309            thinlto_feature,
1310            fdo_prefetch_hints_feature,
1311            autofdo_feature,
1312            build_interface_libraries_feature,
1313            dynamic_library_linker_tool_feature,
1314            symbol_counts_feature,
1315            shared_flag_feature,
1316            linkstamps_feature,
1317            output_execpath_flags_feature,
1318            runtime_library_search_directories_feature,
1319            library_search_directories_feature,
1320            libtool_feature,
1321            archiver_flags_feature,
1322            force_pic_flags_feature,
1323            fission_support_feature,
1324            strip_debug_symbols_feature,
1325            coverage_feature,
1326            supports_pic_feature,
1327            asan_feature,
1328            tsan_feature,
1329            ubsan_feature,
1330        ] + (
1331            [
1332                supports_start_end_lib_feature,
1333            ] if ctx.attr.supports_start_end_lib else []
1334        ) + [
1335            default_compile_flags_feature,
1336            default_link_flags_feature,
1337            libraries_to_link_feature,
1338            user_link_flags_feature,
1339            default_link_libs_feature,
1340            static_libgcc_feature,
1341            fdo_optimize_feature,
1342            supports_dynamic_linker_feature,
1343            dbg_feature,
1344            opt_feature,
1345            user_compile_flags_feature,
1346            sysroot_feature,
1347            unfiltered_compile_flags_feature,
1348            treat_warnings_as_errors_feature,
1349            archive_param_file_feature,
1350        ] + layering_check_features(ctx.attr.compiler)
1351    else:
1352        # macOS artifact name patterns differ from the defaults only for dynamic
1353        # libraries.
1354        artifact_name_patterns = [
1355            artifact_name_pattern(
1356                category_name = "dynamic_library",
1357                prefix = "lib",
1358                extension = ".dylib",
1359            ),
1360        ]
1361        features = [
1362            libtool_feature,
1363            archiver_flags_feature,
1364            supports_pic_feature,
1365            asan_feature,
1366            tsan_feature,
1367            ubsan_feature,
1368        ] + (
1369            [
1370                supports_start_end_lib_feature,
1371            ] if ctx.attr.supports_start_end_lib else []
1372        ) + [
1373            coverage_feature,
1374            default_compile_flags_feature,
1375            default_link_flags_feature,
1376            user_link_flags_feature,
1377            default_link_libs_feature,
1378            fdo_optimize_feature,
1379            supports_dynamic_linker_feature,
1380            dbg_feature,
1381            opt_feature,
1382            user_compile_flags_feature,
1383            sysroot_feature,
1384            unfiltered_compile_flags_feature,
1385            treat_warnings_as_errors_feature,
1386            archive_param_file_feature,
1387        ] + layering_check_features(ctx.attr.compiler)
1388
1389    return cc_common.create_cc_toolchain_config_info(
1390        ctx = ctx,
1391        features = features,
1392        action_configs = action_configs,
1393        artifact_name_patterns = artifact_name_patterns,
1394        cxx_builtin_include_directories = ctx.attr.cxx_builtin_include_directories,
1395        toolchain_identifier = ctx.attr.toolchain_identifier,
1396        host_system_name = ctx.attr.host_system_name,
1397        target_system_name = ctx.attr.target_system_name,
1398        target_cpu = ctx.attr.cpu,
1399        target_libc = ctx.attr.target_libc,
1400        compiler = ctx.attr.compiler,
1401        abi_version = ctx.attr.abi_version,
1402        abi_libc_version = ctx.attr.abi_libc_version,
1403        tool_paths = tool_paths,
1404        builtin_sysroot = ctx.attr.builtin_sysroot,
1405    )
1406
1407cc_toolchain_config = rule(
1408    implementation = _impl,
1409    attrs = {
1410        "cpu": attr.string(mandatory = True),
1411        "compiler": attr.string(mandatory = True),
1412        "toolchain_identifier": attr.string(mandatory = True),
1413        "host_system_name": attr.string(mandatory = True),
1414        "target_system_name": attr.string(mandatory = True),
1415        "target_libc": attr.string(mandatory = True),
1416        "abi_version": attr.string(mandatory = True),
1417        "abi_libc_version": attr.string(mandatory = True),
1418        "cxx_builtin_include_directories": attr.string_list(),
1419        "tool_paths": attr.string_dict(),
1420        "compile_flags": attr.string_list(),
1421        "dbg_compile_flags": attr.string_list(),
1422        "opt_compile_flags": attr.string_list(),
1423        "cxx_flags": attr.string_list(),
1424        "link_flags": attr.string_list(),
1425        "archive_flags": attr.string_list(),
1426        "link_libs": attr.string_list(),
1427        "opt_link_flags": attr.string_list(),
1428        "unfiltered_compile_flags": attr.string_list(),
1429        "coverage_compile_flags": attr.string_list(),
1430        "coverage_link_flags": attr.string_list(),
1431        "supports_start_end_lib": attr.bool(),
1432        "builtin_sysroot": attr.string(),
1433    },
1434    provides = [CcToolchainConfigInfo],
1435)
1436