diff options
author | Yun Peng <pcloudy@google.com> | 2017-09-28 08:23:57 -0400 |
---|---|---|
committer | John Cater <jcater@google.com> | 2017-09-28 08:55:26 -0400 |
commit | 90a4a18c62778def22641b4df06e58b3cc7dfc3e (patch) | |
tree | fb6fb4ef0d5fa83d18eb0c71a7a487ba58bc74f7 /src/main/java/com/google/devtools/build | |
parent | 6ee36ef239b25f66afa83e2657bd0b529b1ff50e (diff) |
Make windows_export_all_symbols feature work for cc_binary
Now Bazel can also export symbols when building dynamic library from
cc_binary.
The interface library generated can be accessed by interface_library output group.
The DEF file can still be accessed by def_file output group even when
windows_export_all_symbols feature is not specified. This is useful when
users want to filter symbols in DEF file before using it, for example,
working around the 64K symbols number limit.
Change-Id: I5b4dae0840e20037c00d500181c40b5faedfdcd8
PiperOrigin-RevId: 170330409
Diffstat (limited to 'src/main/java/com/google/devtools/build')
3 files changed, 110 insertions, 66 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java index 742e5dd37c..6b00ae0d69 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java @@ -290,8 +290,40 @@ public abstract class CcBinary implements RuleConfiguredTargetFactory { CppLinkAction.symbolCountsFileName(binaryPath))); } + Artifact defFile = null; + Artifact interfaceLibrary = null; if (isLinkShared(ruleContext)) { linkActionBuilder.setLibraryIdentifier(CcLinkingOutputs.libraryIdentifierOf(binary)); + + if (featureConfiguration.isEnabled(CppRuleClasses.TARGETS_WINDOWS)) { + ImmutableList.Builder<Artifact> objectFiles = ImmutableList.builder(); + objectFiles.addAll(ccCompilationOutputs.getObjectFiles(false)); + for (LibraryToLink library : linkParams.getLibraries()) { + if (library.containsObjectFiles() + && library.getArtifactCategory() != ArtifactCategory.DYNAMIC_LIBRARY + && library.getArtifactCategory() != ArtifactCategory.INTERFACE_LIBRARY) { + objectFiles.addAll(library.getObjectFiles()); + } + } + defFile = + CppHelper.createDefFileActions( + ruleContext, + ccToolchain.getDefParserTool(), + objectFiles.build(), + binary.getFilename()); + + if (CppHelper.shouldUseDefFile(featureConfiguration)) { + linkActionBuilder.setDefFile(defFile); + } + + // If we are using a toolchain supporting interface library and targeting Windows, we build + // the interface library with the link action and add it to `interface_output` output group. + if (cppConfiguration.useInterfaceSharedObjects()) { + interfaceLibrary = ruleContext.getRelatedArtifact(binary.getRootRelativePath(), ".ifso"); + linkActionBuilder.setInterfaceOutput(interfaceLibrary); + linkActionBuilder.addActionOutput(interfaceLibrary); + } + } } // Store immutable context for use in other *_binary rules that are implemented by @@ -451,6 +483,14 @@ public abstract class CcBinary implements RuleConfiguredTargetFactory { ruleBuilder.addOutputGroup("pdb_file", pdbFile); } + if (defFile != null) { + ruleBuilder.addOutputGroup("def_file", defFile); + } + + if (interfaceLibrary != null) { + ruleBuilder.addOutputGroup("interface_library", interfaceLibrary); + } + return ruleBuilder .addProvider(RunfilesProvider.class, RunfilesProvider.simple(runfiles)) .addProvider( diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppHelper.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppHelper.java index 5bc125633e..e5c871ef8a 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppHelper.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppHelper.java @@ -15,6 +15,7 @@ package com.google.devtools.build.lib.rules.cpp; import static com.google.devtools.build.lib.packages.BuildType.LABEL; +import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; @@ -24,6 +25,7 @@ import com.google.devtools.build.lib.actions.Action; import com.google.devtools.build.lib.actions.ActionOwner; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.actions.MiddlemanFactory; +import com.google.devtools.build.lib.actions.ParameterFile; import com.google.devtools.build.lib.analysis.AnalysisUtils; import com.google.devtools.build.lib.analysis.FileProvider; import com.google.devtools.build.lib.analysis.PlatformConfiguration; @@ -33,6 +35,7 @@ import com.google.devtools.build.lib.analysis.StaticallyLinkedMarkerProvider; import com.google.devtools.build.lib.analysis.ToolchainContext.ResolvedToolchainProviders; 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.actions.SymlinkAction; import com.google.devtools.build.lib.analysis.config.BuildConfiguration; @@ -761,4 +764,64 @@ public class CppHelper { return getArtifactNameForCategory( ruleContext, toolchain, ArtifactCategory.INCLUDED_FILE_LIST, baseName); } + + /** + * Returns true when {@link CppRuleClasses#WINDOWS_EXPORT_ALL_SYMBOLS} feature is enabled and + * {@link CppRuleClasses#NO_WINDOWS_EXPORT_ALL_SYMBOLS} feature is not enabled. + */ + public static boolean shouldUseDefFile(FeatureConfiguration featureConfiguration) { + return featureConfiguration.isEnabled(CppRuleClasses.WINDOWS_EXPORT_ALL_SYMBOLS) + && !featureConfiguration.isEnabled(CppRuleClasses.NO_WINDOWS_EXPORT_ALL_SYMBOLS); + } + + /** + * Create actions for parsing object files to generate a DEF file, should only be used when + * targeting Windows. + * + * @param defParser The tool we use to parse object files for generating the DEF file. + * @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. + */ + public static Artifact createDefFileActions( + RuleContext ruleContext, + Artifact defParser, + ImmutableList<Artifact> objectFiles, + String dllName) { + 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)); + + 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; + } } 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 4978902723..2038daba89 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,8 +14,6 @@ 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; @@ -25,13 +23,9 @@ 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.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.configuredtargets.RuleConfiguredTarget.Mode; @@ -60,7 +54,6 @@ 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 @@ -686,60 +679,6 @@ 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. @@ -1504,11 +1443,13 @@ public final class CppModel { ccToolchain.getDynamicRuntimeLinkInputs()) .addVariablesExtensions(variablesExtensions); - Artifact defFile = - createDefFileActions( - ccOutputs.getObjectFiles(false), - SolibSymlinkAction.getDynamicLibrarySoname(soImpl.getRootRelativePath(), true)); - if (defFile != null) { + if (CppHelper.shouldUseDefFile(featureConfiguration)) { + Artifact defFile = + CppHelper.createDefFileActions( + ruleContext, + ccToolchain.getDefParserTool(), + ccOutputs.getObjectFiles(false), + SolibSymlinkAction.getDynamicLibrarySoname(soImpl.getRootRelativePath(), true)); dynamicLinkActionBuilder.setDefFile(defFile); } |