mesonbuild / meson

The Meson Build System
http://mesonbuild.com
Apache License 2.0
5.57k stars 1.62k forks source link

can't pass multiple @INPUT0@, @INPUT1@ etc. inside a single string inside a command #7696

Open alex-tee opened 4 years ago

alex-tee commented 4 years ago

Describe the bug Wherever commands are given that can take @INPUT0@, @INPUT1@, etc., the values don't get replaced if they are in a single string. see example below.

it seems to only work when each variable to be replaced is in a separate element in the command array, like command: [ 'bash', '-c', '@INPUT0@', '@INPUT1@', '@OUTPUT@', ], which obviously won't work in my use case where I need to use bash (I'm on mingw and my first input is a shell script, and I can't run it directly)

To Reproduce just run meson build && ninja -C build run-target -v

project('meson-test', 'c',
  version : '0.1',
  default_options : ['warning_level=3'])

file1 = configure_file (
  output: 'file1',
  configuration: { 'a':'a' })
file2 = configure_file (
  output: 'file2',
  configuration: { 'a':'a' })

out = custom_target (
  'meson_test',
  output: 'meson_test',
  input: [ file1, file2 ],
  command: [ 'bash', '-c', 'echo @INPUT0@ && echo @INPUT1@ && echo @OUTPUT@' ],
  install : false)

run_target (
  'run-target',
  command: [ 'echo', 'done' ],
  depends: out)

you will see that @INPUT0@ and @INPUT1@ are not getting replaced:

bash -c 'echo @INPUT0@ && echo @INPUT1@ && echo meson_test'
@INPUT0@
@INPUT1@
meson_test

Expected behavior All substitutable values to be replaced, even if they are inside a single string

system parameters

eli-schwartz commented 4 years ago

As I mentioned in IRC:

command: ['bash', '-c', 'echo "$1" && echo "$2"', '_ignored', '@INPUT0@', '@INPUT1@'],

would be the "correct" way to pass options as a list.

It is false to say this doesn't work or is impossible for your use case. You may or may not be correct that meson "should" make this easier.

eli-schwartz commented 4 years ago

That being said, I realize your test case here has a glaring typo: you used @INPUT1 rather than @INPUT1@.

If I correct this typo, your example works the way you requested.

alex-tee commented 4 years ago

That being said, I realize your test case here has a glaring typo: you used @INPUT1 rather than @INPUT1@.

If I correct this typo, your example works the way you requested.

oops, you're right. it doesn't work however if you do echo @INPUT0@ && echo @INPUT1@ && echo @OUTPUT@. it prints:

@INPUT0@
@INPUT1@
meson_test

updated the issue to reflect this

As I mentioned in IRC:

command: ['bash', '-c', 'echo "$1" && echo "$2"', '_ignored', '@INPUT0@', '@INPUT1@'],

would be the "correct" way to pass options as a list.

It is false to say this doesn't work or is impossible for your use case. You may or may not be correct that meson "should" make this easier.

I'm using this for now and it does the job, thanks

Jehan commented 2 years ago

I encountered the same issue and it's very annoying. I needed to add a BOM to a file. So my initial idea was to call:

  custom_target(setup_isl,
    input : [ nobom_setup_isl_tmp ],
    output: [ setup_isl ],
    command: [
      python, '-c',
     'open("@OUTPUT@", "wb").write(b"\\xEF\\xBB\\xBF" + open("@INPUT@", "rb").read())'
    ],
    build_by_default: true,
)

As it turned out, it failed because "@OUTPUT@" was not replaced (only @INPUT@ was). So I had to use the same argument trick as you advised in bash. It works now, but this is making the rule uselessly complicated.

Also because of #1564 which teamed-up with this bug to make my life complicated, I had to bother with fake byte encoding. Anyway this is the rule which worked in the end. A lot less nice:

  custom_target(setup_isl,
    input : [ nobom_setup_isl_tmp ],
    output: [ setup_isl ],
    command: [
      python, '-c',
      'import sys; open(sys.argv[1], "wb").write("\ufeff".encode("utf-8") + open("@INPUT@", "rb").read())',
      '@OUTPUT@'
    ],
    build_by_default: true,
)

(again a case where it would also be nice to have simple way to write/append/prepend data to files, as is discussed (for another use case we encountered) in this thread: https://github.com/mesonbuild/meson/pull/6267#discussion_r894901923)

jpakkane commented 2 years ago

The reason we don't do that is that it is actually unsupportable. We aim to provide features that work reliably across (pretty much) all platforms and inputs. In this case suppose that the file name had a double quote character in it. Merely replacing it in would not work because we would need to detect that it is used inside a Python string that is double quoted and then quote it accordingly (not just quote it so it survives shell execution). While this may seem like a contrived example, the principle is clear:

If you ever need to consider quoting quote characters, your design is broken.

It is not possible to make this reliable because in order to do that we would need to know all possible ways different programs expect their commands strings to be quoted. On the other hand passing standalone arguments to scripts is doable.