How to construct a makefile that support multiple targets with main() - c++

I have a makefile that's been working pretty great for the past couple weeks. However, now that I've added another target to my project with "main", it starts to flip out a bit.
CC=g++
CCOPTS=-g -w
OBJS = $(BINDIR)/manager.o $(BINDIR)/rtngnode.o
TARGETS = $(BINDIR)/manager $(BINDIR)/rtngnode
BINDIR = build
all: $(TARGETS) $(OBJS)
clean:
rm -f $(TARGETS) $(OBJS)
.PHONY: all clean
$(TARGETS): $(OBJS)
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
$(BINDIR)/%.o: %.cpp
$(CC) -c $(CCOPTS) -o $# $<
I don't quite understand makefiles still... so I'm not sure what's going on. I get these two errors:
build/rtngnode.o: In function `__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<int const, Node> > >::new_allocator()':
/home/caleb/Documents/dev/tote2/mp2/rtngnode.cpp:5: multiple definition of `main'
build/manager.o:/home/caleb/Documents/dev/tote2/mp2/manager.cpp:161: first defined here
build/manager.o: In function `main':
manager.cpp:(.text+0xefb): undefined reference to `NetworkConnection::NetworkConnection(char const*, char const*)'
In my rtngnode target, I have dependancies on the tcpcon class... and my manager target also has a main() reference. I'm pretty confused... so not even sure if I'm asking the right question.
I guess my question is:
For OBJS and TARGETS, what goes there? All of my .cpp files? All of my executables?
How do I like the two together?

The other answers are all accurate, but I think the key thing to understand is this rule:
$(TARGETS): $(OBJS)
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
doesn't do what you seem to think that it does. This expands to:
$(BINDIR)/manager $(BINDIR)/rtngnode : $(BINDIR)/manager.o $(BINDIR)/rtngnode.o
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
Make doesn't try to infer some magical matching up of targets to prerequisites here; instead make repeats the entire rule again for each target, but with all the prerequisites. The rule above is identical to writing this:
$(BINDIR)/manager : $(OBJS)
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
$(BINDIR)/rtngnode : $(OBJS)
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
Given this you can see what the problem is: you're trying to link ALL the objects into EACH executable.
Since your programs are built from a single object file with the same prefix as the program name, you actually don't need to write a rule for them at all; you can rely on make's built-in rule for building the programs. Just take the above rule out completely and it should work.

You should bind your executable with exactly one source file containing the "main" function.
As linker tells you, both manager.cpp and rtngnode.cpp have the definition of main function there. You probably do not want to combine them together. I advice you to start from manually building your code using the gcc commands (using gcc -c to produce object files and gcc -o to produce the executable). Once you understand the logic there - proceed writing makefiles.
By the way, if you can choose your build environment - start with cmake which is less cryptic than makefiles.

The most important thing here has nothing to do with your Makefile (which looks reasonably good except for the somewhat lacking use of compiler warnings):
You may have only one main() in your project, across all source files.

So basically, TARGETS should contain your source files (.cpp) which are then compiled to create object files, which should be in the OBJS variable so they are then passed to the linker to create the executable file.
As of right now your Makefile seems correct, the error tells you that you have 2 main() functions declared, one in the rtngnode.cpp file and again in the manager.cpp, this cannot happen or else the machine would not know which one to call when the program is executed.
Also undefined reference errors are most of the time due to a linker error, happening most of the time when you include a library to the compiler with #include but not to the linker usually using the LIBS variable in your makefile.
HERE is a small tutorial on Makefiles, which could also be a good read.

Related

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

Why does GNU make always re-link my project?

I have the following Makefile in a directory full of .cpp and .h files:
CFLAGS=-g -std=c++0x -Wall -pedantic -Wextra -D __STDC_LIMIT_MACROS -D __STDC_FORMAT_MACROS -O0
CXX=g++
LDFLAGS=-lgmp -lmathsat -lz3
all: Foo.o Bar.o
$(CXX) $(CFLAGS) -o myexe Foo.o Bar.o $(LDFLAGS)
depend: .depend
.depend: $(wildcard *.cpp)
rm -f ./.depend
$(CXX) $(CFLAGS) -MM $^ > ./.depend
include .depend
%.o: %.cpp
$(CXX) $(CFLAGS) $(INCLUDE) $< -c
clean:
rm -f *.o myexe
When I hit make, it invariably executes the last step (linking) even when none of the .o files have changed. How can I prevent make from doing that? I'd expect make to output Everything up-to-date or something similar.
I'm on a i686 GNU/Linux machine with GNU Make 3.82 and g++ version 4.8.2.
Make relinks your project because it tries to build all. The rule for all does not create any file named all. Instead it produces myexe. Next time you run make, it will see that there's no all, but there's a rule to build one, so it dutifully executes that rule which happens to link myexe every time you run make.
In order to fix your problem you need to change your makefile to look roughly like this:
all: myexe
echo Build done
myexe: <myexe dependencies go here>
$(CXX) $(CFLAGS) -o myexe $(wildcard *.o) $(LDFLAGS)
Make always tries to build the top rule. For you, this is all. Since your all rule doesn't actually make an all file it will always be run.
Your probably want your all rule to be a myexe rule and, if you want an explicit all rule, have a dependency only rule: all: myexe.
(With GNU Make, you might want to explicitly declare those targets which aren't supposed to generate a real file with a .PHONY rule. e.g. .PHONY: all depend clean.)
make is a rule-based expert system.
You give it a heap of rules and a target (default target is the first one listed), and then it builds a complete dependency tree.
All parts are rebuilt iff they are non-existent resp. older than their dependencies, recursively.
The rule you are stumbling over is this: Because the target all does not create an output file all, make invokes the non-existent-or-outdated rule.
You can correct this by making the target all not do any work but instead just depend on the output file. Marking it .PHONY is also a good idea.

Easy way to build objects for target and x86 at the same time

Currently, this is how I build my object files for my x86 compiler.
CC=g++
%.o: %.cpp
$(CC) $(CFLAGS) $(INCPATH) $(LIBPATH) -DPC -c $^ -o $#
How can I easily switch between g++ and my cross compiler? How can I compile both x86 and binaries for my target at the same time? I seem to be limited to compiling with only one compiler right now. Is there a way to come about this without having to list all my object files one by one?
You could pass the tool chain while giving make
Just an extra variable CROSS_COMPILE would do that
The makefile would rather look like this
CROSS_COMPILE :=
CC=$(CROSS_COMPILE)g++
%.o: %.cpp
$(CC) $(CFLAGS)$(INCPATH) $(LIBPATH) -DPC -c $^ -o $#
So if u just give make then CC is used as g++ and get compiled for x86, if you give make CROSS_COMPILE=arm-none-linux-gnueabi- then it would be compiled for ARM
You can use whatever the tool chain you want the concept remains the same
Sagar's answer does address how to switch between compilers, but does not address how to both do that and the main part of the question, which is how to do both targets at the same time.
To do both targets at the same time, you probably want to separate the objects into directories related to the compiler or target used, and then based on the directory of object, figure out what compiler to use.
So, something like below, in the simplest case, where the sources are in current directory, and the directory is the same as the compiler name. Fill in the user-defined COMPILER function with how you like to calculate your compiler name, based on the directory of the object file, which is the argument $1 to the function.
define COMPILER
$1
endef
.PRECIOUS: %/.
%/.:
mkdir -p $#
.SECONDEXPANSION:
%.o: $$(notdir $$*.cpp) | $$(#D)/.
$(call COMPILER, $(#D)) -c $< -o $#

Makefile - Dependency file in a folder "No such file or directory"

I've got a Makefile that works good so far. Although, as it started growing, recompiling all the sources every time began to take too long. Here's a snippet from the working version:
CC=$(CROSS_COMPILE)g++
CFLAGS=-Wall -I./include -pg -O2
VPATH=./src:./include
all: dotgazer.cpp dotgazer/Dot.cpp
$(CC) $(CFLAGS) $^ -o dotgazer.out `pkg-config --libs opencv`
There are a lot more dependencies, but these two are enough to show what the problem is. I'm trying to move the compilation stage of each cpp file to a separate target. When it comes to the top-level file (dotgazer.cpp) it's not a problem and a general rule %.o: %.cpp works fine. But I can't get the second dependency to work. Here's how it looks now:
CC=$(CROSS_COMPILE)g++
CFLAGS=-Wall -I./include -pg -O2
VPATH=./src:./include
all: dotgazer.o dotgazer/Dot.o
$(CC) $(CFLAGS) $^ -o dotgazer.out `pkg-config --libs opencv`
%.o: %.cpp
$(CC) -c $(CFLAGS) $^ -o $#
dotgazer/Dot.o: dotgazer/Dot.cpp
$(CC) -c $(CFLAGS) $^ -o $#
I've tried different variations of the Dot.o rule but none of them seems to work. The error I get with the one above is:
Fatal error: can't create dotgazer/Dot.o: No such file or directory
How should I do that? I'd most prefer to have the .o files in the same folders as their sources. Also, I'd be thankful for general rules (like %.o: %.cpp) as there are lots of source files and I don't want the Makefile to get too bloated. Thank you!
I think your Makefile is a bit to specific and thus error-prone. I suggest to look at my following example that is way more generic than yours.
My example takes advantage of make's catalouge of implicit rules. For cpp-files exists a generic implicit rule already. So why should one not use it!?
The reference manual describes it as follows:
Compiling C++ programs
n.o is made automatically from n.cc, n.cpp, or n.C with a recipe of the form $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c.
So if you have %.o files as prerequisites like in the rule dotgazer.out: $(OBJS) make applies above implicit rule to all those files automatically. Assumed you have set valid values for CXX, CPPFLAGS and/or CXXFLAGS.
Furthermore you usually don't need to add your sources by hand to a variable. Most of the time all the sources in your project's directory tree are needed to build the executable. If it's not the case you should consider to build a appropriate tree that reflects this.
Since find is responsible to assign the sources to CPPFILES we don't need to set VPATH either. Due to our usage of find and patsubst we have only one explicit file name in our Makefile. That make working on a real project with plenty of different sources much more smooth.
Of course you don't need the all and the clean rule. I just added these for convenience.
CXX=$(CROSS_COMPILE)g++
CPPFLAGS=-I./include
CXXFLAGS=-Wall -pg -O2
LDLIBS=`pkg-config --libs opencv`
CPPFILES=$(shell find . -name "*.cpp")
OBJS=$(patsubst %.cpp, %.o, $(CPPFILES))
all: dotgazer.out
#echo $(CPPFILES)
#echo $(OBJS)
dotgazer.out: $(OBJS)
$(CXX) $(CXXFLAGS) -o $# $^ $(LDLIBS)
clean:
rm -f $(OBJS)

proper usage of makefile

So, I'm trying to understand makefiles. At this moment I have a project with some modules, which are more or less non-dependent on each others.
My directory tree is like this:
root/
- Source/ <-- referenced as $(INPUTPATH)
- Build/ <-- referenced as $(BUILDPATH)
- Release/ <-- referenced as $(OUTPUTPATH)
- Makefile
I want to have the source (.cpp/.h) on the Source/, the objects on the Build/, and the executable on the Release/*.
So, my idea was to have several different targets, and use them like this:
all: maps auxiliars methods
#echo "linking...";\
$(CC) $(CFLAGS) $(OBJS) $(CLIBS) -o ${OUTPUTPATH}/MainProgram
dependency1: $(INPUTPATH)/foo.cpp
#echo "compiling ArbPrecision...";\
cd ${BUILDPATH};\
$(CC) $(CFLAGS) $(CINCLUDE) -c ../$?
dependency2: dependency1 $(INPUTPATH)/bar.cpp
#echo "compiling saddleConstructor...";\
cd ${BUILDPATH};\
$(CC) $(CFLAGS) $(CINCLUDE) -c ../$(INPUTPATH)/bar.cpp
maps: dependency2 $(INPUTPATH)/*Map.cpp
#echo "compiling maps...";\
cd ${BUILDPATH};\
$(CC) $(CFLAGS) $(CINCLUDE) -c ../$(INPUTPATH)/*Map.cpp
... (auxiliars and methods)
The $CINCLUDE and CFLAGS are just compiler stuff like headers and external libs.
Everything works almost perfect: on every target, it asks for other target's dependencies, and for the *cpp on the source. If this does not exist, it calls the target and compiles the *cpp. The executable is created without errors.
However, if I call the "make" twice, the time it takes to compile is the same for the first and second time, even if I don't make any changes on the source. So, apparently, I'm not putting the dependencies right.
Can anyone point me the right direction to perform this compilation? I'm doing something wrong and I'm not getting what it is.
Thanks,
Jorge
Make expects to operate off of files. For each rule, it checks to see if the target file named by that rule (1) exists and (2) is up to date (i.e., modified after any of its dependencies). If the file is not up to date, then it executes the rule to bring it up to date.
Therefore, as your makefile is currently written, when you run make, Make does the following:
all is the first rule, so if you don't specify any arguments, make processes the all rule.
No file named all exists, so the all rule needs to be executed.
all depends on the dependency1 rule. No file named dependency1 exists, so the dependency1 rule needs to be executed.
dependency1 depends on the dependency2 rule. No file named dependency2 exists, so the dependency2 rule needs to be executed.
What you instead want is something similar to the following:
OBJS := foo.o bar.o Map.o
all: $(OUTPUTPATH)/MainProgram
$(OUTPUTPATH)/MainProgram: $(OBJS)
$(CC) $(CFLAGS) $(OBJS) $(CLIBS) -o $(OUTPUTPATH)/MainProgram
%.o: %.cpp
$(CC) $(CFLAGS) $(CINCLUDE) $< -c $#
.PHONY: all
Note the following:
Since Make operates on files, rules' targets and dependencies are listed by filename wherever possible.
Rather than listing the .cpp files individually, an pattern rule is used to build each .o file. Within the pattern rule, the $< and $# automatic variables are used to specify the first prerequisite (file) and the target (file), respectively.
Make echoes its commands by default, so there's no need to echo yourself.
For GNU Make, all is listed as a phony target, to keep Make from looking for a file named all.