Based on some SO questions -- and some further reference found --, I'm trying to build a makefile able to:
$(SRC)
, the .cpp
files to be compiled;.cpp
, producing .o
objects;.so
shared objects from each .o
formerly compiled.What the make file is supposed to do to achieve that is:
$(SRC)
, the .cpp
files to be compiled;.cpp
using -MM
compiler's flag;$(eval ...)
;.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
.
A dependency is a file that is used as input to create the target. A target often depends on several files. A command is an action that make carries out. A rule may have more than one command, each on its own line.
The simple answer is that %.o is a target that matches any file ending in .o. "%.o: %. c" means that any file ending in .o depends on the same filename ending in . c to be present.
If you want a string to have a dollar sign, you can use $$ . This is how to use a shell variable in bash or sh . Note the differences between Makefile variables and Shell variables in this next example.
makefile and Makefile are special names because if make is called without the -f option it automatically searches for them, in this order, and use the first it finds. Note that GNU make also considers GNUmakefile , and prefers it over makefile and Makefile . Other make implementations can have other default names.
-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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With