I am doing my CS homework, which consists of a lot of single-file programs. My working directory looks like this:
133.c 134.c 220.c 281.c 337.c 338.c 339.c makefile
And I wrote a Makefile like this:
%: %.c
${CC} ${CFLAGS} -o $@ $^
So when I want to compile the program for Question 220, I type this:
ibug@wsl:~ $ make 220
gcc -o 220 220.c
ibug@wsl:~ $
I want to write a clean-%
rule so that when I run this in shell, the result should look like below
ibug@wsl:~ $ make clean-133
rm -f 133
ibug@wsl:~ $ make clean-281
rm -f 281
ibug@wsl:~ $ make clean-337
rm -f 337
I've gone so far with this:
.PHONY: clean-%
SRC = $(wildcard %.c)
BIN = $(patsubst %.c,%,$(SRC))
clean-%:
rm -f ??????
What should I put in place of the question marks?
I'm using GNU Make 4.1 (on Windows Subsystem for Linux).
You are looking for the automatic variable $*
, which contains the stem (i.e., the part matched against %
):
clean-%:
rm -f $*
However, keep reading.
Adding the prerequisite clean-%
to the .PHONY
target:
.PHONY: clean-%
does not turn the pattern rule clean-%
into a phony target, but rather turns the explicit rule, whose actual target name is clean-%
(not a pattern), into a phony target.
The reason is that only targets of explicit rules can be made phony targets, a pattern can't be a phony target. So, a phony target that looks like a pattern (i.e., contains %
) is not really a pattern (i.e., the %
is literally a %
).
Adding all the possible values clean-%
could be matched against to .PHONY
won't help either, because phony targets do not match implicit pattern rules. So, if you do:
.PHONY: clean-foo
clean-foo
will never match an implicit pattern rule (i.e., it will never match your clean-%
pattern rule).
clean-xxx
as phony targetsI guess you actually want these clean-xxx
targets to be phony targets, since these targets do not represent actual files on the file system.
Unlike implicit pattern rules, static pattern rules can match phony targets. The following approach consists of defining a single static pattern rule that can match those clean-xxx
phony targets:
list := $(patsubst %.c,%,$(wildcard *.c))
# list of clean-xxx targets
clean-targets := $(addprefix clean-,$(list))
.PHONY: $(clean-targets)
$(clean-targets): clean-%:
rm -f $*
The static pattern rule above will match any of the clean-xxx
phony targets specified in its list of targets (i.e., the $(clean-targets)
.
The following approach consists of dynamically generating these clean-xxx
rules as explicit rules instead of a single pattern rule:
list := $(patsubst %.c,%,$(wildcard *.c))
define create-clean-target
$(eval .PHONY: clean-$1);
$(eval clean-$1:; rm -f $1)
endef
# dynamically generate the clean-xxx targets
$(foreach t,$(list),$(call create-clean-target,$t))
The user-defined function create-target
defines an explicit target clean-xxx
, being xxx
the argument passed to the function. Since this target to be defined is an explicit target, it can be made a phony target as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With