| // 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. |
| * |
| * <p>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<String> 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 {" |
| + " 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++-header-preprocessing'", |
| " action_name: 'c++-header-preprocessing'", |
| " 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++-header-preprocessing'", |
| " 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 <name> 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 <name> |
| 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-preprocessing'", |
| " 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++-header-preprocessing'", |
| " 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++-header-preprocessing'", |
| " 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++-header-preprocessing'", |
| " 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.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'", |
| " }", |
| " }", |
| "}"), |
| ifTrue( |
| !existingFeatureNames.contains(CppRuleClasses.LIPO), |
| "feature {", |
| " name: 'lipo'", |
| " requires { feature: 'autofdo' }", |
| " requires { feature: 'fdo_optimize' }", |
| " requires { feature: 'fdo_instrument' }", |
| " flag_set {", |
| " action: 'c-compile'", |
| " action: 'c++-compile'", |
| " flag_group {", |
| " flag: '-fripa'", |
| " }", |
| " }", |
| "}"), |
| "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_all_available: 'is_cc_test_link_action'", |
| // TODO(b/27153401): This should probably be @loader_path on osx. |
| " flag: ", |
| " '-Wl,-rpath,$EXEC_ORIGIN/%{runtime_library_search_directories}'", |
| " }", |
| " flag_group {", |
| " expand_if_all_available: 'is_not_cc_test_link_action'"), |
| 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 {", |
| " expand_if_all_available: 'output_execpath'", |
| " action: 'c++-link-static-library'", |
| " flag_group {", |
| ifLinux(platform, "flag: 'rcsD'", "flag: '%{output_execpath}'"), |
| ifMac( |
| platform, |
| " flag: '-static'", |
| " flag: '-s'", |
| " 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<String> 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++-header-preprocessing'", |
| " 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++-header-preprocessing'", |
| " 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++-header-preprocessing'", |
| " 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-preprocessing'", |
| " 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-preprocessing'", |
| " 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 ""; |
| } |
| } |
| } |