Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing if a file exists in makefile target, and quitting if not present

Tags:

makefile

gnu

Is there a way to exit with an error condition if a file does not exist? I am currently doing something like this:

all: foo  foo:     test -s /opt/local/bin/gsort || echo "GNU sort does not exist! Exiting..." && exit 

Running make runs the all target, which runs foo.

The expectation is that if the test -s conditional fails, then the echo/exit statements are executed.

However, even if /usr/bin/gsort exists, I get the result of the echo statement but the exit command does not run. This is the opposite of what I am hoping to accomplish.

What is the correct way to do something like the above?

like image 509
Alex Reynolds Avatar asked Jan 15 '13 23:01

Alex Reynolds


People also ask

How do I know if a file is present in makefile?

myApp is for myApplication i.e. the filename by the build process. If you just want to avoid make stopping if the file does not exist, rm -rf myApp could be an alternative. Or preceding the command with a dash ( -rm myApp ) to make make ignore the error from rm (it will however print an ugly message).

What is IFEQ in makefile?

The ifeq directive begins the conditional, and specifies the condition. It contains two arguments, separated by a comma and surrounded by parentheses. Variable substitution is performed on both arguments and then they are compared.

How do I call a target in makefile?

When you type make or make [target] , the Make will look through your current directory for a Makefile. This file must be called makefile or Makefile . Make will then look for the corresponding target in the makefile. If you don't provide a target, Make will just run the first target it finds.

What are typical targets in a makefile?

By default, the goal is the first target in the makefile (not counting targets that start with a period). Therefore, makefiles are usually written so that the first target is for compiling the entire program or programs they describe.


Video Answer


2 Answers

I realize this is a bit old at this point, but you don't need to even use a subshell to test if a file exists in Make.

It also depends on how you want/expect it to run.

Using the wildcard function, like so:

all: foo foo: ifeq (,$(wildcard /opt/local/bin/gsort))     $(error GNU Sort does not exist!) endif 

is one good way to do it. Note here that the ifeq clause is not indented because it is evaluated before the target itself.

If you want this to happen unconditionally for every target, you can just move it outside of a target:

ifeq (,$(wildcard /opt/local/bin/gsort)) $(error GNU Sort does not exist!) endif 
like image 69
KingRadical Avatar answered Sep 19 '22 06:09

KingRadical


exit alone returns the status of the last command executed. In this case, it returns zero, which means everything is ok.

This is, because || and && have equal precedence, and the shell interprets the command as if it were written

( test ... || echo ... ) && exit 

If you want to signal failure you must exit with a non zero value, e.g. exit 1. And if you want to echo and exit, just put the commands in sequence separated by ;

all: foo  foo:     test -s /opt/local/bin/gsort || { echo "GNU sort does not exist! Exiting..."; exit 1; } 
like image 26
Olaf Dietsche Avatar answered Sep 21 '22 06:09

Olaf Dietsche