John Wooten
John Wooten

Reputation: 745

How to modify makefile to compile changed source into object directory except for a list of files

I inherited a makefile that uses GNU Make 3.81. It is overly complicated, IMHO because it does not use patterns. In addition, it does not automatically create an object file directory when needed. I've looked at several examples and read the a GNU makefile manual, but still not seeing something that should be simple. There seem to be many ways recommended, but not clear what to use. I have about 60 c files that need to be compiled into a directory named obj. But, I don't want 6 test programs that have 'main' programs compiled into that directory. They are in a list called OTHERSRCS. I'd like to have the c files less the OTHERSRCS compiled into obj if anything changes in those files. Also, if the obj directory doesn't exist, I'd like to create it. The 'make clean' should remove that directory. I've used ANT with Java and can get the dependencies to work, but I'm not succeeding with this makefile. A simple example would be helpful that used some sort of exclusion along with the pattern for the c files.

Upvotes: 2

Views: 672

Answers (2)

Emil Terman
Emil Terman

Reputation: 526

Here's my Makefile

This should get you going. I tried to be as descriptive as I could.

Edit: To exclude a .c file you can change:

SRC     =   $(shell find $(SRC_DIR) -name '*.c')

to

SRC     =   $(shell find $(SRC_DIR) -name '*.c' ! -iname 'myFile.c')

Upvotes: 1

Mike Kinghan
Mike Kinghan

Reputation: 61560

In this simple example, the C source files in the current directory are foo.c, bar.c, atest.c, anothertest.c. We have:

OTHERSRCS := atest.c anothertest.c

Each of the $(OTHERSRCS) is to be separatedly compiled and linked into a program in current directory. All remaining C source files, whatever the are, are to be compiled into a directory obj, which shall be created when required, and the resulting object files all linked into a program foobar.

Makefile

ALLSRCS := $(wildcard *.c)
OTHERSRCS := atest.c anothertest.c
foobar_SRCS := $(filter-out $(OTHERSRCS),$(ALLSRCS))
foobar_OBJS := $(addprefix obj/,$(foobar_SRCS:.c=.o))
PROGS := foobar atest anothertest

.PHONY: all clean

all : $(PROGS)

obj/%.o: %.c | obj 
    $(COMPILE.c) $< -o $@

obj:
    mkdir -p $@


foobar: $(foobar_OBJS)
    $(LINK.o) -o $@ $^ $(LDLIBS)

clean:
    rm -fr $(PROGS) obj

The default make runs like:

$ make
mkdir -p obj
cc    -c foobar.c -o obj/foobar.o
cc    -c foo.c -o obj/foo.o
cc    -c bar.c -o obj/bar.o
cc   -o foobar obj/foobar.o obj/foo.o obj/bar.o 
cc     atest.c   -o atest
cc     anothertest.c   -o anothertest

and of course make foobar like the first 5 lines of that.

To understand the key details, see 4.3 Types of Prerequisites and 8.2 Functions for String Substitution and Analysis in the manual. No recipes need be written for the programs atest and anothertest in this example because they're correctly built by GNU make's default rules.

If you are going to rework your inherited makefile, consider rationalising the source tree, e.g. by at least not having test sources in the same directory as application sources.

Upvotes: 2

Related Questions