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.

Introduction to GCC

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:

Using GCC

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).

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.

GCC on Windows: MinGW

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.

Using MinGW under Linux as a cross-compiler

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.

Other related tools

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:

Creative Commons Logo Contrat Creative Commons

This article is licensed under Creative Commons Attribution-NoDerivs 2.5 licence (CC-BY-ND).