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

Expansion of $(location) on path with spaces quotes too many times #6531

Open
ob opened this issue Oct 26, 2018 · 16 comments
Open

Expansion of $(location) on path with spaces quotes too many times #6531

ob opened this issue Oct 26, 2018 · 16 comments
Labels
P3 We're not considering working on this, but happy to review a PR. (No assignee) team-Documentation Documentation improvements that cannot be directly linked to other team labels team-Rules-API API for writing rules/aspects: providers, runfiles, actions, artifacts type: bug type: documentation (cleanup)

Comments

@ob
Copy link
Contributor

ob commented Oct 26, 2018

Tested with Bazel 0.18.0 and master as of d4e3ad8.

Small test to reproduce at: https://github.com/ob/bazel-tests/tree/master/spaces

If I run:

$ bazel build --spawn_strategy=standalone -s --sandbox_debug //spaces:no_spaces

I get this output (paths removed and output elided for clarity):

DEBUG: arule.bzl:3:5: Expanding Location Placeholders...
DEBUG: arule.bzl:4:5: Values: ["-c", "$(location adir/foo.c)"]
DEBUG: arule.bzl:5:5: Expansion: ["-c", "spaces/adir/foo.c"]

SUBCOMMAND: # //spaces:no_spaces [action 'SkylarkAction spaces/adir/foo.o']
(cd /private/var/tmp/_bazel_obonilla/124df79d9592378b17b94075fb66c278/execroot/__main__ && \
  exec env - \
  cc -c spaces/adir/foo.c -o bazel-out/darwin-fastbuild/bin/spaces/adir/foo.o)

And the build succeeds. However, if I run:

$ bazel build --spawn_strategy=standalone -s --sandbox_debug //spaces:spaces

I get this output:

DEBUG: arule.bzl:3:5: Expanding Location Placeholders...
DEBUG: arule.bzl:4:5: Values: ["-c", "$(location a dir/foo.c)"]
DEBUG: arule.bzl:5:5: Expansion: ["-c", "'spaces/a dir/foo.c'"]

SUBCOMMAND: # //spaces:spaces [action 'SkylarkAction spaces/a dir/foo.o']
(cd /private/var/tmp/_bazel_obonilla/124df79d9592378b17b94075fb66c278/execroot/__main__ && \
  exec env - \
  cc -c ''\''spaces/a dir/foo.c'\''' -o 'bazel-out/darwin-fastbuild/bin/spaces/a dir/foo.o')
ERROR: BUILD:13:1: SkylarkAction spaces/a dir/foo.o failed (Exit 1): cc failed: error executing command 
  (cd /private/var/tmp/_bazel_obonilla/124df79d9592378b17b94075fb66c278/execroot/__main__ && \
  exec env - \
  cc -c ''\''spaces/a dir/foo.c'\''' -o 'bazel-out/darwin-fastbuild/bin/spaces/a dir/foo.o')
clang: error: no such file or directory: ''spaces/a dir/foo.c''
clang: error: no input files
Target //spaces:spaces failed to build

Note that the input_file is double-quoted. The ctx.expand_location() function seems to have realized there are spaces, and it single quoted the path. Later on, the action quoted it again.

@ob ob changed the title Expansion of $(location) on path with spaces double-quotes argument. Expansion of $(location) on path with spaces quotes too many times Oct 26, 2018
@aiuto
Copy link
Contributor

aiuto commented Oct 29, 2018

Not sure if this is Starlark or Execution. We'll have to sort it out.

@regisd
Copy link
Contributor

regisd commented Oct 30, 2018

Related to #3475

@laurentlb
Copy link
Contributor

The $(location) command has a very subtile (and undocumented?) effect of adding single quotes when the input contains a space.

@laurentlb
Copy link
Contributor

The issue is not specific to Starlark, because I can reproduce it with genrule:

genrule(
    name = "gen",
    srcs = ["a dir/a.cc"],
    outs = ["out"],
    cmd = "echo \"$(location a dir/a.cc)\" && touch $@",
)

@ob
Copy link
Contributor Author

ob commented Oct 31, 2018

The $(location) command has a very subtile (and undocumented?) effect of adding single quotes when the input contains a space.

Is that to work around toolchains that can't deal with spaces? IMHO, it seems wrong to quote at that level. I think quoting should be done as close to the exec as possible no?

Maybe the solution is just to remove that single-quoting from $(location)?

@ob
Copy link
Contributor Author

ob commented Nov 2, 2018

Here's a bit of justification for my rationale: I found the bug through the API ctx.expand_location, which is used in StarLark so you naturally wouldn't expect it to quote.

E.g. if I was dealing with a toolchain that didn't handle spaces, I could always quote the whole $(location ...) section. For instance -iquote '$(location path with spaces)', whereas removing quotes because we quote too much would be difficult and error prone.

@laurentlb
Copy link
Contributor

I agree the sane fix is to remove the quotes.

@ob
Copy link
Contributor Author

ob commented Nov 2, 2018

Having said that, I'm not sure what to do about $(locations ...)... the example in #3475 would still be a problem:

filegroup(
  name = "files",
  srcs = glob(["dir with spaces/**/*"]),
)

genrule(
  name = "example",
  srcs = [":files"],
  outs = ["foo"],
  cmd = "echo FILES: $(locations //:files) | tee $@",
)

@regisd
Copy link
Contributor

regisd commented Nov 3, 2018

IMHO, $(location a dir/a.cc) should fail in the first place with: location takes 1 arg, but 2 were given.
Build file authors should use instead $(location 'a dir/a.cc')

@laurentlb laurentlb added team-Bazel General Bazel product/strategy issues and removed team-Starlark labels Nov 26, 2018
@meisterT meisterT removed their assignment Dec 3, 2018
@dslomov dslomov added team-Starlark and removed team-Bazel General Bazel product/strategy issues labels Jul 5, 2019
@laurentlb laurentlb added P2 We'll consider working on this in future. (Assignee optional) type: bug and removed untriaged labels Jul 8, 2019
@laurentlb
Copy link
Contributor

Assuming it was caused by #3475, cc @katre

@katre
Copy link
Member

katre commented Jul 29, 2019

It's been quite a while since I looked into this code, so I don't have any special insight to offer.

@laurentlb
Copy link
Contributor

cc @laszlocsomor and @meteorcloudy, as it probably affects Windows users more

@brandjon brandjon added P4 This is either out of scope or we don't have bandwidth to review a PR. (No assignee) team-Build-Language type: documentation (cleanup) and removed P2 We'll consider working on this in future. (Assignee optional) team-Starlark labels Feb 17, 2021
@brandjon brandjon added untriaged team-Rules-API API for writing rules/aspects: providers, runfiles, actions, artifacts and removed team-Build-Language labels Nov 4, 2022
@sgowroji sgowroji added the team-Documentation Documentation improvements that cannot be directly linked to other team labels label Jan 11, 2023
@comius comius added P3 We're not considering working on this, but happy to review a PR. (No assignee) and removed P4 This is either out of scope or we don't have bandwidth to review a PR. (No assignee) untriaged labels Sep 25, 2023
@comius
Copy link
Contributor

comius commented Sep 25, 2023

I think this functionality deserves a revamp, however not sure how it looks like.

@aiuto
Copy link
Contributor

aiuto commented Sep 25, 2023

+1 to revamp. I've thought about this many times. My strawman proposal is.

  • genrule.cmd and migrate to genrule.args.
  • args mimics the ctx.action.args api
  • The first args is not always what we execute.
    • There should be an explicit executable. If provided, executable is what we execv. args[0] is what we pass to the executable in argv. Feels like busybox a bit.
    • If you explicitly want bash, then we provide a label (e.g. @bazel_shells//bash:bash).
    • hand wavy ideas about bash on windows? do we allow .bat?
  • in genrule and ctx we stop constructing a command line and passing it to the command interpreter.
    • instead, we use exec and pass unquoted strings to exec, since we are not going through a shell.
    • this still can have problems on windows, but works pretty well for *ix-ish systems.

As a lower cost solution, as a rule author I never pass files paths on the command line. I spill them into a file through that capability in ctx.action.args and have my tools read list of paths from command files. Yes, this can be slightly more overhead, but I don't have to worry about shell escaping. That doesn't help the quick and easy generule.

@fmeum
Copy link
Collaborator

fmeum commented Sep 26, 2023

I think this functionality deserves a revamp, however not sure how it looks like.

I don't have concrete ideas for the API, but I think that any "v2" should:

  1. be implemented in Starlark and maintained outside but close to the Bazel core so that users can pin and update to a particular version of expansion location.
  2. return a "structured" command line, e.g. a ctx.actions.args. This would help quite a bit with ongoing efforts to rewrite paths to be more cache-friendly (CC @gregestren, this is how we could get rid of the --javacopts hack).

@phst
Copy link
Contributor

phst commented Jan 15, 2024

As a lower cost solution, as a rule author I never pass files paths on the command line. I spill them into a file through that capability in ctx.action.args and have my tools read list of paths from command files. Yes, this can be slightly more overhead, but I don't have to worry about shell escaping.

Hmm, AFAIK when using ctx.actions.run there should never be any shell escaping?
In fact, using a param file might cause more trouble because of embedded newlines - they need to be escaped and unescaped as well.

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-Documentation Documentation improvements that cannot be directly linked to other team labels team-Rules-API API for writing rules/aspects: providers, runfiles, actions, artifacts type: bug type: documentation (cleanup)
Projects
None yet
Development

No branches or pull requests