How do I make my makefile create a second executable? - c++

all: exe1 exe2
exe1: obj1
g++ -Wall -Werror -std=c++11 program1.o -o program1 -lgtest
obj1:
g++ -c -Wall -Werror -std=c++11 program1.cc
exe2: obj2
g++ -Wall -Werror -std=c++11 program2.o -o program2
obj2:
g++ -c -Wall -Werror -std=c++11 program2.cc
clean:
rm *.o *.exe
When I run the makefile, only target exe1 is compiled and created into an executable. If I make the target just exe2, I get the error message
make: Nothing to be done for `all'.
How do I make exe2 visible to the makefile?

The makefile should probably look more like this:
# Set the dependencies to the names of the executables you
# want to build
all: program1 program2
#
# Make uses some variables to define tools.
# The most important for you is CXX: Which is set to the C++ compiler.
#
# Notice that target name should match the executable name.
# This is because `make` will check its existence and creation date
# against its dependenc(ies) existence and creation date.
program1: program1.o
$(CXX) -Wall -Werror -std=c++11 program1.o -o program1 -lgtest
program2: program2.o
$(CXX) -Wall -Werror -std=c++11 program2.o -o program2
#
# We can generalize the creation of the object file.
%.o: %.cc
$(CXX) -c -Wall -Werror -std=c++11 $*.cc
clean:
$(RM) *.o *.exe

The "make" utility has many rules to simplify standard build. Compact version can of the Makefile will be:
PROGRAMS = program1 program2
all: $(PROGRAMS)
CXXFLAGS=-Wall -Werror -std=c++11
# Link program1 with the gtest library
program1: LDLIBS=-lgtest
clean:
$(RM) $(PROGRAMS) *.o
# Following section is needed only for binaries that need more than one object.
# Does not apply in the this case, since program1 depends only on program1.o.
# Included for allow extending the makefile.
program3: program3.o second.o # Additional objects here.

Related

Makefile make re is not running all the pattern rules

I have trouble creating dependency files while using make re. The %.d pattern rule will be called before fclean, also only the %.o pattern rule were called by all after fclean.
Here is the output when i use make vs make re:
mkdir -p srcs/depends
c++ -Wall -Werror -Wextra -Wshadow -std=c++98 -pedantic -Iincludes -MM srcs/tests.cpp -o srcs/depends/tests.d
c++ -Wall -Werror -Wextra -Wshadow -std=c++98 -pedantic -Iincludes -MM srcs/main.cpp -o srcs/depends/main.d
mkdir -p srcs/obj
c++ -Wall -Werror -Wextra -Wshadow -std=c++98 -pedantic -Iincludes -c srcs/main.cpp -o srcs/obj/main.o
c++ -Wall -Werror -Wextra -Wshadow -std=c++98 -pedantic -Iincludes -c srcs/tests.cpp -o srcs/obj/tests.o
c++ -lstdc++ srcs/obj/main.o srcs/obj/tests.o -o main
vs (make re)
rm -f -rv srcs/obj srcs/depends
srcs/obj/main.o
srcs/obj/tests.o
srcs/obj
srcs/depends/main.d
srcs/depends/tests.d
srcs/depends
rm -f main
mkdir -p srcs/obj
c++ -Wall -Werror -Wextra -Wshadow -std=c++98 -pedantic -Iincludes -c srcs/main.cpp -o srcs/obj/main.o
c++ -Wall -Werror -Wextra -Wshadow -std=c++98 -pedantic -Iincludes -c srcs/tests.cpp -o srcs/obj/tests.o
c++ -lstdc++ srcs/obj/main.o srcs/obj/tests.o -o main
My makefile:
NAME = main
SRCSDIR = srcs
SRCS = $(wildcard $(SRCSDIR)/*.cpp)
OBJSDIR = srcs/obj
OBJS = $(SRCS:$(SRCSDIR)/%.cpp=$(OBJSDIR)/%.o)
DEPENDSDIR = srcs/depends
DEPENDS = $(SRCS:$(SRCSDIR)/%.cpp=$(DEPENDSDIR)/%.d)
CPPFLAGS = -Wall -Werror -Wextra -Wshadow -std=c++98 -pedantic -Iincludes
DEPFLAGS = -MM
LDFLAGS = -lstdc++
all: $(NAME)
$(NAME): $(OBJS)
c++ $(LDFLAGS) $^ -o $#
$(OBJSDIR)/%.o: $(SRCSDIR)/%.cpp | $(OBJSDIR)
c++ $(CPPFLAGS) -c $< -o $#
$(DEPENDSDIR)/%.d: $(SRCSDIR)/%.cpp | $(DEPENDSDIR)
c++ $(CPPFLAGS) $(DEPFLAGS) $< -o $#
$(OBJSDIR) $(DEPENDSDIR):
mkdir -p $#
-include $(DEPENDS)
clean:
$(RM) -rv $(OBJSDIR) $(DEPENDSDIR)
fclean: clean
$(RM) $(NAME)
re: fclean all
.PHONY: all clean fclean re
I have looked up the gnu make documentation and couldn't find any details. (Maybe I don't know where to look it up). Anybody knows why or are there any other cleaner solution to this ? Thanks in advance
You are using the old-style header file generation method where make builds dependency files, then re-execs itself to read in the changed dependencies. So, when you run make first it parses all the .d files that currently exist (due to the include line) then it tries to rebuild the .d files, then if any have changed it re-execs, then it runs the rest of the makefile. Once it loads all the .d files and determines that they're up to date, make is done with them (for that invocation). If they later get deleted, it's not going to try to recreate them. They will be recreated the next time make is run.
In general, it's a bad idea to have a rule that runs clean and all as prerequisites. What if you enable parallel builds? Now make is running the clean and all rules in parallel. If you want to do this, you need to invoke them as sub-makes rather than via prerequisites, like this:
re:
$(MAKE) fclean
$(MAKE) all
This will ensure each target is built serially, even with parallel builds, and that make will be started from scratch to build all.
Another thing you should consider is using a more modern form of dependency generation; for example: https://make.mad-scientist.net/papers/advanced-auto-dependency-generation/

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 not finding header file from -I include path

I have the makefile given below. When I do make I get the following error
cc -c -o timing.o timing.c
test_c.c:5:17: fatal error: test.h: No such file or directory
#include "test.h"
I have manually verfied that test.h is present in ../include path. I am not sure why this is not finding the header file.It would be great if someone could help.Also I would expect g++ instead of cc
# Makefile template for shared library
CXX = g++ # C++ compiler
CXXFLAGS = -fPIC -Wall -Wextra -O2 -g -I../include #CXX flags
LDFLAGS = -lboost_system -shared # linking flags
RM = rm -f # rm command
TARGET_LIB = libtest.a # target lib
C_SRCS := test_a.c test_b.c
CPP_SRCS := test_c.cpp test_d.cpp
OBJS := $(C_SRCS:.c=.o) $(CPP_SRCS:.cpp=.o)
.PHONY: all
all: ${TARGET_LIB}
$(TARGET_LIB): $(OBJS)
$(CXX) $(CXXFLAGS) ${LDFLAGS} -o $# $^
.PHONY: clean
clean:
-${RM} ${TARGET_LIB} ${OBJS}
~
You have not written a rule for building timing.o from timing.c, so Make uses the default rule it has for that.
But that rule uses CFLAGS, not CXXFLAGS. The CXXFLAGS variable appears in the rule for building object files from C++ sources.
So modify CFLAGS instead of CXXFLAGS, and it should work.

C++ - Makefile Good Practice

I have a Makefile that works for how I'm using it, but will anyone tell me if what I'm doing is good practice? Or if there is a better, cleaner or more efficient way to achieve the goal I am reaching?
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
EXEC = Proj2.out
# The c++ flags to use for compilation
CXXFLAGS = -Wall
# The c++ compiler to use for compilation
CXX = g++
# This section is called on 'make'
# Will call compile, and then call clean
all: compile clean
# Perform action on all object files (May or may not exist)
# The makefile will implicitly compile all .o files needed
# Will also compile them into the EXEC file listed
compile: $(OBJECTS)
$(CXX) $(CXXFLAGS) -o $(EXEC) $(OBJECTS)
# This section is called after compilation is completed
# This will clean all existing .o files listed in the directory
clean:
rm -f *.o
Here is the terminal output when I call 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
rm -f *.o
Is it good practice to use a Makefile like this? Specifically, am I doing the cleaning part of my Makefile correctly?
You should not make all depend on clean at all. By doing this you are ensuring that every time you run make, you have to recompile everything. If you want to do that then using make is itself useless: just write a shell script that compiles and links your code.
The clean target should be a separate target and if you want to clean your workspace you run make clean explicitly.
The other problem with your makefile is that the link rule lists compile as the target, but it builds $(EXE). It's almost never a good idea to have a rule create a file which is not exactly the target you told make it would build. To ensure this, always use $# as the target to generate. Rewrite it like this:
compile: $(EXE)
$(EXE): $(OBJECTS)
$(CXX) $(CXXFLAGS) -o $# $^

Makefile leads to compilation error

I'm trying to compile a program (which isn't mine):
make -f makefile
... using the following makefile:
# Compiler for .cpp files
CPP = g++
# Use nvcc to compile .cu files
NVCC = nvcc
NVCCFLAGS = -arch sm_20 # For fermi's in keeneland
# Add CUDA Paths
ICUDA = /usr/lib/nvidia-cuda-toolkit/include
LCUDA = /usr/lib/nvidia-cuda-toolkit/lib64
# Add CUDA libraries to the link line
LFLAGS += -lcuda -lcudart -L$(LCUDA) -lgomp
# Include standard optimization flags
CPPFLAGS = -O3 -c -I $(ICUDA) -Xcompiler -fopenmp -DTHRUST_DEVICE_BACKEND=THRUST_DEVICE_BACKEND_OMP
# List of all the objects you need
OBJECTS = timer.o ar1.o kGrid.o vfInit.o parameters.o
# Rule that tells make how to make the program from the objects
main : main.o $(OBJECTS)
$(CPP) -o main main.o $(OBJECTS) $(LFLAGS)
# Rule that tells make how to turn a .cu file into a .o
%.o: %.cu
$(NVCC) ${NVCCFLAGS} $(CPPFLAGS) -c $<
# How does make know how to turn a .cpp into a .o? It's built-in!
# but if you wanted to type it out it would look like:
# %.o: %.cpp
# $(CPP) $(CPPFLAGS) -c $<
clean :
rm -f *.o
rm -f core core.*
veryclean :
rm -f *.o
rm -f core core.*
rm -f main
Which results in the following commands:
nvcc -arch sm_20 -O3 -c -I /usr/lib/nvidia-cuda-toolkit/include -Xcompiler -fopenmp -DTHRUST_DEVICE_BACKEND=THRUST_DEVICE_BACKEND_OMP -c main.cu
g++ -O3 -c -I /usr/lib/nvidia-cuda-toolkit/include -Xcompiler -fopenmp -DTHRUST_DEVICE_BACKEND=THRUST_DEVICE_BACKEND_OMP -c -o timer.o timer.cpp
g++: error: unrecognized command line option â-Xcompilerâ
make: *** [timer.o] Error 1
I don't understand the makefile: the -xCompiler flag (in the variable CPPFLAGS) should be used only by the nvcc compiler, not g++. Therefore, I understand why I am getting an error. However, I don't understand, from my basic understanding of the makefile above, why at some point the variable CPPFLAGS follows g++ (variable CPP). I don't see any such sequence in the makefile.
Your main rule requires timer.o. There is no explicit rule for timer.o so make uses a built in implicit rule (as mentioned in the comment at the end of your makefile). The implicit rule for converting .cpp files into .o files has the form
$(CPP) $(CPPFLAGS) -c $<
So it's compiling using the options in CPPFLAGS which contains -Xcompiler. You probably want the -Xcompiler flag to be in NVCCFLAGS and not CPPFLAGS.