From 5bb4ff6886450217f00765c7ed19055ff08e9568 Mon Sep 17 00:00:00 2001 From: Cal Peyser Date: Tue, 15 Nov 2016 20:21:38 +0000 Subject: Implement basic objc executable linking in the CROSSTOOL. The following link features are *not* implemented yet: 1) Objc++ linking semantics 2) Dead stripping 3) --should_prioritize_static_libs 4) DSYM generation 5) Coverage support 6) Swift interop 7) Linkmap -- MOS_MIGRATED_REVID=139232434 --- .../build/lib/rules/cpp/CcToolchainFeatures.java | 2 +- .../build/lib/rules/cpp/CppLinkAction.java | 9 +++- .../build/lib/rules/cpp/CppLinkActionBuilder.java | 41 ++++++++++++--- .../google/devtools/build/lib/rules/cpp/Link.java | 58 ++++++++++++++++++---- .../build/lib/rules/cpp/LinkCommandLine.java | 1 + 5 files changed, 92 insertions(+), 19 deletions(-) (limited to 'src/main/java/com/google/devtools/build/lib/rules/cpp') diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeatures.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeatures.java index ca464d2a1b..bf9e7c5367 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeatures.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeatures.java @@ -1150,7 +1150,7 @@ public class CcToolchainFeatures implements Serializable { * Add a variable that expands a flag group containing a reference to {@code name} for each * entry in {@code values}. */ - public Builder addSequenceVariable(String name, Collection values) { + public Builder addSequenceVariable(String name, Iterable values) { StringSequence.Builder sequenceBuilder = new StringSequence.Builder(); for (String value : values) { sequenceBuilder.addValue(value); diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkAction.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkAction.java index 44004745a0..04dc86895e 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkAction.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkAction.java @@ -95,6 +95,7 @@ public final class CppLinkAction extends AbstractAction private static final String LINK_GUID = "58ec78bd-1176-4e36-8143-439f656b181d"; private static final String FAKE_LINK_GUID = "da36f819-5a15-43a9-8a45-e01b60e10c8b"; + @Nullable private final String mnemonic; private final CppConfiguration cppConfiguration; private final LibraryToLink outputLibrary; private final Artifact linkOutput; @@ -138,6 +139,7 @@ public final class CppLinkAction extends AbstractAction */ CppLinkAction( ActionOwner owner, + String mnemonic, Iterable inputs, ImmutableList outputs, CppConfiguration cppConfiguration, @@ -151,6 +153,11 @@ public final class CppLinkAction extends AbstractAction Map toolchainEnv, ImmutableSet executionRequirements) { super(owner, inputs, outputs); + if (mnemonic == null) { + this.mnemonic = (isLTOIndexing) ? "CppLTOIndexing" : "CppLink"; + } else { + this.mnemonic = mnemonic; + } this.mandatoryInputs = inputs; this.cppConfiguration = cppConfiguration; this.outputLibrary = outputLibrary; @@ -457,7 +464,7 @@ public final class CppLinkAction extends AbstractAction @Override public String getMnemonic() { - return (isLTOIndexing) ? "CppLTOIndexing" : "CppLink"; + return mnemonic; } @Override 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 f2690c6062..9fe8673389 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 @@ -124,6 +124,7 @@ public class CppLinkActionBuilder { @Nullable private final RuleContext ruleContext; private final AnalysisEnvironment analysisEnvironment; private final Artifact output; + @Nullable private String mnemonic; // can be null for CppLinkAction.createTestBuilder() @Nullable private final CcToolchainProvider toolchain; @@ -162,7 +163,7 @@ public class CppLinkActionBuilder { private Iterable allLTOArtifacts = null; private final List variablesExtensions = new ArrayList<>(); - private final List linkActionInputs = new ArrayList<>(); + private final NestedSetBuilder linkActionInputs = NestedSetBuilder.stableOrder(); /** * Creates a builder that builds {@link CppLinkAction} instances. @@ -442,8 +443,11 @@ public class CppLinkActionBuilder { /** Builds the Action as configured and returns it. */ public CppLinkAction build() throws InterruptedException { - Preconditions.checkState( - (libraryIdentifier == null) == (linkType == LinkTargetType.EXECUTABLE)); + // Executable links do not have library identifiers. + boolean hasIdentifier = (libraryIdentifier != null); + boolean isExecutable = linkType.isExecutable(); + Preconditions.checkState(hasIdentifier != isExecutable); + if (interfaceOutput != null && (fake || linkType != LinkTargetType.DYNAMIC_LIBRARY)) { throw new RuntimeException( "Interface output can only be used " + "with non-fake DYNAMIC_LIBRARY targets"); @@ -485,7 +489,7 @@ public class CppLinkActionBuilder { } } - final LibraryToLink outputLibrary = linkType == LinkTargetType.EXECUTABLE + final LibraryToLink outputLibrary = linkType.isExecutable() ? null : LinkerInputs.newInputLibrary(output, linkType.getLinkerOutput(), @@ -651,7 +655,7 @@ public class CppLinkActionBuilder { NestedSetBuilder dependencyInputsBuilder = NestedSetBuilder.stableOrder(); dependencyInputsBuilder.addTransitive(crosstoolInputs); dependencyInputsBuilder.add(toolchain.getLinkDynamicLibraryTool()); - dependencyInputsBuilder.addAll(linkActionInputs); + dependencyInputsBuilder.addTransitive(linkActionInputs.build()); if (runtimeMiddleman != null) { dependencyInputsBuilder.add(runtimeMiddleman); } @@ -737,6 +741,7 @@ public class CppLinkActionBuilder { return new CppLinkAction( getOwner(), + mnemonic, inputsBuilder.deduplicate().build(), actionOutputs, cppConfiguration, @@ -840,6 +845,12 @@ public class CppLinkActionBuilder { protected ActionOwner getOwner() { return ruleContext.getActionOwner(); } + + /** Sets the mnemonic for the link action. */ + public CppLinkActionBuilder setMnemonic(String mnemonic) { + this.mnemonic = mnemonic; + return this; + } /** Set the crosstool inputs required for the action. */ public CppLinkActionBuilder setCrosstoolInputs(NestedSet inputs) { @@ -1143,12 +1154,28 @@ public class CppLinkActionBuilder { } /** - * Sets extra input artifacts to the link action. + * Adds an extra input artifact to the link action. + */ + public CppLinkActionBuilder addActionInput(Artifact input) { + this.linkActionInputs.add(input); + return this; + } + + /** + * Adds extra input artifacts to the link action. */ - public CppLinkActionBuilder addActionInputs(Collection inputs) { + public CppLinkActionBuilder addActionInputs(Iterable inputs) { this.linkActionInputs.addAll(inputs); return this; } + + /** + * Adds extra input artifacts to the link actions. + */ + public CppLinkActionBuilder addTransitiveActionInputs(NestedSet inputs) { + this.linkActionInputs.addTransitive(inputs); + return this; + } private static class LinkArgCollector { String rpathRoot; diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/Link.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/Link.java index ec51c8413f..74f33ab913 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/Link.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/Link.java @@ -103,6 +103,14 @@ public abstract class Link { STATIC, DYNAMIC } + + /** + * Whether a particular link target is executable. + */ + public enum Executable { + EXECUTABLE, + NOT_EXECUTABLE + } /** * Types of ELF files that can be created by the linker (.a, .so, .lo, @@ -115,7 +123,8 @@ public abstract class Link { Staticness.STATIC, "c++-link-static-library", Picness.NOPIC, - ArtifactCategory.STATIC_LIBRARY), + ArtifactCategory.STATIC_LIBRARY, + Executable.NOT_EXECUTABLE), /** An objc static archive. */ OBJC_ARCHIVE( @@ -123,19 +132,35 @@ public abstract class Link { Staticness.STATIC, "objc-archive", Picness.NOPIC, - ArtifactCategory.STATIC_LIBRARY), + ArtifactCategory.STATIC_LIBRARY, + Executable.NOT_EXECUTABLE), /** An objc fully linked static archive. */ OBJC_FULLY_LINKED_ARCHIVE( - ".a", Staticness.STATIC, "objc-fully-link", Picness.NOPIC, ArtifactCategory.STATIC_LIBRARY), + ".a", + Staticness.STATIC, + "objc-fully-link", + Picness.NOPIC, + ArtifactCategory.STATIC_LIBRARY, + Executable.NOT_EXECUTABLE), + /** An objc executable. */ + OBJC_EXECUTABLE( + "", + Staticness.STATIC, + "objc-executable", + Picness.NOPIC, + ArtifactCategory.EXECUTABLE, + Executable.EXECUTABLE), + /** A static archive with .pic.o object files (compiled with -fPIC). */ PIC_STATIC_LIBRARY( ".pic.a", Staticness.STATIC, "c++-link-pic-static-library", Picness.PIC, - ArtifactCategory.STATIC_LIBRARY), + ArtifactCategory.STATIC_LIBRARY, + Executable.NOT_EXECUTABLE), /** An interface dynamic library. */ INTERFACE_DYNAMIC_LIBRARY( @@ -143,7 +168,8 @@ public abstract class Link { Staticness.DYNAMIC, "c++-link-interface-dynamic-library", Picness.NOPIC, // Actually PIC but it's not indicated in the file name - ArtifactCategory.INTERFACE_LIBRARY), + ArtifactCategory.INTERFACE_LIBRARY, + Executable.NOT_EXECUTABLE), /** A dynamic library. */ DYNAMIC_LIBRARY( @@ -151,7 +177,8 @@ public abstract class Link { Staticness.DYNAMIC, "c++-link-dynamic-library", Picness.NOPIC, // Actually PIC but it's not indicated in the file name - ArtifactCategory.DYNAMIC_LIBRARY), + ArtifactCategory.DYNAMIC_LIBRARY, + Executable.NOT_EXECUTABLE), /** A static archive without removal of unused object files. */ ALWAYS_LINK_STATIC_LIBRARY( @@ -159,7 +186,8 @@ public abstract class Link { Staticness.STATIC, "c++-link-alwayslink-static-library", Picness.NOPIC, - ArtifactCategory.ALWAYSLINK_STATIC_LIBRARY), + ArtifactCategory.ALWAYSLINK_STATIC_LIBRARY, + Executable.NOT_EXECUTABLE), /** A PIC static archive without removal of unused object files. */ ALWAYS_LINK_PIC_STATIC_LIBRARY( @@ -167,7 +195,8 @@ public abstract class Link { Staticness.STATIC, "c++-link-alwayslink-pic-static-library", Picness.PIC, - ArtifactCategory.ALWAYSLINK_STATIC_LIBRARY), + ArtifactCategory.ALWAYSLINK_STATIC_LIBRARY, + Executable.NOT_EXECUTABLE), /** An executable binary. */ EXECUTABLE( @@ -175,25 +204,29 @@ public abstract class Link { Staticness.DYNAMIC, "c++-link-executable", Picness.NOPIC, // Picness is not indicate in the file name - ArtifactCategory.EXECUTABLE); + ArtifactCategory.EXECUTABLE, + Executable.EXECUTABLE); private final String extension; private final Staticness staticness; private final String actionName; private final ArtifactCategory linkerOutput; private final Picness picness; + private final Executable executable; LinkTargetType( String extension, Staticness staticness, String actionName, Picness picness, - ArtifactCategory linkerOutput) { + ArtifactCategory linkerOutput, + Executable executable) { this.extension = extension; this.staticness = staticness; this.actionName = actionName; this.linkerOutput = linkerOutput; this.picness = picness; + this.executable = executable; } /** @@ -223,6 +256,11 @@ public abstract class Link { public String getActionName() { return actionName; } + + /** Returns true iff this link type is executable */ + public boolean isExecutable() { + return (executable == Executable.EXECUTABLE); + } } /** diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkCommandLine.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkCommandLine.java index 27e3e4db99..6a95202423 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkCommandLine.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkCommandLine.java @@ -408,6 +408,7 @@ public final class LinkCommandLine extends CommandLine { // TODO(b/30109612): make this pattern the case for all link variants. case OBJC_ARCHIVE: case OBJC_FULLY_LINKED_ARCHIVE: + case OBJC_EXECUTABLE: argv.add(toolPath); argv.addAll(featureConfiguration.getCommandLine(actionName, variables)); break; -- cgit v1.2.3