I want to run certain action in the shell depending on whether a default makefile in the current directory contains a certain target.
#!/bin/sh
make -q some_target
if test $? -le 1 ; then
    true # do something
else
    false # do something else     
fi
This works, because GNU make returns error code 2 if the target is absent, 0 or 1 otherwise. The problem is that is not documented this way. Here is a slice of the man:
-q, --question
        ``Question mode''.  Do not run any commands,  or  print  anything;
        just  return  an exit status that is zero if the specified targets
        are already up to date, nonzero otherwise.
Only zero/nonzero is distinguished. What is the right way to do that?
You should read the GNU make manual rather than the man page: the man page is merely a summary not a complete definition. The manual says:
The exit status of make is always one of three values:
0    The exit status is zero if make is successful
2    The exit status is two if make encounters any errors. It will print messages
     describing the particular errors.
1    The exit status is one if you use the ‘-q’ flag and make determines that
     some target is not already up to date.
Since trying to create a target that doesn't exists is an error, you'll always get an exit code of 2 in that situation.
Late answer, but perhaps it will help people facing the same problem in the future.
I use the approach below, which does require you to modify the Makefile (you need to add a single %-rule-exists pattern rule). If you don't want to do that, you can just run make -n your-target-to-check &> /dev/null directly from your script.
I use this to have commands like autobuild and autoupload, which are included for context in the snippet.
%-rule-exists: 
    @$(MAKE) -n $* &> /dev/null
auto%: %-rule-exists
    $(info Press CTRL-C to stop $*ing)
    @while inotifywait -qq -r -e move -e create -e modify -e delete --exclude "\.#.*" src; do make $* ||: ; date ; done
Example output:
$ make build-rule-exists; echo Exit code: $?
Exit code: 0
$ make nonsense-rule-exists; echo Exit code: $?
Exit code: 2
Note that it does not actually build the target to find out if the rule exists, courtesy of the -n flag of make. I needed it to work even if a build would fail.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With