Emit an event containing Xcode config info.

PiperOrigin-RevId: 301632930
diff --git a/src/main/java/com/google/devtools/build/lib/BUILD b/src/main/java/com/google/devtools/build/lib/BUILD
index 937010e..f341179 100644
--- a/src/main/java/com/google/devtools/build/lib/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/BUILD
@@ -577,6 +577,7 @@
         "//src/main/protobuf:extra_actions_base_java_proto",
         "//src/main/protobuf:spawn_java_proto",
         "//src/main/protobuf:test_status_java_proto",
+        "//src/main/protobuf:xcode_java_proto",
         "//third_party:auto_value",
         "//third_party:flogger",
         "//third_party:guava",
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/XcodeConfigEvent.java b/src/main/java/com/google/devtools/build/lib/analysis/XcodeConfigEvent.java
new file mode 100644
index 0000000..fb0969f
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/analysis/XcodeConfigEvent.java
@@ -0,0 +1,26 @@
+// Copyright 2020 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package com.google.devtools.build.lib.analysis;
+
+import com.google.devtools.build.lib.events.ExtendedEventHandler.Postable;
+import com.google.devtools.build.lib.xcode.proto.XcodeConfig.XcodeConfigRuleInfo;
+
+/** Carries the information passed to an {@code xcode_config} rule for logging purposes. */
+public class XcodeConfigEvent implements Postable {
+  public final XcodeConfigRuleInfo xcodeConfigInfo;
+
+  public XcodeConfigEvent(XcodeConfigRuleInfo xcodeConfigInfo) {
+    this.xcodeConfigInfo = xcodeConfigInfo;
+  }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/BUILD b/src/main/java/com/google/devtools/build/lib/rules/apple/BUILD
index 07fd148..1e6de82 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/BUILD
@@ -25,6 +25,7 @@
         "//src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec",
         "//src/main/java/com/google/devtools/build/lib/skylarkbuildapi/apple",
         "//src/main/java/com/google/devtools/common/options",
+        "//src/main/protobuf:xcode_java_proto",
         "//third_party:guava",
         "//third_party:jsr305",
         "//third_party/protobuf:protobuf_java",
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfig.java b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfig.java
index a4736f8..ee98a98 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfig.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfig.java
@@ -30,10 +30,13 @@
 import com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory;
 import com.google.devtools.build.lib.analysis.RuleContext;
 import com.google.devtools.build.lib.analysis.RunfilesProvider;
+import com.google.devtools.build.lib.analysis.XcodeConfigEvent;
 import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.rules.apple.AppleCommandLineOptions.AppleBitcodeMode;
 import com.google.devtools.build.lib.rules.apple.XcodeConfigInfo.Availability;
+import com.google.devtools.build.lib.xcode.proto.XcodeConfig.XcodeConfigRuleInfo;
+import com.google.devtools.build.lib.xcode.proto.XcodeConfig.XcodeVersionInfo;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -59,6 +62,11 @@
       throws InterruptedException, RuleErrorException, ActionConflictException {
     AppleConfiguration appleConfig = ruleContext.getFragment(AppleConfiguration.class);
     AppleCommandLineOptions appleOptions = appleConfig.getOptions();
+
+    XcodeConfigRuleInfo.Builder infoBuilder = XcodeConfigRuleInfo.newBuilder();
+    if (appleOptions.xcodeVersion != null) {
+      infoBuilder.setXcodeVersionFlag(appleOptions.xcodeVersion);
+    }
     XcodeVersionRuleData explicitDefaultVersion =
         ruleContext.getPrerequisite(
             XcodeConfigRule.DEFAULT_ATTR_NAME,
@@ -66,16 +74,17 @@
             XcodeVersionRuleData.class);
 
     List<XcodeVersionRuleData> explicitVersions =
-        (List<XcodeVersionRuleData>)
             ruleContext.getPrerequisites(
                 XcodeConfigRule.VERSIONS_ATTR_NAME,
                 RuleConfiguredTarget.Mode.TARGET,
                 XcodeVersionRuleData.class);
+
     AvailableXcodesInfo remoteVersions =
         ruleContext.getPrerequisite(
             XcodeConfigRule.REMOTE_VERSIONS_ATTR_NAME,
             RuleConfiguredTarget.Mode.TARGET,
             AvailableXcodesInfo.PROVIDER);
+
     AvailableXcodesInfo localVersions =
         ruleContext.getPrerequisite(
             XcodeConfigRule.LOCAL_VERSIONS_ATTR_NAME,
@@ -83,7 +92,7 @@
             AvailableXcodesInfo.PROVIDER);
 
     XcodeVersionProperties xcodeVersionProperties;
-    XcodeConfigInfo.Availability availability = null;
+    Availability availability = null;
     if (useAvailableXcodesMode(
         explicitVersions, explicitDefaultVersion, localVersions, remoteVersions, ruleContext)) {
       Map.Entry<XcodeVersionRuleData, Availability> xcode =
@@ -92,17 +101,32 @@
               remoteVersions,
               ruleContext,
               appleOptions.xcodeVersion,
-              appleOptions.preferMutualXcode);
+              appleOptions.preferMutualXcode,
+              infoBuilder);
       xcodeVersionProperties = xcode.getKey().getXcodeVersionProperties();
       availability = xcode.getValue();
     } else {
       xcodeVersionProperties =
           resolveExplicitlyDefinedVersion(
-              explicitVersions, explicitDefaultVersion, appleOptions.xcodeVersion, ruleContext);
-      availability = XcodeConfigInfo.Availability.UNKNOWN;
+              explicitVersions,
+              explicitDefaultVersion,
+              appleOptions.xcodeVersion,
+              ruleContext,
+              infoBuilder);
+      availability = Availability.UNKNOWN;
     }
     logger.info(
         String.format("Using Xcode version %s", xcodeVersionProperties.getXcodeVersionString()));
+    if (xcodeVersionProperties.getXcodeVersion().isPresent()) {
+      infoBuilder
+          .setSelectedVersion(xcodeVersionProperties.getXcodeVersionString())
+          .setSelectedVersionAvailability(
+              XcodeConfigRuleInfo.Availability.valueOf(availability.name()));
+    }
+    ruleContext
+        .getAnalysisEnvironment()
+        .getEventHandler()
+        .post(new XcodeConfigEvent(infoBuilder.build()));
     DottedVersion iosSdkVersion =
         (appleOptions.iosSdkVersion != null)
             ? DottedVersion.maybeUnwrap(appleOptions.iosSdkVersion)
@@ -208,7 +232,8 @@
       List<XcodeVersionRuleData> explicitVersions,
       XcodeVersionRuleData explicitDefaultVersion,
       String versionOverrideFlag,
-      RuleContext ruleContext)
+      RuleContext ruleContext,
+      XcodeConfigRuleInfo.Builder infoBuilder)
       throws RuleErrorException {
     if (explicitDefaultVersion != null
         && !Iterables.any(
@@ -233,12 +258,22 @@
         String.format(
             "Determining Xcode version using single-location Xcodes mode: versions=[%s]",
             printableXcodeVersions(explicitVersions)));
+    for (XcodeVersionRuleData version : explicitVersions) {
+      infoBuilder.addExplicitVersions(
+          XcodeVersionInfo.newBuilder()
+              .setVersion(version.getVersion().toString())
+              .addAllAliases(version.getAliases())
+              .build());
+    }
+    infoBuilder.setDefaultVersion(explicitDefaultVersion.getVersion().toString());
+
     Map<String, XcodeVersionRuleData> aliasesToVersionMap = null;
     try {
       aliasesToVersionMap = aliasesToVersionMap(explicitVersions);
     } catch (XcodeConfigException e) {
       throw ruleContext.throwWithRuleError(e);
     }
+
     if (!Strings.isNullOrEmpty(versionOverrideFlag)) {
       // The version override flag is not necessarily an actual version - it may be a version
       // alias.
@@ -271,7 +306,8 @@
       AvailableXcodesInfo remoteVersions,
       RuleContext ruleContext,
       String versionOverrideFlag,
-      boolean preferMutualXcode)
+      boolean preferMutualXcode,
+      XcodeConfigRuleInfo.Builder infoBuilder)
       throws RuleErrorException {
 
     Map<String, XcodeVersionRuleData> localAliasesToVersionMap;
@@ -297,13 +333,34 @@
             printableXcodeVersions(localVersions.getAvailableVersions()),
             printableXcodeVersions(remoteVersions.getAvailableVersions()),
             printableXcodeVersions(mutuallyAvailableVersions)));
+
+    for (XcodeVersionRuleData version : remoteVersions.getAvailableVersions()) {
+      infoBuilder.addRemoteVersions(
+          XcodeVersionInfo.newBuilder()
+              .setVersion(version.getVersion().toString())
+              .addAllAliases(version.getAliases()));
+    }
+    for (XcodeVersionRuleData version : localVersions.getAvailableVersions()) {
+      infoBuilder.addLocalVersions(
+          XcodeVersionInfo.newBuilder()
+              .setVersion(version.getVersion().toString())
+              .addAllAliases(version.getAliases()));
+    }
+    for (XcodeVersionRuleData version : mutuallyAvailableVersions) {
+      infoBuilder.addMutualVersions(
+          XcodeVersionInfo.newBuilder()
+              .setVersion(version.getVersion().toString())
+              .addAllAliases(version.getAliases()));
+    }
+    infoBuilder.setDefaultVersion(localVersions.getDefaultVersion().getVersion().toString());
+
     if (!Strings.isNullOrEmpty(versionOverrideFlag)) {
       XcodeVersionRuleData specifiedVersionFromRemote =
           remoteAliasesToVersionMap.get(versionOverrideFlag);
       XcodeVersionRuleData specifiedVersionFromLocal =
           localAliasesToVersionMap.get(versionOverrideFlag);
       if (specifiedVersionFromLocal != null && specifiedVersionFromRemote != null) {
-        return Maps.immutableEntry(specifiedVersionFromRemote, XcodeConfigInfo.Availability.BOTH);
+        return Maps.immutableEntry(specifiedVersionFromRemote, Availability.BOTH);
       } else if (specifiedVersionFromLocal != null) {
         String error =
             String.format(
@@ -319,7 +376,7 @@
                       printableXcodeVersions(mutuallyAvailableVersions));
         }
         ruleContext.ruleWarning(error);
-        return Maps.immutableEntry(specifiedVersionFromLocal, XcodeConfigInfo.Availability.LOCAL);
+        return Maps.immutableEntry(specifiedVersionFromLocal, Availability.LOCAL);
       } else if (specifiedVersionFromRemote != null) {
         ruleContext.ruleWarning(
             String.format(
@@ -331,7 +388,7 @@
                 versionOverrideFlag,
                 printableXcodeVersions(localVersions.getAvailableVersions()),
                 printableXcodeVersions(remoteVersions.getAvailableVersions())));
-        return Maps.immutableEntry(specifiedVersionFromRemote, XcodeConfigInfo.Availability.REMOTE);
+        return Maps.immutableEntry(specifiedVersionFromRemote, Availability.REMOTE);
       } else { // if (specifiedVersionFromRemote == null && specifiedVersionFromLocal == null)
         ruleContext.throwWithRuleError(
             String.format(
@@ -355,7 +412,7 @@
       }
       // This should never occur. All input versions should be above 0.0.
       checkState(defaultVersion != null);
-      return Maps.immutableEntry(defaultVersion, XcodeConfigInfo.Availability.BOTH);
+      return Maps.immutableEntry(defaultVersion, Availability.BOTH);
     }
     // Select the local default.
     Availability availability = null;
@@ -459,6 +516,6 @@
     return ruleContext.getPrerequisite(
         XcodeConfigRule.XCODE_CONFIG_ATTR_NAME,
         RuleConfiguredTarget.Mode.TARGET,
-        XcodeConfigInfo.PROVIDER);
+        com.google.devtools.build.lib.rules.apple.XcodeConfigInfo.PROVIDER);
   }
 }
diff --git a/src/main/protobuf/BUILD b/src/main/protobuf/BUILD
index 4caa503..809ec17 100644
--- a/src/main/protobuf/BUILD
+++ b/src/main/protobuf/BUILD
@@ -256,6 +256,27 @@
     deps = [":remote_execution_log_java_proto"],
 )
 
+proto_library(
+    name = "xcode_proto",
+    srcs = ["xcode_config.proto"],
+    visibility = ["//visibility:public"],
+)
+
+java_proto_library(
+    name = "xcode_java_proto",
+    deps = [":xcode_proto"],
+)
+
+cc_proto_library(
+    name = "xcode_cc_proto",
+    deps = [":xcode_proto"],
+)
+
+java_library_srcs(
+    name = "xcode_java_proto_srcs",
+    deps = [":xcode_java_proto"],
+)
+
 filegroup(
     name = "srcs",
     srcs = glob(["**"]),
@@ -273,5 +294,6 @@
         ":option_filters_java_proto_srcs",
         ":profile_java_proto_srcs",
         ":remote_execution_log_java_proto_srcs",
+        ":xcode_java_proto_srcs",
     ],
 )
diff --git a/src/main/protobuf/xcode_config.proto b/src/main/protobuf/xcode_config.proto
new file mode 100644
index 0000000..c5588da
--- /dev/null
+++ b/src/main/protobuf/xcode_config.proto
@@ -0,0 +1,67 @@
+// Copyright 2020 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+syntax = "proto3";
+
+package xcode_config;
+
+option java_package = "com.google.devtools.build.lib.xcode.proto";
+
+// Information about a single Xcode version.
+message XcodeVersionInfo {
+  // The canonical version number for this Xcode.
+  string version = 1;
+
+  // The aliases for this version, if present.
+  repeated string aliases = 2;
+
+  // Next ID: 3
+}
+
+// Information about the Xcode config, its dependencies and the selected Xcode.
+message XcodeConfigRuleInfo {
+  enum Availability {
+    UNKNOWN = 0;
+    LOCAL = 1;
+    REMOTE = 2;
+    BOTH = 3;
+  }
+
+  // The Xcode version selected from this configuration to be used in the build.
+  string selected_version = 1;
+
+  // The availability of the selected Xcode version.
+  Availability selected_version_availability = 2;
+
+  // The explicitly listed (location-agnostic) Xcode versions in this
+  // config, if there are any. A config will have either explicit versions or
+  // both local and remote versions.
+  repeated XcodeVersionInfo explicit_versions = 3;
+
+  // The remote Xcode versions in this config, if there are any.
+  repeated XcodeVersionInfo remote_versions = 4;
+
+  // The local Xcode versions in this config, if there are any.
+  repeated XcodeVersionInfo local_versions = 5;
+
+  // The mutually available Xcode versions in this config, if there are any.
+  repeated XcodeVersionInfo mutual_versions = 6;
+
+  // The default version of this Xcode config (explicit or local).
+  string default_version = 7;
+
+  // The value of the --xcode_version flag, if set.
+  string xcode_version_flag = 8;
+
+  // Next ID: 9
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/apple/BUILD b/src/test/java/com/google/devtools/build/lib/rules/apple/BUILD
index b8c4698..173db68 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/apple/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/rules/apple/BUILD
@@ -22,6 +22,7 @@
         "//src/main/java/com/google/devtools/build/lib/packages",
         "//src/main/java/com/google/devtools/build/lib/rules/apple",
         "//src/main/java/com/google/devtools/build/lib/syntax:evaluator",
+        "//src/main/protobuf:xcode_java_proto",
         "//src/test/java/com/google/devtools/build/lib/analysis/util",
         "//src/test/java/com/google/devtools/build/lib/packages:testutil",
         "//src/test/java/com/google/devtools/build/lib/testutil",
diff --git a/src/test/java/com/google/devtools/build/lib/rules/apple/XcodeConfigTest.java b/src/test/java/com/google/devtools/build/lib/rules/apple/XcodeConfigTest.java
index 72ff3ab..ceaac44 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/apple/XcodeConfigTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/apple/XcodeConfigTest.java
@@ -19,8 +19,10 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.eventbus.Subscribe;
 import com.google.devtools.build.lib.actions.ExecutionRequirements;
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.XcodeConfigEvent;
 import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.packages.ConfiguredAttributeMapper;
@@ -30,8 +32,12 @@
 import com.google.devtools.build.lib.packages.StructImpl;
 import com.google.devtools.build.lib.packages.Type;
 import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
+import com.google.devtools.build.lib.xcode.proto.XcodeConfig.XcodeConfigRuleInfo;
+import com.google.devtools.build.lib.xcode.proto.XcodeConfig.XcodeConfigRuleInfo.Availability;
+import com.google.devtools.build.lib.xcode.proto.XcodeConfig.XcodeVersionInfo;
 import java.util.List;
 import java.util.Map;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -41,6 +47,22 @@
  */
 @RunWith(JUnit4.class)
 public class XcodeConfigTest extends BuildViewTestCase {
+  private static class EventRecorder {
+    public XcodeConfigEvent xcodeConfigEvent;
+
+    @Subscribe
+    public synchronized void setXcodeConfigInfo(XcodeConfigEvent xcodeConfigEvent) {
+      // We only care about the top level xcode_config, so drop earlier events.
+      this.xcodeConfigEvent = xcodeConfigEvent;
+    }
+  }
+
+  private final EventRecorder eventRecorder = new EventRecorder();
+
+  @Before
+  public void setUp() {
+    eventBus.register(eventRecorder);
+  }
 
   @Test
   public void testEmptyConfig_noVersionFlag() throws Exception {
@@ -1670,6 +1692,181 @@
     assertXcodeVersion("2.0", "//x:provider_grabber");
   }
 
+  @Test
+  public void testExplicitXcodesModeNoFlag() throws Exception {
+    scratch.file(
+        "xcode/BUILD",
+        "xcode_config(",
+        "    name = 'foo',",
+        "    default = ':version512',",
+        "    versions = [':version512', ':version64'],",
+        ")",
+        "",
+        "xcode_version(",
+        "    name = 'version512',",
+        "    version = '5.1.2',",
+        "    aliases = ['5', '5.1'],",
+        ")",
+        "",
+        "xcode_version(",
+        "    name = 'version64',",
+        "    version = '6.4',",
+        "    aliases = ['6.0', 'foo', '6'],",
+        ")");
+    getConfiguredTarget("//xcode:foo");
+    XcodeConfigRuleInfo expected =
+        XcodeConfigRuleInfo.newBuilder()
+            .setSelectedVersion("5.1.2")
+            .setDefaultVersion("5.1.2")
+            .setSelectedVersionAvailability(Availability.UNKNOWN)
+            .addExplicitVersions(
+                XcodeVersionInfo.newBuilder()
+                    .setVersion("5.1.2")
+                    .addAllAliases(ImmutableList.of("5", "5.1")))
+            .addExplicitVersions(
+                XcodeVersionInfo.newBuilder()
+                    .setVersion("6.4")
+                    .addAllAliases(ImmutableList.of("6.0", "foo", "6")))
+            .build();
+    assertThat(eventRecorder.xcodeConfigEvent.xcodeConfigInfo).isEqualTo(expected);
+  }
+
+  @Test
+  public void testExplicitXcodesModeWithFlag() throws Exception {
+    scratch.file(
+        "xcode/BUILD",
+        "xcode_config(",
+        "    name = 'foo',",
+        "    default = ':version512',",
+        "    versions = [':version512', ':version64'],",
+        ")",
+        "",
+        "xcode_version(",
+        "    name = 'version512',",
+        "    version = '5.1.2',",
+        "    aliases = ['5', '5.1'],",
+        ")",
+        "",
+        "xcode_version(",
+        "    name = 'version64',",
+        "    version = '6.4',",
+        "    aliases = ['6.0', 'foo', '6'],",
+        ")");
+    useConfiguration("--xcode_version=6.4");
+    getConfiguredTarget("//xcode:foo");
+    XcodeConfigRuleInfo expected =
+        XcodeConfigRuleInfo.newBuilder()
+            .setSelectedVersion("6.4")
+            .setDefaultVersion("5.1.2")
+            .setSelectedVersionAvailability(Availability.UNKNOWN)
+            .addExplicitVersions(
+                XcodeVersionInfo.newBuilder()
+                    .setVersion("5.1.2")
+                    .addAllAliases(ImmutableList.of("5", "5.1")))
+            .addExplicitVersions(
+                XcodeVersionInfo.newBuilder()
+                    .setVersion("6.4")
+                    .addAllAliases(ImmutableList.of("6.0", "foo", "6")))
+            .setXcodeVersionFlag("6.4")
+            .build();
+    assertThat(eventRecorder.xcodeConfigEvent.xcodeConfigInfo).isEqualTo(expected);
+  }
+
+  @Test
+  public void testAvailableXcodesModeNoFlag() throws Exception {
+    scratch.file(
+        "xcode/BUILD",
+        "xcode_config(",
+        "    name = 'foo',",
+        "    remote_versions = ':remote',",
+        "    local_versions = ':local',",
+        ")",
+        "",
+        "xcode_version(",
+        "    name = 'version512',",
+        "    version = '5.1.2',",
+        "    aliases = ['5', '5.1'],",
+        ")",
+        "xcode_version(",
+        "    name = 'version84',",
+        "    version = '8.4',",
+        ")",
+        "available_xcodes(",
+        "    name = 'remote',",
+        "    versions = [':version512', ':version84'],",
+        "    default = ':version512',",
+        ")",
+        "available_xcodes(",
+        "    name = 'local',",
+        "    versions = [':version84',],",
+        "    default = ':version84',",
+        ")");
+    useConfiguration("--xcode_version_config=//xcode:foo");
+    getConfiguredTarget("//xcode:foo");
+    XcodeConfigRuleInfo expected =
+        XcodeConfigRuleInfo.newBuilder()
+            .setSelectedVersion("8.4")
+            .setDefaultVersion("8.4")
+            .setSelectedVersionAvailability(Availability.BOTH)
+            .addRemoteVersions(
+                XcodeVersionInfo.newBuilder()
+                    .setVersion("5.1.2")
+                    .addAllAliases(ImmutableList.of("5", "5.1")))
+            .addRemoteVersions(XcodeVersionInfo.newBuilder().setVersion("8.4"))
+            .addLocalVersions(XcodeVersionInfo.newBuilder().setVersion("8.4"))
+            .addMutualVersions(XcodeVersionInfo.newBuilder().setVersion("8.4"))
+            .build();
+    assertThat(eventRecorder.xcodeConfigEvent.xcodeConfigInfo).isEqualTo(expected);
+  }
+
+  @Test
+  public void testAvailableXcodesModeWithFlag() throws Exception {
+    scratch.file(
+        "xcode/BUILD",
+        "xcode_config(",
+        "    name = 'foo',",
+        "    remote_versions = ':remote',",
+        "    local_versions = ':local',",
+        ")",
+        "",
+        "xcode_version(",
+        "    name = 'version512',",
+        "    version = '5.1.2',",
+        "    aliases = ['5', '5.1'],",
+        ")",
+        "xcode_version(",
+        "    name = 'version84',",
+        "    version = '8.4',",
+        ")",
+        "available_xcodes(",
+        "    name = 'remote',",
+        "    versions = [':version512', ':version84'],",
+        "    default = ':version512',",
+        ")",
+        "available_xcodes(",
+        "    name = 'local',",
+        "    versions = [':version84',],",
+        "    default = ':version84',",
+        ")");
+    useConfiguration("--xcode_version=5");
+    getConfiguredTarget("//xcode:foo");
+    XcodeConfigRuleInfo expected =
+        XcodeConfigRuleInfo.newBuilder()
+            .setSelectedVersion("5.1.2")
+            .setDefaultVersion("8.4")
+            .setSelectedVersionAvailability(Availability.REMOTE)
+            .addRemoteVersions(
+                XcodeVersionInfo.newBuilder()
+                    .setVersion("5.1.2")
+                    .addAllAliases(ImmutableList.of("5", "5.1")))
+            .addRemoteVersions(XcodeVersionInfo.newBuilder().setVersion("8.4"))
+            .addLocalVersions(XcodeVersionInfo.newBuilder().setVersion("8.4"))
+            .addMutualVersions(XcodeVersionInfo.newBuilder().setVersion("8.4"))
+            .setXcodeVersionFlag("5")
+            .build();
+    assertThat(this.eventRecorder.xcodeConfigEvent.xcodeConfigInfo).isEqualTo(expected);
+  }
+
   private DottedVersion getSdkVersionForPlatform(ApplePlatform platform) throws Exception {
     ConfiguredTarget xcodeConfig = getConfiguredTarget("//xcode:foo");
     XcodeConfigInfo provider = xcodeConfig.get(XcodeConfigInfo.PROVIDER);