# 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)