blob: 875386d47d04ec1476db345d68e6e7b6ac79eb55 [file] [log] [blame] [edit]
# 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)