-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add basic incompatible target skipping support
This patch aims to implement a basic version of incompatible target skipping outlined here: https://docs.google.com/document/d/12n5QNHmFSkuh5yAbdEex64ot4hRgR-moL1zRimU7wHQ/edit?usp=sharing The implementation in this patch supports target skipping based on the target platform. In a `BUILD` file you can now add constraints that the target platform must satisfy in order for the target to be built and/or tested. For example, use the following snippet to declare a target to be compatible with Windows platforms only: cc_binary( name = "bin", srcs = ["bin.cc"], target_compatible_with = [ "@platforms//os:windows", ], ) Builds triggered with `:all` or `...` on a non-Windows platform will simply skip the incompatible target. An appropriate note is shown on the command line if the `--show_result` threshold is high enough. Targets that transitively depend on incompatible targets are themselves considered incompatible and will also be skipped. Explicitly requesting an incompatible target on the command line is an error and will cause the build to fail. Bazel will print out an appropriate error message and inform the user what constraint could not be satisfied. See the new documentation in this patch for more information. In particular, https://docs.bazel.build/versions/master/platforms.html should be a good bit more informative. This implementation does not make any effort to support expressing compatibility with toolchains. It is possible that using `select()` (commented on below) already makes this possible, but it's not validated or explicitly supported in this patch. During implementation we noticed that `select()` can be quite powerful in combination with `target_compatible_with`. A basic summary of this is also documented on the Platforms page. It may be useful to create helper functions in, say, skylib to help make complex `select()` statements more readable. For example, we could replace the following: target_compatible_with = select({ "@platforms//os:linux": [], "@platforms//os:macos": [], "//conditions:default": [":not_compatible"], }) with something like: target_compatible_with = constraints.any_of([ "@platforms//os:linux", "@platforms//os:macos", ]) That, however, is work for follow-up patches. Many thanks to Austin Schuh (@AustinSchuh) and Greg Estren (@gregestren) for working on the proposal and helping a ton on this patch itself. Also thanks to many others who provided feedback on the implementation. RELNOTES: Bazel skips incompatible targets based on target platform and `target_compatible_with` contents. See https://docs.bazel.build/versions/master/platforms.html for more details.
- Loading branch information
Showing
32 changed files
with
1,545 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
.../com/google/devtools/build/docgen/templates/attributes/common/target_compatible_with.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<p> | ||
<code>List of <a href="../build-ref.html#labels">labels</a>; optional; default | ||
is the empty list</code> | ||
</p> | ||
|
||
<p> | ||
A list of | ||
<code><a href="platform.html#constraint_value">constraint_value</a></code>s | ||
that must be present in the target platform for this target to be considered | ||
"compatible". This is in addition to any constraints already set by the rule | ||
type. If the target platform does not satisfy all listed constraints then the | ||
target is considered "incompatible". Incompatible targets are skipped for | ||
building and testing when globbed (e.g. `//...`, `:all`). When explicitly | ||
specified on the command line, incompatible targets cause bazel to print an | ||
error and cause a build or test failure. | ||
</p> | ||
|
||
<p> | ||
Targets that transitively depend on incompatible targets are themselves | ||
considered incompatible. They are also skipped for building and testing. | ||
</p> | ||
|
||
<p> | ||
An empty list (which is the default) signifies that the target is compatible | ||
with all platforms. | ||
<p> | ||
|
||
<p> | ||
See the <a href="../platforms.html#skipping-incompatible-targets">Platforms</a> | ||
page for more information about incompatible target skipping. | ||
</p> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
81 changes: 81 additions & 0 deletions
81
src/main/java/com/google/devtools/build/lib/analysis/IncompatiblePlatformProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
// 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.common.base.Preconditions; | ||
import com.google.devtools.build.lib.analysis.platform.ConstraintValueInfo; | ||
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; | ||
import javax.annotation.Nullable; | ||
|
||
/** | ||
* Provider instance for the {@code target_compatible_with} attribute. | ||
* | ||
* <p>The presence of this provider is used to indicate that a target is incompatible with the | ||
* current platform. Any target that provides this will automatically be excluded from {@link | ||
* SkyframeAnalysisResult}'s list of configured targets. | ||
* | ||
* <p>This provider is able to keep track of _why_ the corresponding target is considered | ||
* incompatible. If the target is incompatible because the target platform didn't satisfy one of the | ||
* constraints in target_compatible_with, then the relevant constraint is accessible via {@code | ||
* getConstraintResponsibleForIncompatibility()}. On the other hand, if the corresponding target is | ||
* incompatible because one of its dependencies is incompatible, then the incompatible dependency is | ||
* available via {@code getTargetResponsibleForIncompatibility()}. | ||
*/ | ||
@Immutable | ||
public final class IncompatiblePlatformProvider implements TransitiveInfoProvider { | ||
private final ConfiguredTarget targetResponsibleForIncompatibility; | ||
private final ConstraintValueInfo constraintResponsibleForIncompatibility; | ||
|
||
IncompatiblePlatformProvider( | ||
ConfiguredTarget targetResponsibleForIncompatibility, | ||
ConstraintValueInfo constraintResponsibleForIncompatibility) { | ||
this.targetResponsibleForIncompatibility = targetResponsibleForIncompatibility; | ||
this.constraintResponsibleForIncompatibility = constraintResponsibleForIncompatibility; | ||
} | ||
|
||
public static IncompatiblePlatformProvider incompatibleDueToTarget( | ||
ConfiguredTarget targetResponsibleForIncompatibility) { | ||
Preconditions.checkNotNull(targetResponsibleForIncompatibility); | ||
return new IncompatiblePlatformProvider(targetResponsibleForIncompatibility, null); | ||
} | ||
|
||
public static IncompatiblePlatformProvider incompatibleDueToConstraint( | ||
ConstraintValueInfo constraint) { | ||
Preconditions.checkNotNull(constraint); | ||
return new IncompatiblePlatformProvider(null, constraint); | ||
} | ||
|
||
/** | ||
* Returns the incompatible dependency that caused this provider to be present. | ||
* | ||
* <p>This may be null. If it is null, then {@code getConstraintResponsibleForIncompatibility()} | ||
* is guaranteed to be non-null. | ||
*/ | ||
@Nullable | ||
public ConfiguredTarget getTargetResponsibleForIncompatibility() { | ||
return this.targetResponsibleForIncompatibility; | ||
} | ||
|
||
/** | ||
* Returns the constraint that the target platform didn't satisfy. | ||
* | ||
* <p>This may be null. If it is null, then {@code getTargetResponsibleForIncompatibility()} is | ||
* guaranteed to be non-null. | ||
*/ | ||
@Nullable | ||
public ConstraintValueInfo getConstraintResponsibleForIncompatibility() { | ||
return this.constraintResponsibleForIncompatibility; | ||
} | ||
} |
Oops, something went wrong.