-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow Skylark rules to specify whether targets can add execution plat… #5341
Conversation
…form constraints. Change-Id: Ic937b011d1d95aac7dc6d715fa418f54d89198a9
@@ -397,6 +400,14 @@ public BaseFunction rule( | |||
builder.advertiseSkylarkProvider(skylarkProvider); | |||
} | |||
|
|||
// TODO(katre): convert from bool to enum | |||
if (!execCompatibleWith.isEmpty()) { | |||
builder.addExecutionPlatformConstraints(collectConstraintLabels(execCompatibleWith, ast)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally, builtin functions shouldn't depend on the AST of their call site in any way (it's kind of a wart that breaks encapsulation). This function already violates that, but as a tiny step to not making it worse, please replace ast
with ast.getLocation()
in the signature of collectConstraintLabels()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll send another PR shortly making these same changes for toolchains.
@@ -316,6 +317,8 @@ public BaseFunction rule( | |||
SkylarkList<String> toolchains, | |||
String doc, | |||
SkylarkList<?> providesArg, | |||
Boolean executionPlatformConstraintsAllowed, | |||
SkylarkList<String> execCompatibleWith, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The generic type is unchecked by the Skylark calling interface. Change this to SkylarkList<?>
, and use SkylarkList#getContents
to cast to a list of strings.
@@ -397,6 +400,14 @@ public BaseFunction rule( | |||
builder.advertiseSkylarkProvider(skylarkProvider); | |||
} | |||
|
|||
// TODO(katre): convert from bool to enum |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Outdated comment?
@@ -283,6 +288,8 @@ public BaseFunction rule( | |||
SkylarkList<String> toolchains, | |||
String doc, | |||
SkylarkList<?> providesArg, | |||
Boolean executionPlatformConstraintsAllowed, | |||
SkylarkList<String> execCompatibleWith, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<String>
to <?>
as mentioned earlier. (Yes, I see you use generic1 = String.class
, but IIRC that affects documentation generation but isn't actually enforced. Regardless, let's be consistent with the other string list params here and worry about fixing that in the future.)
positional = false, | ||
defaultValue = "False", | ||
doc = | ||
"Whether targets of this rule can set exec_compatible_with to add extra constraints on the execution platform."), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggested rephrasing:
If true, a special attribute named <code>exec_compatible_with</code> of label-list type is added. Targets may use this attribute to specify additional constraints on the execution platform beyond those given in the <code>exec_compatible_with</code> argument to <code>rule()</code>.
Is this wording accurate? Specifically, is exec_compatible_with
considered a real label-list attribute, or is it some kind of string-list with special processing? If it's really a label list, the user would expect ctx.attr.exec_compatible_with
to return a Target object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes: it's a list of labels, which must exist.
No: They can't be resolved as Targets, because execution constraints have to be checked before dependencies are resolved (because the selected toolchains are dependencies, and we need the execution constraints in order to select the proper toolchain).
The user can probably access ctx.attr.exec_compatible_with, I'm just not sure if there's ever a use for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With or without a use for ctx.attr.exec_compatible_with
, if it exists it should be documented, and the easiest way to do that is to refer to it as an "attribute" here.
If setting this bool causes it to be illegal for the user to define their own "exec_compatible_with" attribute in the attrs
dict, we should also say so here, e.g.:
If true, a special attribute named <code>exec_compatible_with</code> of label-list type is added, which must not already exist in `attrs`. ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(backticks to <code>
and </code>
)
positional = false, | ||
defaultValue = "[]", | ||
doc = | ||
"A list of constraints on the execution platform that targets of this rule will use.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggested rephrasing:
A list of constraints on the execution platform that apply to all targets of this rule type.
public void testRuleAddExecutionConstraints() throws Exception { | ||
scratch.file("test/BUILD", "toolchain_type(name = 'my_toolchain_type')"); | ||
evalAndExport( | ||
"def impl(ctx): return None", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: pass
is more idiomatic than return None
scratch.file("test/BUILD", "toolchain_type(name = 'my_toolchain_type')"); | ||
evalAndExport( | ||
"def impl(ctx): return None", | ||
"r1 = rule(impl, ", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: use implementation=impl (on a new line) instead of a positional arg.
} | ||
|
||
@Test | ||
public void testTargetsCanAddExecutionPlatformConstraints() throws Exception { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a new test to illustrate what happens when a user defines the exec_compatible_with attribute themselves (using attrs = ...) -- whatever that behavior is supposed to be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have added such a tes, but it doesn't seem to work, as this is only checked when RuleClass.Builder.build() is called, and for Skylark rules that happens when the rule is exported, and I can't figure out how to write a test that exports a rule. Any pointers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's understandable. Check out SkylarkImportLookupFunction#execAndExport, and SkylarkRuleClassFunctionsTest#evalAndExport.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, that worked!
Change-Id: If9886663c578297d8c7bba5355735ffb2354f39e
Change-Id: I4f19dddc8ccbaf10853b5b842e2597f39fe0911d
Change-Id: I7fb0ed49df7bab74912740571813ef332e729ee9
this.ruleClass = builder.build(ruleClassName, skylarkLabel + "%" + ruleClassName); | ||
try { | ||
this.ruleClass = builder.build(ruleClassName, skylarkLabel + "%" + ruleClassName); | ||
} catch (IllegalArgumentException | IllegalStateException ex) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not too familiar with the rule class builder, but I'm a little wary when I see broad unchecked exception types reraised as a checked exception like this. Can you add a comment mentioning that it's in case there's a conflict in the attribute builder?
Change-Id: Ib74e59fec48102469a5039e045e3f3d0e0d86d8c
…form constraints. Closes bazelbuild#5341. Change-Id: Ib74e59fec48102469a5039e045e3f3d0e0d86d8c PiperOrigin-RevId: 200526448
…form constraints. Closes bazelbuild#5341. Change-Id: Ib74e59fec48102469a5039e045e3f3d0e0d86d8c PiperOrigin-RevId: 200526448
…form constraints.
Change-Id: Ic937b011d1d95aac7dc6d715fa418f54d89198a9