aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java36
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/cpp/BUILD5
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/cpp/SkylarkCcToolchainConfigureTest.java144
-rw-r--r--tools/cpp/BUILD10
-rw-r--r--tools/cpp/crosstool_lib.bzl407
-rw-r--r--tools/cpp/crosstool_utils.bzl276
6 files changed, 863 insertions, 15 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java
index b25dc7fc85..a2da30d674 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java
@@ -50,6 +50,7 @@ import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables;
import com.google.devtools.build.lib.rules.cpp.CppConfiguration.DynamicMode;
import com.google.devtools.build.lib.rules.cpp.CppConfiguration.HeadersCheckingMode;
import com.google.devtools.build.lib.rules.cpp.FdoSupport.FdoMode;
+import com.google.devtools.build.lib.rules.cpp.Link.LinkTargetType;
import com.google.devtools.build.lib.shell.ShellUtils;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
@@ -105,11 +106,8 @@ public final class CcCommon {
}
};
- /** Action configs we request to enable. */
- private static final ImmutableSet<String> DEFAULT_ACTION_CONFIGS =
+ public static final ImmutableSet<String> ALL_COMPILE_ACTIONS =
ImmutableSet.of(
- CppCompileAction.CC_FLAGS_MAKE_VARIABLE_ACTION_NAME,
- CppCompileAction.STRIP_ACTION_NAME,
CppCompileAction.C_COMPILE,
CppCompileAction.CPP_COMPILE,
CppCompileAction.CPP_HEADER_PARSING,
@@ -120,16 +118,29 @@ public final class CcCommon {
CppCompileAction.PREPROCESS_ASSEMBLE,
CppCompileAction.CLIF_MATCH,
CppCompileAction.LINKSTAMP_COMPILE,
- Link.LinkTargetType.STATIC_LIBRARY.getActionName(),
- // We need to create pic-specific actions for link actions, as they will produce
- // differently named outputs.
- Link.LinkTargetType.PIC_STATIC_LIBRARY.getActionName(),
+ CppCompileAction.CC_FLAGS_MAKE_VARIABLE_ACTION_NAME);
+
+ public static final ImmutableSet<String> ALL_LINK_ACTIONS =
+ ImmutableSet.of(
Link.LinkTargetType.INTERFACE_DYNAMIC_LIBRARY.getActionName(),
- Link.LinkTargetType.NODEPS_DYNAMIC_LIBRARY.getActionName(),
Link.LinkTargetType.DYNAMIC_LIBRARY.getActionName(),
- Link.LinkTargetType.ALWAYS_LINK_STATIC_LIBRARY.getActionName(),
- Link.LinkTargetType.ALWAYS_LINK_PIC_STATIC_LIBRARY.getActionName(),
- Link.LinkTargetType.EXECUTABLE.getActionName());
+ Link.LinkTargetType.NODEPS_DYNAMIC_LIBRARY.getActionName(),
+ LinkTargetType.EXECUTABLE.getActionName());
+
+ public static final ImmutableSet<String> ALL_ARCHIVE_ACTIONS =
+ ImmutableSet.of(Link.LinkTargetType.STATIC_LIBRARY.getActionName());
+
+ public static final ImmutableSet<String> ALL_OTHER_ACTIONS =
+ ImmutableSet.of(CppCompileAction.STRIP_ACTION_NAME);
+
+ /** Action configs we request to enable. */
+ public static final ImmutableSet<String> DEFAULT_ACTION_CONFIGS =
+ ImmutableSet.<String>builder()
+ .addAll(ALL_COMPILE_ACTIONS)
+ .addAll(ALL_LINK_ACTIONS)
+ .addAll(ALL_ARCHIVE_ACTIONS)
+ .addAll(ALL_OTHER_ACTIONS)
+ .build();
/** Features we request to enable unless a rule explicitly doesn't support them. */
private static final ImmutableSet<String> DEFAULT_FEATURES =
@@ -142,6 +153,7 @@ public final class CcCommon {
CppRuleClasses.INCLUDE_PATHS,
CppRuleClasses.PIC,
CppRuleClasses.PREPROCESSOR_DEFINES);
+
public static final String CC_TOOLCHAIN_DEFAULT_ATTRIBUTE_NAME = ":cc_toolchain";
/** C++ configuration */
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/BUILD b/src/test/java/com/google/devtools/build/lib/rules/cpp/BUILD
index 7e0b17115b..9d5482bada 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/cpp/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/BUILD
@@ -13,7 +13,10 @@ filegroup(
java_test(
name = "cpp-rules-tests",
srcs = glob(["*.java"]) + ["proto/CcProtoLibraryTest.java"],
- resources = ["//tools/cpp:lib_cc_configure"],
+ resources = [
+ "//tools/cpp:crosstool_utils",
+ "//tools/cpp:lib_cc_configure",
+ ],
tags = ["rules"],
test_class = "com.google.devtools.build.lib.AllTests",
deps = [
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/SkylarkCcToolchainConfigureTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/SkylarkCcToolchainConfigureTest.java
index dbaa612fb3..c3386fff9a 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/cpp/SkylarkCcToolchainConfigureTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/SkylarkCcToolchainConfigureTest.java
@@ -27,6 +27,15 @@ import org.junit.runners.JUnit4;
public class SkylarkCcToolchainConfigureTest extends EvaluationTestCase {
@Test
+ public void testActionNames() throws Exception {
+ newTest()
+ .testStatement("COMPILE_ACTIONS", MutableList.copyOf(env, CcCommon.ALL_COMPILE_ACTIONS))
+ .testStatement("LINK_ACTIONS", MutableList.copyOf(env, CcCommon.ALL_LINK_ACTIONS))
+ .testStatement("ARCHIVE_ACTIONS", MutableList.copyOf(env, CcCommon.ALL_ARCHIVE_ACTIONS))
+ .testStatement("OTHER_ACTIONS", MutableList.copyOf(env, CcCommon.ALL_OTHER_ACTIONS));
+ }
+
+ @Test
public void testSplitEscaped() throws Exception {
newTest()
.testStatement("split_escaped('a:b:c', ':')", MutableList.of(env, "a", "b", "c"))
@@ -47,7 +56,135 @@ public class SkylarkCcToolchainConfigureTest extends EvaluationTestCase {
.testStatement("split_escaped('a%%b', ':')", MutableList.of(env, "a%b"))
.testStatement("split_escaped('a%:', ':')", MutableList.of(env, "a:"));
}
-
+
+ @Test
+ public void testActionConfig() throws Exception {
+ newTest()
+ .testStatement(
+ "action_config('c++-compile', '/usr/bin/gcc')",
+ "\n"
+ + " action_config {\n"
+ + " config_name: 'c++-compile'\n"
+ + " action_name: 'c++-compile'\n"
+ + " tool {\n"
+ + " tool_path: '/usr/bin/gcc'\n"
+ + " }\n"
+ + " }");
+ }
+
+ @Test
+ public void testFeature() throws Exception {
+ newTest()
+ .testStatement(
+ "feature("
+ + "'fully_static_link', "
+ + " [ "
+ + " flag_set("
+ + " ['c++-link-dynamic-library', 'c++-link-nodeps-dynamic-library'], "
+ + " [flag_group([flag('-a'), flag('-b'), flag('-c')])])])",
+ "\n"
+ + " feature {\n"
+ + " name: 'fully_static_link'\n"
+ + " enabled: true\n"
+ + " flag_set {\n"
+ + " action: 'c++-link-dynamic-library'\n"
+ + " action: 'c++-link-nodeps-dynamic-library'\n"
+ + " flag_group {\n"
+ + " flag: '-a'\n"
+ + " flag: '-b'\n"
+ + " flag: '-c'\n"
+ + " }\n"
+ + " }\n"
+ + " }");
+ }
+
+ @Test
+ public void testFeatureThoroughly() throws Exception {
+ newTest()
+ .testStatement(
+ "feature("
+ + "'fully_static_link', "
+ + " [ "
+ + " flag_set("
+ + " ['c++-link-dynamic-library'], "
+ + " [flag_group([flag('-a')])]),"
+ + " flag_set("
+ + " ['c++-link-dynamic-library'],"
+ + " ["
+ + " flag_group("
+ + " [flag('-a')],"
+ + " iterate_over='a'),"
+ + " flag_group("
+ + " [flag('-c')],"
+ + " expand_if_all_available=['a','b'],"
+ + " expand_if_none_available=['a'],"
+ + " expand_if_true=['a','b'],"
+ + " expand_if_false=['a'],"
+ + " expand_if_equal=[['a','val']],"
+ + " ),"
+ + " flag_group("
+ + " [flag('-c')],"
+ + " iterate_over='a',"
+ + " expand_if_all_available=['a','b'],"
+ + " expand_if_none_available=['a'],"
+ + " expand_if_true=['a','b'],"
+ + " expand_if_false=['a'],"
+ + " expand_if_equal=[['a','val']],"
+ + " )"
+ + " ]),"
+ + " flag_set("
+ + " ['c++-link-dynamic-library'], "
+ + " [flag_group([flag_group([flag('-a')])])])"
+ + " ])",
+ "\n"
+ + " feature {\n"
+ + " name: 'fully_static_link'\n"
+ + " enabled: true\n"
+ + " flag_set {\n"
+ + " action: 'c++-link-dynamic-library'\n"
+ + " flag_group {\n"
+ + " flag: '-a'\n"
+ + " }\n"
+ + " }\n"
+ + " flag_set {\n"
+ + " action: 'c++-link-dynamic-library'\n"
+ + " flag_group {\n"
+ + " iterate_over: 'a'\n"
+ + " flag: '-a'\n"
+ + " }\n"
+ + " flag_group {\n"
+ + " expand_if_all_available: 'a'\n"
+ + " expand_if_all_available: 'b'\n"
+ + " expand_if_none_available: 'a'\n"
+ + " expand_if_true: 'a'\n"
+ + " expand_if_true: 'b'\n"
+ + " expand_if_false: 'a'\n"
+ + " expand_if_equal { variable: 'a' value: 'val' }\n"
+ + " flag: '-c'\n"
+ + " }\n"
+ + " flag_group {\n"
+ + " expand_if_all_available: 'a'\n"
+ + " expand_if_all_available: 'b'\n"
+ + " expand_if_none_available: 'a'\n"
+ + " expand_if_true: 'a'\n"
+ + " expand_if_true: 'b'\n"
+ + " expand_if_false: 'a'\n"
+ + " expand_if_equal { variable: 'a' value: 'val' }\n"
+ + " iterate_over: 'a'\n"
+ + " flag: '-c'\n"
+ + " }\n"
+ + " }\n"
+ + " flag_set {\n"
+ + " action: 'c++-link-dynamic-library'\n"
+ + " flag_group {\n"
+ + " flag_group {\n"
+ + " flag: '-a'\n"
+ + " }\n"
+ + " }\n"
+ + " }\n"
+ + " }");
+ }
+
private ModalTestCase newTest(String... skylarkOptions) throws IOException {
return new SkylarkTest(skylarkOptions)
// A mock implementation of Label to be able to parse lib_cc_configure under default
@@ -56,6 +193,9 @@ public class SkylarkCcToolchainConfigureTest extends EvaluationTestCase {
.setUp("def Label(arg):\n return 42")
.setUp(
ResourceLoader.readFromResources(
- TestConstants.BAZEL_REPO_PATH + "tools/cpp/lib_cc_configure.bzl"));
+ TestConstants.BAZEL_REPO_PATH + "tools/cpp/lib_cc_configure.bzl"))
+ .setUp(
+ ResourceLoader.readFromResources(
+ TestConstants.BAZEL_REPO_PATH + "tools/cpp/crosstool_utils.bzl"));
}
}
diff --git a/tools/cpp/BUILD b/tools/cpp/BUILD
index 3ba10505c1..4412b1454f 100644
--- a/tools/cpp/BUILD
+++ b/tools/cpp/BUILD
@@ -219,6 +219,16 @@ filegroup(
srcs = ["lib_cc_configure.bzl"],
)
+filegroup(
+ name = "crosstool_utils",
+ srcs = ["crosstool_utils.bzl"],
+)
+
+filegroup(
+ name = "crosstool_lib",
+ srcs = ["crosstool_lib.bzl"],
+)
+
cc_toolchain_type(name = "toolchain_type")
# A dummy toolchain is necessary to satisfy toolchain resolution until platforms
diff --git a/tools/cpp/crosstool_lib.bzl b/tools/cpp/crosstool_lib.bzl
new file mode 100644
index 0000000000..a2dfde6ffa
--- /dev/null
+++ b/tools/cpp/crosstool_lib.bzl
@@ -0,0 +1,407 @@
+# 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)
diff --git a/tools/cpp/crosstool_utils.bzl b/tools/cpp/crosstool_utils.bzl
new file mode 100644
index 0000000000..caadba1f31
--- /dev/null
+++ b/tools/cpp/crosstool_utils.bzl
@@ -0,0 +1,276 @@
+# 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.
+"""Utility functions for writing crosstool files in Skylark"""
+
+# All possible C++ compile actions
+COMPILE_ACTIONS = [
+ "c-compile",
+ "c++-compile",
+ "c++-header-parsing",
+ "c++-header-preprocessing",
+ "c++-module-compile",
+ "c++-module-codegen",
+ "assemble",
+ "preprocess-assemble",
+ "clif-match",
+ "linkstamp-compile",
+ "cc-flags-make-variable",
+]
+
+# All possible C++ link actions
+LINK_ACTIONS = [
+ "c++-link-interface-dynamic-library",
+ "c++-link-dynamic-library",
+ "c++-link-nodeps-dynamic-library",
+ "c++-link-executable",
+]
+
+# All possible C++ archive actions
+ARCHIVE_ACTIONS = [
+ "c++-link-static-library",
+]
+
+# All remaining actions used by C++ rules that are configured in the CROSSTOOL
+OTHER_ACTIONS = [
+ "strip"
+]
+
+
+def action_config(action_name, tool_path):
+ """Emit action_config message.
+
+ Examples:
+ action_config("c-compile", "/usr/bin/gcc") ->
+ action_config {
+ config_name: 'c-compile'
+ action_name: 'c-compile'
+ tool {
+ tool_path: '/usr/bin/gcc'
+ }
+ }
+
+ Args:
+ action_name: name of the action
+ tool_path: absolute or CROSSTOOL-relative path to the tool
+
+ Returns:
+ a string to be placed into the CROSSTOOL
+ """
+ if action_name == None or action_name == "":
+ fail("action_name must be present")
+ if tool_path == None or tool_path == "":
+ fail("tool_path must be present")
+ return """
+ action_config {{
+ config_name: '{action_name}'
+ action_name: '{action_name}'
+ tool {{
+ tool_path: '{tool_path}'
+ }}
+ }}""".format(action_name=action_name, tool_path=tool_path)
+
+
+def feature(name, flag_sets, enabled = True, provides = None):
+ """Emit feature message.
+
+ Examples:
+ feature("fully_static_link", flag_sets, enabled = False) ->
+ feature {
+ name: 'fully_static_link'
+ enabled = false
+ <flags_sets>
+ }
+
+ Args:
+ name: name of the feature
+ flag_sets: a collection of flag_set messages
+ enabled: whether this feature is turned on by default
+ provides: a symbol this feature provides, used to implement mutually incompatible features
+
+ Returns:
+ a string to be placed into the CROSSTOOL
+ """
+ if name == None or name == "":
+ fail("feature name must be present")
+ return """
+ feature {{
+ name: '{name}'
+ enabled: {enabled}{provides}{flag_sets}
+ }}""".format(
+ provides=("\n provides: '%s'" % provides if provides != None else ""),
+ name=name,
+ enabled=_to_proto_value(enabled),
+ flag_sets="".join(flag_sets))
+
+
+def simple_feature(name, actions, flags, enabled = True, provides = None,
+ expand_if_all_available = [], iterate_over = None):
+ """Sugar for emitting simple feature message.
+
+ Examples:
+ simple_feature("foo", ['c-compile'], flags("-foo")) ->
+ feature {
+ name: 'foo'
+ flag_set {
+ action: 'c-compile'
+ flag_group {
+ flag: '-foo'
+ }
+ }
+ }
+
+ Args:
+ name: name of the feature
+ actions: for which actions should flags be emitted
+ flags: a collection of flag messages
+ enabled: whether this feature is turned on by default
+ provides: a symbol this feature provides, used to implement mutually incompatible features
+ expand_if_all_available: specify which build variables need to be present
+ for this group to be expanded
+ iterate_over: expand this flag_group for every item in the build variable
+
+ Returns:
+ a string to be placed into the CROSSTOOL
+ """
+ if len(flags) == 0:
+ return feature(name, [])
+ else:
+ return feature(
+ name,
+ [flag_set(
+ actions,
+ [flag_group(
+ [flag(f) for f in flags],
+ iterate_over=iterate_over,
+ expand_if_all_available=expand_if_all_available)])],
+ enabled = enabled,
+ provides = provides)
+
+
+def flag_set(actions, flag_groups):
+ """Emit flag_set message.
+
+ Examples:
+ flag_set(['c-compile'], flag_groups) ->
+ flag_set {
+ action: 'c-compile'
+ <flag_groups>
+ }
+
+ Args:
+ actions: for which actions should flags be emitted
+ flag_groups: a collection of flag_group messages
+
+ Returns:
+ a string to be placed into the CROSSTOOL
+ """
+ if actions == None or len(actions) == 0:
+ fail("empty actions list is not allowed for flag_set")
+ if flag_groups == None or len(flag_groups) == 0:
+ fail("empty flag_groups list is not allowed for flag_set")
+ actions_string = ""
+ for action in actions: actions_string += "\n action: '%s'" % action
+
+ return """
+ flag_set {{{actions}{flag_groups}
+ }}""".format(actions=actions_string, flag_groups="".join(flag_groups))
+
+
+def flag_group(
+ content, expand_if_all_available = [], expand_if_none_available = [], expand_if_true = [],
+ expand_if_false = [], expand_if_equal = [], iterate_over = None):
+ """Emit flag_group message.
+
+ Examples:
+ flag_group(flags("-foo %{output_file}"), expand_if_all_available="output_file") ->
+ flag_group { expand_if_all_available: "output_file"
+ flag: "-foo %{output_file}"
+ }
+
+ Args:
+ content: a collection of flag messages or a collection of flag_group messages
+ expand_if_all_available: specify which build variables need to be present
+ for this group to be expanded
+ expand_if_none_available: specify which build variables need to be missing
+ for this group to be expanded
+ expand_if_true: specify which build variables need to be truthy for this group
+ to be expanded
+ expand_if_false: specify which build variables need to be falsey for this group
+ to be expanded
+ expand_if_equal: [[var1, value1], [var2, value2]...] specify what values
+ should specific build variables have for this group to be expanded
+ iterate_over: expand this flag_group for every item in the build variable
+
+ Returns:
+ a string to be placed into the CROSSTOOL
+ """
+ if content == None or len(content)== 0:
+ fail("flag_group without flags is not allowed")
+ conditions = ""
+ for var in expand_if_all_available:
+ conditions += "\n expand_if_all_available: '%s'" % var
+ for var in expand_if_none_available:
+ conditions += "\n expand_if_none_available: '%s'" % var
+ for var in expand_if_true:
+ conditions += "\n expand_if_true: '%s'" % var
+ for var in expand_if_false:
+ conditions += "\n expand_if_false: '%s'" % var
+ for var in expand_if_equal:
+ conditions += "\n expand_if_equal { variable: '%s' value: '%s' }" % (var[0], var[1])
+ return """
+ flag_group {{{conditions}{iterate_over}{content}
+ }}""".format(
+ content="".join(content),
+ iterate_over=("\n iterate_over: '%s'" % iterate_over if iterate_over != None else ""),
+ conditions=conditions)
+
+
+def flag(flag):
+ """Emit flag field.
+
+ Examples:
+ flag("-foo") -> flag: '-foo'
+
+ Args:
+ flag: value to be emitted to the command line
+
+ Returns:
+ a string to be placed into the CROSSTOOL
+ """
+ return "\n flag: '%s'" % flag
+
+
+def flags(*flags):
+ """Sugar for emitting sequence of flag fields.
+
+ Examples:
+ flags("-foo", "-bar") ->
+ flag: '-foo'
+ flag: '-bar'
+
+ Args:
+ *flags: values to be emitted to the command line
+
+ Returns:
+ a string to be placed into the CROSSTOOL
+ """
+ return [flag(f) for f in flags]
+
+
+def _to_proto_value(boolean):
+ if boolean:
+ return "true"
+ else:
+ return "false"