Repository: bazelbuild/bazel
Issue: Cycle error when --platforms is not a platform
Labels: type: bug
P1
team-Configurability

### Description of the problem / feature request:

If you try to use a number of things as a platform, you get a massive garbage error from the cycle detector.

Examples include:
* `sh_binary`
* `rust_binary`
* `config_setting`

### Bugs: what's the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.

This can be reproduced in the repo at https://github.com/m3rcuriel/bazel/tree/cycle_repro by running `bazel build //... --platforms=//:garbage` or even `bazel build //... --platforms=//:test`.

### What operating system are you running Bazel on?

5.3.7.b-3-hardened #1 SMP PREEMPT @1572019254 x86_64 GNU/Linux

### What's the output of `bazel info release`?

`release 0.29.1- (@non-git)`

### If `bazel info release` returns "development version" or "(@non-git)", tell us how you built Bazel.

This version comes from the AUR. Also fails with bazel HEAD (11/20/19) built with the bazel from AUR.

### What's the output of `git remote get-url origin ; git rev-parse master ; git rev-parse HEAD` ?

```
git@github.com:bazelbuild/bazel
2b7e21db100bdc0bd319f37106ed3d9e7c8dbe74
2b7e21db100bdc0bd319f37106ed3d9e7c8dbe74
```

###  Have you found anything relevant by searching the web?

Inspired by https://github.com/bazelbuild/rules_rust/issues/267.


Issue comments:

Pull request review comments:
Is this commented out code intentional? If yes please include a TODO explaining its purpose.
I initially added it, then realized it changes semantics and broke tests, and forgot to completely remove. Now it's really gone.

Patch that resolved the issue:
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/PlatformConfiguration.java b/src/main/java/com/google/devtools/build/lib/analysis/PlatformConfiguration.java
index 756fb44b1e1e1c..12344564ede28c 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/PlatformConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/PlatformConfiguration.java
@@ -16,8 +16,11 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.analysis.config.BuildOptions;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.concurrent.ThreadSafety;
+import com.google.devtools.build.lib.events.Event;
+import com.google.devtools.build.lib.events.EventHandler;
 import com.google.devtools.build.lib.skylarkbuildapi.platform.PlatformConfigurationApi;
 import com.google.devtools.build.lib.util.RegexFilter;
 import java.util.List;
@@ -49,6 +52,19 @@ public class PlatformConfiguration extends BuildConfiguration.Fragment
     this.targetFilterToAdditionalExecConstraints = targetFilterToAdditionalExecConstraints;
   }
 
+  @Override
+  public void reportInvalidOptions(EventHandler reporter, BuildOptions buildOptions) {
+    PlatformOptions platformOptions = buildOptions.get(PlatformOptions.class);
+    // TODO(https://github.com/bazelbuild/bazel/issues/6519): Implement true multiplatform builds.
+    if (platformOptions.platforms.size() > 1) {
+      reporter.handle(
+          Event.warn(
+              String.format(
+                  "--platforms only supports a single target platform: using the first option %s",
+                  this.targetPlatform)));
+    }
+  }
+
   @Override
   public Label getHostPlatform() {
     return hostPlatform;
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PlatformMappingValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/PlatformMappingValue.java
index 151068e997b4d7..d4d6de299c64e2 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/PlatformMappingValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PlatformMappingValue.java
@@ -210,12 +210,8 @@ private BuildConfigurationValue.Key computeMapping(
     if (!originalOptions.get(PlatformOptions.class).platforms.isEmpty()) {
       List<Label> platforms = originalOptions.get(PlatformOptions.class).platforms;
 
-      Preconditions.checkArgument(
-          platforms.size() == 1,
-          "Platform mapping only supports a single target platform but found %s",
-          platforms);
-
-      Label targetPlatform = Iterables.getOnlyElement(platforms);
+      // Platform mapping only supports a single target platform, others are ignored.
+      Label targetPlatform = Iterables.getFirst(platforms, null);
       if (!platformsToFlags.containsKey(targetPlatform)) {
         // This can happen if the user has set the platform and any other flags that would normally
         // be mapped from it on the command line instead of relying on the mapping.


Test patch: