[6.4.0] Add visionOS support (#19436)

This cherry picks https://github.com/bazelbuild/bazel/pull/18905 and
https://github.com/bazelbuild/bazel/pull/19133

Co-authored-by: nglevin <122120823+nglevin@users.noreply.github.com>
diff --git a/MODULE.bazel b/MODULE.bazel
index dd3094f..f7ad0d8 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -12,7 +12,7 @@
 bazel_dep(name = "bazel_skylib", version = "1.2.0")
 bazel_dep(name = "protobuf", version = "3.19.6", repo_name = "com_google_protobuf")
 bazel_dep(name = "grpc", version = "1.47.0", repo_name = "com_github_grpc_grpc")
-bazel_dep(name = "platforms", version = "0.0.5")
+bazel_dep(name = "platforms", version = "0.0.7")
 bazel_dep(name = "rules_pkg", version = "0.7.0")
 bazel_dep(name = "stardoc", version = "0.5.0", repo_name = "io_bazel_skydoc")
 bazel_dep(name = "zstd-jni", version = "1.5.2-3")
diff --git a/distdir_deps.bzl b/distdir_deps.bzl
index 712d75c..4598ea7 100644
--- a/distdir_deps.bzl
+++ b/distdir_deps.bzl
@@ -25,16 +25,17 @@
     #
     ########################################
     "platforms": {
-        "archive": "platforms-0.0.5.tar.gz",
-        "sha256": "379113459b0feaf6bfbb584a91874c065078aa673222846ac765f86661c27407",
+        "archive": "platforms-0.0.7.tar.gz",
+        "sha256": "3a561c99e7bdbe9173aa653fd579fe849f1d8d67395780ab4770b1f381431d51",
         "urls": [
-            "https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.5/platforms-0.0.5.tar.gz",
-            "https://github.com/bazelbuild/platforms/releases/download/0.0.5/platforms-0.0.5.tar.gz",
+            "https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.7/platforms-0.0.7.tar.gz",
+            "https://github.com/bazelbuild/platforms/releases/download/0.0.7/platforms-0.0.7.tar.gz",
         ],
         "used_in": [
             "additional_distfiles",
             "test_WORKSPACE_files",
         ],
+        "package_version": "0.0.7",
     },
     "bazelci_rules": {
         "archive": "bazelci_rules-1.0.0.tar.gz",
diff --git a/src/MODULE.tools b/src/MODULE.tools
index b82be48..6593792 100644
--- a/src/MODULE.tools
+++ b/src/MODULE.tools
@@ -6,7 +6,7 @@
 bazel_dep(name = "rules_proto", version = "4.0.0")
 bazel_dep(name = "rules_python", version = "0.4.0")
 
-bazel_dep(name = "platforms", version = "0.0.4")
+bazel_dep(name = "platforms", version = "0.0.7")
 bazel_dep(name = "protobuf", version = "3.19.6", repo_name = "com_google_protobuf")
 bazel_dep(name = "zlib", version = "1.2.13")
 
diff --git a/src/main/java/com/google/devtools/build/docgen/templates/be/be-nav.vm b/src/main/java/com/google/devtools/build/docgen/templates/be/be-nav.vm
index 38d7385..fb745de 100644
--- a/src/main/java/com/google/devtools/build/docgen/templates/be/be-nav.vm
+++ b/src/main/java/com/google/devtools/build/docgen/templates/be/be-nav.vm
@@ -33,7 +33,7 @@
 #end
 
   <li><a href="${bazelbuildGithub}/rules_appengine" target="_blank" rel="noopener">AppEngine</a></li>
-  <li><a href="${bazelbuildGithub}/rules_apple" target="_blank" rel="noopener">Apple (Swift, iOS, macOS, tvOS, watchOS)</a></li>
+  <li><a href="${bazelbuildGithub}/rules_apple" target="_blank" rel="noopener">Apple (Swift, iOS, macOS, tvOS, visionOS, watchOS)</a></li>
   <li><a href="${bazelbuildGithub}/rules_dotnet" target="_blank" rel="noopener">C#</a></li>
   <li><a href="${bazelbuildGithub}/rules_d" target="_blank" rel="noopener">D</a></li>
   <li><a href="${bazelbuildGithub}/rules_docker" target="_blank" rel="noopener">Docker</a></li>
diff --git a/src/main/java/com/google/devtools/build/docgen/templates/be/be-toc.vm b/src/main/java/com/google/devtools/build/docgen/templates/be/be-toc.vm
index bb0d01f..3821dc6 100644
--- a/src/main/java/com/google/devtools/build/docgen/templates/be/be-toc.vm
+++ b/src/main/java/com/google/devtools/build/docgen/templates/be/be-toc.vm
@@ -20,7 +20,7 @@
     - title: AppEngine
       path: https://github.com/bazelbuild/rules_appengine
       status: external
-    - title: Apple (Swift, iOS, macOS, tvOS, watchOS)
+    - title: Apple (Swift, iOS, macOS, tvOS, visionOS, watchOS)
       path: https://github.com/bazelbuild/rules_apple
       status: external
     - title: C#
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/LocalConfigPlatformFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/LocalConfigPlatformFunction.java
index eecf41a..04907ba 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/LocalConfigPlatformFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/LocalConfigPlatformFunction.java
@@ -162,7 +162,7 @@
             "module(name = \"%s\")",
             // Try to keep this updated with the src/MODULE.tools file. (Due to MVS, even if this is
             // not kept up to date, we'll use the latest version anyhow)
-            "bazel_dep(name = \"platforms\", version = \"0.0.4\")"),
+            "bazel_dep(name = \"platforms\", version = \"0.0.7\")"),
         repositoryName);
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleCommandLineOptions.java b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleCommandLineOptions.java
index 794df22..55dc759 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleCommandLineOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleCommandLineOptions.java
@@ -192,6 +192,10 @@
   @VisibleForTesting public static final String DEFAULT_TVOS_SDK_VERSION = "9.0";
   @VisibleForTesting static final String DEFAULT_IOS_CPU = "x86_64";
 
+  /** The default visionOS CPU value. */
+  public static final String DEFAULT_VISIONOS_CPU =
+      CPU.getCurrent() == CPU.AARCH64 ? "sim_arm64" : "x86_64";
+
   /** The default watchos CPU value. */
   public static final String DEFAULT_WATCHOS_CPU =
       CPU.getCurrent() == CPU.AARCH64 ? "arm64" : "i386";
@@ -298,6 +302,16 @@
   public List<String> iosMultiCpus;
 
   @Option(
+      name = "visionos_cpus",
+      allowMultiple = true,
+      converter = CommaSeparatedOptionListConverter.class,
+      defaultValue = "null",
+      documentationCategory = OptionDocumentationCategory.OUTPUT_PARAMETERS,
+      effectTags = {OptionEffectTag.LOSES_INCREMENTAL_STATE, OptionEffectTag.LOADING_AND_ANALYSIS},
+      help = "Comma-separated list of architectures for which to build Apple visionOS binaries.")
+  public List<String> visionosCpus;
+
+  @Option(
       name = "watchos_cpus",
       allowMultiple = true,
       converter = CommaSeparatedOptionListConverter.class,
@@ -420,6 +434,10 @@
       case TVOS:
         option = tvosMinimumOs;
         break;
+      case VISIONOS:
+        // TODO: Replace with CppOptions.minimumOsVersion
+        option = DottedVersion.option(DottedVersion.fromStringUnchecked("1.0"));
+        break;
       case WATCHOS:
         option = watchosMinimumOs;
         break;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java
index dc7abdb..beb2d9f 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java
@@ -115,6 +115,10 @@
           (options.iosMultiCpus == null || options.iosMultiCpus.isEmpty())
               ? ImmutableList.of(iosCpuFromCpu(coreOptions.cpu))
               : ImmutableList.copyOf(options.iosMultiCpus);
+      ImmutableList<String> visionosCpus =
+          (options.visionosCpus == null || options.visionosCpus.isEmpty())
+              ? ImmutableList.of(AppleCommandLineOptions.DEFAULT_VISIONOS_CPU)
+              : ImmutableList.copyOf(options.visionosCpus);
       ImmutableList<String> watchosCpus =
           (options.watchosCpus == null || options.watchosCpus.isEmpty())
               ? ImmutableList.of(AppleCommandLineOptions.DEFAULT_WATCHOS_CPU)
@@ -133,13 +137,21 @@
               : ImmutableList.copyOf(options.catalystCpus);
 
       return new AutoValue_AppleConfiguration_AppleCpus(
-          appleSplitCpu, iosMultiCpus, watchosCpus, tvosCpus, macosCpus, catalystCpus);
+          appleSplitCpu,
+          iosMultiCpus,
+          visionosCpus,
+          watchosCpus,
+          tvosCpus,
+          macosCpus,
+          catalystCpus);
     }
 
     abstract String appleSplitCpu();
 
     abstract ImmutableList<String> iosMultiCpus();
 
+    abstract ImmutableList<String> visionosCpus();
+
     abstract ImmutableList<String> watchosCpus();
 
     abstract ImmutableList<String> tvosCpus();
@@ -248,6 +260,8 @@
     switch (applePlatformType) {
       case IOS:
         return appleCpus.iosMultiCpus().get(0);
+      case VISIONOS:
+        return appleCpus.visionosCpus().get(0);
       case WATCHOS:
         return appleCpus.watchosCpus().get(0);
       case TVOS:
@@ -296,6 +310,8 @@
     switch (platformType) {
       case IOS:
         return appleCpus.iosMultiCpus();
+      case VISIONOS:
+        return appleCpus.visionosCpus();
       case WATCHOS:
         return appleCpus.watchosCpus();
       case TVOS:
@@ -341,6 +357,14 @@
           }
         }
         return ApplePlatform.IOS_SIMULATOR;
+      case VISIONOS:
+        for (String arch : architectures) {
+          if (ApplePlatform.forTarget(PlatformType.VISIONOS, arch)
+              == ApplePlatform.VISIONOS_DEVICE) {
+            return ApplePlatform.VISIONOS_DEVICE;
+          }
+        }
+        return ApplePlatform.VISIONOS_SIMULATOR;
       case WATCHOS:
         for (String arch : architectures) {
           if (ApplePlatform.forTarget(PlatformType.WATCHOS, arch) == ApplePlatform.WATCHOS_DEVICE) {
@@ -500,6 +524,8 @@
     UNKNOWN("unknown"),
     /** Distinguisher for {@code apple_binary} rule with "ios" platform_type. */
     APPLEBIN_IOS("applebin_ios"),
+    /** Distinguisher for {@code apple_binary} rule with "visionos" platform_type. */
+    APPLEBIN_VISIONOS("applebin_visionos"),
     /** Distinguisher for {@code apple_binary} rule with "watchos" platform_type. */
     APPLEBIN_WATCHOS("applebin_watchos"),
     /** Distinguisher for {@code apple_binary} rule with "tvos" platform_type. */
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/ApplePlatform.java b/src/main/java/com/google/devtools/build/lib/rules/apple/ApplePlatform.java
index a050bbd..b7af54f 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/ApplePlatform.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/ApplePlatform.java
@@ -37,6 +37,8 @@
   MACOS("macos", "MacOSX", PlatformType.MACOS, true),
   TVOS_DEVICE("tvos_device", "AppleTVOS", PlatformType.TVOS, true),
   TVOS_SIMULATOR("tvos_simulator", "AppleTVSimulator", PlatformType.TVOS, false),
+  VISIONOS_DEVICE("visionos_device", "XROS", PlatformType.VISIONOS, true),
+  VISIONOS_SIMULATOR("visionos_simulator", "XRSimulator", PlatformType.VISIONOS, false),
   WATCHOS_DEVICE("watchos_device", "WatchOS", PlatformType.WATCHOS, true),
   WATCHOS_SIMULATOR("watchos_simulator", "WatchSimulator", PlatformType.WATCHOS, false),
   CATALYST("catalyst", "MacOSX", PlatformType.CATALYST, true);
@@ -45,6 +47,10 @@
       ImmutableSet.of("ios_x86_64", "ios_i386", "ios_sim_arm64");
   private static final ImmutableSet<String> IOS_DEVICE_TARGET_CPUS =
       ImmutableSet.of("ios_armv6", "ios_arm64", "ios_armv7", "ios_armv7s", "ios_arm64e");
+  private static final ImmutableSet<String> VISIONOS_SIMULATOR_TARGET_CPUS =
+      ImmutableSet.of("visionos_x86_64", "visionos_sim_arm64");
+  private static final ImmutableSet<String> VISIONOS_DEVICE_TARGET_CPUS =
+      ImmutableSet.of("visionos_arm64");
   private static final ImmutableSet<String> WATCHOS_SIMULATOR_TARGET_CPUS =
       ImmutableSet.of("watchos_i386", "watchos_x86_64", "watchos_arm64");
   private static final ImmutableSet<String> WATCHOS_DEVICE_TARGET_CPUS =
@@ -138,6 +144,10 @@
       return IOS_SIMULATOR;
     } else if (IOS_DEVICE_TARGET_CPUS.contains(targetCpu)) {
       return IOS_DEVICE;
+    } else if (VISIONOS_SIMULATOR_TARGET_CPUS.contains(targetCpu)) {
+      return VISIONOS_SIMULATOR;
+    } else if (VISIONOS_DEVICE_TARGET_CPUS.contains(targetCpu)) {
+      return VISIONOS_DEVICE;
     } else if (WATCHOS_SIMULATOR_TARGET_CPUS.contains(targetCpu)) {
       return WATCHOS_SIMULATOR;
     } else if (WATCHOS_DEVICE_TARGET_CPUS.contains(targetCpu)) {
@@ -245,6 +255,7 @@
   @Immutable
   public enum PlatformType implements ApplePlatformTypeApi {
     IOS("ios"),
+    VISIONOS("visionos"),
     WATCHOS("watchos"),
     TVOS("tvos"),
     MACOS("macos"),
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleToolchain.java b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleToolchain.java
index d042ab8..241a7ec 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleToolchain.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleToolchain.java
@@ -114,6 +114,8 @@
         }
         break;
       case MACOS:
+      case VISIONOS_DEVICE:
+      case VISIONOS_SIMULATOR:
       case WATCHOS_DEVICE:
       case WATCHOS_SIMULATOR:
       case TVOS_DEVICE:
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 5df2422..b2ed13f 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
@@ -126,6 +126,9 @@
         (appleOptions.iosMinimumOs != null)
             ? DottedVersion.maybeUnwrap(appleOptions.iosMinimumOs)
             : iosSdkVersion;
+    DottedVersion visionosSdkVersion = xcodeVersionProperties.getDefaultVisionosSdkVersion();
+    // TODO: Replace with CppOptions.minimumOsVersion
+    DottedVersion visionosMinimumOsVersion = DottedVersion.fromStringUnchecked("1.0");
     DottedVersion watchosSdkVersion =
         (appleOptions.watchOsSdkVersion != null)
             ? DottedVersion.maybeUnwrap(appleOptions.watchOsSdkVersion)
@@ -155,6 +158,8 @@
         new XcodeConfigInfo(
             iosSdkVersion,
             iosMinimumOsVersion,
+            visionosSdkVersion,
+            visionosMinimumOsVersion,
             watchosSdkVersion,
             watchosMinimumOsVersion,
             tvosSdkVersion,
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfigInfo.java b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfigInfo.java
index e569236..d4ce9fb 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfigInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfigInfo.java
@@ -39,6 +39,8 @@
 
   private final DottedVersion iosSdkVersion;
   private final DottedVersion iosMinimumOsVersion;
+  private final DottedVersion visionosSdkVersion;
+  private final DottedVersion visionosMinimumOsVersion;
   private final DottedVersion watchosSdkVersion;
   private final DottedVersion watchosMinimumOsVersion;
   private final DottedVersion tvosSdkVersion;
@@ -52,6 +54,8 @@
   public XcodeConfigInfo(
       DottedVersion iosSdkVersion,
       DottedVersion iosMinimumOsVersion,
+      DottedVersion visionosSdkVersion,
+      DottedVersion visionosMinimumOsVersion,
       DottedVersion watchosSdkVersion,
       DottedVersion watchosMinimumOsVersion,
       DottedVersion tvosSdkVersion,
@@ -64,6 +68,8 @@
       boolean includeXcodeReqs) {
     this.iosSdkVersion = Preconditions.checkNotNull(iosSdkVersion);
     this.iosMinimumOsVersion = Preconditions.checkNotNull(iosMinimumOsVersion);
+    this.visionosSdkVersion = Preconditions.checkNotNull(visionosSdkVersion);
+    this.visionosMinimumOsVersion = Preconditions.checkNotNull(visionosMinimumOsVersion);
     this.watchosSdkVersion = Preconditions.checkNotNull(watchosSdkVersion);
     this.watchosMinimumOsVersion = Preconditions.checkNotNull(watchosMinimumOsVersion);
     this.tvosSdkVersion = Preconditions.checkNotNull(tvosSdkVersion);
@@ -135,6 +141,8 @@
     public XcodeConfigInfoApi<?, ?> xcodeConfigInfo(
         String iosSdkVersion,
         String iosMinimumOsVersion,
+        String visionosSdkVersion,
+        String visionosMinimumOsVersion,
         String watchosSdkVersion,
         String watchosMinimumOsVersion,
         String tvosSdkVersion,
@@ -147,6 +155,8 @@
         return new XcodeConfigInfo(
             DottedVersion.fromString(iosSdkVersion),
             DottedVersion.fromString(iosMinimumOsVersion),
+            DottedVersion.fromString(visionosSdkVersion),
+            DottedVersion.fromString(visionosMinimumOsVersion),
             DottedVersion.fromString(watchosSdkVersion),
             DottedVersion.fromString(watchosMinimumOsVersion),
             DottedVersion.fromString(tvosSdkVersion),
@@ -195,6 +205,9 @@
         return iosMinimumOsVersion;
       case TVOS:
         return tvosMinimumOsVersion;
+      case VISIONOS:
+        // TODO: Replace with CppOptions.minimumOsVersion
+        return DottedVersion.fromStringUnchecked("1.0");
       case WATCHOS:
         return watchosMinimumOsVersion;
       case MACOS:
@@ -216,6 +229,9 @@
       case TVOS_DEVICE:
       case TVOS_SIMULATOR:
         return tvosSdkVersion;
+      case VISIONOS_DEVICE:
+      case VISIONOS_SIMULATOR:
+        return visionosSdkVersion;
       case WATCHOS_DEVICE:
       case WATCHOS_SIMULATOR:
         return watchosSdkVersion;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionProperties.java b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionProperties.java
index f3e6e39..22410e9 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionProperties.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionProperties.java
@@ -36,12 +36,14 @@
       new BuiltinProvider<XcodeVersionProperties>(STARLARK_NAME, XcodeVersionProperties.class) {};
 
   @VisibleForTesting public static final String DEFAULT_IOS_SDK_VERSION = "8.4";
+  @VisibleForTesting public static final String DEFAULT_VISIONOS_SDK_VERSION = "1.0";
   @VisibleForTesting public static final String DEFAULT_WATCHOS_SDK_VERSION = "2.0";
   @VisibleForTesting public static final String DEFAULT_MACOS_SDK_VERSION = "10.11";
   @VisibleForTesting public static final String DEFAULT_TVOS_SDK_VERSION = "9.0";
 
   private final Optional<DottedVersion> xcodeVersion;
   private final DottedVersion defaultIosSdkVersion;
+  private final DottedVersion defaultVisionosSdkVersion;
   private final DottedVersion defaultWatchosSdkVersion;
   private final DottedVersion defaultTvosSdkVersion;
   private final DottedVersion defaultMacosSdkVersion;
@@ -63,7 +65,7 @@
    * specified.
    */
   XcodeVersionProperties(DottedVersion xcodeVersion) {
-    this(xcodeVersion, null, null, null, null);
+    this(xcodeVersion, null, null, null, null, null);
   }
 
   /**
@@ -73,6 +75,7 @@
   XcodeVersionProperties(
       DottedVersion xcodeVersion,
       @Nullable String defaultIosSdkVersion,
+      @Nullable String defaultVisionosSdkVersion,
       @Nullable String defaultWatchosSdkVersion,
       @Nullable String defaultTvosSdkVersion,
       @Nullable String defaultMacosSdkVersion) {
@@ -81,6 +84,10 @@
         Strings.isNullOrEmpty(defaultIosSdkVersion)
             ? DottedVersion.fromStringUnchecked(DEFAULT_IOS_SDK_VERSION)
             : DottedVersion.fromStringUnchecked(defaultIosSdkVersion);
+    this.defaultVisionosSdkVersion =
+        Strings.isNullOrEmpty(defaultVisionosSdkVersion)
+            ? DottedVersion.fromStringUnchecked(DEFAULT_VISIONOS_SDK_VERSION)
+            : DottedVersion.fromStringUnchecked(defaultVisionosSdkVersion);
     this.defaultWatchosSdkVersion =
         Strings.isNullOrEmpty(defaultWatchosSdkVersion)
             ? DottedVersion.fromStringUnchecked(DEFAULT_WATCHOS_SDK_VERSION)
@@ -117,6 +124,13 @@
     return defaultIosSdkVersion != null ? defaultIosSdkVersion.toString() : null;
   }
 
+  /** Returns the default visionOS sdk version to use if this xcode version is in use. */
+  @Nullable
+  @Override
+  public String getDefaultVisionosSdkVersionString() {
+    return defaultVisionosSdkVersion != null ? defaultVisionosSdkVersion.toString() : null;
+  }
+
   /** Returns the default watchos sdk version to use if this xcode version is in use. */
   @Nullable
   @Override
@@ -149,6 +163,11 @@
   }
 
   @Nullable
+  public DottedVersion getDefaultVisionosSdkVersion() {
+    return defaultVisionosSdkVersion;
+  }
+
+  @Nullable
   public DottedVersion getDefaultWatchosSdkVersion() {
     return defaultWatchosSdkVersion;
   }
@@ -174,6 +193,7 @@
     XcodeVersionProperties otherData = (XcodeVersionProperties) other;
     return xcodeVersion.equals(otherData.getXcodeVersion())
         && defaultIosSdkVersion.equals(otherData.getDefaultIosSdkVersion())
+        && defaultVisionosSdkVersion.equals(otherData.getDefaultVisionosSdkVersion())
         && defaultWatchosSdkVersion.equals(otherData.getDefaultWatchosSdkVersion())
         && defaultTvosSdkVersion.equals(otherData.getDefaultTvosSdkVersion())
         && defaultMacosSdkVersion.equals(otherData.getDefaultMacosSdkVersion());
@@ -184,6 +204,7 @@
     return Objects.hash(
         xcodeVersion,
         defaultIosSdkVersion,
+        defaultVisionosSdkVersion,
         defaultWatchosSdkVersion,
         defaultTvosSdkVersion,
         defaultMacosSdkVersion);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionRule.java b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionRule.java
index 41609a3..e813fa0 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionRule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionRule.java
@@ -31,6 +31,7 @@
   static final String VERSION_ATTR_NAME = "version";
   static final String ALIASES_ATTR_NAME = "aliases";
   static final String DEFAULT_IOS_SDK_VERSION_ATTR_NAME = "default_ios_sdk_version";
+  static final String DEFAULT_VISIONOS_SDK_VERSION_ATTR_NAME = "default_visionos_sdk_version";
   static final String DEFAULT_WATCHOS_SDK_VERSION_ATTR_NAME = "default_watchos_sdk_version";
   static final String DEFAULT_TVOS_SDK_VERSION_ATTR_NAME = "default_tvos_sdk_version";
   static final String DEFAULT_MACOS_SDK_VERSION_ATTR_NAME = "default_macos_sdk_version";
@@ -64,6 +65,13 @@
         .add(
             attr(DEFAULT_IOS_SDK_VERSION_ATTR_NAME, STRING)
                 .nonconfigurable("this rule determines configuration"))
+        /* <!-- #BLAZE_RULE(xcode_version).ATTRIBUTE(default_visionos_sdk_version) -->
+        The visionos sdk version that is used by default when this version of xcode is being used.
+        The <code>visionos_sdk_version</code> build flag will override the value specified here.
+        <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
+        .add(
+            attr(DEFAULT_VISIONOS_SDK_VERSION_ATTR_NAME, STRING)
+                .nonconfigurable("this rule determines configuration"))
         /* <!-- #BLAZE_RULE(xcode_version).ATTRIBUTE(default_watchos_sdk_version) -->
         The watchos sdk version that is used by default when this version of xcode is being used.
         The <code>watchos_sdk_version</code> build flag will override the value specified here.
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionRuleData.java b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionRuleData.java
index ff8cc35..2662659 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionRuleData.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionRuleData.java
@@ -52,6 +52,8 @@
             attrMapper.get(XcodeVersionRule.VERSION_ATTR_NAME, Type.STRING));
     String iosSdkVersionString =
         attrMapper.get(XcodeVersionRule.DEFAULT_IOS_SDK_VERSION_ATTR_NAME, Type.STRING);
+    String visionosSdkVersionString =
+        attrMapper.get(XcodeVersionRule.DEFAULT_VISIONOS_SDK_VERSION_ATTR_NAME, Type.STRING);
     String watchosSdkVersionString =
         attrMapper.get(XcodeVersionRule.DEFAULT_WATCHOS_SDK_VERSION_ATTR_NAME, Type.STRING);
     String tvosSdkVersionString =
@@ -63,6 +65,7 @@
         new XcodeVersionProperties(
             xcodeVersion,
             iosSdkVersionString,
+            visionosSdkVersionString,
             watchosSdkVersionString,
             tvosSdkVersionString,
             macosxSdkVersionString);
@@ -115,6 +118,9 @@
             .getDefaultIosSdkVersion()
             .equals(otherData.getXcodeVersionProperties().getDefaultIosSdkVersion())
         && xcodeVersionProperties
+            .getDefaultVisionosSdkVersion()
+            .equals(otherData.getXcodeVersionProperties().getDefaultVisionosSdkVersion())
+        && xcodeVersionProperties
             .getDefaultWatchosSdkVersion()
             .equals(otherData.getXcodeVersionProperties().getDefaultWatchosSdkVersion())
         && xcodeVersionProperties
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java
index ed50433..f991a68 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java
@@ -134,7 +134,8 @@
           "-fexceptions", "-fasm-blocks", "-fobjc-abi-version=2", "-fobjc-legacy-dispatch");
 
   /**
-   * Frameworks implicitly linked to iOS, watchOS, and tvOS binaries when using legacy compilation.
+   * Frameworks implicitly linked to iOS, visionOS, watchOS, and tvOS binaries when using legacy
+   * compilation.
    */
   @VisibleForTesting
   static final NestedSet<String> AUTOMATIC_SDK_FRAMEWORKS =
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/MultiArchBinarySupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/MultiArchBinarySupport.java
index a407517..ff636f9 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/MultiArchBinarySupport.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/MultiArchBinarySupport.java
@@ -251,6 +251,8 @@
         return ConfigurationDistinguisher.APPLEBIN_IOS;
       case CATALYST:
         return ConfigurationDistinguisher.APPLEBIN_CATALYST;
+      case VISIONOS:
+        return ConfigurationDistinguisher.APPLEBIN_VISIONOS;
       case WATCHOS:
         return ConfigurationDistinguisher.APPLEBIN_WATCHOS;
       case TVOS:
@@ -286,6 +288,10 @@
       case CATALYST:
         option = buildOptions.get(AppleCommandLineOptions.class).iosMinimumOs;
         break;
+      case VISIONOS:
+        // TODO: Replace with CppOptions.minimumOsVersion
+        option = DottedVersion.option(DottedVersion.fromStringUnchecked("1.0"));
+        break;
       case WATCHOS:
         option = buildOptions.get(AppleCommandLineOptions.class).watchosMinimumOs;
         break;
@@ -333,6 +339,9 @@
       case MACOS:
         appleCommandLineOptions.macosMinimumOs = minimumOsVersionOption;
         break;
+      case VISIONOS:
+        // TODO: use CppOptions.minimumOsVersion
+        break;
     }
     return splitOptions;
   }
@@ -461,6 +470,13 @@
         }
         cpus = supportedAppleCpusFromMinimumOs(minimumOsVersionOption, cpus, platformType);
         break;
+      case VISIONOS:
+        cpus = buildOptions.get(AppleCommandLineOptions.class).visionosCpus;
+        if (cpus.isEmpty()) {
+          cpus = ImmutableList.of(AppleCommandLineOptions.DEFAULT_VISIONOS_CPU);
+        }
+        cpus = supportedAppleCpusFromMinimumOs(minimumOsVersionOption, cpus, platformType);
+        break;
       case WATCHOS:
         cpus = buildOptions.get(AppleCommandLineOptions.class).watchosCpus;
         if (cpus.isEmpty()) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java
index 4b3e044..946b3fb 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java
@@ -207,8 +207,8 @@
       return builder
           /* <!-- #BLAZE_RULE($objc_sdk_frameworks_depender_rule).ATTRIBUTE(sdk_frameworks) -->
           Names of SDK frameworks to link with (e.g. "AddressBook", "QuartzCore"). "UIKit" and
-          "Foundation" are always included when building for the iOS, tvOS and watchOS platforms.
-          For macOS, only "Foundation" is always included.
+          "Foundation" are always included when building for the iOS, tvOS, visionOS,
+          and watchOS platforms. For macOS, only "Foundation" is always included.
 
           <p> When linking a top level Apple binary, all SDK frameworks listed in that binary's
           transitive dependency graph are linked.
diff --git a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/apple/ApplePlatformTypeApi.java b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/apple/ApplePlatformTypeApi.java
index e110ad9..54edcfe 100644
--- a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/apple/ApplePlatformTypeApi.java
+++ b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/apple/ApplePlatformTypeApi.java
@@ -23,7 +23,7 @@
     name = "apple_platform_type",
     category = DocCategory.BUILTIN,
     doc =
-        "Describes an Apple \"platform type\", such as iOS, macOS, tvOS, or watchOS. This is"
+        "Describes an Apple \"platform type\", such as iOS, macOS, tvOS, visionOS, or watchOS. This is"
             + " distinct from a \"platform\", which is the platform type combined with one or more"
             + " CPU architectures.<p>Specific instances of this type can be retrieved by accessing"
             + " the fields of the <a"
@@ -31,6 +31,7 @@
             + "<li><code>apple_common.platform_type.ios</code></li>"
             + "<li><code>apple_common.platform_type.macos</code></li>"
             + "<li><code>apple_common.platform_type.tvos</code></li>"
+            + "<li><code>apple_common.platform_type.visionos</code></li>"
             + "<li><code>apple_common.platform_type.watchos</code></li></ul><p>Likewise, the"
             + " platform type of an existing platform value can be retrieved using its"
             + " <code>platform_type</code> field.<p>Platform types can be converted to a lowercase"
diff --git a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/apple/XcodeConfigInfoApi.java b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/apple/XcodeConfigInfoApi.java
index 781b5aa..8229f03 100644
--- a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/apple/XcodeConfigInfoApi.java
+++ b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/apple/XcodeConfigInfoApi.java
@@ -104,6 +104,16 @@
               positional = false,
               doc = "The ios minimum os version."),
           @Param(
+              name = "visionosSdkVersion",
+              named = true,
+              positional = false,
+              doc = "The visionOS SDK version."),
+          @Param(
+              name = "visionosMinimumOsVersion",
+              named = true,
+              positional = false,
+              doc = "The visionOS minimum os version."),
+          @Param(
               name = "watchosSdkVersion",
               named = true,
               positional = false,
@@ -144,6 +154,8 @@
     XcodeConfigInfoApi<?, ?> xcodeConfigInfo(
         String iosSdkVersion,
         String iosMinimumOsVersion,
+        String visionosSdkVersion,
+        String visionosMinimumOsVersion,
         String watchosSdkVersion,
         String watchosMinimumOsVersion,
         String tvosSdkVersion,
diff --git a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/apple/XcodePropertiesApi.java b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/apple/XcodePropertiesApi.java
index 4ad4b56..bedfbb4 100644
--- a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/apple/XcodePropertiesApi.java
+++ b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/apple/XcodePropertiesApi.java
@@ -46,6 +46,16 @@
   String getDefaultIosSdkVersionString();
 
   @StarlarkMethod(
+      name = "default_visionos_sdk_version",
+      doc =
+          "The default visionOS sdk version for this version of xcode, or <code>None</code> if "
+              + "unknown.",
+      structField = true,
+      allowReturnNones = true)
+  @Nullable
+  String getDefaultVisionosSdkVersionString();
+
+  @StarlarkMethod(
       name = "default_watchos_sdk_version",
       doc =
           "The default watchOS sdk version for this version of xcode, or <code>None</code> if "
diff --git a/src/main/starlark/builtins_bzl/common/cc/cc_binary.bzl b/src/main/starlark/builtins_bzl/common/cc/cc_binary.bzl
index 4beca92..a657498 100644
--- a/src/main/starlark/builtins_bzl/common/cc/cc_binary.bzl
+++ b/src/main/starlark/builtins_bzl/common/cc/cc_binary.bzl
@@ -33,6 +33,8 @@
 
 _IOS_SIMULATOR_TARGET_CPUS = ["ios_x86_64", "ios_i386", "ios_sim_arm64"]
 _IOS_DEVICE_TARGET_CPUS = ["ios_armv6", "ios_arm64", "ios_armv7", "ios_armv7s", "ios_arm64e"]
+_VISIONOS_SIMULATOR_TARGET_CPUS = ["visionos_x86_64", "visionos_sim_arm64"]
+_VISIONOS_DEVICE_TARGET_CPUS = ["visionos_arm64"]
 _WATCHOS_SIMULATOR_TARGET_CPUS = ["watchos_i386", "watchos_x86_64", "watchos_arm64"]
 _WATCHOS_DEVICE_TARGET_CPUS = ["watchos_armv7k", "watchos_arm64_32"]
 _TVOS_SIMULATOR_TARGET_CPUS = ["tvos_x86_64", "tvos_sim_arm64"]
@@ -555,7 +557,7 @@
         fail("The selected toolchain does not support setting --grte_top (it doesn't specify builtin_sysroot).")
 
 def _is_apple_platform(target_cpu):
-    if target_cpu in _IOS_SIMULATOR_TARGET_CPUS or target_cpu in _IOS_DEVICE_TARGET_CPUS or target_cpu in _WATCHOS_SIMULATOR_TARGET_CPUS or target_cpu in _WATCHOS_DEVICE_TARGET_CPUS or target_cpu in _TVOS_SIMULATOR_TARGET_CPUS or target_cpu in _TVOS_DEVICE_TARGET_CPUS or target_cpu in _CATALYST_TARGET_CPUS or target_cpu in _MACOS_TARGET_CPUS:
+    if target_cpu in _IOS_SIMULATOR_TARGET_CPUS or target_cpu in _IOS_DEVICE_TARGET_CPUS or target_cpu in _VISIONOS_SIMULATOR_TARGET_CPUS or target_cpu in _VISIONOS_DEVICE_TARGET_CPUS or target_cpu in _WATCHOS_SIMULATOR_TARGET_CPUS or target_cpu in _WATCHOS_DEVICE_TARGET_CPUS or target_cpu in _TVOS_SIMULATOR_TARGET_CPUS or target_cpu in _TVOS_DEVICE_TARGET_CPUS or target_cpu in _CATALYST_TARGET_CPUS or target_cpu in _MACOS_TARGET_CPUS:
         return True
     return False
 
diff --git a/src/main/starlark/builtins_bzl/common/objc/transitions.bzl b/src/main/starlark/builtins_bzl/common/objc/transitions.bzl
index 88aec6d..f886f59 100644
--- a/src/main/starlark/builtins_bzl/common/objc/transitions.bzl
+++ b/src/main/starlark/builtins_bzl/common/objc/transitions.bzl
@@ -37,6 +37,14 @@
         if cpu_value == "darwin_arm64":
             return "sim_arm64"
         return DEFAULT_IOS_CPU
+    if platform_type == VISIONOS:
+        cpus = settings["//command_line_option:visionos_cpus"]
+        if len(cpus) > 0:
+            return cpus[0]
+        cpu_value = settings["//command_line_option:cpu"]
+        if cpu_value == "darwin_arm64":
+            return "sim_arm64"
+        return DEFAULT_VISIONOS_CPU
     if platform_type == WATCHOS:
         watchos_cpus = settings["//command_line_option:watchos_cpus"]
         if len(watchos_cpus) == 0:
@@ -64,13 +72,16 @@
     fail("ERROR: Unhandled platform type {}".format(platform_type))
 
 IOS = "ios"
+VISIONOS = "visionos"
 WATCHOS = "watchos"
 TVOS = "tvos"
 MACOS = "macos"
 CATALYST = "catalyst"
 IOS_CPU_PREFIX = "ios_"
+VISIONOS_CPU_PREFIX = "visionos_"
 DARWIN_CPU_PREFIX = "darwin_"
 DEFAULT_IOS_CPU = "x86_64"
+DEFAULT_VISIONOS_CPU = "x86_64"
 DEFAULT_WATCHOS_CPU = "i386"
 DEFAULT_TVOS_CPU = "x86_64"
 DEFAULT_MACOS_CPU = "x86_64"
@@ -122,6 +133,7 @@
     "//command_line_option:ios_multi_cpus",
     "//command_line_option:macos_cpus",
     "//command_line_option:tvos_cpus",
+    "//command_line_option:visionos_cpus",
     "//command_line_option:watchos_cpus",
     "//command_line_option:catalyst_cpus",
     "//command_line_option:platforms",
diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/MockPlatformSupport.java b/src/test/java/com/google/devtools/build/lib/packages/util/MockPlatformSupport.java
index ec3d6f2..b657474 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/util/MockPlatformSupport.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/util/MockPlatformSupport.java
@@ -112,6 +112,10 @@
         "    constraint_setting = ':os',",
         ")",
         "constraint_value(",
+        "    name = 'visionos',",
+        "    constraint_setting = ':os',",
+        ")",
+        "constraint_value(",
         "    name = 'watchos',",
         "    constraint_setting = ':os',",
         ")",
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 51ea58b..cd41a80 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
@@ -445,7 +445,9 @@
             + " tvosMinimumOsVersion='1.6',"
             + " macosSdkVersion='1.7',"
             + " macosMinimumOsVersion='1.8',"
-            + " xcodeVersion='1.9'))]",
+            + " visionosSdkVersion='1.9',"
+            + " visionosMinimumOsVersion='1.10',"
+            + " xcodeVersion='1.11'))]",
         "my_rule = rule(_impl, attrs = { 'dep' : attr.label() })");
     scratch.file("foo/BUILD", "load(':extension.bzl', 'my_rule')", "my_rule(name='test')");
     assertNoEvents();
@@ -466,6 +468,8 @@
                 DottedVersion.fromStringUnchecked("1.7"),
                 DottedVersion.fromStringUnchecked("1.8"),
                 DottedVersion.fromStringUnchecked("1.9"),
+                DottedVersion.fromStringUnchecked("1.10"),
+                DottedVersion.fromStringUnchecked("1.11"),
                 XcodeConfigInfo.Availability.UNKNOWN,
                 /** xcodeVersionFlagValue= */
                 "",
@@ -489,7 +493,9 @@
             + " tvosMinimumOsVersion='1.6',"
             + " macosSdkVersion='1.7',"
             + " macosMinimumOsVersion='1.8',"
-            + " xcodeVersion='1.9'))]",
+            + " visionosSdkVersion='1.9',"
+            + " visionosMinimumOsVersion='1.10',"
+            + " xcodeVersion='1.11'))]",
         "my_rule = rule(_impl, attrs = { 'dep' : attr.label() })");
     scratch.file("foo/BUILD", "load(':extension.bzl', 'my_rule')", "my_rule(name='test')");
     assertNoEvents();
@@ -509,12 +515,14 @@
             + " iosSdkVersion='1.1',"
             + " iosMinimumOsVersion='1.2',"
             + " watchosSdkVersion='1.3',"
-            + " watchosMinimumOsVersion='1.4',"
+            + " watchosMinimumOsVersion='2.4',"
             + " tvosSdkVersion='1.5',"
             + " tvosMinimumOsVersion='1.6',"
             + " macosSdkVersion='1.7',"
             + " macosMinimumOsVersion='1.8',"
-            + " xcodeVersion='1.9')",
+            + " visionosSdkVersion='1.9',"
+            + " visionosMinimumOsVersion='1.10',"
+            + " xcodeVersion='1.11')",
         "  return [result(xcode_version=xcode_version.xcode_version(),"
             + "min_os=xcode_version.minimum_os_for_platform_type(ctx.fragments.apple.single_arch_platform.platform_type)),]",
         "my_rule = rule(_impl, attrs = { 'dep' : attr.label() },  fragments = ['apple'])");
@@ -525,7 +533,7 @@
         (StructImpl)
             myRuleTarget.get(
                 new StarlarkProvider.Key(Label.parseCanonical("//foo:extension.bzl"), "result"));
-    assertThat(info.getValue("xcode_version").toString()).isEqualTo("1.9");
+    assertThat(info.getValue("xcode_version").toString()).isEqualTo("1.11");
     assertThat(info.getValue("min_os").toString()).isEqualTo("1.8");
   }
 
diff --git a/src/test/shell/bazel/android/android_integration_test.sh b/src/test/shell/bazel/android/android_integration_test.sh
index a61fa6f..776a40d 100755
--- a/src/test/shell/bazel/android/android_integration_test.sh
+++ b/src/test/shell/bazel/android/android_integration_test.sh
@@ -232,7 +232,7 @@
 EOF
   cat > MODULE.bazel << 'EOF'
 # Required for android_integration_test_with_platforms
-bazel_dep(name = "platforms", version = "0.0.5")
+bazel_dep(name = "platforms", version = "0.0.7")
 EOF
 
   bazel clean
diff --git a/tools/osx/BUILD b/tools/osx/BUILD
index 7934465..2a0f442 100644
--- a/tools/osx/BUILD
+++ b/tools/osx/BUILD
@@ -3,6 +3,7 @@
     "ios_sdk_version_flag",
     "macos_sdk_version_flag",
     "tvos_sdk_version_flag",
+    "visionos_sdk_version_flag",
     "watchos_sdk_version_flag",
     "xcode_version_flag",
 )
@@ -100,6 +101,8 @@
 
 tvos_sdk_version_flag(name = "tvos_sdk_version_flag")
 
+visionos_sdk_version_flag(name = "visionos_sdk_version_flag")
+
 watchos_sdk_version_flag(name = "watchos_sdk_version_flag")
 
 macos_sdk_version_flag(name = "macos_sdk_version_flag")
diff --git a/tools/osx/xcode_configure.bzl b/tools/osx/xcode_configure.bzl
index e8b7499..e9c4152 100644
--- a/tools/osx/xcode_configure.bzl
+++ b/tools/osx/xcode_configure.bzl
@@ -71,6 +71,7 @@
     ios_sdk_version = _search_sdk_output(xcodebuild_result.stdout, "iphoneos")
     tvos_sdk_version = _search_sdk_output(xcodebuild_result.stdout, "appletvos")
     macos_sdk_version = _search_sdk_output(xcodebuild_result.stdout, "macosx")
+    visionos_sdk_version = _search_sdk_output(xcodebuild_result.stdout, "xros")
     watchos_sdk_version = _search_sdk_output(xcodebuild_result.stdout, "watchos")
     build_contents += "xcode_version(\n  name = '%s'," % name
     build_contents += "\n  version = '%s'," % version
@@ -82,6 +83,8 @@
         build_contents += "\n  default_tvos_sdk_version = '%s'," % tvos_sdk_version
     if macos_sdk_version:
         build_contents += "\n  default_macos_sdk_version = '%s'," % macos_sdk_version
+    if visionos_sdk_version:
+        build_contents += "\n  default_visionos_sdk_version = '%s'," % visionos_sdk_version
     if watchos_sdk_version:
         build_contents += "\n  default_watchos_sdk_version = '%s'," % watchos_sdk_version
     build_contents += "\n)\n"
diff --git a/tools/osx/xcode_version_flag.bzl b/tools/osx/xcode_version_flag.bzl
index a7ede5f..1578a73 100644
--- a/tools/osx/xcode_version_flag.bzl
+++ b/tools/osx/xcode_version_flag.bzl
@@ -98,6 +98,16 @@
         ),
     ))
 
+def _visionos_sdk_version_flag_impl(ctx):
+    """A rule that allows select() to select based on the visionOS SDK version."""
+    xcode_config = ctx.attr._xcode_config[apple_common.XcodeVersionConfig]
+
+    return config_common.FeatureFlagInfo(value = _strip_version(
+        xcode_config.sdk_version_for_platform(
+            apple_common.platform.visionos_device,
+        ),
+    ))
+
 def _watchos_sdk_version_flag_impl(ctx):
     """A rule that allows select() to select based on the watchOS SDK version."""
     xcode_config = ctx.attr._xcode_config[apple_common.XcodeVersionConfig]
@@ -200,6 +210,16 @@
     },
 )
 
+visionos_sdk_version_flag = rule(
+    implementation = _visionos_sdk_version_flag_impl,
+    attrs = {
+        "_xcode_config": attr.label(default = configuration_field(
+            fragment = "apple",
+            name = "xcode_config_label",
+        )),
+    },
+)
+
 watchos_sdk_version_flag = rule(
     implementation = _watchos_sdk_version_flag_impl,
     attrs = {