// Copyright 2014 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. package com.google.devtools.build.lib.rules.cpp; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; /** * A helper class for creating action_configs for the c++ actions. * *

TODO(b/30109612): Replace this with action_configs in the crosstool instead of putting it in * legacy features. */ public class CppActionConfigs { /** A platform for C++ tool invocations. */ public enum CppPlatform { LINUX, MAC } // Note: these configs won't be added to the crosstools that defines no_legacy_features feature // (e.g. ndk, apple, enclave crosstools). Those need to be modified separately. public static String getCppActionConfigs( CppPlatform platform, ImmutableSet existingFeatureNames, String gccToolPath, String cppLinkDynamicLibraryToolPath, String arToolPath, String stripToolPath, boolean supportsEmbeddedRuntimes, boolean supportsInterfaceSharedLibraries) { String cppDynamicLibraryLinkerTool = ""; if (!existingFeatureNames.contains("dynamic_library_linker_tool") && supportsInterfaceSharedLibraries) { cppDynamicLibraryLinkerTool = "" + "feature {" + " name: 'dynamic_library_linker_tool'" + " flag_set {" + " action: 'c++-link-dynamic-library'" + " action: 'c++-link-nodeps-dynamic-library'" + " flag_group {" + " expand_if_all_available: 'generate_interface_library'" + " flag: '" + cppLinkDynamicLibraryToolPath + "'" + " }" + " }" + "}"; } return Joiner.on("\n") .join( ImmutableList.of( "action_config {", " config_name: 'assemble'", " action_name: 'assemble'", " tool {", " tool_path: '" + gccToolPath + "'", " }", " implies: 'legacy_compile_flags'", " implies: 'user_compile_flags'", " implies: 'sysroot'", " implies: 'unfiltered_compile_flags'", " implies: 'compiler_input_flags'", " implies: 'compiler_output_flags'", "}", "action_config {", " config_name: 'preprocess-assemble'", " action_name: 'preprocess-assemble'", " tool {", " tool_path: '" + gccToolPath + "'", " }", " implies: 'legacy_compile_flags'", " implies: 'user_compile_flags'", " implies: 'sysroot'", " implies: 'unfiltered_compile_flags'", " implies: 'compiler_input_flags'", " implies: 'compiler_output_flags'", "}", "action_config {", " config_name: 'linkstamp-compile'", " action_name: 'linkstamp-compile'", " tool {", " tool_path: '" + gccToolPath + "'", " }", " implies: 'legacy_compile_flags'", " implies: 'user_compile_flags'", " implies: 'sysroot'", " implies: 'unfiltered_compile_flags'", " implies: 'compiler_input_flags'", " implies: 'compiler_output_flags'", "}", "action_config {", " config_name: 'c-compile'", " action_name: 'c-compile'", " tool {", " tool_path: '" + gccToolPath + "'", " }", " implies: 'legacy_compile_flags'", " implies: 'user_compile_flags'", " implies: 'sysroot'", " implies: 'unfiltered_compile_flags'", " implies: 'compiler_input_flags'", " implies: 'compiler_output_flags'", "}", "action_config {", " config_name: 'c++-compile'", " action_name: 'c++-compile'", " tool {", " tool_path: '" + gccToolPath + "'", " }", " implies: 'legacy_compile_flags'", " implies: 'user_compile_flags'", " implies: 'sysroot'", " implies: 'unfiltered_compile_flags'", " implies: 'compiler_input_flags'", " implies: 'compiler_output_flags'", "}", "action_config {", " config_name: 'c++-header-parsing'", " action_name: 'c++-header-parsing'", " tool {", " tool_path: '" + gccToolPath + "'", " }", " implies: 'legacy_compile_flags'", " implies: 'user_compile_flags'", " implies: 'sysroot'", " implies: 'unfiltered_compile_flags'", " implies: 'compiler_input_flags'", " implies: 'compiler_output_flags'", "}", "action_config {", " config_name: 'c++-module-compile'", " action_name: 'c++-module-compile'", " tool {", " tool_path: '" + gccToolPath + "'", " }", " implies: 'legacy_compile_flags'", " implies: 'user_compile_flags'", " implies: 'sysroot'", " implies: 'unfiltered_compile_flags'", " implies: 'compiler_input_flags'", " implies: 'compiler_output_flags'", "}", "action_config {", " config_name: 'c++-module-codegen'", " action_name: 'c++-module-codegen'", " tool {", " tool_path: '" + gccToolPath + "'", " }", " implies: 'legacy_compile_flags'", " implies: 'user_compile_flags'", " implies: 'sysroot'", " implies: 'unfiltered_compile_flags'", " implies: 'compiler_input_flags'", " implies: 'compiler_output_flags'", "}", ifTrue( !existingFeatureNames.contains(CppRuleClasses.LEGACY_COMPILE_FLAGS), "feature {", " name: 'legacy_compile_flags'", " enabled: true", " flag_set {", " expand_if_all_available: 'legacy_compile_flags'", " action: 'assemble'", " action: 'preprocess-assemble'", " action: 'linkstamp-compile'", " action: 'c-compile'", " action: 'c++-compile'", " action: 'c++-header-parsing'", " action: 'c++-module-compile'", " action: 'c++-module-codegen'", " action: 'lto-backend'", " action: 'clif-match'", " flag_group {", " iterate_over: 'legacy_compile_flags'", " flag: '%{legacy_compile_flags}'", " }", " }", "}"), ifTrue( !existingFeatureNames.contains(CppRuleClasses.STATIC_LINK_CPP_RUNTIMES), "feature {", " name: 'static_link_cpp_runtimes'", "}"), // Gcc options: // -MD turns on .d file output as a side-effect (doesn't imply -E) // -MM[D] enables user includes only, not system includes // -MF specifies the dotd file name // Issues: // -M[M] alone subverts actual .o output (implies -E) // -M[M]D alone breaks some of the .d naming assumptions // This combination gets user and system includes with specified name: // -MD -MF ifTrue( !existingFeatureNames.contains(CppRuleClasses.DEPENDENCY_FILE), "feature {", " name: 'dependency_file'", " flag_set {", " action: 'assemble'", " action: 'preprocess-assemble'", " action: 'c-compile'", " action: 'c++-compile'", " action: 'c++-module-compile'", " action: 'objc-compile'", " action: 'objc++-compile'", " action: 'c++-header-parsing'", " action: 'clif-match'", " expand_if_all_available: 'dependency_file'", " flag_group {", " flag: '-MD'", " flag: '-MF'", " flag: '%{dependency_file}'", " }", " }", "}"), // GCC and Clang give randomized names to symbols which are defined in // an anonymous namespace but have external linkage. To make // computation of these deterministic, we want to override the // default seed for the random number generator. It's safe to use // any value which differs for all translation units; we use the // path to the object file. ifTrue( !existingFeatureNames.contains(CppRuleClasses.RANDOM_SEED), "feature {", " name: 'random_seed'", " flag_set {", " action: 'c++-compile'", " action: 'c++-module-codegen'", " action: 'c++-module-compile'", " flag_group {", " expand_if_all_available: 'output_file'", " flag: '-frandom-seed=%{output_file}'", " }", " }", "}"), ifTrue( !existingFeatureNames.contains(CppRuleClasses.PIC), "feature {", " name: 'pic'", " flag_set {", " action: 'assemble'", " action: 'preprocess-assemble'", " action: 'linkstamp-compile'", " action: 'c-compile'", " action: 'c++-compile'", " action: 'c++-module-codegen'", " action: 'c++-module-compile'", " expand_if_all_available: 'pic'", " flag_group {", " flag: '-fPIC'", " }", " }", "}"), ifTrue( !existingFeatureNames.contains(CppRuleClasses.PER_OBJECT_DEBUG_INFO), "feature {", " name: 'per_object_debug_info'", " flag_set {", " action: 'assemble'", " action: 'preprocess-assemble'", " action: 'c-compile'", " action: 'c++-compile'", " action: 'c++-module-codegen'", " expand_if_all_available: 'per_object_debug_info_file'", " flag_group {", " flag: '-gsplit-dwarf'", " }", " }", "}"), ifTrue( !existingFeatureNames.contains(CppRuleClasses.PREPROCESSOR_DEFINES), "feature {", " name: 'preprocessor_defines'", " flag_set {", " action: 'preprocess-assemble'", " action: 'linkstamp-compile'", " action: 'c-compile'", " action: 'c++-compile'", " action: 'c++-header-parsing'", " action: 'c++-module-compile'", " action: 'clif-match'", " flag_group {", " iterate_over: 'preprocessor_defines'", " flag: '-D%{preprocessor_defines}'", " }", " }", "}"), ifTrue( !existingFeatureNames.contains("includes"), "feature {", " name: 'includes'", " enabled: true", " flag_set {", " action: 'preprocess-assemble'", " action: 'linkstamp-compile'", " action: 'c-compile'", " action: 'c++-compile'", " action: 'c++-header-parsing'", " action: 'c++-module-compile'", " action: 'clif-match'", " action: 'objc-compile'", " action: 'objc++-compile'", " flag_group {", " expand_if_all_available: 'includes'", " iterate_over: 'includes'", " flag: '-include'", " flag: '%{includes}'", " }", " }", "}"), ifTrue( !existingFeatureNames.contains(CppRuleClasses.INCLUDE_PATHS), "feature {", " name: 'include_paths'", " flag_set {", " action: 'preprocess-assemble'", " action: 'linkstamp-compile'", " action: 'c-compile'", " action: 'c++-compile'", " action: 'c++-header-parsing'", " action: 'c++-module-compile'", " action: 'clif-match'", " action: 'objc-compile'", " action: 'objc++-compile'", " flag_group {", " iterate_over: 'quote_include_paths'", " flag: '-iquote'", " flag: '%{quote_include_paths}'", " }", " flag_group {", " iterate_over: 'include_paths'", " flag: '-I%{include_paths}'", " }", " flag_group {", " iterate_over: 'system_include_paths'", " flag: '-isystem'", " flag: '%{system_include_paths}'", " }", " }", "}"), ifTrue( !existingFeatureNames.contains(CppRuleClasses.FDO_INSTRUMENT), "feature {", " name: 'fdo_instrument'", " provides: 'profile'", " flag_set {", " action: 'c-compile'", " action: 'c++-compile'", " action: 'c++-link-dynamic-library'", " action: 'c++-link-nodeps-dynamic-library'", " action: 'c++-link-executable'", " flag_group {", " flag: '-fprofile-generate=%{fdo_instrument_path}'", " flag: '-fno-data-sections'", " }", " }", "}"), ifTrue( !existingFeatureNames.contains(CppRuleClasses.FDO_OPTIMIZE), "feature {", " name: 'fdo_optimize'", " provides: 'profile'", " flag_set {", " action: 'c-compile'", " action: 'c++-compile'", " expand_if_all_available: 'fdo_profile_path'", " flag_group {", " flag: '-fprofile-use=%{fdo_profile_path}'", " flag: '-Xclang-only=-Wno-profile-instr-unprofiled'", " flag: '-Xclang-only=-Wno-profile-instr-out-of-date'", " flag: '-fprofile-correction'", " }", " }", "}"), ifTrue( !existingFeatureNames.contains(CppRuleClasses.FDO_PREFETCH_HINTS), "feature {", " name: 'fdo_prefetch_hints'", " flag_set {", " action: 'c-compile'", " action: 'c++-compile'", " action: 'lto-backend'", " expand_if_all_available: 'fdo_prefetch_hints_path'", " flag_group {", " flag: '-Xclang-only=-mllvm'", " flag: '-Xclang-only=-prefetch-hints-file=%{fdo_prefetch_hints_path}'", " }", " }", "}"), ifTrue( !existingFeatureNames.contains(CppRuleClasses.XBINARYFDO), "feature {", " name: 'xbinaryfdo'", " provides: 'profile'", " flag_set {", " action: 'c-compile'", " action: 'c++-compile'", " expand_if_all_available: 'fdo_profile_path'", " flag_group {", " flag: '-fauto-profile=%{fdo_profile_path}'", " flag: '-fprofile-correction'", " }", " }", "}"), ifTrue( !existingFeatureNames.contains(CppRuleClasses.AUTOFDO), "feature {", " name: 'autofdo'", " provides: 'profile'", " flag_set {", " action: 'c-compile'", " action: 'c++-compile'", " expand_if_all_available: 'fdo_profile_path'", " flag_group {", " flag: '-fauto-profile=%{fdo_profile_path}'", " flag: '-fprofile-correction'", " }", " }", "}"), "action_config {", " config_name: 'c++-link-executable'", " action_name: 'c++-link-executable'", " tool {", " tool_path: '" + gccToolPath + "'", " }", " implies: 'symbol_counts'", " implies: 'strip_debug_symbols'", " implies: 'linkstamps'", " implies: 'output_execpath_flags'", " implies: 'runtime_library_search_directories'", " implies: 'library_search_directories'", " implies: 'libraries_to_link'", " implies: 'force_pic_flags'", " implies: 'user_link_flags'", " implies: 'legacy_link_flags'", " implies: 'linker_param_file'", " implies: 'fission_support'", " implies: 'sysroot'", "}", "action_config {", " config_name: 'c++-link-nodeps-dynamic-library'", " action_name: 'c++-link-nodeps-dynamic-library'", " tool {", " tool_path: '" + gccToolPath + "'", " }", ifTrue( supportsInterfaceSharedLibraries, "implies: 'build_interface_libraries'", "implies: 'dynamic_library_linker_tool'"), " implies: 'symbol_counts'", " implies: 'strip_debug_symbols'", " implies: 'shared_flag'", " implies: 'linkstamps'", " implies: 'output_execpath_flags'", " implies: 'runtime_library_search_directories'", " implies: 'library_search_directories'", " implies: 'libraries_to_link'", " implies: 'user_link_flags'", " implies: 'legacy_link_flags'", " implies: 'linker_param_file'", " implies: 'fission_support'", " implies: 'sysroot'", "}", "action_config {", " config_name: 'c++-link-dynamic-library'", " action_name: 'c++-link-dynamic-library'", " tool {", " tool_path: '" + gccToolPath + "'", " }", ifTrue( supportsInterfaceSharedLibraries, "implies: 'build_interface_libraries'", "implies: 'dynamic_library_linker_tool'"), " implies: 'symbol_counts'", " implies: 'strip_debug_symbols'", " implies: 'shared_flag'", " implies: 'linkstamps'", " implies: 'output_execpath_flags'", " implies: 'runtime_library_search_directories'", " implies: 'library_search_directories'", " implies: 'libraries_to_link'", " implies: 'user_link_flags'", " implies: 'legacy_link_flags'", " implies: 'linker_param_file'", " implies: 'fission_support'", " implies: 'sysroot'", "}", "action_config {", " config_name: 'c++-link-static-library'", " action_name: 'c++-link-static-library'", " tool {", " tool_path: '" + arToolPath + "'", " }", " implies: 'archiver_flags'", " implies: 'linker_param_file'", "}", ifTrue( supportsInterfaceSharedLibraries, "feature {", " name: 'build_interface_libraries'", " flag_set {", " expand_if_all_available: 'generate_interface_library'", " action: 'c++-link-dynamic-library'", " action: 'c++-link-nodeps-dynamic-library'", " flag_group {", " flag: '%{generate_interface_library}'", " flag: '%{interface_library_builder_path}'", " flag: '%{interface_library_input_path}'", " flag: '%{interface_library_output_path}'", " }", " }", "}", // Order of feature declaration matters, cppDynamicLibraryLinkerTool has to // follow right after build_interface_libraries. cppDynamicLibraryLinkerTool), ifTrue( !existingFeatureNames.contains("symbol_counts"), "feature {", " name: 'symbol_counts'", " flag_set {", " expand_if_all_available: 'symbol_counts_output'", " action: 'c++-link-executable'", " action: 'c++-link-dynamic-library'", " action: 'c++-link-nodeps-dynamic-library'", " flag_group {", " flag: '-Wl,--print-symbol-counts=%{symbol_counts_output}'", " }", " }", "}"), ifTrue( !existingFeatureNames.contains("shared_flag"), "feature {", " name: 'shared_flag'", " flag_set {", " action: 'c++-link-dynamic-library'", " action: 'c++-link-nodeps-dynamic-library'", " flag_group {", " flag: '-shared'", " }", " }", "}"), ifTrue( !existingFeatureNames.contains("linkstamps"), "feature {", " name: 'linkstamps'", " flag_set {", " action: 'c++-link-executable'", " action: 'c++-link-dynamic-library'", " action: 'c++-link-nodeps-dynamic-library'", " expand_if_all_available: 'linkstamp_paths'", " flag_group {", " iterate_over: 'linkstamp_paths'", " flag: '%{linkstamp_paths}'", " }", " }", "}"), ifTrue( !existingFeatureNames.contains("output_execpath_flags"), "feature {", " name: 'output_execpath_flags'", " flag_set {", " expand_if_all_available: 'output_execpath'", " action: 'c++-link-dynamic-library'", " action: 'c++-link-nodeps-dynamic-library'", " action: 'c++-link-executable'", " flag_group {", " flag: '-o'", " flag: '%{output_execpath}'", " }", " }", "}"), ifTrue( !existingFeatureNames.contains("runtime_library_search_directories"), "feature {", " name: 'runtime_library_search_directories',", " flag_set {", " expand_if_all_available: 'runtime_library_search_directories'", " action: 'c++-link-executable'", " action: 'c++-link-dynamic-library'", " action: 'c++-link-nodeps-dynamic-library'", " flag_group {", " iterate_over: 'runtime_library_search_directories'", " flag_group {", ifTrue( supportsEmbeddedRuntimes, " expand_if_true: 'is_cc_test'", // TODO(b/27153401): This should probably be @loader_path on osx. " flag: ", " '-Wl,-rpath,$EXEC_ORIGIN/%{runtime_library_search_directories}'", " }", " flag_group {", " expand_if_false: 'is_cc_test'"), ifLinux( platform, " flag: '-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}'"), ifMac( platform, " flag: '-Wl,-rpath,@loader_path/%{runtime_library_search_directories}'"), " }", " }", " }", "}"), ifTrue( !existingFeatureNames.contains("library_search_directories"), "feature {", " name: 'library_search_directories'", " flag_set {", " expand_if_all_available: 'library_search_directories'", " action: 'c++-link-executable'", " action: 'c++-link-dynamic-library'", " action: 'c++-link-nodeps-dynamic-library'", " flag_group {", " iterate_over: 'library_search_directories'", " flag: '-L%{library_search_directories}'", " }", " }", "}"), ifTrue( !existingFeatureNames.contains("archiver_flags"), "feature {", " name: 'archiver_flags'", " flag_set {", " action: 'c++-link-static-library'", " flag_group {", ifLinux(platform, "flag: 'rcsD'"), ifMac(platform, "flag: '-static'", "flag: '-s'"), " }", " flag_group {", " expand_if_all_available: 'output_execpath'", ifLinux(platform, "flag: '%{output_execpath}'"), ifMac(platform, "flag: '-o'", "flag: '%{output_execpath}'"), " }", " }", " flag_set { ", " action: 'c++-link-static-library'", " expand_if_all_available: 'libraries_to_link'", " flag_group {", " iterate_over: 'libraries_to_link'", " flag_group {", " expand_if_equal {", " variable: 'libraries_to_link.type'", " value: 'object_file'", " }", " flag: '%{libraries_to_link.name}'", " }", " flag_group {", " expand_if_equal {", " variable: 'libraries_to_link.type'", " value: 'object_file_group'", " }", " iterate_over: 'libraries_to_link.object_files'", " flag: '%{libraries_to_link.object_files}'", " }", " }", " }", "}"), ifTrue( !existingFeatureNames.contains("libraries_to_link"), "feature {", " name: 'libraries_to_link'", " flag_set {", " expand_if_all_available: 'libraries_to_link'", " action: 'c++-link-executable'", " action: 'c++-link-dynamic-library'", " action: 'c++-link-nodeps-dynamic-library'", " flag_group {", " iterate_over: 'libraries_to_link'", " flag_group {", " expand_if_equal: {", " variable: 'libraries_to_link.type'", " value: 'object_file_group'", " }", " flag: '-Wl,--start-lib'", " }", ifLinux( platform, " flag_group {", " expand_if_true: 'libraries_to_link.is_whole_archive'", " flag: '-Wl,-whole-archive'", " }", " flag_group {", " expand_if_equal: {", " variable: 'libraries_to_link.type'", " value: 'object_file_group'", " }", " iterate_over: 'libraries_to_link.object_files'", " flag: '%{libraries_to_link.object_files}'", " }", " flag_group {", " expand_if_equal: {", " variable: 'libraries_to_link.type'", " value: 'object_file'", " }", " flag: '%{libraries_to_link.name}'", " }", " flag_group {", " expand_if_equal: {", " variable: 'libraries_to_link.type'", " value: 'interface_library'", " }", " flag: '%{libraries_to_link.name}'", " }", " flag_group {", " expand_if_equal: {", " variable: 'libraries_to_link.type'", " value: 'static_library'", " }", " flag: '%{libraries_to_link.name}'", " }", " flag_group {", " expand_if_equal: {", " variable: 'libraries_to_link.type'", " value: 'dynamic_library'", " }", " flag: '-l%{libraries_to_link.name}'", " }", " flag_group {", " expand_if_equal: {", " variable: 'libraries_to_link.type'", " value: 'versioned_dynamic_library'", " }", " flag: '-l:%{libraries_to_link.name}'", " }", " flag_group {", " expand_if_true: 'libraries_to_link.is_whole_archive'", " flag: '-Wl,-no-whole-archive'", " }"), ifMac( platform, " flag_group {", " expand_if_equal: {", " variable: 'libraries_to_link.type'", " value: 'object_file_group'", " }", " iterate_over: 'libraries_to_link.object_files'", " flag_group {", " expand_if_false: 'libraries_to_link.is_whole_archive'", " flag: '%{libraries_to_link.object_files}'", " }", " flag_group {", " expand_if_true: 'libraries_to_link.is_whole_archive'", " flag: '-Wl,-force_load,%{libraries_to_link.object_files}'", " }", " }", " flag_group {", " expand_if_equal: {", " variable: 'libraries_to_link.type'", " value: 'object_file'", " }", " flag_group {", " expand_if_false: 'libraries_to_link.is_whole_archive'", " flag: '%{libraries_to_link.name}'", " }", " flag_group {", " expand_if_true: 'libraries_to_link.is_whole_archive'", " flag: '-Wl,-force_load,%{libraries_to_link.name}'", " }", " }", " flag_group {", " expand_if_equal: {", " variable: 'libraries_to_link.type'", " value: 'interface_library'", " }", " flag_group {", " expand_if_false: 'libraries_to_link.is_whole_archive'", " flag: '%{libraries_to_link.name}'", " }", " flag_group {", " expand_if_true: 'libraries_to_link.is_whole_archive'", " flag: '-Wl,-force_load,%{libraries_to_link.name}'", " }", " }", " flag_group {", " expand_if_equal: {", " variable: 'libraries_to_link.type'", " value: 'static_library'", " }", " flag_group {", " expand_if_false: 'libraries_to_link.is_whole_archive'", " flag: '%{libraries_to_link.name}'", " }", " flag_group {", " expand_if_true: 'libraries_to_link.is_whole_archive'", " flag: '-Wl,-force_load,%{libraries_to_link.name}'", " }", " }", " flag_group {", " expand_if_equal: {", " variable: 'libraries_to_link.type'", " value: 'dynamic_library'", " }", " flag: '-l%{libraries_to_link.name}'", " }", " flag_group {", " expand_if_equal: {", " variable: 'libraries_to_link.type'", " value: 'versioned_dynamic_library'", " }", " flag: '-l:%{libraries_to_link.name}'", " }"), " flag_group {", " expand_if_equal: {", " variable: 'libraries_to_link.type'", " value: 'object_file_group'", " }", " flag: '-Wl,--end-lib'", " }", " }", " flag_group {", " expand_if_true: 'thinlto_param_file'", " flag: '-Wl,@%{thinlto_param_file}'", " }", " }", "}"), ifTrue( !existingFeatureNames.contains("force_pic_flags"), "feature {", " name: 'force_pic_flags'", " flag_set {", " expand_if_all_available: 'force_pic'", " action: 'c++-link-executable'", " flag_group {", " flag: '-pie'", " }", " }", "}"), ifTrue( !existingFeatureNames.contains("user_link_flags"), "feature {", " name: 'user_link_flags'", " flag_set {", " expand_if_all_available: 'user_link_flags'", " action: 'c++-link-executable'", " action: 'c++-link-dynamic-library'", " action: 'c++-link-nodeps-dynamic-library'", " flag_group {", " iterate_over: 'user_link_flags'", " flag: '%{user_link_flags}'", " }", " }", "}"), ifTrue( !existingFeatureNames.contains("legacy_link_flags"), "feature {", " name: 'legacy_link_flags'", " flag_set {", " expand_if_all_available: 'legacy_link_flags'", " action: 'c++-link-executable'", " action: 'c++-link-dynamic-library'", " action: 'c++-link-nodeps-dynamic-library'", " flag_group {", " iterate_over: 'legacy_link_flags'", " flag: '%{legacy_link_flags}'", " }", " }", "}"), ifTrue( !existingFeatureNames.contains("fission_support"), "feature {", " name: 'fission_support'", " flag_set {", " action: 'c++-link-executable'", " action: 'c++-link-dynamic-library'", " action: 'c++-link-nodeps-dynamic-library'", " flag_group {", " expand_if_all_available: 'is_using_fission'", " flag: '-Wl,--gdb-index'", " }", " }", "}"), ifTrue( !existingFeatureNames.contains("strip_debug_symbols"), "feature {", " name: 'strip_debug_symbols'", " flag_set {", " action: 'c++-link-executable'", " action: 'c++-link-dynamic-library'", " action: 'c++-link-nodeps-dynamic-library'", " flag_group {", " expand_if_all_available: 'strip_debug_symbols'", " flag: '-Wl,-S'", " }", " }", "}"), ifTrue( !existingFeatureNames.contains(CppRuleClasses.COVERAGE), "feature {", " name: 'coverage'", "}", "feature {", " name: 'llvm_coverage_map_format'", " provides: 'profile'", " flag_set {", " action: 'preprocess-assemble'", " action: 'c-compile'", " action: 'c++-compile'", " action: 'c++-module-compile'", " action: 'objc-compile'", " action: 'objc++-compile'", " flag_group {", " flag: '-fprofile-instr-generate'", " flag: '-fcoverage-mapping'", " }", " }", " flag_set {", " action: 'c++-link-dynamic-library'", " action: 'c++-link-nodeps-dynamic-library'", " action: 'c++-link-executable'", " action: 'objc-executable'", " action: 'objc++-executable'", " flag_group {", " flag: '-fprofile-instr-generate'", " }", " }", " requires {", " feature: 'coverage'", " }", "}", "feature {", " name: 'gcc_coverage_map_format'", " provides: 'profile'", " flag_set {", " action: 'preprocess-assemble'", " action: 'c-compile'", " action: 'c++-compile'", " action: 'c++-module-compile'", " action: 'objc-compile'", " action: 'objc++-compile'", " action: 'objc-executable'", " action: 'objc++-executable'", " flag_group {", " expand_if_all_available: 'gcov_gcno_file'", " flag: '-fprofile-arcs'", " flag: '-ftest-coverage'", " }", " }", " flag_set {", " action: 'c++-link-dynamic-library'", " action: 'c++-link-nodeps-dynamic-library'", " action: 'c++-link-executable'", " flag_group {", " flag: '--coverage'", " }", " }", " requires {", " feature: 'coverage'", " }", "}"), "action_config {", " config_name: 'strip'", " action_name: 'strip'", " tool {", " tool_path: '" + stripToolPath + "'", " }", " flag_set {", " flag_group {", " flag: '-S'", ifLinux(platform, "flag: '-p'"), " flag: '-o'", " flag: '%{output_file}'", " }", ifLinux( platform, " flag_group {", " flag: '-R'", " flag: '.gnu.switches.text.quote_paths'", " flag: '-R'", " flag: '.gnu.switches.text.bracket_paths'", " flag: '-R'", " flag: '.gnu.switches.text.system_paths'", " flag: '-R'", " flag: '.gnu.switches.text.cpp_defines'", " flag: '-R'", " flag: '.gnu.switches.text.cpp_includes'", " flag: '-R'", " flag: '.gnu.switches.text.cl_args'", " flag: '-R'", " flag: '.gnu.switches.text.lipo_info'", " flag: '-R'", " flag: '.gnu.switches.text.annotation'", " }"), " flag_group {", " iterate_over: 'stripopts'", " flag: '%{stripopts}'", " }", " flag_group {", " flag: '%{input_file}'", " }", " }", "}")); } public static String getFeaturesToAppearLastInToolchain( ImmutableSet existingFeatureNames) { return Joiner.on("\n") .join( ImmutableList.of( ifTrue( !existingFeatureNames.contains("fully_static_link"), "feature {", " name: 'fully_static_link'", " flag_set {", " action: 'c++-link-executable'", " action: 'c++-link-dynamic-library'", " flag_group {", " flag: '-static'", " }", " }", "}"), ifTrue( !existingFeatureNames.contains("user_compile_flags"), "feature {", " name: 'user_compile_flags'", " enabled: true", " flag_set {", " expand_if_all_available: 'user_compile_flags'", " action: 'assemble'", " action: 'preprocess-assemble'", " action: 'linkstamp-compile'", " action: 'c-compile'", " action: 'c++-compile'", " action: 'c++-header-parsing'", " action: 'c++-module-compile'", " action: 'c++-module-codegen'", " action: 'lto-backend'", " action: 'clif-match'", " flag_group {", " iterate_over: 'user_compile_flags'", " flag: '%{user_compile_flags}'", " }", " }", "}"), ifTrue( !existingFeatureNames.contains("sysroot"), "feature {", " name: 'sysroot'", " enabled: true", " flag_set {", " action: 'preprocess-assemble'", " action: 'linkstamp-compile'", " action: 'c-compile'", " action: 'c++-compile'", " action: 'c++-header-parsing'", " action: 'c++-module-compile'", " action: 'c++-link-executable'", " action: 'c++-link-dynamic-library'", " action: 'c++-link-nodeps-dynamic-library'", " action: 'clif-match'", " action: 'lto-backend'", " flag_group {", " expand_if_all_available: 'sysroot'", " flag: '--sysroot=%{sysroot}'", " }", " }", "}"), // unfiltered_compile_flags contain system include paths. These must be added // after the user provided options (present in legacy_compile_flags build // variable above), otherwise users adding include paths will not pick up their own // include paths first. ifTrue( !existingFeatureNames.contains("unfiltered_compile_flags"), "feature {", " name: 'unfiltered_compile_flags'", " enabled: true", " flag_set {", " expand_if_all_available: 'unfiltered_compile_flags'", " action: 'assemble'", " action: 'preprocess-assemble'", " action: 'linkstamp-compile'", " action: 'c-compile'", " action: 'c++-compile'", " action: 'c++-header-parsing'", " action: 'c++-module-compile'", " action: 'c++-module-codegen'", " action: 'lto-backend'", " action: 'clif-match'", " flag_group {", " iterate_over: 'unfiltered_compile_flags'", " flag: '%{unfiltered_compile_flags}'", " }", " }", "}"), ifTrue( !existingFeatureNames.contains("linker_param_file"), "feature {", " name: 'linker_param_file'", " flag_set {", " expand_if_all_available: 'linker_param_file'", " action: 'c++-link-executable'", " action: 'c++-link-dynamic-library'", " action: 'c++-link-nodeps-dynamic-library'", " flag_group {", " flag: '-Wl,@%{linker_param_file}'", " }", " }", " flag_set {", " expand_if_all_available: 'linker_param_file'", " action: 'c++-link-static-library'", " flag_group {", " flag: '@%{linker_param_file}'", " }", " }", "}"), ifTrue( !existingFeatureNames.contains("compiler_input_flags"), "feature {", " name: 'compiler_input_flags'", " enabled: true", " flag_set {", " action: 'assemble'", " action: 'preprocess-assemble'", " action: 'c-compile'", " action: 'c++-compile'", " action: 'linkstamp-compile'", " action: 'c++-module-compile'", " action: 'c++-module-codegen'", " action: 'objc-compile'", " action: 'objc++-compile'", " action: 'c++-header-parsing'", " action: 'lto-backend'", " expand_if_all_available: 'source_file'", " flag_group {", " flag: '-c'", " flag: '%{source_file}'", " }", " }", "}"), ifTrue( !existingFeatureNames.contains("compiler_output_flags"), "feature {", " name: 'compiler_output_flags'", " enabled: true", " flag_set {", " action: 'assemble'", " action: 'preprocess-assemble'", " action: 'c-compile'", " action: 'c++-compile'", " action: 'linkstamp-compile'", " action: 'c++-module-compile'", " action: 'c++-module-codegen'", " action: 'objc-compile'", " action: 'objc++-compile'", " action: 'c++-header-parsing'", " action: 'lto-backend'", " flag_group {", " expand_if_all_available: 'output_assembly_file'", " flag: '-S'", " }", " flag_group {", " expand_if_all_available: 'output_preprocess_file'", " flag: '-E'", " }", " flag_group {", " expand_if_all_available: 'output_file'", " flag: '-o'", " flag: '%{output_file}'", " }", " }", "}"))); } private static String ifLinux(CppPlatform platform, String... lines) { // Platform `LINUX` also includes FreeBSD. return ifTrue(platform == CppPlatform.LINUX, lines); } private static String ifMac(CppPlatform platform, String... lines) { return ifTrue(platform == CppPlatform.MAC, lines); } private static String ifTrue(boolean condition, String... lines) { if (condition) { return Joiner.on("\n").join(lines); } else { return ""; } } }