Writing dependencies in makefile, with makefile

3.8k Views Asked by At

Based on some SO questions -- and some further reference found --, I'm trying to build a makefile able to:

  • find, given the directories in $(SRC), the .cpp files to be compiled;
  • compile the .cpp, producing .o objects;
  • generate .so shared objects from each .o formerly compiled.

What the make file is supposed to do to achieve that is:

  • find, given the directories in $(SRC), the .cpp files to be compiled;
  • build the dependency list for each .cpp using -MM compiler's flag;
  • annotate/add each dependency using $(eval ...);
  • evaluate/solve each dependency found, producing both the .o and .so files.

What do I have so far: I've been able to do quite the whole thing, except for making it work (: The error I'm getting states that there is, somehow, an empty label '' as dependency:

$ make make: * No rule to make target ', needed by /home/rubens/bin/label.o'. Stop.

So, here is the makefile I'm yet not able to run:

# Directories
SRC := process init
BIN := $(HOME)/bin

LIB := watershed
LIBPATH := $(WATERSHED)/lib
INC := $(WATERSHED)/include $(XERCES)/include

# Paths
MPICPP := mpic++
SOURCES := $(shell find $(SRC) -name '*.cpp')
OBJECTS := $(addprefix $(BIN)/, $(notdir $(SOURCES:.cpp=.o)))
SHARED := $(OBJECTS:.o=.so)

# Flags 
CFLAGS := -std=c++0x -O2 -Wall -fPIC
CFLAGS += $(foreach inc, $(INC), -I $(inc))
LFLAGS :=
LFLAGS += $(foreach lib, $(LIB), -l $(lib))
LFLAGS += $(foreach path, $(LIBPATH), -L $(lib))

# Rules
$(SHARED): | bindir
%.o:
        @echo $@ -- [$<][$^][$*]
        @echo $(MPICPP) $(CFLAGS) -c $< -o $@

%.so: %.o
        @echo $(MPICPP) $(LFLAGS) -shared $< -o $@

bindir:
        @mkdir -p $(BIN)

# Utilities
.PHONY: all clean
all: $(SHARED)
clean:
        @rm -f $(OBJECTS) $(SHARED)

# Dependencies
define dependencies
$(addprefix $(BIN)/, $(notdir $(1:.cpp=.o))): \
        $(shell $(MPICPP) $(CFLAGS) -MM $(1) | sed 's/^.*\.o:[ ]*//')
endef
$(foreach src, $(SOURCES), $(eval $(call dependencies, $(src))))

Where exactly seems to be the error: It seems to be caused by the dependency generation step, as, when I remove any empty lines , piping the output to grep, as follows:

define dependencies
$(addprefix $(BIN)/, $(notdir $(1:.cpp=.o))): \
        $(shell $(MPICPP) $(CFLAGS) -MM $(1) | sed 's/^.*\.o:[ ]*//' | \
        grep -v ^$)
endef

The error somehow digivolves to an empty list of dependencies; I'm able to see the list is actually empty with the echo's in rule %.o: -- the only variables not empty are $@ and $*.

/home/rubens/bin/label.o -- [][][/home/rubens/bin/label]

mpic++ -std=c++0x -O2 -Wall -fPIC -I /home/rubens/libwatershed/include -I /home/rubens/xerces-c-3.1.1/include -c -o /home/rubens/bin/label.o

mpic++ -l watershed -L -shared /home/rubens/bin/label.o -o /home/rubens/bin/label.so

Any advice on better ways to solve this are very, very welcome; yet, I would really like to finish writing this makefile, before I get to use something like Cmake or Scons.

2

There are 2 best solutions below

1
On BEST ANSWER

-MM will already generate the dependencies on a Makefile format so you could simplify this by generating the dependencies for each *.cpp into a same file, then just doing an -include $(DEPS_FILE). That's probably more maintainable than using eval.

1
On

At line of definition of makefile variable SOURCES, search for the cpp files, you probably have to rewrite like this: find $(SRC) -name "*.cpp"