Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check existence of the target in a makefile

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?

like image 807
sshilovsky Avatar asked May 24 '14 21:05

sshilovsky


2 Answers

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.

like image 158
MadScientist Avatar answered Sep 28 '22 01:09

MadScientist


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.

like image 23
wvdschel Avatar answered Sep 28 '22 01:09

wvdschel