2121import com .google .common .collect .Iterables ;
2222import com .google .devtools .build .lib .actions .ActionRegistry ;
2323import com .google .devtools .build .lib .actions .Artifact ;
24+ import com .google .devtools .build .lib .actions .ArtifactRoot ;
2425import com .google .devtools .build .lib .actions .CommandLineExpansionException ;
2526import com .google .devtools .build .lib .analysis .FileProvider ;
2627import com .google .devtools .build .lib .analysis .RuleContext ;
@@ -87,7 +88,9 @@ public CcLinkingOutputs getCcLinkingOutputs() {
8788 private final BuildConfiguration configuration ;
8889 private final CppConfiguration cppConfiguration ;
8990
90- private final List <Artifact > nonCodeLinkerInputs = new ArrayList <>();
91+ private final NestedSetBuilder <Artifact > additionalLinkerInputsBuilder =
92+ NestedSetBuilder .stableOrder ();
93+ private final List <Artifact > linkerOutputs = new ArrayList <>();
9194 private final List <String > linkopts = new ArrayList <>();
9295 private final List <CcLinkingContext > ccLinkingContexts = new ArrayList <>();
9396 private final NestedSetBuilder <Artifact > linkstamps = NestedSetBuilder .stableOrder ();
@@ -96,6 +99,7 @@ public CcLinkingOutputs getCcLinkingOutputs() {
9699 @ Nullable private Artifact linkerOutputArtifact ;
97100 private LinkTargetType staticLinkType = LinkTargetType .STATIC_LIBRARY ;
98101 private LinkTargetType dynamicLinkType = LinkTargetType .NODEPS_DYNAMIC_LIBRARY ;
102+ private NestedSet <Artifact > additionalLinkerInputs ;
99103 private boolean neverlink ;
100104
101105 private boolean emitInterfaceSharedLibraries ;
@@ -194,19 +198,27 @@ public CcLinkingHelper addAdditionalLinkstampDefines(List<String> additionalLink
194198 return this ;
195199 }
196200
197- /** Adds the corresponding non-code files as linker inputs. */
201+ /**
202+ * Adds the corresponding non-code files as linker inputs.
203+ *
204+ * <p>TODO(bazel-team): There is no practical difference in non-code inputs and additional linker
205+ * inputs in CppLinkActionBuilder. So these should be merged. Even before that happens, it's
206+ * totally fine for nonCodeLinkerInputs to contains precompiled libraries.
207+ */
198208 public CcLinkingHelper addNonCodeLinkerInputs (List <Artifact > nonCodeLinkerInputs ) {
199- for (Artifact nonCodeLinkerInput : nonCodeLinkerInputs ) {
200- String basename = nonCodeLinkerInput .getFilename ();
201- Preconditions .checkArgument (!Link .OBJECT_FILETYPES .matches (basename ));
202- Preconditions .checkArgument (!Link .ARCHIVE_LIBRARY_FILETYPES .matches (basename ));
203- Preconditions .checkArgument (!Link .SHARED_LIBRARY_FILETYPES .matches (basename ));
204- this .nonCodeLinkerInputs .add (nonCodeLinkerInput );
205- }
206- if (fdoContext .getPropellerOptimizeInputFile () != null
207- && fdoContext .getPropellerOptimizeInputFile ().getLdArtifact () != null ) {
208- this .nonCodeLinkerInputs .add (fdoContext .getPropellerOptimizeInputFile ().getLdArtifact ());
209- }
209+ this .additionalLinkerInputsBuilder .addAll (nonCodeLinkerInputs );
210+ return this ;
211+ }
212+
213+ public CcLinkingHelper addTransitiveAdditionalLinkerInputs (
214+ NestedSet <Artifact > additionalLinkerInputs ) {
215+ this .additionalLinkerInputsBuilder .addTransitive (additionalLinkerInputs );
216+ return this ;
217+ }
218+
219+ /** TODO(bazel-team): Add to Starlark API */
220+ public CcLinkingHelper addLinkerOutputs (List <Artifact > linkerOutputs ) {
221+ this .linkerOutputs .addAll (linkerOutputs );
210222 return this ;
211223 }
212224
@@ -361,6 +373,9 @@ public CcLinkingOutputs link(CcCompilationOutputs ccOutputs)
361373 throws RuleErrorException , InterruptedException {
362374 Preconditions .checkNotNull (ccOutputs );
363375
376+ Preconditions .checkState (additionalLinkerInputs == null );
377+ additionalLinkerInputs = additionalLinkerInputsBuilder .build ();
378+
364379 // Create link actions (only if there are object files or if explicitly requested).
365380 //
366381 // On some systems, the linker gives an error message if there are no input files. Even with
@@ -401,7 +416,8 @@ public CcLinkingContext buildCcLinkingContextFromLibrariesToLink(
401416 CcLinkingContext .LinkOptions .of (
402417 ImmutableList .copyOf (linkopts ), symbolGenerator )))
403418 .addLibraries (librariesToLink )
404- .addNonCodeInputs (nonCodeLinkerInputs )
419+ // additionalLinkerInputsBuilder not expected to be a big list for now.
420+ .addNonCodeInputs (additionalLinkerInputsBuilder .build ().toList ())
405421 .addLinkstamps (linkstampBuilder .build ())
406422 .build ();
407423 }
@@ -629,7 +645,6 @@ private CppLinkAction registerActionForStaticLibrary(
629645 CppLinkAction action =
630646 newLinkActionBuilder (linkedArtifact , linkTargetTypeUsedForNaming )
631647 .addObjectFiles (ccOutputs .getObjectFiles (usePic ))
632- .addNonCodeInputs (nonCodeLinkerInputs )
633648 .addLtoCompilationContext (ccOutputs .getLtoCompilationContext ())
634649 .setUsePicForLtoBackendActions (usePic )
635650 .setLinkingMode (LinkingMode .STATIC )
@@ -694,7 +709,6 @@ private boolean createDynamicLinkAction(
694709 .addActionInputs (linkActionInputs )
695710 .addLinkopts (linkopts )
696711 .addLinkopts (sonameLinkopts )
697- .addNonCodeInputs (nonCodeLinkerInputs )
698712 .addVariablesExtensions (variablesExtensions );
699713
700714 dynamicLinkActionBuilder .addObjectFiles (ccOutputs .getObjectFiles (usePic ));
@@ -829,28 +843,43 @@ private boolean createDynamicLinkAction(
829843
830844 private CppLinkActionBuilder newLinkActionBuilder (
831845 Artifact outputArtifact , LinkTargetType linkType ) {
832- return new CppLinkActionBuilder (
833- ruleErrorConsumer ,
834- actionConstructionContext ,
835- label ,
836- outputArtifact ,
837- configuration ,
838- ccToolchain ,
839- fdoContext ,
840- featureConfiguration ,
841- semantics )
842- .setGrepIncludes (grepIncludes )
843- .setIsStampingEnabled (isStampingEnabled )
844- .setTestOrTestOnlyTarget (isTestOrTestOnlyTarget )
845- .setLinkType (linkType )
846- .setLinkerFiles (
847- (cppConfiguration .useSpecificToolFiles ()
848- && linkType .linkerOrArchiver () == LinkerOrArchiver .ARCHIVER )
849- ? ccToolchain .getArFiles ()
850- : ccToolchain .getLinkerFiles ())
851- .setLinkArtifactFactory (linkArtifactFactory )
852- .setUseTestOnlyFlags (useTestOnlyFlags )
853- .addExecutionInfo (executionInfo );
846+ if (!additionalLinkerInputsBuilder .isEmpty ()) {
847+ if (fdoContext .getPropellerOptimizeInputFile () != null
848+ && fdoContext .getPropellerOptimizeInputFile ().getLdArtifact () != null ) {
849+ this .additionalLinkerInputsBuilder .add (
850+ fdoContext .getPropellerOptimizeInputFile ().getLdArtifact ());
851+ }
852+ }
853+ CppLinkActionBuilder builder =
854+ new CppLinkActionBuilder (
855+ ruleErrorConsumer ,
856+ actionConstructionContext ,
857+ label ,
858+ outputArtifact ,
859+ configuration ,
860+ ccToolchain ,
861+ fdoContext ,
862+ featureConfiguration ,
863+ semantics )
864+ .setGrepIncludes (grepIncludes )
865+ .setMnemonic (
866+ featureConfiguration .isEnabled (CppRuleClasses .LANG_OBJC ) ? "ObjcLink" : null )
867+ .setIsStampingEnabled (isStampingEnabled )
868+ .setTestOrTestOnlyTarget (isTestOrTestOnlyTarget )
869+ .setLinkType (linkType )
870+ .setLinkerFiles (
871+ (cppConfiguration .useSpecificToolFiles ()
872+ && linkType .linkerOrArchiver () == LinkerOrArchiver .ARCHIVER )
873+ ? ccToolchain .getArFiles ()
874+ : ccToolchain .getLinkerFiles ())
875+ .setLinkArtifactFactory (linkArtifactFactory )
876+ .setUseTestOnlyFlags (useTestOnlyFlags )
877+ .addTransitiveActionInputs (additionalLinkerInputs )
878+ .addExecutionInfo (executionInfo );
879+ for (Artifact output : linkerOutputs ) {
880+ builder .addActionOutput (output );
881+ }
882+ return builder ;
854883 }
855884
856885 /**
@@ -876,12 +905,28 @@ private Artifact getLinkedArtifact(LinkTargetType linkTargetType) throws RuleErr
876905 linkedName =
877906 CppHelper .getArtifactNameForCategory (
878907 ruleErrorConsumer , ccToolchain , linkTargetType .getLinkerOutput (), linkedName );
908+
909+ ArtifactRoot artifactRoot = configuration .getBinDirectory (label .getRepository ());
910+ if (linkTargetType .equals (LinkTargetType .OBJC_FULLY_LINKED_ARCHIVE )) {
911+ // TODO(blaze-team): This unfortunate editing of the name is here bedcause Objective-C rules
912+ // were creating this type of archive without the lib prefix, unlike what the objective-c
913+ // toolchain says with getArtifactNameForCategory.
914+ // This can be fixed either when implicit outputs are removed from objc_library by keeping the
915+ // lib prefix, or by editing the toolchain not to add it.
916+ Preconditions .checkState (linkedName .startsWith ("lib" ));
917+ linkedName = linkedName .substring (3 );
918+ artifactRoot =
919+ ((RuleContext ) actionConstructionContext ).getRule ().hasBinaryOutput ()
920+ ? configuration .getBinDir ()
921+ : configuration .getGenfilesDir ();
922+ }
879923 PathFragment artifactFragment =
880924 PathFragment .create (label .getName ()).getParentDirectory ().getRelative (linkedName );
881925
882926 return CppHelper .getLinkedArtifact (
883927 label ,
884928 actionConstructionContext ,
929+ artifactRoot ,
885930 configuration ,
886931 linkTargetType ,
887932 linkedArtifactNameSuffix ,
0 commit comments