waffleman
waffleman

Reputation: 4339

A Concise Makefile

I am doing some Makefile refactoring and trying to figure out the most concise way to implement a Makefile that does the following:

  1. Has one variable that has all the source files listed (can be both C and C++ files)
  2. All object files are generated in OBJ_DIR
  3. The object directory is created if it does not exist

Here is what I have so far:

...

OBJ_DIR = obj/
BIN_DIR = bin/
PROGRAM = program

SRCS = test1.cpp test2.c

OBJS  = $(addprefix $(OBJ_DIR), \
        $(patsubst %.cpp, %.o,  \
        $(patsubst %.c, %.o, $(SRCS))))

$(BIN_DIR)$(PROGRAM) : $(OBJS)
    $(CREATE_OUT_DIR)
    $(LINK)

$(OBJ_DIR)%.o : %.c
    $(CREATE_OBJ_DIR)
    $(CCOMPILE)

$(OBJ_DIR)%.o : %.cpp
    $(CREATE_OBJ_DIR)
    $(CPPCOMPILE)

...

I'd like to eliminate the call to $(CREATE_OBJ_DIR) for every .o compile. Anyone know how to do this? I tried adding this, but then it would not build the object files:

$(OBJS): | $(OBJ_DIR)

$(OBJ_DIR):
    $(CREATE_OBJ_DIR)

Upvotes: 5

Views: 817

Answers (3)

SuperJames
SuperJames

Reputation: 787

This is what I do:

$(OBJ_LOC)/%.o: $(SRC_LOC)/%.c
    @[ -d $(OBJ_LOC) ] || mkdir -p $(OBJ_LOC)
    g++ ...

But, I am looking at these other answers with great interest.

Upvotes: 0

deek0146
deek0146

Reputation: 984

You already seem to have solved your first point: Have them all in one variable (I shouldn't think you actually need to to separate them into TEMP1 and TEMP2 like you have, just have different build rules)

For the second point, you can tell the compiler where to output the object files (for g++ its like this:

g++ -c MySourceFile.cpp -o obj/MySourceFile.o

The make rule for this would look like:

obj/%.o: %.cpp
    g++ -c $*.cpp -o obj/$*.o

And your third point is also easily solved, as you can have a build rule for it (Just put the directory name in the dependency list for the target, before all of the objects are listed), and the build rule would look like this

obj:
    mkdir obj

Edit: or following your code examples:

$(BIN_DIR)$(PROGRAM) : $(BIN_DIR) $(OBJS) 
$(LINK)

$(BIN_DIR):
    $(CREATE_OUT_DIR) 

Upvotes: 3

Chen Levy
Chen Levy

Reputation: 16408

As for your 3rd point: This question has been asked here before. Unfortunately there is no really good answer for this, and you need to find the least ugly hack from the answer. Personally, I vote for the marker file solution.

Upvotes: 1

Related Questions