Reputation: 7440
I've checked a few posts on SO, but not able to get the answer I want.
I want to run a Stata script as part of a Makefile. So in one of my targets, I define
live_data:
@echo "Executing Stata code"
StataIC -e 'stata_code.do'
@exit_status=$?
@echo "Finished execution of Stata code."
@echo Code finished with exit code of $(exit_status)
However, whenever I look at the output of my make all
command (which includes live_data
), I see
Executing Stata code
StataIC -e stata_code.do'
Finished execution of Stata code.
Code finished with exit code of
Basically, the variable exit_code
is always empty.
However, if I pop up a terminal and simply run StataIC -e stata_code.do
followed by exit_status=$?
and echo $exit_status
, I get the correct result (0 or 1). Could someone point me to what exactly I'm missing here?
Upvotes: 0
Views: 180
Reputation: 530853
Note that you can simplify the recipe so that you don't need to save the value of $?
.
live_data:
@echo "Executing Stata code"; \
StataIC -e 'stata_code.do'; \
printf '%s\n' "Finished execution of Stata code." \
"Code finished with exit code of $$?"
Here, both strings are arguments to a single printf
called immediately after StataIC
, so $?
correctly refers to the exit status of StataIC
.
Upvotes: 1
Reputation: 99084
You have a couple of problems. First, as @AProgrammer has pointed out, each line in a recipe is executed in its own subshell, so a variable set in one line does not survive into the next:
trial:
@var=blue
@echo this command has no access to what was stored in var
The solution is to put the commands in one line
trial:
@var=blue ; echo this command can use what was stored in var
and if that's too long, wrap the line with a backslash:
trial:
@var=blue ;\
echo this command can use what was stored in var
(Note that there is only one TAB, the one just before the @
; the whitespace to the left of "echo" is just some spaces to make the rule easy to read.)
Second, you must be careful about the syntax. The way to expand a variable in Make is $(var)
, but the way to expand it in a shell is $var
; using either syntax in the other context will not give you the result you want.
var=red
$(info $(var)) # this is a Make command
trial:
@var=blue ; echo this is a shell command, so $(var) will not work
Third, although a command in a rule is a shell command, Make will attempt to expand any variable it sees before running the rule, so we must escape the '$' in "$var" with another '$':
trial:
@var=blue ; echo $var will not work, but $$var will
Put it all together and we get:
live_data:
@echo "Executing Stata code" ; \
StataIC -e 'stata_code.do' ; \
exit_status=$$? ; \
echo "Finished execution of Stata code." ; \
echo Code finished with exit code of $$exit_status
Upvotes: 1