-
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
Add a new include()
directive to MODULE.bazel files
#21855
Conversation
TODO:
|
As this is our last chance to do so, are there any further restrictions we would want to apply? Some ideas:
I'm also not sure whether BFS is the most intuitive ordering. If I branch out a
I find
We have to make a choice here as to whether we want to build this logic into Bazel or buildozer. The latter doesn't operate on files that aren't explicitly mentioned as cli args yet and I don't know what it would take to change this. In any case, we'll have to deal with the complexity that the repo mapping for extension label resolution is spread across multiple files (see my second point on restrictions we may want to apply).
Are you referring to the lockfile update logic? With the new lockfile format, |
More thoughts:
|
This is already enforced (
Are you saying that, to
BFS is just used to load the segment files (and compile them). The actual ordering is "source order", so essentially DFS.
Agreed. If other people concur, I'll probably change it to something more like
Ah yeah, that would be great!
Could you clarify this a bit more? Why is this a new thing for imported files only?
I don't know if enforcing a scheme is a good idea, especially if the scheme is anything more than a suffix check ( |
Not necessarily in the same segment, but one that came before it. I.e., make sure that the repo mapping entries applied to labels are evident when reading the "concatenated" segments in order. But it's not a must if we can solve the
I find
In MODULE.bazel, you can currently do
It's unfortunately not that easy: |
daadadb
to
0063cd4
Compare
module_import()
directive to MODULE.bazel filesinclude()
directive to MODULE.bazel files
I think the "exported proxy" idea is probably better. We probably don't even need to enforce it -- if you use something like
I'm not worried about But anyway, I went with
IMO that's fine? Still doesn't necessarily mean we need to enforce a convention for segments. |
We might get away with no convention, but I'm not fully certain: In addition to conditional formatting (say spacing between extension usages and their Independent of the technical challenges, I'm also a strong proponent of first-class tool integration (think How about a |
8291a41
to
8482dd0
Compare
Hmm, I understand the concern better now. I think maybe acutally Anyway, I just added some more documentation, and the implementation should be ready for review. |
if (node.getName().equals(INCLUDE_IDENTIFIER)) { | ||
// If we somehow reach the `include` identifier but NOT as the other allowed cases above, | ||
// cry foul. | ||
error( |
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.
Just noting that extension proxies called include
will break with this. I think that's fine, but technically not backwards compatible for 7.2.0. But maybe that's okay?
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.
hmm... that's indeed annoying. I kind of just brushed it off (because who names their extension/proxy "include"??) but it's indeed a hard breakage, and potentially non-addressable if the usage is in a dep (not your root module).
I suppose we could further soften the impact by allowing include
to be the sole occupant of the left-hand side of an assignment. But with code like
my_ext = use_extension(...)
include = my_ext.include
include(attr = "abc")
we'll still incorrectly complain about keyword arguments being used with the include
directive. I guess that's a much smaller blast radius.
This crucially still doesn't allow something like
blah = include
blah("//:abc.MODULE.bazel")
which would cause a runtime error because we don't pre-load //:abc.MODULE.bazel
but will need it during evaluation. That was what I wanted to avoid the most.
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.
Could we return from the visitor after the first assignment to include
? That would be similar to how you can override global symbols in Starlark.
Edit: and don't handle any include
from that point on in a special way.
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 a good idea -- basically removes the risk. done.
* TODO: This field is a hack. It's not needed by anything other than {@code ModCommand}, during | ||
* the {@code bazel mod tidy} command. Doing it this way assumes that {@code bazel mod tidy} | ||
* cannot touch any included segments. This is unsatisfactory; we should do it properly at some | ||
* point, although that seems quite difficult. |
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.
We can do it as a follow-up. Should we file an issue for this?
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.
filed #22063
public void addOverride(String moduleName, ModuleOverride override) throws EvalException { | ||
ModuleOverride existingOverride = overrides.putIfAbsent(moduleName, override); | ||
if (existingOverride != null) { | ||
throw Starlark.errorf("multiple overrides for dep %s found", moduleName); | ||
} | ||
} | ||
|
||
public InterimModule buildModule() throws EvalException { | ||
public InterimModule buildModule(@Nullable Registry registry) throws EvalException { |
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.
Why is this needed?
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.
this was just a mostly unrelated mini-refactor because the registry isn't used until the very end where the module is built. Before, we passed in registry
to the constructor of the thread context, which is a little bit unnecessary.
@Wyverald Is it the right time to update the PR description now? I have a rough understanding by reading the code, but want to better confirm the ideas in this PR. |
ah sorry, I updated the commit message but forgot about the PR description. Updated |
This new directive allows the root module to divide its MODULE.bazel into multiple segments. This directive can only be used by root modules; only files in the main repo may be included; variable bindings are only visible in the file they occur in, not in any included or including files. See the docs for `include()` (in `ModuleFileGlobals.java`) for more details. RELNOTES: Added a new `include()` directive to MODULE.bazel files. Fixes #17880.
8482dd0
to
110993e
Compare
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.
LGTM with few comments
@Override | ||
public void visit(DotExpression node) { | ||
visit(node.getObject()); | ||
if (includeWasAssigned || !node.getField().getName().equals(INCLUDE_IDENTIFIER)) { |
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.
Is the includeWasAssigned
needed here? If so, please update the comment.
@Test | ||
public void checkSyntax_good_includeIdentifierReassigned() throws Exception { | ||
String program = """ | ||
include = print |
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.
Could you add one legitimate call to include
before this assignment?
scratch.overwriteFile( | ||
rootDirectory.getRelative("MODULE.bazel").getPathString(), | ||
"module(name='aaa')", | ||
"include('@haha//java:MODULE.bazel.segment')"); |
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.
We could already update the naming scheme.
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.
oops sorry, I didn't realize you left new comments. I'll send a follow-up
[ | ||
'module(name="foo")', | ||
'bazel_dep(name="bbb", version="1.0")', | ||
'include("//java:MODULE.bazel.segment")', |
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.
See above.
Will this go into 7.2? |
yes -- I'll prepare the cherry-pick PRs later |
This new directive allows the root module to divide its `MODULE.bazel` into multiple segments. This directive can only be used by root modules; only files in the main repo may be included; variable bindings are only visible in the file they occur in, not in any included or including files. See the docs for `include()` (in `ModuleFileGlobals.java`) for more details. In follow-ups, we'll need to address: 1. Enforcing the loaded files to have some sort of naming format (tentatively `foo.MODULE.bazel` where `foo` is anything) 2. Making `bazel mod tidy` work with included files RELNOTES: Added a new `include()` directive to `MODULE.bazel` files. Fixes #17880. Closes #21855. PiperOrigin-RevId: 627034184 Change-Id: Ifc2f616cf0791445daeeac9ca5ec4478e83382aa
This new directive allows the root module to divide its `MODULE.bazel` into multiple segments. This directive can only be used by root modules; only files in the main repo may be included; variable bindings are only visible in the file they occur in, not in any included or including files. See the docs for `include()` (in `ModuleFileGlobals.java`) for more details. In follow-ups, we'll need to address: 1. Enforcing the loaded files to have some sort of naming format (tentatively `foo.MODULE.bazel` where `foo` is anything) 2. Making `bazel mod tidy` work with included files RELNOTES: Added a new `include()` directive to `MODULE.bazel` files. Fixes bazelbuild#17880. Closes bazelbuild#21855. PiperOrigin-RevId: 627034184 Change-Id: Ifc2f616cf0791445daeeac9ca5ec4478e83382aa
This new directive allows the root module to divide its
MODULE.bazel
into multiple segments. This directive can only be used by root modules; only files in the main repo may be included; variable bindings are only visible in the file they occur in, not in any included or including files. See the docs forinclude()
(inModuleFileGlobals.java
) for more details.In follow-ups, we'll need to address:
foo.MODULE.bazel
wherefoo
is anything)bazel mod tidy
work with included filesRELNOTES: Added a new
include()
directive toMODULE.bazel
files.Fixes #17880.