How to include a makefile into an other makefile?
Thanks to @Jonathan-wakely to provide the initial concepts for this solution.
There are probably many things that may be improved, but it works.
Requirements summary:
- Makefiles should work standalone
- The main makefile will includes sub-makefiles
- No conflicts or path problem should appear.
A simple solution is to call recursively makefiles:
- Create a "normal" script for leaf makefiles
- Using an empty target allow to execute always make calls for example "sub-make:" without any requirement after ":"
- Use the "-C" parameter to set the root directory for the make call.
- Create the final linking with binaries created by sub-makefiles.
Example for the main makefile:
#all make recursive calls
sub-make:
make -C Vector3D
make -C Color
#final linking
CPP = g++
FLAGS = $(CXXINCS) -Wall -O0
all: main
main: main.o Vector3D/Vector3D.o Color/Color.o
$(CPP) main.o Vector3D/Vector3D.o Color/Color.o -o main
main.o: main.cpp
$(CPP) -c main.cpp -o main.o $(FLAGS)
There is probably a better way to provide *.o binaries to the linker without writing all full path, but that is another problem.
Creating the clean target. For leaf makefiles, there are no special considerations to take, but for the main makefile, it must call sub-clean rules.
clean:
make -C Vector3D clean
make -C Color clean
rm -f *.o main
EDITING:
Here is the makefile structure I have done, for if it may be useful to anyone.
To work, All classes must be in it own folder with:
- .hpp header
- .cpp code
- main.cpp for testing
- Required classes (LIBS) directory are specified with "$(LIBSPATH)LibName" in relation to this makefile.
Makefile
#Following configuration may be set with a parameter:
# e.g: make FLAGS="-Wall -O0"
FLAGS = $(CXXINCS) -Wall -O0
#Configurable variables
EXEC = main
CLASS = World
LIBS = Color Vector3D Triangle
LIBSPATH = ../
#Static content
CPP = g++
OBJS = $(foreach dir, $(LIBS), $(LIBSPATH)$(dir)/$(dir))
all: $(EXEC)
clean:
rm -f *.o $(EXEC)
$(foreach dir,$(LIBS),make clean --no-print-directory -C $(LIBSPATH)$(dir);)
$(EXEC): $(CLASS).o $(EXEC).o $(OBJS:=.o)
$(CPP) $(CLASS).o $(OBJS:=.o) $(EXEC).o -o $(EXEC)
$(EXEC).o: $(EXEC).cpp
$(CPP) -c $(EXEC).cpp -o $(EXEC).o $(CXXFLAGS)
$(CLASS).o: $(CLASS).cpp $(CLASS).hpp
$(CPP) -c $(CLASS).cpp -o $(CLASS).o $(CXXFLAGS)
$(OBJS:=.o): $(OBJS:=.cpp) $(OBJS:=.hpp)
make --no-print-directory -C $(LIBSPATH)$(strip $(foreach dir,$(LIBS),$(if $(findstring $(dir),$@),$(dir))))
I would like all makefile independent, so I may copy/past the class folder into a new project and it still working, or I may exec the makefile alone without changes on it.
I'm pretty sure that's not possible. Your makefiles either need to be standalone, in which case you can make the top-level files invoke make
in lower level directories recursively (so do not include
them) or you can have a single non-recursive makefile formed by including other makefiles. I don't think it's possible to do both.
How to include (correctly) a makefile into an other makefile?
The only valid answer is "using the include
directive" (other than the usual "it depends".) Any other advice depends on the structure of the makefiles. Makefiles designed to be included will obviously be easier to include. Just including some random makefile and hoping it will work ... won't work. Check out Implementing non-recursive make and Boilermake for how to make non-recursive makefiles work.
Note that there's no need to include them at the top of the file and doing so may be a bad idea, as the default target becomes the first one in the included file.