blob: 8d2ce143177a3e9395d3ff149bf53ae0cacb955e [file] [log] [blame]
# 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"],
[_force_pic_flag(platform)],
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 _force_pic_flag(platform):
if _is_linux(platform):
return "-pie"
elif _is_darwin(platform):
return "-Wl,-pie"
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)