A Makefile with Multiple Executables

2018-12-31 17:14发布

I am trying to write a makefile which uses macros to create multiple executables from multiple files at once. I tried searching through previously answered questions but, because I am fairly new to programming in C as well as working with gcc, I was not able to find an answer to my question.

Here is what I have so far:

CC=gcc
CFLAGS=-I.
OBJ = ex1.c ex3.c
EXECUTABLE = ex1 ex3

$(EXECUTABLE): $(OBJ)
    gcc -o $@ $^ $(CFLAGS)

clean:
    rm -f $(EXECUTABLE)

I would like the line

$(EXECUTABLE): $(OBJ)

to create executables ex1 and ex3 from files ex1.c ex3.c respectively.

标签: c makefile
4条回答
无与为乐者.
2楼-- · 2018-12-31 17:15

Some suggestions (assuming you use GNU make, not something else)

First, run once make -p, you'll understand what builtin rules make is knowing. Look in particular for COMPILE.c and LINK.c

Then, I suggest

 CFLAGS= -g -Wall -I.

(because you really want -g for debugging, and -Wall to get most warnings)

And you probably don't need

$(EXECUTABLE): $(OBJ)
    gcc -o $@ $^ $(CFLAGS)

However, I suggest adding before most other rules

.PHONY: all clean

all: $(EXECUTABLES)

Actually, I would code your Makefile (for GNU make!) as follow

# file Makefile
CC= gcc
RM= rm -vf
CFLAGS= -Wall -g
CPPFLAGS= -I.
SRCFILES= ex1.c ex2.c ## or perhaps $(wildcard *.c)
OBJFILES= $(patsubst %.c, %.o, $(SRCFILES))
PROGFILES= $(patsubst %.c, %, $(SRCFILES))

.PHONY: all clean

all: $(PROGFILES)
clean:
     $(RM) $(OBJFILES) $(PROGFILES) *~
## eof Makefile

Remember that tab is a significant character in Makefile-s (action part of rules). In this answer, lines starting with four spaces at least should really start with a tab character.

Once everything is debugged consider running make clean to clean everything, and then make -j CFLAGS=-O2 all to compile in parallel everything with optimizations.

At last, I recommend using remake and running remake -x to debug complex Makefile-s

Of course, I'm supposing that your directory has only single-file programs.

BTW, there are other builder programs. Perhaps you might consider omake

Don't forget to use a version control system like git for your source files. It is also time to learn such a tool.

查看更多
笑指拈花
3楼-- · 2018-12-31 17:23

For this particular case, where each executable has a single source file with .c extension, all you need is a one line Makefile:

all: ex1 ex3

The built-in default rules for make then work already:

$ make
cc -O2 -pipe   ex1.c  -o ex1
cc -O2 -pipe   ex3.c  -o ex3

Behind the scene, make is using the POSIXly mandated built-in single suffix rule

.c:
    $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<

Vary the command to your liking with make CC=gcc CFLAGS=-O2 LDFLAGS=-s and similar.

Trivia of the day: in fact, if you are willing to name the targets when invoking make, you can use an empty or even run without any Makefile:

$ make -f /dev/null CC=gcc CFLAGS=-O2 LDFLAGS=-s ex1 ex3
gcc -O2 -s ex1.c  -o ex1
gcc -O2 -s ex3.c  -o ex3
$ rm -f Makefile ex1 ex3
$ make CC=gcc CFLAGS=-O2 LDFLAGS=-s ex1 ex3
gcc -O2 -s ex1.c  -o ex1
gcc -O2 -s ex3.c  -o ex3

Make magic!

As a rule of thumb, don't reinvent the wheel (or rules), use the rules that are already there. It simplifies your and make's life a lot. This makes for small and sexy makefiles to impress the ladies with :-)

查看更多
明月照影归
4楼-- · 2018-12-31 17:31

The following answer includes multiple executable such as initiate, process1, process2, ..., process4.

LOCAL_INCLUDE=./

all: clean process_first process_second init

process_first:
    gcc -g -o process1  -I$(LOCAL_INCLUDE) process1.c  -lzmq  -L. -L./.
    gcc -g -o process2  -I$(LOCAL_INCLUDE) process2.c  -lzmq  -L. -L./.

process_second:
    gcc -g -o process3  -I$(LOCAL_INCLUDE) process3.c  -lzmq  -L. -L./.
    gcc -g -o process4  -I$(LOCAL_INCLUDE) process4.c  -lzmq  -L. -L./.

init:
    gcc -g -o initiate -I$(LOCAL_INCLUDE) initiate.c -lzmq -lconfig -lpthread -L. -L./. -ldl -lrt

clean:
    rm -rf init_manager.o init_manager
    rm -rf process1 process2 process3 process4

NOTE: It is a good practice to clean and touch all the executable files before making them again.

查看更多
像晚风撩人
5楼-- · 2018-12-31 17:36

You're close, but you need a pattern rule:

$(EXECUTABLE): % : %.c

And then a default rule to make it build both:

all: $(EXECUTABLE)
查看更多
登录 后发表回答