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
Related
Just taking a use case for this instance. I'm compiling a c++ file, and sometimes, I'd like to compile without debugging symbols i.e. the -g enabled and sometimes I would like to enable it.
So, I thought of just making two targets in which the second target would reassign a make variable(is it possible) and change the compiling options. I wonder if such a behaviour is possible to achieve with makefiles?
Below is some pseudocode demo and the user enters make first#bg into the command line:
gpp = g++ -std=c++17
first: hello.cpp
$(gpp) hello.cpp -o $#
#/* some other recipes, assuming the list is really long*/
first#bg: main.o
gpp = g++ -g -std=c++17
execute_all_recipe_of_first_target_which_is_really_long_to_copy()
main.o: main.cpp
$(gpp) main.cpp -c -o main.o #the value of gpp should'd also changed here since first#bg executed
If it is possible please provide me with the actual syntax for the demonstrated behaviour. Thanks in advance.
You can do something like this:
first#bg: gpp += -g
first#bg: first
Note that it's more idiomatic to define CXX=g++ and CXXFLAGS=-std=c++17 and then tweak CXXFLAGS, and use make DEBUG=1 for debug builds:
CXX=g++
CXXFLAGS=-std=c++17
ifeq ($(DEBUG), 1)
CXXFLAGS+=-g
endif
Then invoke the compiler as $(CXX) $(CXXFLAGS) hello.cpp -o $# for example. See also this link
while using g++ (version 4.9.2) from MinGW provided with Code::Blocks IDE, I am getting incredibly huge .exe files, going up to 1000KB for a "Hello, World!" program. I use exactly the same compiling options as like it would be compiled from "inside" of Code::Blocks (mingw32-g++.exe -Wall -g hello.cpp -o hello.exe, anyway, i just copy it from the Code::Blocks log window), but unlike that way, which produced about 70KB output for Debug target and 50KB for Release, this keeps on making incredibly large output.
Did anyone else meet a similar issue?
[EDIT] My project (created only for testing Makefiles purposes) consists on two files, main.cpp and fun.cpp (no headers). Here is main.cpp:
#include<iostream>
using namespace std;
void fun(void);
int main()
{
cout<<"Hello Make!"<<endl;
fun();
return 0;
}
and here is fun.cpp:
#include<iostream>
using namespace std;
void fun()
{
cout<<"Hello from The Module!"<<endl;
}
And finally, this is my Makefile:
CC = mingw32-g++
CFLAGS = -Wall -Os -lto
all: main.o fun.o
${CC} -o hello.exe $^
relink:
mingw32-g++ -o hello.exe hello.o fun.o
main.o: main.cpp
mingw32-g++ ${CFLAGS} -c main.cpp -o $#
fun.o: fun.cpp
mingw32-g++ ${CFLAGS} -c fun.cpp -o $#
clean:
del *.o
When compiling this "project" under Code::Blocks I get the following
log
When using Makefile, the output file is 1024KB large:
(print screen)
Debug builds will usually be larger than optimized (aka "release") ones. Try adding -O2 or -O3 to your build options (or -Os to specifically optimize for size).
Also, if you don't need the debug symbols in a release build then remove -g (or remove them afterwards with the strip command).
Also; compiling with Link-Time Optimization can sometimes yield a size reduction (in addition to a performance improvement) - for that use the -lto option (in addition to one of the -O options).
The above should give you a significant size reduction.
See the gcc manual for more details on the options.
I've tried to add the following lines to my makefile in order to add some MATLAB plots to my C++ routine, to set the environment variables:
export PATH='/APP/MATLAB/R2013a/bin':$PATH
export LD_LIBRARY_PATH='/APP/MATLAB/R2013a/bin/glnxa64:/APP/MATLAB/R2013a/sys/os/gnlxa64':$LD_LIBRARY_PATH
And to provide the code with the correct location for the include files at compilation time:
.cpp.o:
g++ -c -DUNIX $(DEBUG) -I $(NR_DIR):/APP/MATLAB/R2013a/extern/include/ $<
$(CMD): $(OBJ)
g++ -o $# $(OBJ) -L$(NR_DIR) -lnr -DUNIX -I $(NR_DIR):/APP/MATLAB/R2013a/extern/include/
Where I've only added :/APP/MATLAB/R2013a/extern/include/ to the includes.
The compilation runs normally, except that the one .cpp file I've made changes to (which is the one that requires the new includes) sends the following error:
which sounds like I should install g++ but how could that be if g++ is run for all the other files properly and it's also working just fine compiling the original program?
I would like to know if I am making a mistake in the compiler call and if the exports are not all right. This is working properly on my laptop but now that I've tried to migrate the program to our school's cluster it's become messy.
The -I option to g++ does not presume a semicolon-divided directories list. This means you have to use -I option for each directory. Example:
-I $(NR_DIR) -I/APP/MATLAB/R2013a/extern/include
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.
I am taking a C++ course in college and they want us to manually type in all of the test files... I know, however, that there is a way to do it with out, which is how I ended up with the current(http://pastebin.com/6d9UtKM4) makefile. My question is, why is this makefile automatically removing all the .o files it uses for compiling when it is done? It's not killing me, but I would like to preserve the .o files. I have pasted the makefile here(http://pastebin.com/6d9UtKM4). I have also pasted the current result of running "make tests" here(http://pastebin.com/h3Ny3dib). (Note the part at the bottom of that page that removes all the .o files automatically.)
I would also like to be able to make it generate it like this:
g++ -o compileDir/assembler.o -c -Wall src/assembler.cpp
g++ -o compileDir/string.o -c -Wall src/string.cpp
g++ -c -Wall -o compileDir/test_assignment.o testSrc/test_assignment.cpp
g++ -o testDir/test_assignment compileDir/test_assignment.o compileDir/string.o compileDir/assembler.o
g++ -c -Wall -o compileDir/test_bracket.o testSrc/test_bracket.cpp
g++ -o testDir/test_bracket compileDir/test_bracket.o compileDir/string.o compileDir/assembler.o
testDir/test_bracket
testDir/test_assignment
In other words, I want it to compile everything, then run everything. I hope this isn't too much to ask!
Edit: Additional Information: (This is the code that does "make tests")
tests: assembler.o string.o $(test_output) $(test_stringOutput)
#echo '--- Testing complete ---'
$(testDir)%: $(compileDir)%.o string.o
g++ -o $# $< $(compileDir)string.o $(compileDir)assembler.o
$#
#echo ''
$(compileDir)%.o: $(testSourceDir)%.cpp
g++ -c -Wall -o $# $<
$(compileDir)%.o: $(testStringSrc)%.cpp
g++ -c -Wall -o $# $<
EDIT: -----------------------------------------
Resolved via comments:
Adding this line fixed it:
.PRECIOUS $(compileDir)%.o
You might add
.PRECIOUS: %.o
which should be implicit, but perhaps you've got a weird setup.
Make treats your .o files as intermediate and removes them. You can prevent automatic deletion of those by adding them a dependency of the special .SECONDARY target. See Chains of Implicit Rules for more details. Good luck!