diff options
Diffstat (limited to 'src/main/java/com/google/devtools')
10 files changed, 255 insertions, 50 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java index 922d542d35..21a5a31ffd 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java @@ -355,37 +355,51 @@ public class BazelRuleClassProvider { } }; - public static final RuleSet CPP_RULES = - new RuleSet() { - @Override - public void init(Builder builder) { - builder.addConfig( - CppOptions.class, new CppConfigurationLoader(Functions.<String>identity())); - - builder.addBuildInfoFactory(new CppBuildInfo()); - builder.addDynamicTransitionMaps(CppRuleClasses.DYNAMIC_TRANSITIONS_MAP); - - builder.addRuleDefinition(new CcToolchainRule()); - builder.addRuleDefinition(new CcToolchainSuiteRule()); - builder.addRuleDefinition(new CcToolchainAlias.CcToolchainAliasRule()); - builder.addRuleDefinition(new CcIncLibraryRule()); - builder.addRuleDefinition(new BazelCppRuleClasses.CcLinkingRule()); - builder.addRuleDefinition(new BazelCppRuleClasses.CcDeclRule()); - builder.addRuleDefinition(new BazelCppRuleClasses.CcBaseRule()); - builder.addRuleDefinition(new BazelCppRuleClasses.CcRule()); - builder.addRuleDefinition(new BazelCppRuleClasses.CcBinaryBaseRule()); - builder.addRuleDefinition(new BazelCcBinaryRule()); - builder.addRuleDefinition(new BazelCcTestRule()); - builder.addRuleDefinition(new BazelCppRuleClasses.CcLibraryBaseRule()); - builder.addRuleDefinition(new BazelCcLibraryRule()); - builder.addRuleDefinition(new BazelCcIncLibraryRule()); - } + /** + * Set the label for Windows DEF parser. In bazel, it should be + * @bazel_tools//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 + */ + public static final RuleSet CPP_RULES = cppRules("@bazel_tools//tools/def_parser:def_parser"); + + public static RuleSet cppRules() { + return cppRules(null); + } - @Override - public ImmutableList<RuleSet> requires() { - return ImmutableList.of(CoreRules.INSTANCE, PLATFORM_RULES); - } - }; + public static RuleSet cppRules(String defParserLabel) { + return new RuleSet() { + @Override + public void init(Builder builder) { + builder.addConfig( + CppOptions.class, new CppConfigurationLoader(Functions.<String>identity())); + + builder.addBuildInfoFactory(new CppBuildInfo()); + builder.addDynamicTransitionMaps(CppRuleClasses.DYNAMIC_TRANSITIONS_MAP); + + builder.addRuleDefinition(new CcToolchainRule(defParserLabel)); + builder.addRuleDefinition(new CcToolchainSuiteRule()); + builder.addRuleDefinition(new CcToolchainAlias.CcToolchainAliasRule()); + builder.addRuleDefinition(new CcIncLibraryRule()); + builder.addRuleDefinition(new BazelCppRuleClasses.CcLinkingRule()); + builder.addRuleDefinition(new BazelCppRuleClasses.CcDeclRule()); + builder.addRuleDefinition(new BazelCppRuleClasses.CcBaseRule()); + builder.addRuleDefinition(new BazelCppRuleClasses.CcRule()); + builder.addRuleDefinition(new BazelCppRuleClasses.CcBinaryBaseRule()); + builder.addRuleDefinition(new BazelCcBinaryRule()); + builder.addRuleDefinition(new BazelCcTestRule()); + builder.addRuleDefinition(new BazelCppRuleClasses.CcLibraryBaseRule()); + builder.addRuleDefinition(new BazelCcLibraryRule()); + builder.addRuleDefinition(new BazelCcIncLibraryRule()); + } + + @Override + public ImmutableList<RuleSet> requires() { + return ImmutableList.of(CoreRules.INSTANCE, PLATFORM_RULES); + } + }; + } public static final RuleSet CPP_PROTO_RULES = new RuleSet() { diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCcTestRule.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCcTestRule.java index 72e9517572..292bd9c38b 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCcTestRule.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCcTestRule.java @@ -29,6 +29,7 @@ import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType; import com.google.devtools.build.lib.packages.TriState; import com.google.devtools.build.lib.rules.cpp.CppConfiguration; import com.google.devtools.build.lib.rules.cpp.CppRuleClasses; +import com.google.devtools.build.lib.util.OS; /** Rule definition for cc_test rules. */ public final class BazelCcTestRule implements RuleDefinition { @@ -37,7 +38,11 @@ public final class BazelCcTestRule implements RuleDefinition { return builder .requiresConfigurationFragments(CppConfiguration.class) .setImplicitOutputsFunction(CppRuleClasses.CC_BINARY_DEBUG_PACKAGE) - .override(attr("linkstatic", BOOLEAN).value(false)) + // We don't want C++ tests to be dynamically linked by default on Windows, + // because windows_export_all_symbols is not enabled by default, and it cannot solve + // all symbols visibility issues, for example, users still have to use __declspec(dllimport) + // to decorate data symbols imported from DLL. + .override(attr("linkstatic", BOOLEAN).value(OS.getCurrent() == OS.WINDOWS)) .override(attr("stamp", TRISTATE).value(TriState.NO)) // Oh weary adventurer, endeavour not to remove this attribute, enticing as that may be, // given that no code referenceth it. Should ye be on the verge of yielding to the 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. |