Written by David Henry, june 4th of 2006
This article is about the GCC compiler suite and its win32 port, MinGW. It does not intend to be a complete reference for these tools, but a “starter” guide, or at least a little reference article of the most used features of GCC.
This document targets beginner programmers who want to use the free GCC compiler, or simply developpers who want to port their programs to another platform with GCC and want to learn how to use it.
I will cover here both how to compile native programs with GCC on GNU/Linux and Windows and how to do cross-compiling with MinGW on non-Windows platforme.
GCC stands for “GNU Compiler Collection”. It is a compiler suite provided by the GNU Project. It was originally written by Richard Stallman in 1987 in order to have a free (Open Source) C compiler for building the GNU Operating System. It originally stood for “GNU C Compiler”. GCC is licensed under the terms of the GNU Public Licence (GPL).
GCC is an amazing compiler suite, it includes front ends for 7 languages (officially, others front ends exist), targets a lot of architectures (about 50 processors!) and runs on a lot of Operating Systems, including GNU/Linux, MacOS and Windows (Open Source OS are generally build with this compiler). other GCC-based compilers or front ends exists for more specific targets like microcontrollers.
Here is the list of officially supported languages and their front end:
GCC is a command line compiler. It does just what it was designed for: compiling. You can write your code with any text editor, such as vim, emacs (better), kwrite, or more bloated stuff like IDEs Kdevelop, Eclipse (*cough*) or Code::blocks.
I will use the well known “hello world” program for illustrating the commands, in C:
#include <stdio.h> int main () { printf ("Hello world!\n"); return 0; }
Assuming that this program has been written in the file hello.c, you can compile it by simply invoking GCC with the file as parameter. In a shell, type the following command (the $ indicates the command line prompt, don't write it):
$ gcc hello.c
This will produce a binary file called a.out. You can execute it with this command:
$ ./a.out
As expected, it will print in the shell the string “Hello world!”. If you have multiple source files, you can pass them all to GCC; they will be compiled and linked together:
$ gcc hello.c foo.c bar.c
You may want to give a name other than “a.out” to your program. Use the -o
option followed by the name (note that you can place this option anywhere, like any
option):
$ gcc -o hello hello.c
You can tell GCC to just compile a source file with the -c
option:
$ gcc -c hello.c
It will produce an intermediary object file hello.o. You will need to call the linker in order to obtain an executable binary. To invoke the linker, you just call GCC with the object files:
$ gcc -o hello hello.o
Thus, you can compile each source file of your program separately, and then call the linker:
$ gcc -c hello.c $ gcc -c foo.c $ gcc -c bar.c $ gcc -o hello hello.o foo.o bar.o
By default, GCC searches in the /usr/local/include and /usr/include
directories for header files (you know, the one you include with the #include
directive).
You can specify additional include paths with the -I
option followed by
the absolute or relative path. By convention, we don't put any space between the
-I
option and the path. For example, if you have header files in
/somewhere/include, call:
$ gcc -o hello -I/somewhere/include hello.c
To link with a library, use the -l
option followed by the name of the
library whithout the “lib” prefix in its name and with no extension. For example, assume
you want to link hello with the libpng (because it can produce a
cool smiley in a PNG file). You have the libpng.a file (the static library needed
at compile time) installed in /usr/lib (the standard library directory):
$ gcc -o hello hello.c -lpng
As for header files, GCC searches for library files to link with in the
/usr/local/lib and /usr/lib directories. You can specify additional
library paths with the -L
option, like for includes:
$ gcc -o hello -L/somewhere/lib hello.c
You can define some macros with the -D
option, followed by the macro
name and eventually its value (separated by an equal symbol). The following will compile
our source file and define the macro VALUE
with a value of 10:
$ gcc -o hello hello.c -DVALUE=10
GCC has options for optimizing the compilation. You can control optimization with
five options: -O
(or -O1
), -O2
, -O3
,
-Os
and -O0
(do not optimize). Each of them represent a
level of optimizations and corresponds to a group of individual optimizations. Individual
optimizations start with the letter “f” in their name (see the manual for more info about
them).
-O
: First optimization level. The compiler try to reduce code size
and execution time without performing any optimizations that take a great deal of
compilation time;-O2
: Optimize even more. As compared to -O, this option increases both
compilation time and the performance of the generated code;-O3
: Optimize yet more. -O3 turns on all optimizations specified by
-O2 and some more;-Os
: Optimize for size. -Os enables all -O2 optimizations that do not
typically increase code size. It also performs further optimizations designed to reduce
code size;-O0
: Do not optimize. This is the default.By default, the executable produced by GCC keeps its symbol table and relocation
information in it. It results in larger binary files. You can remove them by passing the
-s
(for “strip”) option to the linker:
$ gcc -o hello hello.o foo.o bar.o -s
The symbol table is useful when debugging, so do not use this option when debugging!
Also, I would recommend you to enable all warnings with the -Wall
option,
and to release your programs without any warning. Individual warning options start with the
letter “W” in their name (see the manual). Even better, you can use the
-Werror
option to tell GCC to treat warnings like errors!
You can tell GCC which standard to use with the -std
option, followed by
an equal symbol and the name of the standard. See the manual for the list of supported
standards for each language. For the C language, you may use c89
for Ansi C,
or c99
for C99. For Ansi C, you can use the -ansi
option
instead of -std
:
$ gcc -o hello1 hello.c -ansi $ gcc -o hello2 hello.c -std=c99
The -pedantic
option enables all the warnings demanded by strict ISO C and
ISO C++ and will reject all programs that use forbidden extensions or that do not follow ISO
C and ISO C++. The -pedantic-errors
turns these warnings to errors.
Now maybe you want to program in C++. That's pretty the same thing. Here is the famous hello world in C++:
#include <iostream> int main () { std::cout << "Hello world!" << std::endl; return 0; }
The compilation is similar to C's version. Note that we link with the libstdc++ library (because we use iostream):
$ g++ -o hello hello.cpp -lstdc++
To finish, I will present you the ultimate g++ warning option, teh
-Weffc++
option! If you can compile a whole project with with this option
turned on, combined with the -Werror
option, you are a Jedi :p
(hint: it's currently impossible with the standard library)
That's all for GCC. I think I have covered the most used options. If you want more, take a look at the manual.
MinGW is the native port of GCC on Windows. MinGW stands for “Minimalist GNU for Windows”. It provides a collection of tools to produce native Windows programs. This project has been started in July 1998. Unfortunately, MinGW is a bit lagging behind the GCC project.
MinGW includes header files and libraries for programming with the win32
API. It also provides
an implementation (sometimes partial) of some POSIX functions that are not present
on others compilers, like Microsoft Visual Studio. The
opendir
/readdir
functions for reading directories are
an example of these.
Installing MinGW is really simple. You can get it on the MinGW download page. Download the latest mingw installer and run it. By default, it will install in C:\MinGW.
I recommend you to also download and install MSYS, a package which provides very useful tools when working with GCC like a shell (bash) or the make utility.
Your GCC environment on Windows is now ready. You can run the MSYS shell and use GCC like mentioned in the previous section.
MinGW can also be used on Linux systems as a cross-compiler, so you can build native Windows executables on your preferred development platform ;-)
Some distributions like Debian provide packages for MinGW. Just use
apt-get
(or your distro's package tool) to install them:
# apt-get install mingw32
It will also install packages mingw32-binutils and mingw32-runtime
as dependencies. You can then invoke GCC by calling i586-mingw32msvc-gcc
,
i586-mingw32msvc-g++
, etc., instead of gcc
, g++
,
...
Note that C++ programs will be much more large than ones produced on Linux or by Microsoft Visual Studio. This is because the standard library must be statically linked into the binary.
In this section I will quickly present some other tools that are used with GCC. I will not explain how to use them however, it is beyond the scope of this article.
make is the utility to know when developping with GCC!
This is used to automate compilations. You put your compilation instructions in a
Makefile and then invoke make
on your shell to run the compilation
process. It can also determine which pieces of your program must be recompiled, avoiding
a full recompilation each time you make a change.
gdb is the GNU Debugger tool. To enable debugging you must compile
with the -g
option and disable optimizations. Another very good tool for
debugging memory leaks is valgrind.
colorgcc is a colorization wrapper for GCC. It is really easier to read GCC output with colors for warnings and errors.
Here are some links if you want to read more about GCC and MinGW:
This article is licensed under Creative Commons Attribution-NoDerivs 2.5 licence (CC-BY-ND).