aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/rules
diff options
context:
space:
mode:
authorGravatar Yun Peng <pcloudy@google.com>2017-09-15 15:59:14 +0200
committerGravatar László Csomor <laszlocsomor@google.com>2017-09-18 11:25:37 +0200
commit394211bf88b88c25036429e99894fa7c60eaaace (patch)
treea5a99354a9f3b8530bb0d98d61d8844b21348ecd /src/main/java/com/google/devtools/build/lib/rules
parentf8480fac37692083b2f9c4e69b9b9e9e2c9b1853 (diff)
Bazel now can build dynamic library from cc_library
Working towards: https://github.com/bazelbuild/bazel/issues/3311 When building dynamic library on Windows, Bazel builds an import library and a DLL. Bazel provides a feature called windows_export_all_symbols, if this feature is enabled(and no_windows_export_all_symbols is not) for a cc_library, then Bazel parses object files of that cc_library to generate a DEF file that will be used during linking time to export symbols from DLL. This feature can be specified at crosstool, package, target and command line level. A few differences from Unix platforms: 1. We don't build the shared library on Windows by default, users have to specifiy --output_groups=dynamic_library for building dynamic libraries. This output group is also available on other platforms. 2. By default, cc_test is dynamically linked on Unix, but it will be statically linked on Windows by default. (meaning the default value of linkstatic in cc_test is 1 on Windows, and 0 on other platforms) 3. For global data symbols, __declspec(dllimport) must still be used in source files. Remaining issues: 1. Extensions for import library and DLL are not correct yet. 2. DLLs are not guaranteed to be available during runtime yet. 3. Diamond problem If a cc_library A is specified as linkstatic=0, then no dynamic library will be built for it, so if another cc_library B depends on it, A will be statically linked into B, and if a cc_binary C depends on B, A will also be statically linked into C and B will be dynamically linked to C. This is wrong because A is duplicated in both B and C. It is essentially a diamond problem describled in C++ Transitive Library. (https://docs.google.com/document/d/1-tv0_79zGyBoDmaP_pYWaBVUwHUteLpAs90_rUl-VY8/edit?usp=sharing) Hopefully, we can avoid this by using cc_shared_library rule in future. Change-Id: I23640d4caf8afe65d60b1522af6368536d7a8408 PiperOrigin-RevId: 168829958
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules')
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java33
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java20
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java3
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProvider.java12
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainRule.java24
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java24
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppModel.java92
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java16
8 files changed, 205 insertions, 19 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java
index b846dfaef3..e90dda7c54 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java
@@ -187,11 +187,17 @@ public abstract class CcLibrary implements RuleConfiguredTargetFactory {
// doesn't support it, then register an action which complains when triggered,
// which only happens when some rule explicitly depends on the dynamic library.
if (!createDynamicLibrary && !supportsDynamicLinker) {
- Artifact solibArtifact =
+ ImmutableList.Builder<Artifact> dynamicLibraries = ImmutableList.builder();
+ dynamicLibraries.add(
+ CppHelper.getLinuxLinkedArtifact(
+ ruleContext, ruleContext.getConfiguration(), LinkTargetType.DYNAMIC_LIBRARY));
+ if (ccToolchain.getCppConfiguration().useInterfaceSharedObjects()) {
+ dynamicLibraries.add(
CppHelper.getLinuxLinkedArtifact(
- ruleContext, ruleContext.getConfiguration(), LinkTargetType.DYNAMIC_LIBRARY);
+ ruleContext, ruleContext.getConfiguration(), LinkTargetType.INTERFACE_DYNAMIC_LIBRARY));
+ }
ruleContext.registerAction(new FailAction(ruleContext.getActionOwner(),
- ImmutableList.of(solibArtifact), "Toolchain does not support dynamic linking"));
+ dynamicLibraries.build(), "Toolchain does not support dynamic linking"));
} else if (!createDynamicLibrary
&& ruleContext.attributes().isConfigurable("srcs")) {
// If "srcs" is configurable, the .so output is always declared because the logic that
@@ -199,11 +205,17 @@ public abstract class CcLibrary implements RuleConfiguredTargetFactory {
// Here, where we *do* have the correct value, it may not contain any source files to
// generate an .so with. If that's the case, register a fake generating action to prevent
// a "no generating action for this artifact" error.
- Artifact solibArtifact =
+ ImmutableList.Builder<Artifact> dynamicLibraries = ImmutableList.builder();
+ dynamicLibraries.add(
+ CppHelper.getLinuxLinkedArtifact(
+ ruleContext, ruleContext.getConfiguration(), LinkTargetType.DYNAMIC_LIBRARY));
+ if (ccToolchain.getCppConfiguration().useInterfaceSharedObjects()) {
+ dynamicLibraries.add(
CppHelper.getLinuxLinkedArtifact(
- ruleContext, ruleContext.getConfiguration(), LinkTargetType.DYNAMIC_LIBRARY);
+ ruleContext, ruleContext.getConfiguration(), LinkTargetType.INTERFACE_DYNAMIC_LIBRARY));
+ }
ruleContext.registerAction(new FailAction(ruleContext.getActionOwner(),
- ImmutableList.of(solibArtifact), "configurable \"srcs\" triggers an implicit .so output "
+ dynamicLibraries.build(), "configurable \"srcs\" triggers an implicit .so output "
+ "even though there are no sources to compile in this configuration"));
}
@@ -258,9 +270,12 @@ public abstract class CcLibrary implements RuleConfiguredTargetFactory {
NestedSetBuilder<Artifact> filesBuilder = NestedSetBuilder.stableOrder();
filesBuilder.addAll(LinkerInputs.toLibraryArtifacts(linkedLibraries.getStaticLibraries()));
filesBuilder.addAll(LinkerInputs.toLibraryArtifacts(linkedLibraries.getPicStaticLibraries()));
- filesBuilder.addAll(LinkerInputs.toNonSolibArtifacts(linkedLibraries.getDynamicLibraries()));
- filesBuilder.addAll(
- LinkerInputs.toNonSolibArtifacts(linkedLibraries.getExecutionDynamicLibraries()));
+
+ if (!featureConfiguration.isEnabled(CppRuleClasses.TARGETS_WINDOWS)) {
+ filesBuilder.addAll(LinkerInputs.toNonSolibArtifacts(linkedLibraries.getDynamicLibraries()));
+ filesBuilder.addAll(
+ LinkerInputs.toNonSolibArtifacts(linkedLibraries.getExecutionDynamicLibraries()));
+ }
CcLinkingOutputs linkingOutputs = info.getCcLinkingOutputs();
if (!featureConfiguration.isEnabled(CppRuleClasses.HEADER_MODULE_CODEGEN)) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java
index 02c7c26002..58d3f603a0 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java
@@ -89,6 +89,12 @@ public final class CcLibraryHelper {
+ "hidden_header_tokens"
+ OutputGroupProvider.INTERNAL_SUFFIX;
+ /** A string constant for the name of archive library(.a, .lo) output group. */
+ public static final String ARCHIVE_LIBRARY_OUTPUT_GROUP_NAME = "cc_archive";
+
+ /** A string constant for the name of dynamic library output group. */
+ public static final String DYNAMIC_LIBRARY_OUTPUT_GROUP_NAME = "cc_dynamic_library";
+
/**
* A group of source file types and action names for builds controlled by CcLibraryHelper.
* Determines what file types CcLibraryHelper considers sources and what action configs are
@@ -1137,10 +1143,20 @@ public final class CcLibraryHelper {
configuration,
Link.LinkTargetType.DYNAMIC_LIBRARY,
linkedArtifactNameSuffix));
+
+ if (ccToolchain.getCppConfiguration().useInterfaceSharedObjects()
+ && emitInterfaceSharedObjects) {
+ dynamicLibrary.add(
+ CppHelper.getLinuxLinkedArtifact(
+ ruleContext,
+ configuration,
+ LinkTargetType.INTERFACE_DYNAMIC_LIBRARY,
+ linkedArtifactNameSuffix));
+ }
}
- outputGroups.put("archive", archiveFile.build());
- outputGroups.put("dynamic_library", dynamicLibrary.build());
+ outputGroups.put(ARCHIVE_LIBRARY_OUTPUT_GROUP_NAME, archiveFile.build());
+ outputGroups.put(DYNAMIC_LIBRARY_OUTPUT_GROUP_NAME, dynamicLibrary.build());
}
/**
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java
index 48afc4455f..e44b32b7ff 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java
@@ -392,6 +392,9 @@ public class CcToolchain implements RuleConfiguredTargetFactory {
cppConfiguration.supportsInterfaceSharedObjects()
? ruleContext.getPrerequisiteArtifact("$link_dynamic_library_tool", Mode.HOST)
: null,
+ ruleContext.attributes().has("$def_parser")
+ ? ruleContext.getPrerequisiteArtifact("$def_parser", Mode.HOST)
+ : null,
getEnvironment(ruleContext),
builtInIncludeDirectories,
sysroot);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProvider.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProvider.java
index 8f85034126..b79164bbeb 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProvider.java
@@ -63,6 +63,7 @@ public final class CcToolchainProvider extends ToolchainInfo {
ImmutableList.<Artifact>of(),
NestedSetBuilder.<Pair<String, String>>emptySet(Order.COMPILE_ORDER),
null,
+ null,
ImmutableMap.<String, String>of(),
ImmutableList.<PathFragment>of(),
null);
@@ -90,6 +91,7 @@ public final class CcToolchainProvider extends ToolchainInfo {
private final ImmutableList<Artifact> builtinIncludeFiles;
private final NestedSet<Pair<String, String>> coverageEnvironment;
@Nullable private final Artifact linkDynamicLibraryTool;
+ @Nullable private final Artifact defParser;
private final ImmutableMap<String, String> environment;
private final ImmutableList<PathFragment> builtInIncludeDirectories;
@Nullable private final PathFragment sysroot;
@@ -118,6 +120,7 @@ public final class CcToolchainProvider extends ToolchainInfo {
ImmutableList<Artifact> builtinIncludeFiles,
NestedSet<Pair<String, String>> coverageEnvironment,
Artifact linkDynamicLibraryTool,
+ Artifact defParser,
ImmutableMap<String, String> environment,
ImmutableList<PathFragment> builtInIncludeDirectories,
@Nullable PathFragment sysroot) {
@@ -145,6 +148,7 @@ public final class CcToolchainProvider extends ToolchainInfo {
this.builtinIncludeFiles = builtinIncludeFiles;
this.coverageEnvironment = coverageEnvironment;
this.linkDynamicLibraryTool = linkDynamicLibraryTool;
+ this.defParser = defParser;
this.environment = environment;
this.builtInIncludeDirectories = builtInIncludeDirectories;
this.sysroot = sysroot;
@@ -330,6 +334,14 @@ public final class CcToolchainProvider extends ToolchainInfo {
}
/**
+ * Returns the tool which should be used to parser object files for generating DEF file on
+ * Windows. The label of this tool is //third_party/def_parser:def_parser.
+ */
+ public Artifact getDefParserTool() {
+ return defParser;
+ }
+
+ /**
* Returns the tool that builds interface libraries from dynamic libraries.
*/
public Artifact getInterfaceSoBuilder() {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainRule.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainRule.java
index c691d434b3..5f9f07a4e3 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainRule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainRule.java
@@ -41,6 +41,23 @@ import com.google.devtools.build.lib.rules.cpp.CppRuleClasses.LipoTransition;
public final class CcToolchainRule implements RuleDefinition {
/**
+ * The label points to the Windows object file parser. In bazel, it should be
+ * //tools/def_parser:def_parser, otherwise it should be null.
+ *
+ * <p>TODO(pcloudy): Remove this after Bazel rule definitions are not used internally anymore.
+ * Related bug b/63658220
+ */
+ private final String defParserLabel;
+
+ public CcToolchainRule(String defParser) {
+ this.defParserLabel = defParser;
+ }
+
+ public CcToolchainRule() {
+ this.defParserLabel = null;
+ }
+
+ /**
* Determines if the given target is a cc_toolchain or one of its subclasses. New subclasses
* should be added to this method.
*/
@@ -60,6 +77,13 @@ public final class CcToolchainRule implements RuleDefinition {
@Override
public RuleClass build(Builder builder, RuleDefinitionEnvironment env) {
final Label zipper = env.getToolsLabel("//tools/zip:zipper");
+ if (defParserLabel != null) {
+ builder.add(
+ attr("$def_parser", LABEL)
+ .cfg(HOST)
+ .singleArtifact()
+ .value(env.getLabel(defParserLabel)));
+ }
return builder
.setUndocumented()
.requiresConfigurationFragments(CppConfiguration.class)
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java
index 2d47b74687..7a21660d3c 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java
@@ -79,6 +79,8 @@ public class CppLinkActionBuilder {
*/
public static final String THINLTO_PARAM_FILE_VARIABLE = "thinlto_param_file";
+ public static final String DEF_FILE_PATH_VARIABLE = "def_file_path";
+
/**
* A build variable to let thinlto know where it should write linker flags when indexing.
*/
@@ -190,6 +192,7 @@ public class CppLinkActionBuilder {
private LinkStaticness linkStaticness = LinkStaticness.FULLY_STATIC;
private String libraryIdentifier = null;
private ImmutableMap<Artifact, Artifact> ltoBitcodeFiles;
+ private Artifact defFile;
private boolean fake;
private boolean isNativeDeps;
@@ -561,10 +564,13 @@ public class CppLinkActionBuilder {
}
switch (linkType) {
- // We currently can't split dynamic library links if they have interface outputs. That was
- // probably an unintended side effect of the change that introduced interface outputs.
+ // On Unix, we currently can't split dynamic library links if they have interface outputs.
+ // That was probably an unintended side effect of the change that introduced interface
+ // outputs.
+ // On Windows, We can always split the command line when building DLL.
case DYNAMIC_LIBRARY:
- return interfaceOutput == null;
+ return (interfaceOutput == null
+ || featureConfiguration.isEnabled(CppRuleClasses.TARGETS_WINDOWS));
case EXECUTABLE:
case STATIC_LIBRARY:
case PIC_STATIC_LIBRARY:
@@ -819,6 +825,9 @@ public class CppLinkActionBuilder {
dependencyInputsBuilder.addAll(linkstamps);
dependencyInputsBuilder.addTransitive(compilationInputs.build());
}
+ if (defFile != null) {
+ dependencyInputsBuilder.add(defFile);
+ }
Iterable<Artifact> expandedInputs =
LinkerInputs.toLibraryArtifacts(
@@ -1095,6 +1104,11 @@ public class CppLinkActionBuilder {
return this;
}
+ public CppLinkActionBuilder setDefFile(Artifact defFile) {
+ this.defFile = defFile;
+ return this;
+ }
+
/**
* Adds a single object file to the set of inputs.
*/
@@ -1533,6 +1547,10 @@ public class CppLinkActionBuilder {
INTERFACE_LIBRARY_OUTPUT_VARIABLE,
shouldGenerateInterfaceLibrary ? interfaceLibraryOutput.getExecPathString() : "ignored");
+ if (defFile != null) {
+ buildVariables.addStringVariable(DEF_FILE_PATH_VARIABLE, defFile.getExecPathString());
+ }
+
// Variables arising from the toolchain
buildVariables
.addAllStringVariables(toolchain.getBuildVariables())
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppModel.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppModel.java
index 72b65a983f..2fcd33209b 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppModel.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppModel.java
@@ -14,6 +14,8 @@
package com.google.devtools.build.lib.rules.cpp;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Supplier;
@@ -23,10 +25,14 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.FailAction;
+import com.google.devtools.build.lib.actions.ParameterFile;
import com.google.devtools.build.lib.analysis.AnalysisEnvironment;
import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
+import com.google.devtools.build.lib.analysis.actions.CustomCommandLine;
+import com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction;
+import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.config.PerLabelOptions;
import com.google.devtools.build.lib.analysis.test.InstrumentedFilesCollector;
@@ -54,6 +60,7 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import javax.annotation.Nullable;
/**
* Representation of a C/C++ compilation. Its purpose is to share the code that creates compilation
@@ -681,6 +688,60 @@ public final class CppModel {
}
/**
+ * Create actions for parsing object files to generate a DEF file, should on be used on Windows.
+ *
+ * <p>The method only creates the actions when WINDOWS_EXPORT_ALL_SYMBOLS feature is enabled and
+ * NO_WINDOWS_EXPORT_ALL_SYMBOLS feature is not enabled.
+ *
+ * @param objectFiles A list of object files to parse
+ * @param dllName The DLL name to be written into the DEF file, it specifies which DLL is required
+ * at runtime
+ * @return The DEF file artifact, null if actions are not created.
+ */
+ @Nullable
+ public Artifact createDefFileActions(ImmutableList<Artifact> objectFiles, String dllName) {
+ if (!featureConfiguration.isEnabled(CppRuleClasses.WINDOWS_EXPORT_ALL_SYMBOLS)
+ || featureConfiguration.isEnabled(CppRuleClasses.NO_WINDOWS_EXPORT_ALL_SYMBOLS)) {
+ return null;
+ }
+ Artifact defFile = ruleContext.getBinArtifact(ruleContext.getLabel().getName() + ".def");
+ CustomCommandLine.Builder argv = new CustomCommandLine.Builder();
+ for (Artifact objectFile : objectFiles) {
+ argv.addDynamicString(objectFile.getExecPathString());
+ }
+
+ Artifact paramFile =
+ ruleContext.getDerivedArtifact(
+ ParameterFile.derivePath(defFile.getRootRelativePath()), defFile.getRoot());
+
+ ruleContext.registerAction(
+ new ParameterFileWriteAction(
+ ruleContext.getActionOwner(),
+ paramFile,
+ argv.build(),
+ ParameterFile.ParameterFileType.SHELL_QUOTED,
+ UTF_8));
+
+ Artifact defParser = ccToolchain.getDefParserTool();
+ ruleContext.registerAction(
+ new SpawnAction.Builder()
+ .addInput(paramFile)
+ .addInputs(objectFiles)
+ .addOutput(defFile)
+ .setExecutable(defParser)
+ .useDefaultShellEnvironment()
+ .addCommandLine(
+ CustomCommandLine.builder()
+ .addExecPath(defFile)
+ .addDynamicString(dllName)
+ .addPrefixedExecPath("@", paramFile)
+ .build())
+ .setMnemonic("DefParser")
+ .build(ruleContext));
+ return defFile;
+ }
+
+ /**
* Constructs the C++ compiler actions. It generally creates one action for every specified source
* file. It takes into account LIPO, fake-ness, coverage, and PIC, in addition to using the
* settings specified on the current object. This method should only be called once.
@@ -1417,11 +1478,14 @@ public final class CppModel {
configuration,
LinkTargetType.INTERFACE_DYNAMIC_LIBRARY,
linkedArtifactNameSuffix);
- sonameLinkopts =
- ImmutableList.of(
- "-Wl,-soname="
- + SolibSymlinkAction.getDynamicLibrarySoname(
- soImpl.getRootRelativePath(), /* preserveName= */ false));
+ // TODO(b/28946988): Remove this hard-coded flag.
+ if (!featureConfiguration.isEnabled(CppRuleClasses.TARGETS_WINDOWS)) {
+ sonameLinkopts =
+ ImmutableList.of(
+ "-Wl,-soname="
+ + SolibSymlinkAction.getDynamicLibrarySoname(
+ soImpl.getRootRelativePath(), /* preserveName= */ false));
+ }
}
CppLinkActionBuilder dynamicLinkActionBuilder =
@@ -1442,6 +1506,24 @@ public final class CppModel {
ccToolchain.getDynamicRuntimeLinkInputs())
.addVariablesExtensions(variablesExtensions);
+ Artifact defFile =
+ createDefFileActions(
+ ccOutputs.getObjectFiles(false),
+ SolibSymlinkAction.getDynamicLibrarySoname(soImpl.getRootRelativePath(), true));
+ if (defFile != null) {
+ dynamicLinkActionBuilder.setDefFile(defFile);
+ }
+
+ // On Windows, we cannot build a shared library with symbols unresolved, so here we dynamically
+ // link to all it's dependencies.
+ if (featureConfiguration.isEnabled(CppRuleClasses.TARGETS_WINDOWS)) {
+ CcLinkParams.Builder ccLinkParamsbuilder =
+ CcLinkParams.builder(/* linkingStatically= */ false, /* linkShared= */ true);
+ ccLinkParamsbuilder.addCcLibrary(
+ ruleContext, false, ImmutableList.of(), CcLinkingOutputs.EMPTY);
+ dynamicLinkActionBuilder.addLinkParams(ccLinkParamsbuilder.build(), ruleContext);
+ }
+
if (!ccOutputs.getLtoBitcodeFiles().isEmpty()
&& featureConfiguration.isEnabled(CppRuleClasses.THIN_LTO)) {
dynamicLinkActionBuilder.setLtoIndexing(true);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java
index 275c717353..4e8139e096 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java
@@ -311,6 +311,22 @@ public class CppRuleClasses {
public static final String GENERATE_PDB_FILE = "generate_pdb_file";
/**
+ * A string constant for a feature that automatically exporting symbols on Windows. Bazel
+ * generates a DEF file for object files of a cc_library, then use it at linking time. This
+ * feature should only be used for toolchains targeting Windows, and the toolchain should support
+ * using DEF files for exporting symbols.
+ */
+ public static final String WINDOWS_EXPORT_ALL_SYMBOLS = "windows_export_all_symbols";
+
+ /** A string constant for a feature to disable WINDOWS_EXPORT_ALL_SYMBOLS. */
+ public static final String NO_WINDOWS_EXPORT_ALL_SYMBOLS = "no_windows_export_all_symbols";
+
+ /**
+ * A string constant for a feature that indicates we are using a toolchain building for Windows.
+ */
+ public static final String TARGETS_WINDOWS = "targets_windows";
+
+ /**
* A string constant for no_stripping feature, if it's specified, then no strip action config is
* needed, instead the stripped binary will simply be a symlink (or a copy on Windows) of the
* original binary.