0

I have a make target, that first calls a CAE tool which generates reports. When this is done, the target calls a python script that shall take the content of the CAE reports (or more specific some grep'ed lines of the reports) as argument.

A minimum example is

target1:
  date > ./bar.txt
  echo $(shell cat ./bar.txt)

Problem is, that make expands the $(shell cat ./bar.txt) before the first command has been called and bar.txt has been updated. So for this minimum example, the echo prints the content of bar.txt before the update (the date from the previous target run).

( I know that I simply could write this example in another way without variables and the shell function call, this is just for the sake of showing the problem where I call a tool that takes an argument from a shell call. So actually I want to do sth like this:

target1:
  cae_tool_call
  report_eval.py -text "$(shell cat $(generated_report) | grep 'foo')"

where cae_tool_call generates the generated_report. And this -text "argument" does not resolve the argument without an explicit call of the shell function. )

I already tried with actual shell variables (instead of make variables), double escapes, immediate vs deferred variables but have no working solution yet. Any ideas?

#######################################

Edit to show some unexpected behavior:

I have this python script argument_example.py

import argparse

def main():
  parser = argparse.ArgumentParser()
  parser.add_argument("-r", "--reporttext", help="text string", required=True)
  args=parser.parse_args()

  if args.reporttext:
    print(args.reporttext)

main()

It just prints the text given with argument -r.

And I have these two make targets:

####################################
#this does not work

REPORTNAME := ./bar.txt

variable_report:
    date > $REPORTNAME
    python3 ./argument_example.py --reporttext "`(cat $REPORTNAME)`"

####################################
#this works

static_report:
    date > ./bar.txt
    python3 ./argument_example.py --reporttext "`(cat ./bar.txt)`"

When calling variable_report, the python scripts prints the outdated bar.txt content. When calling static_report, the python script prints the updated content.

wwwweb
  • 3
  • 2

1 Answers1

0

make recipes are already shell scripts. Never use the shell make function inside a recipe. In your first simple example use:

target1:
    date > bar.txt
    cat bar.txt

In your other example use:

generated_report := name-of-generated-report
target1:
    cae_tool_call
    report_eval.py -text "`cat $(generated_report) | grep 'foo'`"

Or even better:

generated_report := name-of-generated-report
target1:
    cae_tool_call
    report_eval.py -text "`grep 'foo' $(generated_report)`"
Renaud Pacalet
  • 25,260
  • 3
  • 34
  • 51
  • Well, thanks for your response, but I have to use the shell command I think. For the first example it works without, as you suggested (expected, as it was just a showcase that is more complicated than it should be). For the second example (which is the real world thing), it does not resolve the shell command in the argument without the prepended shell call (i.e. report_eval.py gets the string "cat $(generated_report) | grep 'foo'" as argument instead of the resolved value). – wwwweb Nov 10 '22 at 09:47
  • 1
    I think you don't understand the most important part: make recipes are already shell scripts. Using the `shell` make function in a recipe does not make sense. Use your shell. Type the backticks around `cat $(generated_report) | grep 'foo'` as I wrote them (command substitution). This will execute the command in a sub-shell and return whatever it should. – Renaud Pacalet Nov 10 '22 at 09:59
  • You could also use the more recent syntax for command substitution: `$(cat ...)` but then you would have to escape the `$` sign such that make does not expand this as if it was a make variable: `$$(cat ...)`. This is one of the rare occasions where the old backticks are useful. – Renaud Pacalet Nov 10 '22 at 10:03
  • I tried with the backticks and the double escape. It resolves the shell command but it cannot take this as argument. The argument is a text string. So for example if the cat call resolves to "foo has been found", the python tool is called with -text foo has been found. That does not work. I have to put " around the argument that it is recognized as a (single) string. And then neither backtips nor double escape works withing these ". – wwwweb Nov 10 '22 at 10:12
  • 1
    You have a shell issue here, not make. Can you run this manually on the command line? If yes what command do you type? If not try to get this fixed first on the command line. If you don't know how to do something on the command line there are very little chances that you can solve your problem with make. – Renaud Pacalet Nov 10 '22 at 10:24
  • Yes, is is possible that it is a shell problem. I followed your hint to try on bash and got some unexpected result. When using $generated_report in thew argument it does not work. When I replace $generated_report by the actual static ./bar.txt, it works. So it is maybe a problem about expansion of this variable. I will add the example code to the initial question. – wwwweb Nov 10 '22 at 11:10
  • Added python script and make target to the initial post. Thanks for your patience btw ;-) . – wwwweb Nov 10 '22 at 11:20
  • This time it's a make expansion problem. `REPORTNAME` is a make variable. Expand it with `$(REPORTNAME)`, not `$REPORTNAME` which is for shell variable expansions. When make sees `$REPORTNAME` it expands make variable `R`and concatenates `EPORTNAME` to the result. Not what you want. And note that if `REPORTNAME` was a shell variable you would need `$$REPORTNAME`in a recipe, to escape the make expansion and pass `$REPORTNAME` to the shell. – Renaud Pacalet Nov 10 '22 at 11:46
  • Oh right, did not see that. Ok, I think I got it. Thanks! – wwwweb Nov 10 '22 at 11:51
  • Note that `"(cat ./bar.txt)` and `(cat $(REPORTNAME))` uselessly launch a subshell. Prefer `cat ./bar.txt` and `cat $(REPORTNAME)` (no outer parentheses). – Renaud Pacalet Nov 10 '22 at 11:53
  • 2
    That's still a [useless use of `cat`](https://stackoverflow.com/questions/11710552/useless-use-of-cat); you want simply `report_eval.py -text $$(grep 'foo' $(generated_report))` – tripleee Nov 10 '22 at 11:54
  • @tripleee Yep. But what they really want is `report_eval.py -text "$$(grep 'foo' $(generated_report))"` (double quotes apparently needed by the python script). I edit my answer to add this, even if it's not related to their issue. – Renaud Pacalet Nov 10 '22 at 11:56