# 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", "feature", "simple_feature", "flag_set", "flag_group", "flags", "COMPILE_ACTIONS", "LINK_ACTIONS", "ARCHIVE_ACTIONS") 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( "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("-o", "%{output_object_file}"), expand_if_all_available=["output_object_file"], ), flag_group( flags("-S", "-o", "%{output_assembly_file}"), expand_if_all_available=["output_assembly_file"], ), flag_group( flags("-E", "-o", "%{output_preprocess_file}"), expand_if_all_available=["output_preprocess_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("-lgcov") 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)