Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write a Makefile rule to remove files (clean) only if the files are present?

Tags:

makefile

It looks to me like Makefile rules can be roughly classified into "positive" and "negative" ones: "positive" rules create missing or update outdated files, while "negative" ones remove files.

Writing prerequisites for "positive" rules is quite easy: if the target and the prerequisite are file names, make by default runs the recipe if the target is missing or outdated (a missing file in this context may be viewed as an infinitely old file).

However, consider a "negative" rule, for example for target clean. A usual way to write it seems to be something like this:

clean:
    rm -f *.log *.synctex.gz *.aux *.out *.toc

This is clearly not the best way to do:

  1. rm is executed even when there is nothing to do,

  2. its error messages and exit status need to be suppressed with -f flag, which has other (possibly undesirable) effects, and

  3. the fact that there were nothing to do for target clean is not reported to the user, unlike what is normal for "positive" targets.

My question is: how to write a Makefile rule that shall be processed by make only if certain files are present? (Like what would be useful for make clean.)

like image 370
Alexey Avatar asked Nov 07 '15 11:11

Alexey


People also ask

How do you clean files in makefile?

Makefile can also directly make on how to run miscellaneous commands when asked explicitly, for instance, cleaning up the directory, i.e., removing certain files. To delete object files and executable files, type: make clean. Note that clean is not a file but a name of action.

How do you make a clean target in makefile?

The Cleanup Rule clean: rm *.o prog3 This is an optional rule. It allows you to type 'make clean' at the command line to get rid of your object and executable files. Sometimes the compiler will link or compile files incorrectly and the only way to get a fresh start is to remove all the object and executable files.

Which target of make is used to remove all generated files?

make clean: Only remove files that have been generated.

What is a rule in makefile?

A rule appears in the makefile and says when and how to remake certain files, called the rule's targets (most often only one per rule). It lists the other files that are the prerequisites of the target, and the recipe to use to create or update the target.


2 Answers

how to write a Makefile rule that shall be processed by make only if certain files are present? (Like what would be useful for make clean.)

You can do it like so:

filenames := a b c

files := $(strip $(foreach f,$(filenames),$(wildcard $(f))))

all: $(filenames)

$(filenames):
    touch $@

clean:
ifneq ($(files),)
    rm -f $(files)
endif

Example session:

$ make
touch a
touch b
touch c
$ make clean
rm -f a b c
$ make clean
make: Nothing to be done for 'clean'.

Useful perhaps for some purposes, but it strikes me as a strained refinement for make clean.

like image 163
Mike Kinghan Avatar answered Nov 15 '22 10:11

Mike Kinghan


This can be easily remedied:

clean:
    for file in *.log *.synctex.gz *.aux *.out *.toc; do \
        if [ -e "$file" ]; then \
            rm "$$file" || exit 1; \
        else \
            printf 'No such file: %s\n' "$file" \
        fi \
    done

The if statement is necessary unless your shell supports and has enabled nullglob or something similar.

If your printf supports %q you should use that instead of %s to avoid possible corruptions of your terminal when printing weird filenames.

like image 27
l0b0 Avatar answered Nov 15 '22 11:11

l0b0