Makefile with sub-directories

Right now I am doing Object-Oriented-Programming (OOP) in C++, and
I am getting to the point where I want each pair of class files (one .h
file and one .cpp file) in there own directory. How do I edit my Makefile
so that it looks in these sub-directories? Can this be done with the -I
command? My Makefile works except when I put `ThisExample.cpp' and `ThisExample.o' in a subdirectory called 'This'. I get the following error
message:

prompt# make
make: *** No rule to make target `ThisExample.cpp', needed by `ThisExample.o'. Stop.

Thanks in advance for your time and help in solving this problem.

------------------------------------------------------------------------

This is my Makefile:

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Makefile for Unix & Linux Systems #
# using a GNU C++ compiler #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# compiler flags
# -g --Enable debugging
# -Wall --Turn on all warnings
# -D_USE_FIXED_PROTOTYPES_
# --Force the compiler to use the correct headers
# -ansi --Don't use GNU ext; do use ansi standard.

CXX = g++
CXXFLAGS = -ansi -Wall

INCLUDE = -I./This/This*
OBJECTS = main.o ThisExample.o
EXE = Example
MAIN = main
TARGET1 = ThisExample

#Link command:
$(EXE): $(OBJECTS)
$(CXX) $(CXXFlAGS) $(INCLUDE) $(OBJECTS) -o $(EXE)

#Compilation commands:
$(MAIN).o: $(MAIN).cpp
$(CXX) $(CXXFlAGS) $(INCLUDE) -c $(MAIN).cpp -o $(MAIN).o

$(TARGET1).o: $(TARGET1).cpp
$(CXX) $(CXXFlAGS) $(INCLUDE) -c $(TARGET1).cpp -o $(TARGET1).o


#make clean
clean:
rm -f *.o



aargh, make and subdirectories.

There are two ways of dealing with this:

1. Recursive make
In each subdirectory you have a Makefile that compiles the code in that subdirectory to object files.
There is a main Makefile in the root directory that calls these Makefiles and then does a final link
http://www.makelinux.net/make3/make3-CHP-6-SECT-1

2. Have one Makefile in the root using full paths from there for every operation (compilation and linking)

Recursive make is the traditional way but is actually full of holes, see this
http://miller.emu.id.au/pmiller/books/rmch/

With a single Makefile you have to put the paths into the commands, you could use macros or just literals

I started off with recursive make but then abandoned it for one Makefile. The whole thing is handcrafted, when I add
a new class, I have to add new commands to build and link it into my (growing) Makefile

as a treat a small part of my Makefile

# maths object files
math/Vec3.o : math/Vec3.h math/Vec3.cpp
g++ -c -o math/Vec3.o math/Vec3.cpp
math/Vec4.o : math/Vec3.o math/Vec4.h math/Vec4.cpp
g++ -c -o math/Vec4.o math/Vec4.cpp
math/Quat.o : math/Vec4.o math/Quat.h math/Quat.cpp
g++ -c -o math/Quat.o math/Quat.cpp

tedious maybe, if you don't want to do this that's understandable. Using this method the whole dependency tree is defined precisely (including header files). So if I make a change only that part that needs to be recompiled is done so and nothing is missed out.
While I think subdirectories are a good way to group files, I do think a directory for each and every .cpp/.h pair is overkill. I tend to group when by functionality: all the parser files in one subdirectory, the gui files in another, the utility files another, ... There are usually about a handful of directories.

But not each and every pair!!!

And I speak from bitter, currently ongoing, experience merging a project where someone had the same bright idea. So we now have 100+ subdirectories in the project, most with just two files. It is far from easy to maintain!
To: andywestken

Right now I am just getting started with multiple files. As the number of files increases I will find a better system.
Another Question:

How do I specify the full path for the .h file(s)?

-------------------------------------------------------------------------------------
Here is my new Makefile:

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Makefile for Unix & Linux Systems #
# using a GNU C++ compiler #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# compiler flags
# -g --Enable debugging
# -Wall --Turn on all warnings
# -D_USE_FIXED_PROTOTYPES_
# --Force the compiler to use the correct headers
# -ansi --Don't use GNU ext; do use ansi standard.

CXX = g++
CXXFLAGS = -O3 -ansi -Wall
DEBUGFLAGS = -g -ansi -Wall

#Link command:
Example: main.o ./This/ThisExample.o
$(CXX) main.o ./This/ThisExample.o -o Example

#Compilation commands:
main.o: main.cpp
$(CXX) -c main.cpp -o main.o

./This/ThisExample.o: ./This/ThisExample.cpp
$(CXX) -c ./This/ThisExample.cpp -o ./This/ThisExample.o


#make clean
clean:
rm -f *.o
-------------------------------------------------------------------------------------

Here is the output:

g++ -c main.cpp -o main.o
main.cpp:3:25: fatal error: ThisExample.h: No such file or directory
compilation terminated.
make: *** [main.o] Error 1
:-) As long as it's before you exceed 10 subdirectories!
Last edited on
Try adding -I./This to the compiler instructions.

You might also need -I. (or should it be -I..) if ThisExample.h includes files from the parent directory.
Here is the final Makefile:

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Makefile for Unix & Linux Systems #
# using a GNU C++ compiler #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# compiler flags
# -g --Enable debugging
# -Wall --Turn on all warnings
# -D_USE_FIXED_PROTOTYPES_
# --Force the compiler to use the correct headers
# -ansi --Don't use GNU ext; do use ansi standard.

CXX = g++
CXXFLAGS = -O3 -ansi -Wall
DEBUGFLAGS = -g -ansi -Wall
INCLUDE = -I./This

#Link command:
Example: main.o ./This/ThisExample.o
$(CXX) $(CXXFLAGS) $(INCLUDE) main.o ./This/ThisExample.o -o Example

#Compilation commands:
main.o: main.cpp
$(CXX) $(CXXFLAGS) $(INCLUDE) -c main.cpp -o main.o

./This/ThisExample.o: ./This/ThisExample.cpp
$(CXX) $(CXXFLAGS) $(INCLUDE) -c ./This/ThisExample.cpp -o ./This/ThisExample.o


#make clean
clean:
rm -f *.o
--------------------------------------------------------------------------------------------------------------
Thanks for the help. It is working perfectly!
Topic archived. No new replies allowed.