diff options
author | 2018-06-28 05:38:50 -0700 | |
---|---|---|
committer | 2018-06-28 05:39:55 -0700 | |
commit | c71157f9a826db25e2588a0147de76e97ff30eb2 (patch) | |
tree | deeea287e7e47c4db04b7e8f99f5e133900ea181 /src/main/java/com | |
parent | 74a9f015270083d51e0e32e8390a33c3aecb9a2c (diff) |
Expose Skylark API to the C++ toolchain
This is an implementation of the design at
https://docs.google.com/document/d/1g91BWJITcYw_X-VxsDC0VgUn5E9g0kRBGoBSpoO41gA/edit>.
More thorough documentation will be sent in a separate cl. The api was approved
at
https://docs.google.com/document/d/1M8JA7kzZnWpLZ3WEX9rp6k2u_nlwE8smsHYgVTSSJ9k/edit?ts=5b292400#.
Work towards #4571 (only the docs are missing).
RELNOTES: None.
PiperOrigin-RevId: 202464331
Diffstat (limited to 'src/main/java/com')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java | 167 | ||||
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcModuleApi.java | 432 |
2 files changed, 586 insertions, 13 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java index d6b450debd..0e7eca0a51 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java @@ -14,15 +14,180 @@ package com.google.devtools.build.lib.rules.cpp; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; import com.google.devtools.build.lib.analysis.platform.ToolchainInfo; +import com.google.devtools.build.lib.collect.nestedset.NestedSet; +import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; +import com.google.devtools.build.lib.collect.nestedset.Order; import com.google.devtools.build.lib.packages.Provider; +import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration; import com.google.devtools.build.lib.skylarkbuildapi.cpp.CcModuleApi; +import com.google.devtools.build.lib.syntax.EvalException; +import com.google.devtools.build.lib.syntax.EvalUtils; +import com.google.devtools.build.lib.syntax.SkylarkDict; +import com.google.devtools.build.lib.syntax.SkylarkList; +import com.google.devtools.build.lib.syntax.SkylarkNestedSet; +import javax.annotation.Nullable; /** A module that contains Skylark utilities for C++ support. */ -public class CcModule implements CcModuleApi { +public class CcModule + implements CcModuleApi<CcToolchainProvider, FeatureConfiguration, CcToolchainVariables> { @Override public Provider getCcToolchainProvider() { return ToolchainInfo.PROVIDER; } + + @Override + public FeatureConfiguration configureFeatures( + CcToolchainProvider toolchain, + SkylarkList<String> requestedFeatures, + SkylarkList<String> unsupportedFeatures) + throws EvalException { + return CcCommon.configureFeaturesOrThrowEvalException( + ImmutableSet.copyOf(requestedFeatures), + ImmutableSet.copyOf(unsupportedFeatures), + toolchain); + } + + @Override + public String getToolForAction(FeatureConfiguration featureConfiguration, String actionName) { + return featureConfiguration + .getToolForAction(actionName) + .getToolPathFragment() + .getSafePathString(); + } + + @Override + public boolean isEnabled(FeatureConfiguration featureConfiguration, String featureName) { + return featureConfiguration.isEnabled(featureName); + } + + @Override + public SkylarkList<String> getCommandLine( + FeatureConfiguration featureConfiguration, + String actionName, + CcToolchainVariables variables) { + return SkylarkList.createImmutable(featureConfiguration.getCommandLine(actionName, variables)); + } + + @Override + public SkylarkDict<String, String> getEnvironmentVariable( + FeatureConfiguration featureConfiguration, + String actionName, + CcToolchainVariables variables) { + return SkylarkDict.copyOf( + null, featureConfiguration.getEnvironmentVariables(actionName, variables)); + } + + @Override + public CcToolchainVariables getCompileBuildVariables( + CcToolchainProvider ccToolchainProvider, + FeatureConfiguration featureConfiguration, + Object sourceFile, + Object outputFile, + Object userCompileFlags, + Object includeDirs, + Object quoteIncludeDirs, + Object systemIncludeDirs, + Object defines, + boolean usePic, + boolean addLegacyCxxOptions) + throws EvalException { + return CompileBuildVariables.setupVariablesOrThrowEvalException( + featureConfiguration, + ccToolchainProvider, + convertFromNoneable(sourceFile, /* defaultValue= */ null), + convertFromNoneable(outputFile, /* defaultValue= */ null), + /* gcnoFile= */ null, + /* dwoFile= */ null, + /* ltoIndexingFile= */ null, + /* includes= */ ImmutableList.of(), + asStringNestedSet(userCompileFlags), + /* cppModuleMap= */ null, + usePic, + /* fakeOutputFile= */ null, + /* fdoStamp= */ null, + /* dotdFileExecPath= */ null, + /* variablesExtensions= */ ImmutableList.of(), + /* additionalBuildVariables= */ ImmutableMap.of(), + /* directModuleMaps= */ ImmutableList.of(), + asStringNestedSet(includeDirs), + asStringNestedSet(quoteIncludeDirs), + asStringNestedSet(systemIncludeDirs), + asStringNestedSet(defines), + addLegacyCxxOptions); + } + + @Override + public CcToolchainVariables getLinkBuildVariables( + CcToolchainProvider ccToolchainProvider, + FeatureConfiguration featureConfiguration, + Object librarySearchDirectories, + Object runtimeLibrarySearchDirectories, + Object userLinkFlags, + Object outputFile, + Object paramFile, + Object defFile, + boolean isUsingLinkerNotArchiver, + boolean isCreatingSharedLibrary, + boolean mustKeepDebug, + boolean useTestOnlyFlags, + boolean isStaticLinkingMode) + throws EvalException { + return LinkBuildVariables.setupVariables( + isUsingLinkerNotArchiver, + /* binDirectoryPath= */ null, + convertFromNoneable(outputFile, /* defaultValue= */ null), + isCreatingSharedLibrary, + convertFromNoneable(paramFile, /* defaultValue= */ null), + /* thinltoParamFile= */ null, + /* thinltoMergedObjectFile= */ null, + mustKeepDebug, + /* symbolCounts= */ null, + ccToolchainProvider, + featureConfiguration, + useTestOnlyFlags, + /* isLtoIndexing= */ false, + asStringNestedSet(userLinkFlags), + /* interfaceLibraryBuilder= */ null, + /* interfaceLibraryOutput= */ null, + /* ltoOutputRootPrefix= */ null, + convertFromNoneable(defFile, /* defaultValue= */ null), + /* fdoSupport= */ null, + asStringNestedSet(runtimeLibrarySearchDirectories), + /* librariesToLink= */ null, + asStringNestedSet(librarySearchDirectories), + /* isLegacyFullyStaticLinkingMode= */ false, + isStaticLinkingMode); + } + + @Override + public CcToolchainVariables getVariables() { + return CcToolchainVariables.EMPTY; + } + + /** + * Converts an object that can be the NoneType to the actual object if it is not or returns the + * default value if none. + */ + @SuppressWarnings("unchecked") + protected static <T> T convertFromNoneable(Object obj, @Nullable T defaultValue) { + if (EvalUtils.isNullOrNone(obj)) { + return defaultValue; + } + return (T) obj; + } + + /** Converts an object that can be the either SkylarkNestedSet or None into NestedSet. */ + protected NestedSet<String> asStringNestedSet(Object o) throws EvalException { + SkylarkNestedSet skylarkNestedSet = convertFromNoneable(o, /* defaultValue= */ null); + if (skylarkNestedSet != null) { + return skylarkNestedSet.getSet(String.class); + } else { + return NestedSetBuilder.emptySet(Order.STABLE_ORDER); + } + } } diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcModuleApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcModuleApi.java index a7732ffa85..73c5e498a8 100644 --- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcModuleApi.java +++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcModuleApi.java @@ -14,24 +14,34 @@ package com.google.devtools.build.lib.skylarkbuildapi.cpp; + import com.google.devtools.build.lib.skylarkbuildapi.ProviderApi; +import com.google.devtools.build.lib.skylarkinterface.Param; +import com.google.devtools.build.lib.skylarkinterface.ParamType; import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable; import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; +import com.google.devtools.build.lib.syntax.EvalException; +import com.google.devtools.build.lib.syntax.Runtime.NoneType; +import com.google.devtools.build.lib.syntax.SkylarkDict; +import com.google.devtools.build.lib.syntax.SkylarkList; +import com.google.devtools.build.lib.syntax.SkylarkNestedSet; -/** - * Utilies related to C++ support. - */ -@SkylarkModule(name = "cc_common", doc = "Utilities related to C++ support.") -public interface CcModuleApi { +/** Utilites related to C++ support. */ +@SkylarkModule( + name = "cc_common", + doc = "Utilities for C++ compilation, linking, and command line " + "generation.") +public interface CcModuleApi< + CcToolchainProviderT extends CcToolchainProviderApi, + FeatureConfigurationT extends FeatureConfigurationApi, + CcToolchainVariablesT extends CcToolchainVariablesApi> { @SkylarkCallable( - name = "CcToolchainInfo", - doc = - "The key used to retrieve the provider that contains information about the C++ " - + "toolchain being usCced", - structField = true - ) - public ProviderApi getCcToolchainProvider(); + name = "CcToolchainInfo", + doc = + "The key used to retrieve the provider that contains information about the C++ " + + "toolchain being usCced", + structField = true) + ProviderApi getCcToolchainProvider(); @Deprecated @SkylarkCallable( @@ -42,4 +52,402 @@ public interface CcModuleApi { + "config_settings.flag_values{'@bazel_tools//tools/cpp:compiler'}", structField = true) default void compilerFlagExists() {} + + @SkylarkCallable( + name = "configure_features", + doc = "Creates a feature_configuration instance.", + parameters = { + @Param( + name = "cc_toolchain", + doc = "cc_toolchain for which we configure features.", + positional = false, + named = true, + type = CcToolchainProviderApi.class), + @Param( + name = "requested_features", + doc = "List of features to be enabled.", + positional = false, + named = true, + defaultValue = "[]", + type = SkylarkList.class), + @Param( + name = "unsupported_features", + doc = "List of features that are unsupported by the current rule.", + positional = false, + named = true, + defaultValue = "[]", + type = SkylarkList.class), + }) + FeatureConfigurationT configureFeatures( + CcToolchainProviderT toolchain, + SkylarkList<String> requestedFeatures, + SkylarkList<String> unsupportedFeatures) + throws EvalException; + + @SkylarkCallable( + name = "get_tool_for_action", + doc = "Returns tool path for given action.", + parameters = { + @Param( + name = "feature_configuration", + doc = "Feature configuration to be queried.", + positional = false, + named = true, + type = FeatureConfigurationApi.class), + @Param( + name = "action_name", + doc = + "Name of the action. Has to be one of the names in " + + "@bazel_tools//tools/build_defs/cc:action_names.bzl.", + named = true, + positional = false), + }) + String getToolForAction(FeatureConfigurationT featureConfiguration, String actionName); + + @SkylarkCallable( + name = "is_enabled", + doc = "Returns True if given feature is enabled in the feature configuration.", + parameters = { + @Param( + name = "feature_configuration", + doc = "Feature configuration to be queried.", + positional = false, + named = true, + type = FeatureConfigurationApi.class), + @Param( + name = "feature_name", + doc = "Name of the feature.", + named = true, + positional = false), + }) + boolean isEnabled(FeatureConfigurationT featureConfiguration, String featureName); + + @SkylarkCallable( + name = "get_memory_inefficient_command_line", + doc = + "Returns flattened command line flags for given action, using given variables for " + + "expansion. Flattens nested sets and ideally should not be used, or at least " + + "should not outlive analysis. Work on memory efficient function returning Args is " + + "ongoing.", + parameters = { + @Param( + name = "feature_configuration", + doc = "Feature configuration to be queried.", + positional = false, + named = true, + type = FeatureConfigurationApi.class), + @Param( + name = "action_name", + doc = + "Name of the action. Has to be one of the names in " + + "@bazel_tools//tools/build_defs/cc:action_names.bzl.", + named = true, + positional = false), + @Param( + name = "variables", + doc = "Build variables to be used for template expansions.", + named = true, + positional = false, + type = CcToolchainVariablesApi.class), + }) + SkylarkList<String> getCommandLine( + FeatureConfigurationT featureConfiguration, + String actionName, + CcToolchainVariablesT variables); + + @SkylarkCallable( + name = "get_environment_variables", + doc = "Returns environment variables to be set for given action.", + parameters = { + @Param( + name = "feature_configuration", + doc = "Feature configuration to be queried.", + positional = false, + named = true, + type = FeatureConfigurationApi.class), + @Param( + name = "action_name", + doc = + "Name of the action. Has to be one of the names in " + + "@bazel_tools//tools/build_defs/cc:action_names.bzl.", + named = true, + positional = false), + @Param( + name = "variables", + doc = "Build variables to be used for template expansion.", + positional = false, + named = true, + type = CcToolchainVariablesApi.class), + }) + SkylarkDict<String, String> getEnvironmentVariable( + FeatureConfigurationT featureConfiguration, + String actionName, + CcToolchainVariablesT variables); + + @SkylarkCallable( + name = "create_compile_variables", + doc = "Returns variables used for compilation actions.", + parameters = { + @Param( + name = "cc_toolchain", + doc = "cc_toolchain for which we are creating build variables.", + positional = false, + named = true, + type = CcToolchainProviderApi.class), + @Param( + name = "feature_configuration", + doc = "Feature configuration to be queried.", + positional = false, + named = true, + type = FeatureConfigurationApi.class), + @Param( + name = "source_file", + doc = + "Optional source file for the compilation. Please prefer passing source_file here " + + "over appending it to the end of the command line generated from " + + "cc_common.get_memory_inefficient_command_line, as then it's in the power of " + + "the toolchain author to properly specify and position compiler flags.", + named = true, + positional = false, + defaultValue = "None", + noneable = true), + @Param( + name = "output_file", + doc = + "Optional output file of the compilation. Please prefer passing output_file here " + + "over appending it to the end of the command line generated from " + + "cc_common.get_memory_inefficient_command_line, as then it's in the power of " + + "the toolchain author to properly specify and position compiler flags.", + named = true, + positional = false, + defaultValue = "None", + noneable = true), + @Param( + name = "user_compile_flags", + doc = "Depset of additional compilation flags (copts).", + positional = false, + named = true, + defaultValue = "None", + noneable = true, + allowedTypes = { + @ParamType(type = NoneType.class), + @ParamType(type = SkylarkNestedSet.class) + }), + @Param( + name = "include_directories", + doc = "Depset of include directories.", + positional = false, + named = true, + defaultValue = "None", + noneable = true, + allowedTypes = { + @ParamType(type = NoneType.class), + @ParamType(type = SkylarkNestedSet.class) + }), + @Param( + name = "quote_include_directories", + doc = "Depset of quote include directories.", + positional = false, + named = true, + defaultValue = "None", + noneable = true, + allowedTypes = { + @ParamType(type = NoneType.class), + @ParamType(type = SkylarkNestedSet.class) + }), + @Param( + name = "system_include_directories", + doc = "Depset of system include directories.", + positional = false, + named = true, + defaultValue = "None", + noneable = true, + allowedTypes = { + @ParamType(type = NoneType.class), + @ParamType(type = SkylarkNestedSet.class) + }), + @Param( + name = "preprocessor_defines", + doc = "Depset of preprocessor defines.", + positional = false, + named = true, + defaultValue = "None", + noneable = true, + allowedTypes = { + @ParamType(type = NoneType.class), + @ParamType(type = SkylarkNestedSet.class) + }), + @Param( + name = "use_pic", + doc = "When true the compilation will generate position independent code.", + positional = false, + named = true, + defaultValue = "False"), + // TODO(b/65151735): Remove once we migrate crosstools to features + @Param( + name = "add_legacy_cxx_options", + doc = + "When true the flags will contain options coming from legacy cxx_flag crosstool " + + "fields.", + named = true, + positional = false, + defaultValue = "False") + }) + CcToolchainVariablesT getCompileBuildVariables( + CcToolchainProviderT ccToolchainProvider, + FeatureConfigurationT featureConfiguration, + Object sourceFile, + Object outputFile, + Object userCompileFlags, + Object includeDirs, + Object quoteIncludeDirs, + Object systemIncludeDirs, + Object defines, + boolean usePic, + boolean addLegacyCxxOptions) + throws EvalException; + + @SkylarkCallable( + name = "create_link_variables", + doc = "Returns link variables used for linking actions.", + parameters = { + @Param( + name = "cc_toolchain", + doc = "cc_toolchain for which we are creating build variables.", + positional = false, + named = true, + type = CcToolchainProviderApi.class), + @Param( + name = "feature_configuration", + doc = "Feature configuration to be queried.", + positional = false, + named = true, + type = FeatureConfigurationApi.class), + @Param( + name = "library_search_directories", + doc = "Depset of directories where linker will look for libraries at link time.", + positional = false, + named = true, + defaultValue = "None", + noneable = true, + allowedTypes = { + @ParamType(type = NoneType.class), + @ParamType(type = SkylarkNestedSet.class) + }), + @Param( + name = "runtime_library_search_directories", + doc = "Depset of directories where loader will look for libraries at runtime.", + positional = false, + named = true, + defaultValue = "None", + noneable = true, + allowedTypes = { + @ParamType(type = NoneType.class), + @ParamType(type = SkylarkNestedSet.class) + }), + @Param( + name = "user_link_flags", + doc = "Depset of additional link flags (linkopts).", + positional = false, + named = true, + defaultValue = "None", + noneable = true, + allowedTypes = { + @ParamType(type = NoneType.class), + @ParamType(type = SkylarkNestedSet.class) + }), + @Param( + name = "output_file", + doc = "Optional output file path.", + named = true, + positional = false, + defaultValue = "None", + noneable = true), + @Param( + name = "param_file", + doc = "Optional param file path.", + named = true, + positional = false, + defaultValue = "None", + noneable = true), + @Param( + name = "def_file", + doc = "Optional .def file path.", + named = true, + positional = false, + defaultValue = "None", + noneable = true), + // TODO(b/65151735): Remove once we migrate crosstools to features + @Param( + name = "is_using_linker", + doc = + "True when using linker, False when archiver. Caller is responsible for keeping " + + "this in sync with action name used (is_using_linker = True for linking " + + "executable or dynamic library, is_using_linker = False for archiving static " + + "library).", + named = true, + positional = false, + defaultValue = "True"), + // TODO(b/65151735): Remove once we migrate crosstools to features + @Param( + name = "is_linking_dynamic_library", + doc = + "True when creating dynamic library, False when executable or static library. " + + "Caller is responsible for keeping this in sync with action name used. " + + "" + + "This field will be removed once b/65151735 is fixed.", + named = true, + positional = false, + defaultValue = "False"), + // TODO(b/65151735): Remove once we migrate crosstools to features + @Param( + name = "must_keep_debug", + doc = + "When set to True, bazel will expose 'strip_debug_symbols' variable, which is " + + "usually used to use the linker to strip debug symbols from the output file.", + named = true, + positional = false, + defaultValue = "True"), + // TODO(b/65151735): Remove once we migrate crosstools to features + @Param( + name = "use_test_only_flags", + doc = + "When set to True flags coming from test_only_linker_flag crosstool fields will" + + " be included." + + "" + + "This field will be removed once b/65151735 is fixed.", + named = true, + positional = false, + defaultValue = "False"), + // TODO(b/65151735): Remove once we migrate crosstools to features + @Param( + name = "is_static_linking_mode", + doc = + "True when using static_linking_mode, False when using dynamic_linking_mode. " + + "Caller is responsible for keeping this in sync with 'static_linking_mode' " + + "and 'dynamic_linking_mode' features enabled on the feature configuration. " + + "" + + "This field will be removed once b/65151735 is fixed.", + named = true, + positional = false, + defaultValue = "True"), + }) + CcToolchainVariablesT getLinkBuildVariables( + CcToolchainProviderT ccToolchainProvider, + FeatureConfigurationT featureConfiguration, + Object librarySearchDirectories, + Object runtimeLibrarySearchDirectories, + Object userLinkFlags, + Object outputFile, + Object paramFile, + Object defFile, + boolean isUsingLinkerNotArchiver, + boolean isCreatingSharedLibrary, + boolean mustKeepDebug, + boolean useTestOnlyFlags, + boolean isStaticLinkingMode) + throws EvalException; + + @SkylarkCallable(name = "empty_variables", documented = false) + CcToolchainVariablesT getVariables(); } |