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