Mr. D February 2016

Makefile with multiple directories and dependencies

``I am pretty new to Makefile and I am trying to build a project. This is the structure of my project:

-Project
|-generic
|  |-include
|  |-src
|-specific
|  |-include
|  |-src
|-Makefile
|-bin    

Here generic contains mainly interface classes (virtual), and files in specific may depends on those. I want to compile all sources and put their corresponding .o files in bin and also create a static library in bin.

EDIT:

CC=k1-g++
CPPFLAGS=-c -I$(GENERIC_INCLUDE_DIR) -I$(SPECIFIC_INCLUDE_DIR) -Os -std=gnu++11 -mos=nodeos 
CXXFLAGS=-c -I$(GENERIC_INCLUDE_DIR) -I$(SPECIFIC_INCLUDE_DIR) -Os -std=gnu++11 -mos=nodeos 
LFLAGS=-pthread -lnodeos  

GENERIC_INCLUDE_DIR=generic/include
SPECIFIC_INCLUDE_DIR=specific/include
GENERIC_SRC_DIR=generic/src
SPECIFIC_SRC_DIR=specific/src


LIB = libengine.a
BIN_DIR=bin

vpath %.cpp $(GENERIC_SRC_DIR) $(SPECIFIC_SRC_DIR)
SOURCES := $(wildcard $(GENERIC_SRC_DIR)/*.cpp $(SPECIFIC_SRC_DIR)/*.cpp)
#SOURCES := $(wildcard $(GENERIC_SRC_DIR)/*.cpp $(SPECIFIC_SRC_DIR)/*.cpp)
SOURCES := $(notdir $(SOURCES))
OBJECTS := $(patsubst %.cpp,$(BIN_DIR)/%.cpp.o,$(SOURCES))



all: $(OBJECTS) $(LIB)

$(LIB): $(OBJECTS)
    ar -cvq $(BIN_DIR)/$@ $^

#$(BIN_DIR)/%.cpp.o: $(GENERIC_SRC_DIR)/%.cpp
#   $(CC) $(CPPFLAGS) $< $(LFLAGS) -o $@

$(BIN_DIR)/%.cpp.o: %.cpp
    $(CC) $(CPPFLAGS) $< $(LFLAGS) -o $@




.PHONY: clean

clean:
    rm -f $(BIN_DIR)/* 

Any help would be appreciated

Answers


Beta February 2016

Suppose you have generic/src/foo.cpp and specific.src/bar.cpp.

This:

$(BIN_DIR)/%.o: %.cpp
    $(CC) $(CPPFLAGS) $*.cpp -o $@

is pretty close to what you need (I've replaced $(BIN_DIR)/$*.o with the automatic variable $@, which expands to the name of the target); the only problem is that it doesn't work. This rule tells Make it can build obj/foo.o from foo.cpp, but there is no foo.cpp. There's a generic/src/foo.cpp, but Make doesn't know that that's what you meant. We could write a rule like this:

$(BIN_DIR)/%.o: $(GENERIC_SRC_DIR)/%.cpp
    $(CC) $(CPPFLAGS) $*.cpp -o $@

But a tidier way is to use the vpath directive:

vpath %.cpp $(GENERIC_SRC_DIR) $(SPECIFIC_SRC_DIR)

$(BIN_DIR)/%.o: %.cpp
    $(CC) $(CPPFLAGS) $*.cpp -o $@

This will do nicely for building any one object file, but you say you want to compile "all sources". That isn't always a good idea, but if that's what you want it isn't hard, we use wildcard to obtain a list of all the sources, then convert that into a list of corresponding object files, then build them all:

SOURCES := $(wildcard $(GENERIC_SRC_DIR)/*.cpp $(SPECIFIC_SRC_DIR)/*.cpp)
SOURCES := $(notdir $(SOURCES))
OBJECTS := $(patsubst %.cpp,%.o, $(SOURCES))
# We could have done that all in one line, but this way is easier to read.

all: $(OBJECTS)

Now for the library:

vpath %.o $(BIN_DIR)

$(BIN_DIR)/$(LIB): $(OBJECTS)
    ar -cvq $@ $^

Further refinements a

Post Status

Asked in February 2016
Viewed 1,074 times
Voted 14
Answered 1 times

Search




Leave an answer