Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate multiple executable files in one Makefile?

My directory contains 2 source files: a.c and b.c. I want to generate executable file a from a.c and b from b.c. Now I can only figure out one method to write Makefile:

all:  
    gcc -o a a.c
    gcc -o b b.c

It seems a little awkward, is it better method?

like image 543
Nan Xiao Avatar asked Oct 14 '25 15:10

Nan Xiao


2 Answers

The answers are fine, still I think you need some insight in how make works:

The basic functionality of make is to create output files from input files if necessary. make decides what is necessary by comparing timestamps: If any input file is newer than an output file created from it, the recipe for this output file is executed.

This means with just a rule named all, this rule is always executed (except when you happen to have a recent file actually called all -- to prevent this behavior, you have to list all as a .PHONY target, that is one that doesn't actually create a file). Your original Makefile is equivalent to a simple shell script, so it doesn't use make properly.

The minimal "correct" version of your Makefile should look like this:

all: a b

a: a.c
    gcc -o a a.c

b: b.c
    gcc -o b b.c

.PHONY: all

So, all is "phony" and depends on a and b. a is only rebuilt when a.c changed, b is only rebuilt when b.c changed.

In a real project, your programs are probably made from more than just one source file and in this case, you can really take advantage of make: Have it build object files of your translation units, so only the parts that changed are actually rebuilt. It's overkill for your tiny example, but could e.g. look like this:

a_OBJS:= a.o
b_OBJS:= b.o

all: a b

a: $(a_OBJS)
    gcc -o$@ $^

b: $(b_OBJS)
    gcc -o$@ $^

%.o: %.c
    gcc -c -o$@ $<

clean:
    rm -f *.o

.PHONY: all clean

You would just have to add more object files to a_OBJS and b_OBJS to include new translation units in your build. The pattern rule %.o: %.c will match them. There's a lot more to discover, I suggest starting with the GNU make manual.

I think the follow method is better:

all: a b
a: a.c
  gcc -o a a.c
b: b.c
  gcc -o b b.c

In your version, make all will always run gcc twice, whether or not a.c and b.c are modified. In this version gcc will be run only when necessary.

Of course you can use some magic (for-loop or similar) to create the rules but I think the difference between my and your method is clear.

like image 32
uzsolt Avatar answered Oct 17 '25 23:10

uzsolt