How to build multiple targets with similar name?

2019-07-25 00:29发布

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.

2条回答
一纸荒年 Trace。
2楼-- · 2019-07-25 00:52

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.

查看更多
趁早两清
3楼-- · 2019-07-25 01:04

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 
查看更多
登录 后发表回答