The GNU GCC is a collection of compilers that was initially created only for the C language and the acronym meant GNU C Compiler, but over time several other programming languages were added, such as: C++, Objective-C, Objective-C++, Fortran, Ada, D, Go, Rust and Java. And the meaning of the acronym became: GNU Compiler Collection.
For Windows specifically, you can also directly access this link: How to Install GCC/G++ MinGW on Windows and on any other system just use their package manager.
All the links mentioned here I will leave in the description of this video.
It is also necessary to remember that almost 100% of the flags and parameters used by GCC also work with the clang
and clang++
compilers. They’ve already done this on purpose for compatibility, in case companies want to migrate in the future.
The difference between flag and parameter is that the flag influences the binary to be generated, the parameter does not, that is, it is used for programs already built. A compiler can have both (because it is also a program, but it builds binaries), whereas a program only uses parameters.
Now let’s get to know 10 most used GNU GCC flags and parameters!
First of all check your compiler version with g++ --version
or gcc --version
, some things might not work if your version is too old.
In a basic C/C++ code to compile just use the command: gcc
for C language and g++
for C++. Examples:
main.cpp
main.c
Some alternative commands to gcc/g++ can be: basic mode, alias or symbolic link are:
To compile, run:
In fact, the cc
command was the standard C compiler for Unix, but the source code was not available.
-o
parameterIf you want to save to a different binary name, use the -o
parameter:
Let’s use
g++
as a base, but usegcc
if you want to achieve the same result.
warnings
and errors
The -Wall
flag means Warnig all
. When there is a flag starting with W
that means it is to detect warnings, in this case for all/all, actually a set of flags, there are more than 40 .
Suppose you created a variable and didn’t use it anywhere in your code. If you compile normally, this will pass, but if you use -Wall
, the compiler will warn you:
g++ -Wall main.cpp
Even so the program compiles, it’s just a warning. If you want to turn this warning into an error, i.e., not compile if there is a warning, you need to combine this flag with another flag which is -Werro
, it treats the warning as an error:
That is, if you remove the binary and recompile, note that the binary will not be built.
The
-g
parameter is used for debugging at the operating system level. It’s always good to use it in conjunction with-Wall and -Werror
.
If we use this variable, note that compilation will pass even with -Wall and -Werror
:
But notice that we have the function arguments being passed but not being used. To stop this we can use the flag: -Wextra
, but it needs to be together with -Wall and -Werror
:
Either we use these parameters or we need to remove them.
Formerly there was a bug in the compilers that even if you removed it, it was possible to obtain parameters via the command line, for that there was the technique of using the void
parameter, but this is no longer necessary:
According to the dictionary, pedantic is one who cares excessively about small details or rules and the name justifies it.
That is, the -pedantic
parameter checks if your code complies with ISO rules, for example:
When compiling, note:
Remembering that
-pendatic-errors
does not enable as an error, it is like an alias for-pedantic
itself.
You can see all the compiler steps using the --verbose
or -v
parameter
This is usually enabled by default on systems that compile from scratch, like Gentoo, for example, which is where I’m at.
Sanitizers was developed by Google and is such well-made software that it has been natively adopted by the GNU GCC: https://github.com/google/sanitizers.
It checks for memory violations and as its name suggests: disinfects!
Suppose we have this code:
If we compile normally and run it several times, note that nothing will be displayed, but in one of the executions it will present the bug:
Now if we compile with Sanitize:
Note that running the program will not run and will give you details of the addressing violation:
Observation: Note that the size of the binary grows a lot when using it, that way you understand why some programming languages that call themselves safe memory have such large binaries, because they already have all these flags by default activated in the compiler . I particularly think this is bad, because the programmer doesn’t know what he’s doing. But, if you want you can create a Bash function in your
~/.bashrc
and add all parameters to gcc/g++ automatically, including static analyzers and other tools, but remember your binaries will grow significantly!
Or
In the GTKmm series we use the -MMD
parameter. It serves to separate the headers and include them later in the linker.
First of all let’s know what the linker is about. It is a program that merges two binary files together.
Suppose we have this code that needs to compile 2 .cpp
files:
We could compile like this directly: g++ main.cpp class.cpp
.
But, using the linker (in GCC the linker can use gcc/g++ itself) we can separate the headers and optimize our compilation:
However, when there are many headers, it can be duplicated several times to include them, so the -MMD
parameter is used.
To make it easy to understand, let’s use the GTKmm series project that is at: https://github.com/terroo/pass-firefox
Let’s clone, check the Makefile and modify.
That is, the headers are in a separate file to be included later by the linker.
C/C++ compilers create assembly code and then compile assembly code. That’s why the new programming languages are seen as a front-end for C/C++, more precisely the C++ that LLVM is written on.
There are several assembly compilers, and GNU GCC has its own which is the GNU Assembler (an alternative to NASM), and uses the as
command.
To generate assembly code:
View the generated assembly code:
Use compile as
to generate the binary:
Now just compile main.o
We’ve talked about situations where the size of the binary can get quite large depending on the flags you pass in, but this can be improved by using the -O2
flag, actually you can use several numbers: -O1
, - O2
, -O3
, …. but above 2 it’s dangerous depending on the machine you’re compiling, simple machines (2 processors and 8GB of RAM) it’s better to use a maximum of -O2
:
Test code:
The GNU GCC is huge, it has a world of flags and parameters, for everyone use the manual: