Makefile with multiple targets and creates a directory with executable - c++

I don't often use makefiles therefore I only how to make basic ones. I've tried reading on how to solve my issue but I am lost. What I need is a makefile that has two targets all and test. Both of these targets need to compile the program with g++ -std=c+11 -Wall -Werror -ansi -pedantic and the only file that needs to be compiled is main.cpp when the executable is built by the compiler it needs to put the executable in a new directory called bin. And I'm assuming that if I were to use the makefile again it would need to check if bin was already created.
I know how to create a simple makefile such as
all:
g++ -std=c++11 -Wall -Werror -ansi -pedantic main.cpp
That creates an executable named a.out in the current directory, but that's about as far as my knowledge of makefileS go

All that a Makefile does is specify the build dependencies, and the commands to execute to build those dependencies.
Things like creating the output directories, et. al. is not make's job per se, but rather something that's up to the commands that makes executes to do. Neither does the Makefile specify where the output of the build commands go. That, of course, is specified by the actual commands that get executed. With gcc, for example, the -o option specifies where the compilation output goes. So:
all: bin/main
test: bin/main
bin/main: main.cpp
mkdir -p bin
g++ -std=c++11 -Wall -Werror -ansi -pedantic -o bin/main main.cpp
It's very convenient to use mkdir -p in these situations. If the given directory does not exist, it gets created. If it already exists, mkdir just quietly terminates without an error.

Related

C++ Makefile that includes ddd debugger option

I'm kind of new to Makefiles and i'm trying to include a debugger option in my makefile that opens the debugger when I type "make debug." However, that command returns an error. I already have the ddd debugger installed in my virtual machine. This is my makefile below. Any help?
main: main.cpp puzzle.cpp fuse.cpp
g++ --std=c++11 -o main main.cpp
./main
clean:
-rm -f *.o main
debug:
g++ --std=c++11 -g debug main.cpp puzzle.cpp fuse.cpp ddd debug
TL;DR
g++ --std=c++11 -g debug main.cpp puzzle.cpp fuse.cpp ddd debug
This line is in error. It tells G++ to compile, using the options --std=c++11 -g, the list of files given -- including "ddd" and "debug" (twice) -- to a.out (or a.exe if you're on Windows / Cygwin).
That is not what you wanted, and as "debug" and "ddd" are unlikely to be valid C++ source files, the compiler run fails.
If you type make debug, then make will execute the debug rule:
debug:
g++ --std=c++11 -g debug main.cpp puzzle.cpp fuse.cpp ddd debug
If no file named debug exists (*), make will attempt to recreate it using the command:
g++ --std=c++11 -g debug main.cpp puzzle.cpp fuse.cpp ddd debug
I don't quite know what you expect that command to do. I guess that you intended two commands to be executed in sequence:
debug:
g++ --std=c++11 -g debug main.cpp puzzle.cpp fuse.cpp
ddd debug
However, the compiler line is in error. I guess you wanted something like this (note the -o):
g++ --std=c++11 -g -o debug main.cpp puzzle.cpp fuse.cpp
main: main.cpp puzzle.cpp fuse.cpp
g++ --std=c++11 -o main main.cpp
./main
This is broken several ways.
This rule instructs make to rebuild main from scratch whenever any of the files main.cpp, puzzle.cpp or fuse.cpp is touched. However, the command you are giving only recompiles main.cpp -- the other two files are never (re)compiled.
A good Makefile rule only does what is needed to (re)build the file it is named by, and is as generic as possible.
For example, to "tell" make how to create a *.o file from any given *.cpp file ($# and #< being placeholder for "target of rule" and "first dependency", respectively):
%.o: %.cpp
g++ --std=c++11 -o $# #<
Once you have that, you can tell make how to build your executable from individual object files ($^ being a placeholder for "all the dependencies"):
main: main.o puzzle.o fuse.o
g++ --std=c++11 -o $# $^
This way, if you touch one of the source files (e.g. puzzle.cpp), only that one object file gets rebuilt, and the main executable relinked. With large projects, this significantly reduces (re)compile times.
(*) If you have rules that do not actually create a file, you should label them as .PHONY, so make will execute them even if a file by that name happens to exist already.
You also usually want to disable optimization for debugging, to avoid some of the stranger things that can happen with optimization on.
So (for easier example compiling with -g debugging information always):
.PHONY: debug
%.o: %.cpp
g++ --std=c++11 -g -O0 -o $# #<
main: main.o puzzle.o fuse.o
g++ --std=c++11 -g -O0 -o $# #^
debug: main
ddd main
What your Makefile also does not take into account is that an object file also needs to be recompiled when any of the header files it includes are touched. This kind of dependency handling is easy to do with GCC, but beyond the scope of this answer. Let me point to the Makefile tutorial at OSDev.org (which was mostly written by me) for a step-by-step introduction on how to get a Makefile "right".
ddd debug needs to be on a line by itself to execute as a separate command, and you need to add the missing -o switch:
debug:
g++ --std=c++11 -g -o debug main.cpp puzzle.cpp fuse.cpp
ddd debug
However, this will not execute if debug already exists; make tries to optimize and it will not run a recipe if the target already exists, or is newer than the listed dependencies (which are none).
Instead, break this rule up into two pieces. The binary (with dependencies listed), and the run command (which should be marked as a phony target). The phony target will make sure that the recipe still runs even if there is a file with the same name as the recipe's output name (run-debug in this example).
debug: main.cpp puzzle.cpp fuse.cpp
g++ --std=c++11 -g -o debug main.cpp puzzle.cpp fuse.cpp
run-debug: debug
ddd debug
.PHONY: run-debug
This way, make run-debug will always invoke the debugger (if compilation succeeded), but compilation will not be performed if the debug binary is newer than your source files.
I'm not super-familiar with ddd, but some debuggers will look up the binary in a similar way to shells, so you may need to modify the ddd line to be:
ddd ./debug
Don't forget to patch up your clean rule to (1) delete debug and (2) be phony:
clean:
-rm -f *.o main debug
.PHONY: clean run-debug

Changed .h file in C++ does not need to be compiled again?

I have the following question. After a successful compilation, if I compile it again after I only change some content in one of the .h files, the computer says:
make: Nothing to be done for `all'.
Can I force the compiler to compile again even if I have only modified the .h files?
If you want your output to be updated when header files change, then you have to add it to your dependency statement:
myprogram: myprogram.cpp myprogam.h
c++ -o myprogram myprogram.cpp
Typically we don't do it this way because the code that does things stays in the cpp file. If you are on unix and want to force a rebuild, just touch a cpp file to update its timestamp (forcing a rebuild) with "touch myprogram.cpp", for example, or delete your existing executable.
If you are using make without a Makefile, letting it infer dependencies, it will probably not infer the header dependencies. In this case, either blow away your executable or touch your source file.
Sounds like your Makefile does not have dependencies configured correctly. That is what you should look into fixing.
If you really want to just force a rebuild rather than fix the underlying problem. Then you can do a make clean before your make all or, if the Makefile does not have a "clean" target, delete all the generated object files and libs/executables and then run make all again.
You can force make to rebuild everything using the --always-make command line option.
However, it sounds like you don't have your dependencies setup properly in your Makefile. If your code (.cpp files) actually include headers, then generally your target for compiling them should have a prerequisite on the header files that it includes.
There is a simpler way than the accepted answer. Simply add -MD to your compiler flags in your Makefile, and -include myfile.d at the end of the Makefile (listing all source files with a *.d extension instead). This will, respectively, generate and reference additional *.d dependency files in your build folder (wherever your *.o files go) when you make, so you do not need to explicitly add every single header file to your makefile dependencies.
This is useful for projects with a long list of header files. Furthermore, this way, you know that you can't forget to include a header file in your Makefile dependencies, preventing troubleshooting time lost later when you think your binary updated when you changed a header file, but it actually didn't because you forgot to put it in the Makefile.
For example, use gcc -MD -I. -c myfile.cpp -o obj/myfile.o, and you can keep your Makefile dependencies as just foo: myfile.cpp without myfile.h.
A shortcut way to do this so you only need to list all files once is something like the following:
# Beginning of Makefile etc. etc.
# Only need to list all files once, right here.
SRCS = myfile.cpp myfile2.cpp
OBJS = $(SRCS:%.cpp=%.o)
# put .o and .d files in ./obj/
# (Assumes 'obj' directory exists)
FULLOBJS = $(addprefix obj/,$(OBJS))
# rule to make object (*.o) files
$(FULLOBJS): obj/%.o:%.cpp
gcc -MD -I. -c %< -o $#
# rule to make binary
foo: $(FULLOBJS)
g++ -o $# $(FULLOBJS)
# rule to clean (Note that it also deletes *.d files)
.PHONY: clean
clean:
rm -rf obj/*.o obj/*.d foo
# include dependency files (*.d) if available
-include $(FULLOBJS:%.o=%.d)
Can I force the compiler to compile again even if I have only modified
the .h files?
Yes ... but you probably want to improve your make (tool).
What I do is to force the most recent compile of the file in question, where the command generated by make shows.
Example:
# ... noise
g++ -O3 -ggdb -std=c++14 -Wall -Wextra -Wshadow -Wnon-virtual-dtor -pedantic -Wcast-align -Wcast-qual -Wconversion -Wpointer-arith -Wunused -Woverloaded-virtual -O0 lmbm101_11.cc -o lmbm101_11 -L../../bag -lbag_i686 -lnet_i686 -lposix_i686 -lzlib_i686 -lrt -pthread
# ... more noise.
To force a build, I highlight the "command" make created (starts with "g++", and resides between noise and more noise), and invoke it instead of make.
This is trivial using emacs on Linux. Might not be so easy on other systems.
You might consider copying this command into the file, for future use.
( i.e. I bypass make until I choose to fix my make file. )

How to compile and run a program that uses multiple files through terminal?

So I'm trying to practice and learn how to use a text editor and the command line interface (terminal on mac) but i'm having trouble getting it to compile. I'm writing in c++ and i've separated my main file, class and class definitions into multiple files. I want to compile and run the program using terminal but am having issues. I use
g++ file1.cpp file2.cpp file3.h -o run
to compile and I get the error message "cannot specify -o when generating multiple output files."
I'm planning on having even more files in this program and don't know if this is even the best way to compile each time? Regardless, how do I compile this program so that I can run? I know the program doesn't have any errors because I tested it in the IDE Xcode.
If you really want, you could type several commands (-std=c++11 tells the compiler that it is C++11 code, -Wall asks for almost all warnings, -Wextra asks for more of them, -g asks for debug information, and -c avoids a linking step)
g++ -std=c++11 -Wall -Wextra -g -c file1.cpp
g++ -std=c++11 -Wall -Wextra -g -c file2.cpp
g++ -std=c++11 -Wall -Wextra -g -c file3.cpp
These commands are generating object files file1.o, file2.o, file3.o which you can link to make an executable:
g++ -std=c++11 -g file1.o file2.o file3.o -o run
BTW, you could have run all in a single command:
g++ -std=c++11 -Wall -Wextra -g file1.cpp file2.cpp file3.cpp -o run
but this is not optimal (since usually you edit one file at once, and the other files might not need to be recompiled).
But you really want to use GNU make, by writing your Makefile (see this example) and simply compiling with make; if you change only file2.cpp then make would notice that only file2.o has to be regenerated (and the final link to make again run)
You don't need to compile header files (they are preprocessed by the g++ compiler). You might be interested in precompiled headers and makefile dependencies generation.
Once your program is debugged (with the help of a debugger like gdb and also of valgrind....) you could ask the compiler to do optimizations by replacing -g with -O or -O2 (you could even compile with both -g -O). If you benchmark your program (e.g. with time) don't forget to ask the compiler to optimize!
PS. Your g++ commands might need more arguments, e.g. -I... to add an include directory, -DNAME to define a preprocessor name, -L... to add a library directory, -l... to link a library, and order of arguments is important for g++

Makefile target errors

I have been reading a book on SFML game development and they use unique_ptr's. And to use them I know that I must use the -std=c++11 flag when compiling, however I have been having issues doing this with a Makefile. Below is a copy of my Makefile:
flags = -lsfml-graphics -lsfml-window -lsfml-system
main: main.cpp texture_holder.o
g++ main.cpp texture_holder.o -o Run $(flags) -std=c++11
texture_holder: texture_holder.cpp texture_holder.h
g++ texture_holder.cpp -c -std=c++11
.PHONY: clean
clean:
rm *.o Run
When just typing make I get errors about unique_ptr not being a member of std. But what I can't figure out, is that when I type make texture_holder texture_holder.cpp does compile just fine then running make builds the application. Do I have something ordered wrong or am I missing anything? If it helps, I can attach the code that I am using, but like I said, it builds just fine when I build the texture_holder target first.
You have wrong rule for texture_holder.o, it should be this:
texture_holder.o: texture_holder.cpp texture_holder.h
g++ texture_holder.cpp -c -std=c++11
Ie. including the .o extension.
What happens with your question's version is, when you do make texture_holder, you execute that particular rule, which does not actually create corresponding file texture_holder, it creates texture_holder.o, because well, that's what the commend produces. The texture_holder rule is effectively a phony rule, similar to main and clean (and btw, you should add main to .PHONY too).
If you make main, then to create texture_holder.o, make uses implicit rule (because there is no explicit one), which uses different compile command.
You have a rule for making texture_holder, not texture_holder.o. The rule for main will attempt to make texture_holder.o using the default compilation rule, not your special one. The default rule won't specify -std=c++11, hence the error.

Am I using a Makefile for C++ correctly?

Makefile
default:
(!) g++ -Werror -Wunused-variable -Wunused-value -Wunused-function -Wfloat-equal -Wall -ansi -o main -pedantic-errors main.cpp
'/home/HomeName/Desktop/main'
I have been using this code to compile a C++ file. Is this a good way of using this code in the makefile? Moreover, I wonder if the line marked with (!) has the compiler options in the correct order.
So, your makefile itself does not contain the '(!)' marking, I believe.
What you have 'works'. It compiles the program with a stringent set of options and then runs it by absolute pathname.
However, it is not very flexible:
it will only build main if you run make
it will always build main even if you built it a moment ago
if you run make main, it will use a different set of commands to build the program, and it won't run the program.
It would be better - it would allow you to move the code more easily - if the line to run the program used the current directory.
And it would be better if you used some of the built-in features of make.
The C++ and C compilers are very tolerant of various orders for their options; what you have is OK.
Inside make, the C++ compiler is known by the macro CXX; it takes a set of flags defined by CXXFLAGS. You could, therefore, use:
CXX = g++
CXXFLAGS_W = -Werror -Wunused-variable -Wunused-value -Wunused-function \
-Wfloat-equal -Wall
CXXFLAGS_M = -ansi -pedantic-errors
CXXFLAGS = ${CXXFLAGS_M} ${CXFLAGS_W}
all: main
./main
This allows you to run make, make all and make main and get the program main built. If you use either of the first two, the program will also be run. It will only recompile the program if the source has changed since it was last compiled. If you have other programs in the directory, say 'exercise2.cpp' and 'exercise3.cpp', then you'd be able to say make exercise2 exercise3 and those would now be compiled in much the same way that main is.
If you really wanted to run the program after building it (probably not something you'd do in the long-term), then you'd probably rewrite the compilation rule (assuming GNU Make):
% : %.cpp
${CXX} ${CXXFLAGS} -o $# $*.cpp
./$#
If you have a classic or POSIX variant of make, you'd write:
.cpp:
${CXX} ${CXXFLAGS} -o $# $*.cpp
./$#
The notation using '%' is more flexible when it is available.