4
\$\begingroup\$

I have an instructor who is very stringent on makefiles only containing rules and dependencies that need to be included.

The structure for the program is very basic. The requirement is to produce two executable files: a3b and a3m. There was some code duplication, so I included that in a source code file called myarray.c (with a header by the same name).

I have already tested the makefile, and everything seems to work. However, can the makefile be cleaner or more accurate (such as removing or adding rules or dependencies)?

The macro names and values were specified by the instructor.

CFLAGS = -g -Wall - Werror
CC = gcc
LD = gcc
PROG1 = a3b
PROG2 = a3m
PROG3 = myarray
OBJ1 = a3b.o
OBJ2 = a3m.o
OBJ3 = myarray.o

all : $(PROG1) $(PROG2) $(PROG3)

$(PROG1) : $(OBJ1) $(PROG3)
    $(LD) $(OBJ1) $(OBJ3) -o $(PROG1)

$(PROG2): $(OBJ2) $(PROG3)
    $(LD) $(OBJ2) $(OBJ3) -o $(PROG2)

$(PROG3): $(OBJ3) $(PROG3).h
    $(LD) $(PROG3).c -c

clean :
    /bin/rm -f *.o a.out $(PROG1) $(PROG2) $(PROG3)
\$\endgroup\$

2 Answers 2

5
\$\begingroup\$

Your OBJ* variables are unnecessary, as they are just the executable name with a .o extension. You can simplify by doing something like this:

$(PROG1) : [email protected] $(OBJ3) 
    $(LD) $^ -o $@

$@ expands to the name of the recipe's target, and $^ expands to the list of prerequisites. Note that this also replaces PROG3 with OBJ3, since that's what is actually used in the recipe. Using PROG3 here can cause unnecessary rebuilding if PROG3 changes but OBJ3 doesn't (unlikely in your case, but common in more complex makefiles).

If myarray.c is just common code, do you need to build it into its own program? Your PROG3 recipe may be unnecessary. If all you really need is myarray.o, You can eliminate the PROG3 recipe by simply adding myarray.o to the prerequisite lists of your other targets.

myarray.o: myarray.h

$(PROG1) : [email protected] myarray.o
    $(LD) $^ -o $@

$(PROG2): [email protected] myarray.o
    $(LD) $^ -o $@

The myarray.o target is only there to ensure that it is rebuilt when the header changes. The dependencies will cascade down and cause the programs to be rebuilt as well. You don't need a recipe for this rule if make's default .c-to-.o rule is sufficient for you.

In this form, your two recipes are practically identical. You can take advantage of this to consolidate them into a single, generic rule:

myarray.o: myarray.h

%: %.o myarray.o
    $(LD) $^ -o $@
\$\endgroup\$
5
\$\begingroup\$

clean and all are not files should therefore be declared as phony.

.PHONY: clean all
all : $(PROG1) $(PROG2) $(PROG3)
...
clean :
    /bin/rm -f *.o a.out $(PROG1) $(PROG2) $(PROG3)
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.