Skip to content
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 support for reading a list of target patterns for from a file #8609

Closed
robbertvanginkel opened this issue Jun 11, 2019 · 9 comments
Closed
Labels
P3 We're not considering working on this, but happy to review a PR. (No assignee) team-OSS Issues for the Bazel OSS team: installation, release processBazel packaging, website type: feature request

Comments

@robbertvanginkel
Copy link
Contributor

Description of the problem / feature request:

Add support for reading a list of target patterns for from a file for bazel {build,test} (in addition to supporting target patterns in argv)

Feature requests: what underlying problem are you trying to solve with this feature?

We have a command based on query that selects a set of targets (based on this bazel-discuss and #7962) and passes these to bazel build. Roughly something like:

bazel query ... | grep | sed | awk > foo
bazel test $(<foo)

However, this becomes problematic if the output of query + modifications is long, specifically longer than the ARG_MAX the system supports:

# write non-null arg file that is longer than getconf ARG_MAX
$ dd if=/dev/zero bs=1 count=$((1+$(getconf ARG_MAX))) | tr "\0" "\7" > foo
$ bazel build $(<foo)
-bash: /usr/local/bin/bazel: Argument list too long

I currently work around this by using xargs, as it splits the incoming stream into multiple bazel invocations if it is too big.

bazel query ... | grep | sed | awk | xargs bazel test --

I don't however want multiple bazel invocations as this means I need to support reading/merging multiple logs, build event files etc etc.

Ideally bazel would support reading a list of arguments from a file, maybe even generically like:

$ cat argfile.txt
--bazelrc=/dev/null
build
--
//some/...
...
//targets:here
$ bazel --argfile=argfile.txt

But at least I'd like to find a way to have bazel test and build read the list of target patterns from a file (or any other method of passing it a list of arbitrary length).

What operating system are you running Bazel on?

MacOS / Linux

What's the output of bazel info release?

release 0.26.1

Have you found anything relevant by searching the web?

The bazel query documentation suggests using shell command substitution like:

  bazel query deps(//my:target) --output=label | grep ... | sed ... | awk ... > foo
  bazel query "kind(cc_binary, set($(<foo)))"

However, this fails once the query output is longer than ARG_MAX as described above.

bazel/site/docs/query.html

Lines 490 to 493 in aca672f

<pre>
bazel query deps(//my:target) --output=label | grep ... | sed ... | awk ... &gt; foo
bazel query "kind(cc_binary, set($(&lt;foo)))"
</pre>

@jin
Copy link
Member

jin commented Jun 12, 2019

You can achieve this using:

$ bazel query ... | awk '$0="build:my_target_group "$0' > .bazelrc
$ bazel build --config=my_target_group

Would that work for you?

@kastiglione
Copy link
Contributor

I would like this feature too. Bazel supports actions that use args files, so maybe why not bazel too?

The bazelrc approach would not work for us, our repo has a checked in .bazelrc.

@Globegitter
Copy link

@kastiglione you can probably use try-import to have a secondary bazelrc that is on gitignore. Also @robbertvanginkel given the background of this ticket you might be interested in: #8521

@kastiglione
Copy link
Contributor

I didn't know about try-import thanks. I still think bazel should support an args file, it's very common.

@robbertvanginkel
Copy link
Contributor Author

@jin thanks for the suggestion, I did not know you could put build targets into the bazelrc.

I guess that technically fixes my issue, although I agree with @kastiglione that having general argfile support would be nice. Should I open a general issue for that or do you want to keep this one open and rename it to "Add support for argfiles".

@robbertvanginkel
Copy link
Contributor Author

@jin I tried this and it works for the number of targets we have in our repository today, but when I tried to do it with a list double the number of targets I get an odd grpc error:

$ bazel query //...:* | awk '$0="build:changed_build_targets "$0' > targetsrc
Loading: 0 packages loaded
$ wc -l targetsrc
   28896 targetsrc
$ bazel --bazelrc=targetsrc build --nobuild --config changed_build_targets
INFO: Invocation ID: 01a66a7e-b60e-443c-be4f-9d097235db10
INFO: Analyzed 28896 targets (45 packages loaded, 41441 targets configured).
INFO: Found 28896 targets...
INFO: Elapsed time: 50.703s
INFO: 0 processes.
INFO: Build completed successfully, 0 total actions
$ bazel query //...:* | awk '$0="build:changed_build_targets "$0' >> targetsrc # append and see if this scales with twice the number of targets
$ wc -l targetsrc
   57792 targetsrc
Loading: 0 packages loaded
$ bazel --bazelrc=targetsrc build --nobuild --config changed_build_targets

Server terminated abruptly (error code: 1, error message: 'Received RST_STREAM with error code 8', log file: '/private/var/tmp/_bazel_robbert/b21ffbdb27bc569a3409d8e5058938fa/server/jvm.out')

$ cat /private/var/tmp/_bazel_robbert/b21ffbdb27bc569a3409d8e5058938fa/server/jvm.out
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by io.netty.util.internal.ReflectionUtil (file:/private/var/tmp/_bazel_robbert/install/1a037b6c0d8096293d1eecfde6528fbd/_embedded_binaries/A-server.jar) to field sun.nio.ch.SelectorImpl.selectedKeys
WARNING: Please consider reporting this to the maintainers of io.netty.util.internal.ReflectionUtil
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

Any idea why this could be?

@dslomov dslomov added team-Bazel General Bazel product/strategy issues untriaged labels Jun 24, 2019
@dslomov dslomov added P2 We'll consider working on this in future. (Assignee optional) type: feature request P3 We're not considering working on this, but happy to review a PR. (No assignee) and removed untriaged P2 We'll consider working on this in future. (Assignee optional) labels Jul 5, 2019
@dslomov dslomov added team-OSS Issues for the Bazel OSS team: installation, release processBazel packaging, website and removed team-Bazel General Bazel product/strategy issues labels Jul 19, 2019
@robbertvanginkel
Copy link
Contributor Author

You can achieve this using:

$ bazel query ... | awk '$0="build:my_target_group "$0' > .bazelrc
$ bazel build --config=my_target_group

Would that work for you?

We've been using this for a while and while it works, it makes --announce_rc output bloated as that now outputs all targets too.

It would be great if Bazel could support running from argfiles. Any pointers for where to start?

@robbertvanginkel
Copy link
Contributor Author

I debugged the Server terminated abruptly (error code: 1, error message: 'Received RST_STREAM with error code 8') error message a bit further, looking at the server's logs I can see the following:

200107 22:26:32.939:WT 18 [io.grpc.netty.NettyServerStream$TransportState.deframeFailed] Exception processing message
io.grpc.StatusRuntimeException: RESOURCE_EXHAUSTED: gRPC message exceeds maximum size 4194304: 4211608
	at io.grpc.Status.asRuntimeException(Status.java:523)

grpc/grpc-java's DEFAULT_MAX_MESSAGE_SIZE is 4 MiB so it seems like the earlier proposed trick isn't a sufficient workaround for reading a list of targets from a file. We've encountered some long target lists that this won't work anymore.

I looked a bit through Bazel's source code to find out where to add functionality to read target patterns from a file and stumbled upon the undocumented --experimental_allow_project_files.

@Option(
name = "experimental_allow_project_files",
defaultValue = "false",
documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
effectTags = {OptionEffectTag.CHANGES_INPUTS},
metadataTags = {OptionMetadataTag.EXPERIMENTAL, OptionMetadataTag.HIDDEN},
help = "Enable processing of +<file> parameters."
)
public boolean allowProjectFiles;

Based on what I've read in ProjectFile.java and ProjectFileSupport.java it seems like project files should allow a user to specify a build command like

bazel build --experimental_allow_project_files -- +path/to/projectfile

where path/to/projectfile would be a file that contains some target patterns/modifiers. I haven't been able to find the format of this projectfile anywhere, as the code path requires a ProjectFile.Provider but it seems like none is provided to the BlazeRuntime:

ProjectFile.Provider projectFileProvider = null;
for (BlazeModule module : blazeModules) {
ProjectFile.Provider candidate = module.createProjectFileProvider();
if (candidate != null) {
Preconditions.checkState(projectFileProvider == null,
"more than one module defines a project file provider");
projectFileProvider = candidate;
}
}

as no module implements createProjectFileProvider() https://source.bazel.build/search?q=.createProjectFileProvider&sq=&ss=bazel.

Should I try to implement a ProjectFile.Provider and send in a PR? Is there a google internal one that never made it into opensource? Is there a plan to make --experimental_allow_project_files non experimental at some point? I'd really like to have a non-hacky way to have bazel read a list of target patterns to build from a file.

cc @vladmos who committed related to the flag in 58e3891.

@michajlo
Copy link
Contributor

There's some prior art for this in query (--query_file, see also QueryEnvironmentBasedCommand.java). This could be a more direct route with less gotchas than full param file support or "project file" support.

robbertvanginkel added a commit to uber-common/bazel that referenced this issue Mar 4, 2020
An alternative to bazelbuild#10796 to fix bazelbuild#8609.

As bazelbuild#8609 (comment) points out there's currently a --query_file to read a query pattern from file, but there's no analogous feature available for build/test. Generic parameter file support attempted in bazelbuild#10796 turns out to be a little more complex than expected due to bazel's client/server architecture and likely requires some design document.

This PR would fix help bazelbuild#8609 without rushing into any designs, so we can spend time properly designing generic parameter files while also alleviating the immediate problem with a known/simpler pattern.
apattidb pushed a commit to databricks/bazel that referenced this issue Apr 17, 2023
An alternative to bazelbuild#10796 to fix bazelbuild#8609.

As bazelbuild#8609 (comment) points out there's currently a `--query_file` to read a query pattern from file, but there's no analogous feature available for build/test. Generic parameter file support attempted in bazelbuild#10796 turns out to be a little more complex than expected due to bazel's client/server architecture and likely requires some design document.

This PR would fix help bazelbuild#8609 without rushing into any designs, so we can spend time properly designing generic parameter files while also alleviating the immediate problem with a  known/simpler pattern.

Closes bazelbuild#10856.

PiperOrigin-RevId: 298953350
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P3 We're not considering working on this, but happy to review a PR. (No assignee) team-OSS Issues for the Bazel OSS team: installation, release processBazel packaging, website type: feature request
Projects
None yet
6 participants