Generate multiple builds in one makefile - c++

I want to have my unit test built along with my project every time I run make. I tried to do this with the following code in my Makefile:
DEPS = Parallel.cpp Resistor.cpp Series.cpp Source.cpp
TEST = Parallel.cpp Resistor.cpp Series.cpp Test.cpp
resistor: $(DEPS)
g++ -std=c++11 -o resistor $(DEPS) -I. -g
test: $(TEST)
g++ -std=c++11 -o test $(TEST) -I. -g
Yet when I look at the directory I only see ./resistor and not ./test.... BTW any advice for improving my makefile in other ways is welcome.

You could add the following rule as the first rule in your Makefile:
all: resistor test
Then run make:
$ make
g++ -std=c++11 -o resistor Parallel.cpp Resistor.cpp Series.cpp Source.cpp -I. -g
g++ -std=c++11 -o test Parallel.cpp Resistor.cpp Series.cpp Test.cpp -I. -g
Per the make documentation:
By default, make starts with the first target (not targets whose
names start with ‘.’).

Related

First Makefile Questions: No rule to make target

I'm attempting to create my first ever Makefile and looking for the most simple, understandable version--even if it isn't "good practice." I'll deal with that at a later time. :)
Basically, I just want to run make in the command line and have it execute the several g++ commands so I don't have to. For example, instead of entering the following (at top level dir) in the command line...
$g++ -c ./src/RaspPi4Main.cpp -o ./src/RaspPi4Main.o
$g++ -c ./src/funcI2cCom/funcI2cCom.cpp -o ./src/funcI2cCom/funcI2cCom.o
$g++ -o ./bin/RaspPi4Main ./src/RaspPi4Main.o ./src/funcI2cCom/funcI2cCom.o -lwiringPi
...I'd like something similar to my attempt at a Makefile:
RaspPi4Main: RaspPi4Main.o funcI2cCom.o (and all header files? or not needed if added below?)
g++ -o ./bin/RaspPi4Main ./src/RaspPi4Main.o ./src/funcI2cCom/funcI2cCom.o -lwiringPi
RaspPi4Main.o: RaspPi4Main.cpp
g++ -c ./src/RaspPi4Main.cpp -o ./src/RaspPi4Main.o
funcI2cCom.o: funcI2cCom.cpp funcI2cCom.h
g++ -c ./src/funcI2cCom/funcI2cCom.cpp -o ./src/funcI2cCom/funcI2cCom.o
Hopefully, I'm close? Thanks!
As a first step, you need to make sure your recipes produce their target and that inputs are either files or targets of other rules:
bin/RaspPi4Main: src/RaspPi4Main.o src/funcI2cCom/funcI2cCom.o
g++ -o bin/RaspPi4Main src/RaspPi4Main.o src/funcI2cCom/funcI2cCom.o -lwiringPi
src/RaspPi4Main.o: src/RaspPi4Main.cpp
g++ -c src/RaspPi4Main.cpp -o src/RaspPi4Main.o
src/funcI2cCom/funcI2cCom.o: src/funcI2cCom/funcI2cCom.cpp src/funcI2cCom/funcI2cCom.h
g++ -c src/funcI2cCom/funcI2cCom.cpp -o src/funcI2cCom/funcI2cCom.o
Note that this is quite verbose. You can shorten it quite significantly by making use of automatic variables. Concretely, $# is the name of the target, $< is the name of the first dependency, and $^ are all dependencies:
bin/RaspPi4Main: src/RaspPi4Main.o src/funcI2cCom/funcI2cCom.o
g++ -o $# $^ -lwiringPi
src/RaspPi4Main.o: src/RaspPi4Main.cpp
g++ -c $< -o $#
src/funcI2cCom/funcI2cCom.o: src/funcI2cCom/funcI2cCom.cpp src/funcI2cCom/funcI2cCom.h
g++ -c $< -o $#
Note that there's quite some repetition. Luckily, Make already knows how to compile a .cpp file into a .o file through implicit rules. Thus you can omit the recipes for these rules:
bin/RaspPi4Main: src/RaspPi4Main.o src/funcI2cCom/funcI2cCom.o
g++ -o $# $^ -lwiringPi
src/RaspPi4Main.o: src/RaspPi4Main.cpp
src/funcI2cCom/funcI2cCom.o: src/funcI2cCom/funcI2cCom.cpp src/funcI2cCom/funcI2cCom.h

Error while compiling a project which includes CPLEX tool

I am working on the project which has to include the CPLEX tool at some point.
More in detail, I have the following classes implemented
(i.e. the corresponding files): Random.cpp, Instance.cpp, Timer.cpp. Solution.cpp which are included into Hybrid_ea.cpp which also have to include cplex library.
Finally, the project has been executed by running Algorithm.cpp (the main() function defined here).
I want to run the project on Linux platform, creating Makefile which looks like:
TARGET = Algorithm
CXXFLAGS = -ansi -O3
GENOBJS = Random.o
#CPLOBJS = Timer.o Random.o Instance.o Hybrid_ea.o
GREOBJS = Timer.o Random.o Instance.o Solution.o Hybrid_ea.o
SYSTEM = x86-64_linux
LIBFORMAT = static_pic
CPLEXDIR = /home/root/Desktop/projects/software/cplex-12.5/cplex
CONCERTDIR = /home/root/Desktop/projects/software/cplex-12.5/concert
CCC = g++
CCOPT = -m64 -O -fPIC -fexceptions -DNDEBUG -DIL_STD -std=c++11 -fpermissive -w
CPLEXBINDIR = $(CPLEXDIR)/bin/$(BINDIST)
CPLEXLIBDIR = $(CPLEXDIR)/lib/$(SYSTEM)/$(LIBFORMAT)
CONCERTLIBDIR = $(CONCERTDIR)/lib/$(SYSTEM)/$(LIBFORMAT)
CCLNFLAGS = -L$(CPLEXLIBDIR) -lilocplex -lcplex -L$(CONCERTLIBDIR) -lconcert -lm -pthread
CLNFLAGS = -L$(CPLEXLIBDIR) -lcplex -lm -pthread
CONCERTINCDIR = $(CONCERTDIR)/include
CPLEXINCDIR = $(CPLEXDIR)/include
CCFLAGS = $(CCOPT) -I$(CPLEXINCDIR) -I$(CONCERTINCDIR)
all: ${TARGET}
Algorithm: Algorithm.o $(GREOBJS)
$(CCC) $(CCFLAGS) Algorithm.o $(GREOBJS) -o Algorithm $(CCLNFLAGS)
Algorithm.o: Algorithm.cpp
$(CCC) -c $(CCFLAGS) Algorithm.cpp -o Algorithm.o
clean:
#rm -f *~ *.o ${TARGET} core
The linking process is somehow wrong. I checked, my CPLEX version is the right one since the others, simpler projects can be executed;
The full output given when trying to compile the project:
g++ -c -m64 -O -fPIC -fexceptions -DNDEBUG -DIL_STD -std=c++11 -fpermissive -w -I/home/root/Desktop/projects/LCAPS_software/cplex-12.5/cplex/include -I/home/root/Desktop/projects/LCAPS_software/cplex-12.5/concert/include Algorithm.cpp -o Algorithm.o
g++ -ansi -O3 -c -o Timer.o Timer.cc
g++ -ansi -O3 -c -o Random.o Random.cc
g++ -ansi -O3 -c -o Instance.o Instance.cpp
g++ -ansi -O3 -c -o Solution.o Solution.cpp
g++ -ansi -O3 -c -o hybrid_ea.o hybrid_ea.cpp
In file included from hybrid_ea.cpp:22:0:
hybrid_ea.h:39:10: fatal error: ilcplex/ilocplex.h: No such file or directory
#include <ilcplex/ilocplex.h>
^~~~~~~~~~~~~~~~~~~~
compilation terminated.
<builtin>: recipe for target 'hybrid_ea.o' failed
make: *** [hybrid_ea.o] Error 1
Any help would be appreciated.
Only the file Algorithm.cpp is compiled with appropriate options for finding the CPLEX include files:
-I/home/root/Desktop/projects/LCAPS_software/cplex-12.5/cplex/include
-I/home/root/Desktop/projects/LCAPS_software/cplex-12.5/concert/include
As hybrid_ea.h also tries to include some CPLEX header files, the compilation of hybrid_ea.cpp should also have the options above.
If the makefile that you posted in your question is complete, then I suspect that the issue is the following: you didn't define a specific command to compile any .cc or .cpp file, except for Algorithm.cpp. Therefore, all other files are compiled using a default command g++ -ansi -O3 -c -o [file].o [file].cpp. And this default command doesn't have the include directives for the location of the CPLEX libraries.
As explained in ftp://ftp.gnu.org/old-gnu/Manuals/make-3.79.1/html_chapter/make_10.html, these files are compiled using make's implicit rules. The implicit rule for C++ files is to use $(CXX) -c $(CPPFLAGS) $(CXXFLAGS). Notice how this rule uses CPPFLAGS and CXXFLAGS rather than the variable CCFLAGS that you defined at the end of your makefile to include the proper include directives.
So changing the end of your makefile to the following should work:
CPPFLAGS = $(CCOPT) -I$(CPLEXINCDIR) -I$(CONCERTINCDIR)
all: ${TARGET}
Algorithm: Algorithm.o $(GREOBJS)
$(CCC) $(CCFLAGS) Algorithm.o $(GREOBJS) -o Algorithm $(CCLNFLAGS)
clean:
#rm -f *~ *.o ${TARGET} core
Once you define the variable CPPFLAGS, it will be used automatically to compile any .cpp file that you have in your project.

Makefile with pthread won't compile properly with multiple versions

For a project, I have to create a simple makefile for the source code which includes pthreads and command line arguments (if those matter to include).
The first version of the makefile that didn't work was this:
mr: mr.o
g++ -std=c++11 -pthread mr.o -o mr
mr.o: mapred.cc
g++ -std=c++11 -pthread -c mapred.cc
clean:
rm *.o mr
and I got the following error that the object file did not exist?
So then I decided to flip the two first statements around:
mr.o: mapred.cc
g++ -std=c++11 -pthread -c mapred.cc
mr: mr.o
g++ -std=c++11 -pthread mr.o -o mr
clean:
rm *.o mr
and it compiles, sort of? All I get in the terminal is:
g++ -std=c++11 -pthread -c mapred.cc
and nothing else. When I look at what files were created, all I see is a new file mapred.o created but no executable. So no errors but not fully completed. If you guys have any tips to help me out that would be very appreciated. Thank you!
If you don't specify an explicit output name with the -o option, then the compiler will name object file the same as the source file but with an .o suffix.
In your case, the command
g++ -std=c++11 -pthread -c mapred.cc
will create an object file named mapread.o.
Either use mapread.o for your target names and when linking, or use the -o option:
g++ -std=c++11 -pthread -c mapred.cc -o mr.o
As for your second problem, unless you specify an explicit target when invoking make, it will only use the first target and nothing else.

Running HTTP server example from Boost Asio

I'm getting errors when trying to run the HTTP server example that comes with the source of the boost library, under the path: boost_1_59_0/libs/asio/example/cpp11/http/server/.
I already ran this following commands in the boost_1_59_0 directory:
$ ./bootstrap.sh
$ sudo ./bjam install
$ sudo ./b2 install
After installing all targets, i tried to compile the main.cpp and the server.cpp with this command: g++ -std=c++0x -o main main.cpp -I "/home/user/Desktop/boost_1_59_0" -L "/home/user/Desktop/boost_1_59_0/libs/" -lboost_system.
Any suggestion on how to compile this server example?
I linked all files from the boost_1_59_0/libs/asio/example/cpp11/http/server/ folder after the main.cpp, as #Richard Hodges suggested. It still didn't work, i got errors concerning lpthread, so i added it to the compiling options. The program compiled but it failed the execution, returning an error saying that it didn't find the library libboost_system.so.1.59.0. I tried linking the folders with -L /path/to/library but it didn't work.
Solution:
My compilation command:
g++ -std=gnu++0x -o main main.cpp server.cpp connection.cpp connection_manager.cpp reply.cpp mime_types.cpp request_handler.cpp request_parser.cpp -I "/home/user/Desktop/boost_1_59_0" -lboost_system -lpthread
I solved it with this commands:
$ LD_LIBRARY_PATH="/usr/local/lib/"
$ sudo ldconfig
And then I just ran the executable and it worked!
Here's a simple makefile I just concocted that works:
all:server
CPPFLAGS+=-std=c++11 -Wall -pedantic
CPPFLAGS+=-g -O2
CPPFLAGS+=-pthread
LDFLAGS+=-lboost_system
%.o:%.cpp
$(CXX) $(CPPFLAGS) $^ -c -o $#
server:$(patsubst %.cpp,%.o,$(wildcard *.cpp))
$(CXX) $(CPPFLAGS) $^ -o $# $(LDFLAGS)
It runs make:
g++ -std=c++11 -Wall -pedantic -g -O2 -pthread connection.cpp -c -o connection.o
g++ -std=c++11 -Wall -pedantic -g -O2 -pthread connection_manager.cpp -c -o connection_manager.o
g++ -std=c++11 -Wall -pedantic -g -O2 -pthread main.cpp -c -o main.o
g++ -std=c++11 -Wall -pedantic -g -O2 -pthread mime_types.cpp -c -o mime_types.o
g++ -std=c++11 -Wall -pedantic -g -O2 -pthread reply.cpp -c -o reply.o
g++ -std=c++11 -Wall -pedantic -g -O2 -pthread request_handler.cpp -c -o request_handler.o
g++ -std=c++11 -Wall -pedantic -g -O2 -pthread request_parser.cpp -c -o request_parser.o
g++ -std=c++11 -Wall -pedantic -g -O2 -pthread server.cpp -c -o server.o
g++ -std=c++11 -Wall -pedantic -g -O2 -pthread connection.o connection_manager.o main.o mime_types.o reply.o request_handler.o request_parser.o server.o -o server -lboost_system
And the test program runs:
$ ./server 0.0.0.0 9889 . &
$ GET http://localhost:9889/main.cpp > main.cpp.0
Check the files
$ md5sum main.cpp*
be5dc1c26b5942101a7895de6baedcee main.cpp
be5dc1c26b5942101a7895de6baedcee main.cpp.0
Don't forget to kill the server when you're done

C++ - Makefile using g++

I have made a Makefile for my CMSC 202 course project, 'Blackjack'. It does everything I need it to and it works perfectly. You may be asking why I posted here then, this is because I have no idea how it works and I didn't use any other resources but myself to create it.
Here is my Makefile code.
# Object files to either reference or create
OBJECTS = Proj2.o Blackjack.o Deck.o Card.o Hand.o Player.o
# The executable file that will be created at the end
EXEC = Proj2.out
# The flags to use for compilation
FLAGS = -Wall
# The code compiler to use for compilation
CC = g++
# Perform action on all object files (May or may not exist)
all: $(OBJECTS)
$(CC) $(FLAGS) -o $(EXEC) $(OBJECTS)
Here is the terminal output when I call make in the terminal.
g++ -c -o Proj2.o Proj2.cpp
g++ -c -o Blackjack.o Blackjack.cpp
g++ -c -o Deck.o Deck.cpp
g++ -c -o Card.o Card.cpp
g++ -c -o Hand.o Hand.cpp
g++ -c -o Player.o Player.cpp
g++ -Wall -o Proj2.out Proj2.o Blackjack.o Deck.o Card.o Hand.o Player.o
Can anyone tell me how the .o files are being compiled? It does not look like they are being prompted to be compiled with that g++ -c -o $.o $.cpp command anywhere in the Makefile. Nor did I state to use any .cpp files.
Thank you in advance for your help.
Edit
Thanks to all your great help, this is now the terminal output I receive when using make.
g++ -Wall -c -o Proj2.o Proj2.cpp
g++ -Wall -c -o Blackjack.o Blackjack.cpp
g++ -Wall -c -o Deck.o Deck.cpp
g++ -Wall -c -o Card.o Card.cpp
g++ -Wall -c -o Hand.o Hand.cpp
g++ -Wall -c -o Player.o Player.cpp
g++ -Wall -o Proj2.out Proj2.o Blackjack.o Deck.o Card.o Hand.o Player.o
Thank you so much to all of you who have contributed.
Make has a set of implicit rules (see here for a reference). For instance
Compiling C++ programs
`n.o' is made automatically from `n.cc' or `n.C' with a command of the form
`$(CXX) -c $(CPPFLAGS) $(CXXFLAGS)'.
Most make's will also use this rule for .cpp files.
When make sees there's a x.o requirement for one of your targets, it will try to see if it can generate x.o using implicit rules, and in your case find it can do it starting from a .cpp file.
This Makefile uses implicit rules which are a great way to reduce duplication.
By default the first target will be built, here all. It depends on a number
of object files listed in a variable $OBJECTS, e.g. Proj2.o who's
dependencies aren't listed in the Makefile. Now if make sees an input file in the current directory
with a matching name, e.g. Proj2.cpp it will try
to build Proj2.o from it (there are other implicit rules for sources in
other languages). Proj2.o would then be built by default with the command
$(CXX) $(CXXFLAGS) -c -o Proj2.o
where $(CXX) the name of the C++ compiler (g++ in your case).
The explicit build step for all assembles all the object files into the
target executable.
Looking at above build command you'll notice a small problem in your Makefile. Since the flags to the C++ compiler are given in a variable FLAGS and not the standard CXXFLAGS no warnings will be emitted when building the object files. Using the standard name would fix this (you do want warnings, maybe even more than -Wall gives you).