Any way to use variables as rules and prerequisites in GNU Make? - c++

I'm trying to set up my Makefile in such a way that I can define all of the inputs and outputs in some variables so I only have to write a single rule to compile the project. This allows me to minimize Makefile code and still have control over what is in my project. This is the relevant snippet of code:
ROOT_OBJS= \
$(B)/main.o \
$(B)/src1.o
ROOT_SRC= \
$(SRC)/main.cpp \
$(SRC)/src1.cpp
$(TARGET) : $(ROOT_OBJS)
$(LD) $(LD_FLAGS) $^ -o $#
$(ROOT_OBJS) : $(ROOT_SRC)
$(CXX) $(CFLAGS) $< -o $#
This mostly works except for the $< part in the second rule, it always uses main.cpp. Is there any fix to this or am I going about this the wrong way?
EDIT: for clarification, this is the output I expect:
g++ main.cpp -o main.o
g++ src1.cpp -o src1.o
This is the output I get:
g++ main.cpp -o main.o
g++ main.cpp -o src1.o
I am aware this is because $< takes the first dependency, I thought make would be smart enough to figure it out because the .o behavior is what I want.
$^ is not what I am looking for. I want gcc to make a separate object file for each cpp file.

$< always takes the first prerequisite. Since your rule expands to
$(B)/main.o $(B)/src1.o : $(SRC)/main.cpp $(SRC)/src1.cpp
$(CXX) $(CFLAGS) $< -o $#
$(SRC)/main.cpp is always that first prerequisite. There is no magical connection between $(B)/main.o and $(SRC)/main.cpp as far as make is concerned.
If you want your rules to make this connection, you have to code it into the rules. There are several ways to get this right. The most straight forward is to write separate rules for each target:
$(B)/main.o : $(SRC)/main.cpp
$(CXX) $(CFLAGS) $< -o $#
$(B)/src1.o : $(SRC)/src1.cpp
$(CXX) $(CFLAGS) $< -o $#
You can also use a pattern rule like this:
$(B)/%.o : $(SRC)/%.cpp
$(CXX) $(CFLAGS) $< -o $#
Here, $< does the right thing because $(SRC)/%.cpp is parameterized with the pattern, so it will expand to the correct source file.
The biggest gun you have is generating the individual rules:
STEMS := main src1
$(foreach stem,$(STEMS), \
$(eval $(B)/$(stem).o: $(SRC)/$(stem).cpp ; $(CXX) $(CFLAGS) $< -o $#))
Here I loop over all the words in $(STEMS) with the $(foreach) intrinsic function call and generate one rule per iteration with the $(eval) function call. This is GNU Make syntax, only, other make implementations are likely not to have these features. However, it is the most general and flexible way to tell make what to do. GNU Make's function call syntax is turing complete, so you can perform any calculations you need to come up with the correct rules. Readability will suffer, though, so use this with care.

Related

what does % mean in a makefile rule

So i know that the pattern rule %.o : %.cpp is for making any file.o from a file.cpp
But what I want is different. Let's say I want to make a file1.o from folder1/file1.cpp, and a file2.o from folder2/file2.cpp.
What i thought about doing was :
file1=folder1/file1
file2=folder2/file2
%.o: $(%).cpp
But that doesn't work. Do anyone have an idea on how to do that apart from manually doing :
file1=folder1/file1
file2=folder2/file2
file1.o: $(file1).cpp
file2.o: $(file2).cpp
The meaning of % in GNU Make is documented in the seciton on Defining and Redefining Pattern Rules.
If the target name is foo.o, then % is foo. I don't want to go into any more depth on the meaning of % here.
In your case, the dependencies between the object files and the source files cannot be expressed easily using a single simple rule. I would advise making the rules explicit instead of using a pattern-based rule.
file1.o : folder1/file1.cpp
file2.o : folder2/file2.cpp
You'll need to add the commands to build those targets too.
file1.o : folder1/file1.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $# $^
file2.o : folder2/file2.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $# $^

Looping makefile with multiple main functions

I am trying to write a makefile that can create one executable per main function.
I have a list of files: main1.cpp, main2.cpp, and main3.cpp. They each contain an int main() function. Obviously I can't build these into one exec, which is not the goal here, so how can I build each one of these into its own executable? This is one solution:
main1: main1.cpp
$(CC) -o $# $^
main2: main2.cpp
$(CC) -o $# $^
main3: main3.cpp
$(CC) -o $# $^
But there MUST be a better way to do this. Is there some type of looping feature to makefiles that will make this process easier? Like a for loop?
A mixture of wildcard, patsubst and static pattern rules, plus the standard make variables for C++ compilation and linking:
SRCS := $(wildcard main*.cpp)
EXES := $(patsubst %.cpp,%,$(SRCS))
$(EXES): %: %.cpp
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $# $< $(LDLIBS)
But as make knows already how to make all this you could as well get rid of your Makefile and just type make main1...
While it's not a very sophisticated makefile, your solution is fine for three simple programs. You could make it more generic and support building all three targets at the same time with an "all" target.
all: main1 main2 main3
main1: main1.cpp
$(CC) -o $# $^
main2: main2.cpp
$(CC) -o $# $^
main3: main3.cpp
$(CC) -o $# $^

Simple Makefile using WiringPi

I'm new to Makefiles. I've been making a simple C++ library using WiringPi for my RaspberyPi related projects. So far its very simple with things like an LED class, DuelLED, Motor, Button, etc (both .h and .cpp). I was able to piece together a Makefile but I am getting an error "No rule to make target RumPi.o needed by RumPi". (Note: The name of my library is called RumPi)
Thanks for all the help, Here is the final fix:
CXX = g++
CXXFLAGS = -std=c++11
LDLIBS = -lwiringPi
HEADERS = Components/Headers/RumPi.h ./Common.h Components/Headers/Component.h Components/Headers/Vehicle.h Components/Headers/Motor.h Components/Headers/Receiver.h Components/Headers/DualLED.h Components/Headers/LED.h Components/Headers/RGBLED.h Components/Headers/Relay.h
OBJECTS = RumPi.o Vehicle.o Motor.o Receiver.o DualLED.o LED.o RGBLED.o Relay.o
default: RumPi
RumPi: $(OBJECTS)
$(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $#
%.o: Components/Implementations/%.cpp
$(CXX) $(CXXFLAGS) -c -o $# $<
$(OBJECTS): $(HEADERS)
clean:
-rm -f $(OBJECTS)
-rm -f RumPi
That message means make can't figure out how to build that target (RumPi.o). Do you have a Components/Implementations/RumPi.cpp file? Do all the header files you've listed in the $(HEADERS) variable actually exist? If either of those is not true, then your pattern rule will not match. If your pattern rule doesn't match (and the default rule doesn't match) then make can't figure out how to build the object file.
If you want full details you can run make -d and examine the debug output. You might want to redirect it to a file so you can look at it with less or a text editor since there's a lot of output.
By the way, you should not add the -lwiringPi option to your compile line. Libraries are only used at link time, not compile time.
ETA
Something else you should consider is rewriting your pattern rule so that only the source file is listed as a prerequisite and moving the headers to a separate line:
%.o: Components/Implementations/%.cpp
gcc -c $< -o $# -lwiringPi
$(OBJECTS): $(HEADERS)
The advantage to this is you'll get a clearer error message if one of the headers is not found. When you use a pattern rule, make will try to match all the patterns it can and if none match it tells you it doesn't know how to build the target. Since there are usually many different ways to build a target, make doesn't show an error for every one that doesn't match.
But if you declare a direct explicit prerequisite relationship between two files, rather than using a pattern that may or may not match, then if there is a missing file make will tell you directly.
ETA2
In your original makefile you had a rule like this:
RumPi: $(OBJECTS)
gcc $(OBJECTS) -o $# -lwiringPi
but then later you removed it. Why did you take this out? You need this rule to tell make how to link your executable file RumPi.
Also, you shouldn't be using gcc as the compiler/linker for C++ code; gcc is for C, not C++. You should use g++ for C++ code. And it's best to contain this information in variables so it's easy to find and modify (even from the command line if you like). The standard variable names for the C++ compiler is CXX etc.
Your makefile should look something like this:
CXX = g++
CXXFLAGS = -std=c++11
LDLIBS = -lwiringPi
HEADERS = Components/Headers/RumPi.h ./Common.h Components/Headers/Component.h \
Components/Headers/Vehicle.h Components/Headers/Motor.h Components/Headers/Receiver.h \
Components/Headers/DualLED.h Components/Headers/LED.h Components/Headers/RGBLED.h \
Components/Headers/Relay.h
OBJECTS = RumPi.o Vehicle.o Motor.o Receiver.o DualLED.o LED.o RGBLED.o Relay.o
default: RumPi
RumPi: $(OBJECTS)
$(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $#
%.o: Components/Implementations/%.cpp
$(CXX) $(CXXFLAGS) -c -o $# $<
$(OBJECTS): $(HEADERS)
clean:
-rm -f $(OBJECTS)
-rm -f RumPi

makefile picks the same source file again and again for different objects

I am trying to write a makefile, suppose I have 4 source files in a directory src/app/:
src/app/file1.cpp
src/app/file2.cpp
src/app/file3.cpp
src/app/file4.cpp
and I want to create different object files (i.e. file1.o, file2.o etc.) into another directory called obj/. In the makefile, I am defining the variables like this:
$(SRC) := $(wildcard src/app/*.cpp)
$(OBJ) := $(addprefix obj/,$(notdir $(SRC:.cpp=.o)))
and my commands are like this:
all: $(OBJ)
$(OBJ): $(SRC)
$(CC) $(CFLAGS) -I/src/app/app.h -c $< -o $#
so when I run make, I see these operations:
g++ -g -Wall -I/src/app/app.h -c src/app/file1.cpp -o obj/file1.o
g++ -g -Wall -I/src/app/app.h -c src/app/file1.cpp -o obj/file2.o
g++ -g -Wall -I/src/app/app.h -c src/app/file1.cpp -o obj/file3.o
g++ -g -Wall -I/src/app/app.h -c src/app/file1.cpp -o obj/file4.o
You can see, the object files have different names but the source file is the same. How do I fix it ?
Please note that I can't use %.o: %.cpp since I have other targets in my makefile for different purposes.
If you can't use
obj/%.o: src/app/%.cpp
then the second simplest way is to add $(OBJ): to the front:
$(OBJ): obj/%.o: src/app/%.cpp
It's called "static pattern rules" - look it up in the GNU Make manual.
I have found a way to solve this (thanks to Zereges for the idea):
$(RGAOBJ): $(RGASRC)
$(CC) $(CFLAGS) -I/src/app/app.h -c \
$(addprefix src/app/,$(notdir $(#:.o=.cpp))) -o $#
I think there is a better way to do.
So any other pointer will be helpful.
The $< variable picks up the first dependency. It is used with generic targets which have variable targets and produce different results. The compile target would match a pattern as target and have a generic dependency. The first target doesn't change in your case.
Your constraint of not being able to use a generic rule is entirely defeating the purpose of the $< variable. A somewhat naive work-around is to translate the destination name back into the source, e.g.,
$(OBJ): $(SRC)
$(CC) $(CFLAGS) -I/src/app/app.h -c $(#:%.o=%.cpp) -o $#
The problem with that approach is that no all object files depend on all source files. As a result, every time one of the source files is changed all object files are produced. For tiny projects and source that may be viable. On anything which I'd consider a real project neither of these conditions holds.
My understanding on your statement on not being able to use pattern rules is that you already have rules for the same pattern but you need to build some targets with some special rules. A work around for that situation is to build targets with a custom suffix which actually build something different and just use a marker file to prevent unnecessary rebuilds. For example:
all: $(OBJ:%=%.custom)
%.o.custom: %.cpp
$(CC) $(CFLAGS) -W -I/src/app/app.h -c $< -o $(#:%.custom=%) && touch $#

Write makefile for .cpp and .hpp c++

I need help to create a proper makefile (supporting incremental compilation) for multiple .hpp and .cpp files.
I've been looking for information about how to create a proper makefile, but I'm not really sure on how to do it.
I have the following files:
2048.cpp, game.cpp, game.hpp, gameutils.cpp, gameutils.hpp, menu.cpp, menu.hpp, saveandback.cpp, saveandback.hpp and tile.hpp
Right now I'm using the following makefile:
all: 2048.cpp tile.hpp menu.hpp menu.cpp gameutils.hpp gameutils.cpp saveandback.hpp saveandback.cpp game.hpp game.cpp
g++ -g -W -Wall --pedantic -DNDEBUG 2048.cpp -o power
clean:
$(RM) power
Thank you for your help.
Caveat: I haven't used make in a while so I may be a little rusty on POSIX vs. GNU-make specific stuff. There may also be new features released in the last few years that I'm not aware of. Please feel free to give corrections. Also most of this is from memory.
There are a few things missing from your knowledge set here that you can use to create a decent makefile that only re-compiles things when needed:
Generic Rules - These can be used to provide a generic rule for building a filename with one suffix from another. E.g. the following defines a rule for creating any *.o from its corresponding *.cpp:
%.o: %.cpp
stuff
In POSIX make these rules are actually specified as:
.cpp.o:
stuff
I'm using GNU syntax below but you can (and might want to) replace with POSIX syntax (moot if you leave them out and use the implicit rules, though, see below).
Automatic Variables
$< will expand to the input of the rule.
$# will expand to the target of the rule.
Variables - You can declare variables and give them values, e.g.:
SOURCES=2048.cpp gameutils.cpp saveandback.cpp
Etc.
Text Replacement - You can use text replacement functions to replace suffixes, e.g.:
OBJECTS=$(SOURCES:.cpp=.o)
Will set OBJECTS equal to SOURCES but with the .cpp's changed to .o.
Multiple Rules - If multiple rules are specified for the same target, their prerequisites are merged.
Phony Targets
Putting that all together you can get a start, leaving out header dependencies for now:
SOURCES=2048.cpp menu.cpp gameutils.cpp saveandback.cpp game.cpp
OBJECTS=$(SOURCES:.cpp=.o)
power: $(OBJECTS)
g++ $(OBJECTS) -o $#
%.o: %.cpp
g++ -c $< -o $#
And it's traditional to define an all rule, which is a phony target since there isn't actually a file named "all":
.PHONY: all
SOURCES=2048.cpp menu.cpp gameutils.cpp saveandback.cpp game.cpp
OBJECTS=$(SOURCES:.cpp=.o)
all: power
power: $(OBJECTS)
g++ $(OBJECTS) -o $#
%.o: %.cpp
g++ -c $< -o $#
Now, make actually has some default rules already, including one for %.o: %.cpp, and also it has some default variables. So you can reduce the above to this if you'd like (personally I prefer to explicitly specify rules, but that's just me):
.PHONY: all
SOURCES=2048.cpp menu.cpp gameutils.cpp saveandback.cpp game.cpp
OBJECTS=$(SOURCES:.cpp=.o)
all: power
power: $(OBJECTS)
$(CXX) $(CXXFLAGS) $(OBJECTS) -o $#
Now, as for your headers, keeping in mind the multiple rules thing, you can simply add those prerequisites by hand based on their includes, e.g.:
.PHONY: all
SOURCES=2048.cpp menu.cpp gameutils.cpp saveandback.cpp game.cpp
OBJECTS=$(SOURCES:.cpp=.o)
all: power
power: $(OBJECTS)
$(CXX) $(CXXFLAGS) $(OBJECTS) -o $#
2048.o: menu.hpp game.hpp
menu.o: menu.hpp
game.o: game.hpp
And so on. You probably also want a "clean" rule, another phony target, and it doesn't hurt to put your binary name in a variable since you use it in a few places, e.g.:
.PHONY: all clean
SOURCES=2048.cpp menu.cpp gameutils.cpp saveandback.cpp game.cpp
OBJECTS=$(SOURCES:.cpp=.o)
BINARY=power
all: $(BINARY)
clean:
$(RM) $(BINARY) $(OBJECTS)
$(BINARY): $(OBJECTS)
$(CXX) $(CXXFLAGS) $(OBJECTS) -o $#
And actually if you pass -MM to gcc it'll generate Makefile dependencies automatically for you, based on the source file's includes. See here for details and an example.