Introduce linkmap support for --experimental_objc_crosstool=all

PiperOrigin-RevId: 153161442
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/CrosstoolCompilationSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/CrosstoolCompilationSupport.java
index e118149..773fb33 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/CrosstoolCompilationSupport.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/CrosstoolCompilationSupport.java
@@ -100,6 +100,8 @@
    */
   private static final String NO_GENERATE_DEBUG_SYMBOLS_FEATURE_NAME = "no_generate_debug_symbols";
 
+  private static final String GENERATE_LINKMAP_FEATURE_NAME = "generate_linkmap";
+
   private static final ImmutableList<String> ACTIVATED_ACTIONS =
       ImmutableList.of(
           "objc-compile",
@@ -306,6 +308,14 @@
       executableLinkAction.addActionOutput(dsymBundleZip);
     }
 
+    if (objcConfiguration.generateLinkmap()) {
+      Artifact linkmap = intermediateArtifacts.linkmap();
+      extensionBuilder
+          .setLinkmap(linkmap)
+          .addVariableCategory(VariableCategory.LINKMAP_VARIABLES);
+      executableLinkAction.addActionOutput(linkmap);
+    }
+
     executableLinkAction.addVariablesExtension(extensionBuilder.build());
     ruleContext.registerAction(executableLinkAction.build());
 
@@ -447,6 +457,9 @@
     } else {
       activatedCrosstoolSelectables.add(NO_GENERATE_DEBUG_SYMBOLS_FEATURE_NAME);
     }
+    if (configuration.getFragment(ObjcConfiguration.class).generateLinkmap()) {
+      activatedCrosstoolSelectables.add(GENERATE_LINKMAP_FEATURE_NAME);
+    }
 
     activatedCrosstoolSelectables.addAll(ruleContext.getFeatures());
     return configuration
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcVariablesExtension.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcVariablesExtension.java
index ac15390..0e98cb3 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcVariablesExtension.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcVariablesExtension.java
@@ -46,6 +46,7 @@
   static final String OBJC_LIBRARY_EXEC_PATHS_VARIABLE_NAME = "objc_library_exec_paths";
   static final String CC_LIBRARY_EXEC_PATHS_VARIABLE_NAME = "cc_library_exec_paths";
   static final String IMPORTED_LIBRARY_EXEC_PATHS_VARIABLE_NAME = "imported_library_exec_paths";
+  static final String LINKMAP_EXEC_PATH = "linkmap_exec_path";
 
   // executable linking variables
   static final String FRAMEWORK_NAMES_VARIABLE_NAME = "framework_names";
@@ -60,7 +61,7 @@
   // dsym variables
   static final String DSYM_PATH_VARIABLE_NAME = "dsym_path";
   static final String DSYM_BUNDLE_ZIP_VARIABLE_NAME = "dsym_bundle_zip";
-  
+
   private final RuleContext ruleContext;
   private final ObjcProvider objcProvider;
   private final CompilationArtifacts compilationArtifacts;
@@ -75,6 +76,7 @@
   private final ImmutableSet<VariableCategory> activeVariableCategories;
   private final DsymOutputType dsymOutputType;
   private final Artifact dsymBundleZip;
+  private final Artifact linkmap;
 
   private ObjcVariablesExtension(
       RuleContext ruleContext,
@@ -89,7 +91,8 @@
       ImmutableList<String> attributeLinkopts,
       ImmutableSet<VariableCategory> activeVariableCategories,
       DsymOutputType dsymOutputType,
-      Artifact dsymBundleZip) {
+      Artifact dsymBundleZip,
+      Artifact linkmap) {
     this.ruleContext = ruleContext;
     this.objcProvider = objcProvider;
     this.compilationArtifacts = compilationArtifacts;
@@ -104,6 +107,7 @@
     this.activeVariableCategories = activeVariableCategories;
     this.dsymOutputType = dsymOutputType;
     this.dsymBundleZip = dsymBundleZip;
+    this.linkmap = linkmap;
   }
 
   /** Type of build variable that can optionally exported by this extension. */
@@ -111,7 +115,8 @@
     ARCHIVE_VARIABLES,
     FULLY_LINK_VARIABLES,
     EXECUTABLE_LINKING_VARIABLES,
-    DSYM_VARIABLES;
+    DSYM_VARIABLES,
+    LINKMAP_VARIABLES;
   }
 
   @Override
@@ -131,6 +136,9 @@
     if (activeVariableCategories.contains(VariableCategory.DSYM_VARIABLES)) {
       addDsymVariables(builder);
     }
+    if (activeVariableCategories.contains(VariableCategory.LINKMAP_VARIABLES)) {
+      addLinkmapVariables(builder);
+    }
   }
 
   private void addPchVariables(CcToolchainFeatures.Variables.Builder builder) {
@@ -217,6 +225,10 @@
         FileSystemUtils.removeExtension(dsymBundleZip.getExecPath()).getPathString());
   }
 
+  private void addLinkmapVariables(CcToolchainFeatures.Variables.Builder builder) {
+    builder.addStringVariable(LINKMAP_EXEC_PATH, linkmap.getExecPathString());
+  }
+
   /** A Builder for {@link ObjcVariablesExtension}. */
   static class Builder {
     private RuleContext ruleContext;
@@ -231,6 +243,7 @@
     private ImmutableList<String> attributeLinkopts;
     private DsymOutputType dsymOutputType;
     private Artifact dsymBundleZip;
+    private Artifact linkmap;
     
     private final ImmutableSet.Builder<VariableCategory> activeVariableCategoriesBuilder =
         ImmutableSet.builder();
@@ -313,6 +326,12 @@
       return this;
     }
 
+    /** Sets the Artifact for the linkmap. */
+    public Builder setLinkmap(Artifact linkmap) {
+      this.linkmap = linkmap;
+      return this;
+    }
+
     public ObjcVariablesExtension build() {
       
       ImmutableSet<VariableCategory> activeVariableCategories =
@@ -337,6 +356,9 @@
       if (activeVariableCategories.contains(VariableCategory.DSYM_VARIABLES)) {
         Preconditions.checkNotNull(dsymOutputType, "missing dsym output type");
       }
+      if (activeVariableCategories.contains(VariableCategory.LINKMAP_VARIABLES)) {
+        Preconditions.checkNotNull(linkmap, "missing linkmap artifact");
+      }
 
       return new ObjcVariablesExtension(
           ruleContext,
@@ -351,7 +373,8 @@
           attributeLinkopts,
           activeVariableCategories,
           dsymOutputType,
-          dsymBundleZip);
+          dsymBundleZip,
+          linkmap);
     }
   }
 }