So I have the exact same question as the one below, but no one has answered it.
Pattern matching Makefile with multiple executable targets
I am trying to build a series of small test files each have a pattern of "test*.c" to test my library.
I wanted to write a makefile that builds executables for every one of the test files all at once (each name: test1, test2, test3..etc.). However, I am not sure how to achieve that.
What I have so far is the following:
SRC := $(shell find *.c)
ALL_PROG := $(patsubst %.c, %, *.c)
.PHONY: all
all: $(ALL_PROG)
$(ALL_PROG): $(SRC)
-gcc $< -o $@
This is a bad attempt because the targets take all .c files as dependency, which caused circular dependency.
Using shell script can get the job done very easily, but I am wondering if there's a way to do the same job.
Thanks in advance.
Use $(ALL_PROG): %: %.c
instead of $(ALL_PROG): $(SRC)
.
Here is an example Makefile I might use with GNU make
:
CC := gcc
CFLAGS := -Wall -O2
LDFLAGS := -lm
PROGS := $(patsubst %.c, %, $(wildcard *.c))
.PHONY: all clean test $(patsubst %, test@%, $(PROGS))
all: $(PROGS)
clean:
rm -f $(PROGS)
$(PROGS): %: %.c
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@
$(patsubst %, test@%, $(PROGS)): test@%: %
./$^
test: $(patsubst %, test@%, $(PROGS))
As usual, note that the indentation should use a Tab rather than spaces; the editor used here on stackoverflow.com auto-converts them to spaces.
The PROGS
variable will contain the names of all *.c
files in the directory.
The .PHONY:
directive tells Make which targets do not refer to actual files. The $(patsubst %, test@%, $(PROGS))
expands to the list of executable names, with each name prepended with test@
: if the directory contains files foo.c
and bar.c
, this expands to test@foo test@bar
.
The $(PROGS): %: %.c
recipe compiles each .c file to the corresponding binary.
The $(patsubst %, test@%, $(PROGS)): test@%: %
recipe creates a test target for each binary. If we have files foo.c
and bar.c
, then this rule expands to test@foo test@bar: test@%: %
. This means that for both test@foo
and test@bar
targets, the corresponding test@%
target requires the %
binary. The ./$^
in turn expands to ./%
, and thus the binary name. (If you don't want Make to show the command being run, use @./$^
. If you don't care if a test fails, use -./$^
.)
The test
recipe expands to test@foo
test@bar
if we have foo.c
and bar.c
; i.e. all possible test targets.
You can run make clean test
to recompile all .c files in the directory, and execute them.
If you are only worried about a specific test program, say foo.c
, you can run make test@foo
, which will recompile the program if foo.c
is newer than foo
.
You can do that. I am updating a simple make file which builds multiple targets. You can modify it as your requirement.
TEST1 = test1.exe
TEST2 = test2.exe
### Executable Program Files ###
all : $(TEST1) $(TEST2)
$(TEST1) : test1.c
gcc -o $(TEST1) test1.c
$(TEST2) : test2.c
gcc -o $(TEST2) test2.c