Reputation: 320
So far, I have a Makefile that looks like this:
# Program list:
# a.cpp, a.h,
# b.cpp, b.h,
# c.cpp. c.h,
# d.cpp, d.h,
# commonA.cpp, commonA.h,
# commonB.cpp, commonB.h,
# mainA.cpp, mainB.cpp,
# mainC.cpp, mainD.cpp.
CXX=g++
CXXFLAGS = -std=c++11 -g -Wall
prog1: mainA.cpp a.cpp
$(CXX) $(CXXFLAGS) programOne mainA.cpp a.cpp
prog2: mainB.cpp b.cpp
$(CXX) $(CXXFLAGS) programTwo mainB.cpp b.cpp
prog3: mainC.cpp c.cpp commonA.cpp
$(CXX) $(CXXFLAGS) programThree mainC.cpp c.cpp commonA.cpp
prog4: mainD.cpp d.cpp commonA.cpp commonB.cpp
$(CXX) $(CXXFLAGS) programFour mainD.cpp d.cpp commonA.cpp commonB.cpp
# etc...
I've had a look at the make GNU documentation, and it's fairly daunting - I've tried to understand as much as I can from it. I was wondering given my example how would I be able to shorten this even more than what it currently is? Is there a good rule to use that could make all the object files for each of the files in the program list above, and then I include the particular objects for each part? Any help is much appreciated!
Upvotes: 0
Views: 482
Reputation: 101081
Here's a tip: make has built-in rules that know how to create all kinds of different targets. Taking advantage of them will give you the shortest possible makefile.
Here's another tip: make uses string comparison to match up targets, prerequisites, and rules. So choosing the names of your files and programs wisely will give the best chance of taking advantage of make's built-in rules.
For example, you know already that a source file foo.cpp
will be compiled into an object file foo.o
. Make has a built-in rule that will handle that for you. If you also choose to name one of your source files so that it maps to the name of the program you want to create, you can take advantage of a built-in rule that will link your program as well.
As mentioned in the comments above, your rules are broken because the makefile target is named one thing (e.g., prog1
) but the link line generates a different thing: programOne
(here I'm assuming you simply forgot the -o
option in your link line when you posted your code... please remember that when asking for help on SO--or really anywhere--it's best to create a SSCE). That should never happen for a non-special target; every rule should create a file with the identical name as the target.
Typically for C/C++ programs, the source file containing main()
is named the same as the program you want to create. So for example if you want to create a program programOne
then the source file containing main()
should be named programOne.cpp
.
If you follow these recommendations, then your entire makefile can be just:
CXX = g++
CXXFLAGS = -std=c++11 -g -Wall
all: programOne
programOne: programOne.o a.o
and that's it. Make knows how to build those targets for you so you don't have to tell it. If you want more programs, just add them as well:
all: programOne programTwo
programOne: programOne.o a.o
programTwo: programTwo.o b.o
The one issue left is header files prerequisites. If you want you can declare them yourself like this:
programOne.o: programOne.h a.h
etc. That's very simple but tedious to maintain. If you want to get make to configure them for you you can, but it's not simple. See this discussion for some ideas.
Upvotes: 1