dpalma
dpalma

Reputation: 510

Make doesn't automatically invoke my "clean" target

I have seen similar questions, but in my case none of the answers given work. I have written the following Makefile:

# Compiler to use
CC = gcc

# flags to pass compiler
CFLAGS = -ggdb3 -O0 -std=c99 -Wall -Werror

# Name for the executable
EXE = cuaterniones

# space-separated list of header files
HDRS = cuaternion.h

# space-separated list of libraries, if any,
# each of which should be prefixed with -l
LIBS = -lm

# space-separated list of source files
SRCS = main.c cuaternion.c

# automatically generated list of object files
OBJS = $(SRCS:.c=.o)

# default target
$(EXE): $(OBJS) $(HDRS) Makefile
    $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS)

# dependencies 
$(OBJS): $(HDRS) Makefile

# housekeeping
clean:
    rm -f *.o

As it can be inferred, I want to remove all object files after compiling. However, when I call make, the program is compiled, but object files are not removed. However, if I do: make clean, it works as expected. The thing is, I have seen that this should be automatic, if I call make it should automatically clean the files for me, and that is what I want. Moreover, I want to know why it is not working, what is my mistake?

Upvotes: 1

Views: 3849

Answers (2)

William Pursell
William Pursell

Reputation: 212258

First, it is unusual for make clean to not also remove the executable, as most people would expect it to do. Perhaps you need a clean-obj target, or similar. In any case, it is not automatic and you need to call it explicitly. eg.:

$(EXE): $(OBJS) $(HDRS) Makefile
    $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS)
    $(MAKE) clean

Here $(MAKE) evaluates to the make command used (usually 'make' but could be 'gmake' or something else). But, as mentioned above, the convention is that make clean should remove the executable, so you probably want to use a different name for a target that only removes object files.

Upvotes: 3

JB.
JB.

Reputation: 42114

If you don't say anything, make only strives to make the first target, a.k.a. the default target.

Your clean target isn't the first target, isn't a dependency of the first target, and isn't a target from the command line, so make isn't instructed to go through it.

You could get it included in the default target by splitting them as such:

default: $(EXE) clean     # as a first target

But I wouldn't recommend it, it's not a dependency that makes sense, and it won't work at all if you try to run it in parallel.

I personally would just go for a workflow where I simply don't clean after build unless I specifically need to, in which case I'd likely use a canned make && make clean command line.

Another aproach would be to have the object files built as implicit intermediate targets—I think GNU make cleans those up automatically.

Upvotes: 2

Related Questions