|  | # pylint: disable=g-bad-file-header | 
|  | # Copyright 2018 The Bazel Authors. All rights reserved. | 
|  | # | 
|  | # Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | # you may not use this file except in compliance with the License. | 
|  | # You may obtain a copy of the License at | 
|  | # | 
|  | #    http://www.apache.org/licenses/LICENSE-2.0 | 
|  | # | 
|  | # Unless required by applicable law or agreed to in writing, software | 
|  | # distributed under the License is distributed on an "AS IS" BASIS, | 
|  | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | # See the License for the specific language governing permissions and | 
|  | # limitations under the License. | 
|  | """Library of common crosstool features.""" | 
|  |  | 
|  | load( | 
|  | "@bazel_tools//tools/cpp:crosstool_utils.bzl", | 
|  | "ARCHIVE_ACTIONS", | 
|  | "COMPILE_ACTIONS", | 
|  | "LINK_ACTIONS", | 
|  | "feature", | 
|  | "flag_group", | 
|  | "flag_set", | 
|  | "flags", | 
|  | "simple_feature", | 
|  | ) | 
|  |  | 
|  | def get_features_to_appear_first(platform): | 
|  | """Returns standard features that should appear in the top of the toolchain. | 
|  |  | 
|  | Args: | 
|  | platform: one of [ k8, darwin, msvc ] | 
|  |  | 
|  | Returns: | 
|  | a collection of features to be put into crosstool | 
|  | """ | 
|  | return [ | 
|  | simple_feature("no_legacy_features", [], []), | 
|  | simple_feature( | 
|  | "legacy_compile_flags", | 
|  | COMPILE_ACTIONS, | 
|  | ["%{legacy_compile_flags}"], | 
|  | expand_if_all_available = ["legacy_compile_flags"], | 
|  | iterate_over = "legacy_compile_flags", | 
|  | ), | 
|  | simple_feature( | 
|  | "dependency_file", | 
|  | COMPILE_ACTIONS, | 
|  | ["-MD", "-MF", "%{dependency_file}"], | 
|  | expand_if_all_available = ["dependency_file"], | 
|  | ), | 
|  | simple_feature( | 
|  | "random_seed", | 
|  | COMPILE_ACTIONS, | 
|  | ["-frandom-seed=%{output_file}"], | 
|  | ), | 
|  | simple_feature( | 
|  | "pic", | 
|  | COMPILE_ACTIONS, | 
|  | ["-fPIC"], | 
|  | expand_if_all_available = ["pic"], | 
|  | ), | 
|  | simple_feature( | 
|  | "per_object_debug_info", | 
|  | COMPILE_ACTIONS, | 
|  | ["-gsplit-dwarf"], | 
|  | expand_if_all_available = ["per_object_debug_info_file"], | 
|  | ), | 
|  | simple_feature( | 
|  | "preprocessor_defines", | 
|  | COMPILE_ACTIONS, | 
|  | ["-D%{preprocessor_defines}"], | 
|  | iterate_over = "preprocessor_defines", | 
|  | expand_if_all_available = ["preprocessor_defines"], | 
|  | ), | 
|  | simple_feature( | 
|  | "includes", | 
|  | COMPILE_ACTIONS, | 
|  | ["-include", "%{includes}"], | 
|  | iterate_over = "includes", | 
|  | expand_if_all_available = ["includes"], | 
|  | ), | 
|  | simple_feature( | 
|  | "quote_include_paths", | 
|  | COMPILE_ACTIONS, | 
|  | ["-iquote", "%{quote_include_paths}"], | 
|  | iterate_over = "quote_include_paths", | 
|  | expand_if_all_available = ["quote_include_paths"], | 
|  | ), | 
|  | simple_feature( | 
|  | "include_paths", | 
|  | COMPILE_ACTIONS, | 
|  | ["-I%{include_paths}"], | 
|  | iterate_over = "include_paths", | 
|  | expand_if_all_available = ["include_paths"], | 
|  | ), | 
|  | simple_feature( | 
|  | "system_include_paths", | 
|  | COMPILE_ACTIONS, | 
|  | ["-isystem", "%{system_include_paths}"], | 
|  | iterate_over = "system_include_paths", | 
|  | expand_if_all_available = ["system_include_paths"], | 
|  | ), | 
|  | simple_feature( | 
|  | "symbol_counts", | 
|  | LINK_ACTIONS, | 
|  | ["-Wl,--print-symbol-counts=%{symbol_counts_output}"], | 
|  | expand_if_all_available = ["symbol_counts_output"], | 
|  | ), | 
|  | simple_feature( | 
|  | "shared_flag", | 
|  | LINK_ACTIONS, | 
|  | ["-shared"], | 
|  | expand_if_all_available = ["symbol_counts_output"], | 
|  | ), | 
|  | simple_feature( | 
|  | "output_execpath_flags", | 
|  | LINK_ACTIONS, | 
|  | ["-o", "%{output_execpath}"], | 
|  | expand_if_all_available = ["output_execpath"], | 
|  | ), | 
|  | simple_feature( | 
|  | "runtime_library_search_directories", | 
|  | LINK_ACTIONS, | 
|  | [_runtime_library_directory_flag(platform)], | 
|  | iterate_over = "runtime_library_search_directories", | 
|  | expand_if_all_available = ["runtime_library_search_directories"], | 
|  | ), | 
|  | simple_feature( | 
|  | "library_search_directories", | 
|  | LINK_ACTIONS, | 
|  | ["-L%{library_search_directories}"], | 
|  | iterate_over = "library_search_directories", | 
|  | expand_if_all_available = ["library_search_directories"], | 
|  | ), | 
|  | simple_feature("_archiver_flags", ARCHIVE_ACTIONS, _archiver_flags(platform)), | 
|  | feature( | 
|  | "libraries_to_link", | 
|  | [ | 
|  | flag_set(ARCHIVE_ACTIONS, [ | 
|  | flag_group( | 
|  | [ | 
|  | flag_group( | 
|  | flags("%{libraries_to_link.name}"), | 
|  | expand_if_equal = [["libraries_to_link.type", "object_file"]], | 
|  | ), | 
|  | flag_group( | 
|  | flags("%{libraries_to_link.object_files}"), | 
|  | expand_if_equal = [["libraries_to_link.type", "object_file_group"]], | 
|  | iterate_over = "libraries_to_link.object_files", | 
|  | ), | 
|  | ], | 
|  | iterate_over = "libraries_to_link", | 
|  | expand_if_all_available = ["libraries_to_link"], | 
|  | ), | 
|  | ]), | 
|  | flag_set(LINK_ACTIONS, [ | 
|  | flag_group( | 
|  | [ | 
|  | flag_group( | 
|  | flags("-Wl,--start-lib"), | 
|  | expand_if_equal = [["libraries_to_link.type", "object_file_group"]], | 
|  | ), | 
|  | ] + | 
|  | _libraries_to_link_flag_groupss(platform) + [ | 
|  | flag_group( | 
|  | flags("-Wl,--end-lib"), | 
|  | expand_if_equal = [["libraries_to_link.type", "object_file_group"]], | 
|  | ), | 
|  | ], | 
|  | iterate_over = "libraries_to_link", | 
|  | ), | 
|  | flag_group(flags("-Wl,@%{thinlto_param_file}"), expand_if_true = ["thinlto_param_file"]), | 
|  | ]), | 
|  | ], | 
|  | ), | 
|  | simple_feature( | 
|  | "force_pic_flags", | 
|  | ["c++-link-executable"], | 
|  | ["-pie"], | 
|  | expand_if_all_available = ["force_pic"], | 
|  | ), | 
|  | simple_feature( | 
|  | "user_link_flags", | 
|  | LINK_ACTIONS, | 
|  | ["%{user_link_flags}"], | 
|  | iterate_over = "user_link_flags", | 
|  | expand_if_all_available = ["user_link_flags"], | 
|  | ), | 
|  | simple_feature( | 
|  | "legacy_link_flags", | 
|  | LINK_ACTIONS, | 
|  | ["%{legacy_link_flags}"], | 
|  | iterate_over = "legacy_link_flags", | 
|  | expand_if_all_available = ["legacy_link_flags"], | 
|  | ), | 
|  | simple_feature( | 
|  | "fission_support", | 
|  | LINK_ACTIONS, | 
|  | ["-Wl,--gdb-index"], | 
|  | expand_if_all_available = ["is_using_fission"], | 
|  | ), | 
|  | simple_feature( | 
|  | "strip_debug_symbols", | 
|  | LINK_ACTIONS, | 
|  | ["-Wl,-S"], | 
|  | expand_if_all_available = ["strip_debug_symbols"], | 
|  | ), | 
|  | _coverage_feature(platform), | 
|  | simple_feature("strip_flags", ["strip"], _strip_flags(platform)), | 
|  | ] | 
|  |  | 
|  | def get_features_to_appear_last(platform): | 
|  | """Returns standard features that should appear at the end of the toolchain. | 
|  |  | 
|  | Args: | 
|  | platform: one of [ k8, darwin, msvc ] | 
|  |  | 
|  | Returns: | 
|  | a collection of features to be put into crosstool | 
|  | """ | 
|  | return [ | 
|  | simple_feature( | 
|  | "user_compile_flags", | 
|  | COMPILE_ACTIONS, | 
|  | ["%{user_compile_flags}"], | 
|  | expand_if_all_available = ["user_compile_flags"], | 
|  | iterate_over = "user_compile_flags", | 
|  | ), | 
|  | simple_feature( | 
|  | "sysroot", | 
|  | COMPILE_ACTIONS + LINK_ACTIONS, | 
|  | ["--sysroot=%{sysroot}"], | 
|  | expand_if_all_available = ["sysroot"], | 
|  | ), | 
|  | simple_feature( | 
|  | "unfiltered_compile_flags", | 
|  | COMPILE_ACTIONS, | 
|  | ["%{unfiltered_compile_flags}"], | 
|  | expand_if_all_available = ["unfiltered_compile_flags"], | 
|  | iterate_over = "unfiltered_compile_flags", | 
|  | ), | 
|  | simple_feature( | 
|  | "linker_param_file", | 
|  | LINK_ACTIONS, | 
|  | [_linker_param_file_flag(platform)], | 
|  | expand_if_all_available = ["linker_param_file"], | 
|  | ), | 
|  | simple_feature( | 
|  | "archiver_param_file", | 
|  | ARCHIVE_ACTIONS, | 
|  | [_archiver_param_file_flag(platform)], | 
|  | expand_if_all_available = ["linker_param_file"], | 
|  | ), | 
|  | simple_feature( | 
|  | "compiler_input_flags", | 
|  | COMPILE_ACTIONS, | 
|  | ["-c", "%{source_file}"], | 
|  | expand_if_all_available = ["source_file"], | 
|  | ), | 
|  | feature( | 
|  | "compiler_output_flags", | 
|  | [ | 
|  | flag_set(COMPILE_ACTIONS, [ | 
|  | flag_group( | 
|  | flags("-S"), | 
|  | expand_if_all_available = ["output_assembly_file"], | 
|  | ), | 
|  | flag_group( | 
|  | flags("-E"), | 
|  | expand_if_all_available = ["output_preprocess_file"], | 
|  | ), | 
|  | flag_group( | 
|  | flags("-o", "%{output_file}"), | 
|  | expand_if_all_available = ["output_file"], | 
|  | ), | 
|  | ]), | 
|  | ], | 
|  | ), | 
|  | ] | 
|  |  | 
|  | def _is_linux(platform): | 
|  | return platform == "k8" | 
|  |  | 
|  | def _is_darwin(platform): | 
|  | return platform == "darwin" | 
|  |  | 
|  | def _is_msvc(platform): | 
|  | return platform == "msvc" | 
|  |  | 
|  | def _coverage_feature(use_llvm_format): | 
|  | if use_llvm_format: | 
|  | compile_flags = flags("-fprofile-instr-generate", "-fcoverage-mapping") | 
|  | link_flags = flags("-fprofile-instr-generate") | 
|  | else: | 
|  | compile_flags = flags("-fprofile-arcs", "-ftest-coverage") | 
|  | link_flags = flags("--coverage") | 
|  | return feature( | 
|  | "coverage", | 
|  | [ | 
|  | flag_set(COMPILE_ACTIONS, [flag_group(compile_flags)]), | 
|  | flag_set(LINK_ACTIONS, [flag_group(link_flags)]), | 
|  | ], | 
|  | enabled = False, | 
|  | provides = "profile", | 
|  | ) | 
|  |  | 
|  | def _runtime_library_directory_flag(platform): | 
|  | if _is_linux(platform): | 
|  | return "-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}" | 
|  | elif _is_darwin(platform): | 
|  | return "-Wl,-rpath,@loader_path/%{runtime_library_search_directories}" | 
|  | elif _is_msvc(platform): | 
|  | fail("todo") | 
|  | else: | 
|  | fail("Unsupported platform: " + platform) | 
|  |  | 
|  | def _archiver_flags(platform): | 
|  | if _is_linux(platform): | 
|  | return ["rcsD", "%{output_execpath}"] | 
|  | elif _is_darwin(platform): | 
|  | return ["-static", "-s", "-o", "%{output_execpath}"] | 
|  | elif _is_msvc(platform): | 
|  | fail("todo") | 
|  | else: | 
|  | fail("Unsupported platform: " + platform) | 
|  |  | 
|  | def _library_to_link_with_worce_load(variable_type, variable, flag = "", iterate = False): | 
|  | return [ | 
|  | flag_group( | 
|  | [ | 
|  | flag_group( | 
|  | flags( | 
|  | "-Wl,-force_load," + flag + "%{" + variable + "}", | 
|  | expand_if_true = ["libraries_to_link.is_whole_archive"], | 
|  | ), | 
|  | ), | 
|  | flag_group( | 
|  | flags( | 
|  | flag + "%{" + variable + "}", | 
|  | expand_if_false = ["libraries_to_link.is_whole_archive"], | 
|  | ), | 
|  | ), | 
|  | ], | 
|  | iterate_over = variable if iterate else None, | 
|  | expand_if_equal = [["libraries_to_link.type", variable_type]], | 
|  | ), | 
|  | ] | 
|  |  | 
|  | def _libraries_to_link_flag_groupss(platform): | 
|  | if _is_linux(platform): | 
|  | return [ | 
|  | flag_group( | 
|  | flags("-Wl,-whole-archive"), | 
|  | expand_if_true = ["libraries_to_link.is_whole_archive"], | 
|  | ), | 
|  | flag_group( | 
|  | flags("-Wl,--start-lib"), | 
|  | expand_if_equal = [["libraries_to_link.type", "object_file_group"]], | 
|  | ), | 
|  | flag_group( | 
|  | flags("%{libraries_to_link.object_files}"), | 
|  | iterate_over = "libraries_to_link.object_files", | 
|  | expand_if_equal = [["libraries_to_link.type", "object_file_group"]], | 
|  | ), | 
|  | flag_group( | 
|  | flags("-Wl,--end-lib"), | 
|  | expand_if_equal = [["libraries_to_link.type", "object_file_group"]], | 
|  | ), | 
|  | flag_group( | 
|  | flags("%{libraries_to_link.name}"), | 
|  | expand_if_equal = [["libraries_to_link.type", "object_file"]], | 
|  | ), | 
|  | flag_group( | 
|  | flags("%{libraries_to_link.name}"), | 
|  | expand_if_equal = [["libraries_to_link.type", "interface_library"]], | 
|  | ), | 
|  | flag_group( | 
|  | flags("%{libraries_to_link.name}"), | 
|  | expand_if_equal = [["libraries_to_link.type", "static_library"]], | 
|  | ), | 
|  | flag_group( | 
|  | flags("-l%{libraries_to_link.name}"), | 
|  | expand_if_equal = [["libraries_to_link.type", "dynamic_library"]], | 
|  | ), | 
|  | flag_group( | 
|  | flags("-l:%{libraries_to_link.name}"), | 
|  | expand_if_equal = [["libraries_to_link.type", "versioned_dynamic_library"]], | 
|  | ), | 
|  | flag_group( | 
|  | flags("-Wl,-no-whole-archive"), | 
|  | expand_if_true = ["libraries_to_link.is_whole_archive"], | 
|  | ), | 
|  | ] | 
|  | if _is_darwin(platform): | 
|  | return [ | 
|  | flag_group( | 
|  | flags("-Wl,--start-lib"), | 
|  | expand_if_equal = [["libraries_to_link.type", "object_file_group"]], | 
|  | ), | 
|  | _library_to_link_with_worce_load( | 
|  | "object_file_group", | 
|  | "libraries_to_link.object_files", | 
|  | iterate = True, | 
|  | ), | 
|  | flag_group( | 
|  | flags("-Wl,--end-lib"), | 
|  | expand_if_equal = [["libraries_to_link.type", "object_file_group"]], | 
|  | ), | 
|  | _library_to_link_with_worce_load("object_file", "libraries_to_link.name"), | 
|  | _library_to_link_with_worce_load("interface_library", "libraries_to_link.name"), | 
|  | _library_to_link_with_worce_load("static_library", "libraries_to_link.name"), | 
|  | _library_to_link_with_worce_load("dynamic_library", "libraries_to_link.name", flag = "-l"), | 
|  | _library_to_link_with_worce_load("versioned_dynamic_library", "libraries_to_link.name", flag = "-l:"), | 
|  | ] | 
|  | elif _is_msvc(platform): | 
|  | fail("todo") | 
|  | else: | 
|  | fail("Unsupported platform: " + platform) | 
|  |  | 
|  | def _strip_flags(platform): | 
|  | if _is_linux(platform): | 
|  | return [ | 
|  | "-S", | 
|  | "-p", | 
|  | "-o", | 
|  | "%{output_file}", | 
|  | "-R", | 
|  | ".gnu.switches.text.quote_paths", | 
|  | "-R", | 
|  | ".gnu.switches.text.bracket_paths", | 
|  | "-R", | 
|  | ".gnu.switches.text.system_paths", | 
|  | "-R", | 
|  | ".gnu.switches.text.cpp_defines", | 
|  | "-R", | 
|  | ".gnu.switches.text.cpp_includes", | 
|  | "-R", | 
|  | ".gnu.switches.text.cl_args", | 
|  | "-R", | 
|  | ".gnu.switches.text.lipo_info", | 
|  | "-R", | 
|  | ".gnu.switches.text.annotation", | 
|  | ] | 
|  | elif _is_darwin(platform): | 
|  | return ["-S", "-o", "%{output_file}"] | 
|  | elif _is_msvc(platform): | 
|  | fail("todo") | 
|  | else: | 
|  | fail("Unsupported platform: " + platform) | 
|  |  | 
|  | def _linker_param_file_flag(platform): | 
|  | if _is_linux(platform): | 
|  | return "-Wl,@%{linker_param_file}" | 
|  | elif _is_darwin(platform): | 
|  | return "-Wl,@%{linker_param_file}" | 
|  | elif _is_msvc(platform): | 
|  | fail("todo") | 
|  | else: | 
|  | fail("Unsupported platform: " + platform) | 
|  |  | 
|  | def _archiver_param_file_flag(platform): | 
|  | if _is_linux(platform): | 
|  | return "@%{linker_param_file}" | 
|  | elif _is_darwin(platform): | 
|  | return "@%{linker_param_file}" | 
|  | elif _is_msvc(platform): | 
|  | fail("todo") | 
|  | else: | 
|  | fail("Unsupported platform: " + platform) |