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