Here is the makefile:
.PHONY: all clean
CC = gcc
CFLAGS = -g -m32 -std=c17
BIN = bin
ALG_SRCS = $(wildcard alg/*.c)
COMMON_SRCS = $(wildcard *.c)
ALG_OBJS = $(patsubst alg/%.c, $(BIN)/%.o, $(ALG_SRCS))
COMMON_OBJS = $(patsubst %.c, $(BIN)/%.o, $(COMMON_SRCS))
ALG_EXES = $(patsubst alg/%.c, $(BIN)/%, $(ALG_SRCS))
all: $(ALG_EXES)
$(BIN)/%: $(BIN)/%.o $(COMMON_OBJS) | $(BIN)
$(CC) $(CFLAGS) -o $@ $^ -lncursesw
$(BIN)/%.o: %.c | $(BIN)
$(CC) $(CFLAGS) -c $< -o $@
$(BIN)/%.o: alg/%.c | $(BIN)
$(CC) $(CFLAGS) -c $< -o $@
$(BIN):
mkdir -p $(BIN)
clean:
rm -rf $(BIN)
Example execution:
$ make
mkdir -p bin
gcc -g -m32 -std=c17 -c alg/basic.c -o bin/basic.o
gcc -g -m32 -std=c17 -c graph.c -o bin/graph.o
gcc -g -m32 -std=c17 -c grid.c -o bin/grid.o
gcc -g -m32 -std=c17 -c main.c -o bin/main.o
gcc -g -m32 -std=c17 -o bin/basic bin/basic.o bin/graph.o bin/grid.o bin/main.o -lncursesw
gcc -g -m32 -std=c17 -c alg/colors.c -o bin/colors.o
gcc -g -m32 -std=c17 -o bin/colors bin/colors.o bin/graph.o bin/grid.o bin/main.o -lncursesw
rm bin/main.o bin/graph.o bin/basic.o bin/colors.o bin/grid.o
I did not ask for the object files to be removed, nor did I call "clean". Why does rm bin/main.o bin/graph.o bin/basic.o bin/colors.o bin/grid.o
still happen?
Are you sure that you showed us the right makefile for that output? That looks very wrong to me and when I recreate your makefile and setup locally I don't see the behavior you see. What version of GNU Make do you have?
The rm
command I get, and what I fully expected and seems correct, is this:
rm bin/basic.o bin/colors.o
This makes sense because these two files are considered intermediate files (see the link urznow posted in a comment above).
The other object files cannot be intermediate files because they are listed explicitly as prerequisites in the $(BIN)/%: $(BIN)/%.o $(COMMON_OBJS)
rule.
Anyway, to avoid things being considered intermediate you can list them as prerequisites of some rule in the makefile (note, this rule doesn't actually have to be run it just has to exist). So one option is to add a "helper" rule like this:
objs: $(COMMON_OBJS) $(ALG_OBJS)
.PHONY: objs
(but, as I say, in my repro of your makefile only $(ALG_OBJS)
is needed here). This lists all the object files as prerequisites of an explicit target which makes them non-intermediate.
Another option is to change the rule that builds binaries from an implicit rule (pattern rule here) into an explicit rule, using a static pattern rule:
$(ALG_EXES): $(BIN)/%: $(BIN)/%.o $(COMMON_OBJS) | $(BIN)
$(CC) $(CFLAGS) -o $@ $^ -lncursesw
Either one will work.
BTW, you probably want to be using :=
assignment in your makefiles, at least for the wildcard
functions, just to gain a bit of efficiency.