GCC and Make: Compiling, Linking and Building C/C++ Applications
GCC and Make: Compiling, Linking and Building C/C++ Applications
GCC and Make: Compiling, Linking and Building C/C++ Applications
html
C/C++ Applications
1.6 Ge�ng Started
1.7 GCC Compila�on Process
1.8 Headers (.h), Sta�c Libraries (.lib
1.9 GCC Environment Variables
1.10 U�li�es for Examining the Compiled Files
2. GNU Make
1. GCC (GNU Compiler Collection) 2.1 First Makefile By Example
2.2 More on Makefile
2.3 A Sample Makefile
1.1 A Brief History and Introduction to GCC 2.4 Brief Summary
The original GNU C Compiler (GCC) is developed by Richard Stallman, the founder of the GNU Project. Richard
Stallman founded the GNU project in 1984 to create a complete Unix-like opera�ng system as free so�ware, to
promote freedom and coopera�on among computer users and programmers.
GCC, formerly for "GNU C Compiler", has grown over �mes to support many languages such as C (gcc), C++ (g++), Objec�ve-C, Objec�ve-C++, Java (gcj),
Fortran (gfortran), Ada (gnat), Go (gccgo), OpenMP, Cilk Plus, and OpenAcc. It is now referred to as "GNU Compiler Collec�on". The mother site for GCC is
h�p://gcc.gnu.org/. The current version is GCC 7.3, released on 2018-01-25.
GCC is a key component of so-called "GNU Toolchain", for developing applica�ons and wri�ng opera�ng systems. The GNU Toolchain includes:
1. GNU Compiler Collec�on (GCC): a compiler suite that supports many languages, such as C/C++ and Objec�ve-C/C++.
2. GNU Make: an automa�on tool for compiling and building applica�ons.
3. GNU Binu�ls: a suite of binary u�lity tools, including linker and assembler.
4. GNU Debugger (GDB).
5. GNU Autotools: A build system including Autoconf, Autoheader, Automake and Libtool.
6. GNU Bison: a parser generator (similar to lex and yacc).
GCC is portable and run in many opera�ng pla�orms. GCC (and GNU Toolchain) is currently available on all Unixes. They are also ported to Windows (by Cygwin,
MinGW and MinGW-W64). GCC is also a cross-compiler, for producing executables on different pla�orm.
GCC Versions
The various GCC versions are:
GCC version 1 (1987): Ini�al version that support C.
GCC version 2 (1992): supports C++.
GCC version 3 (2001): incorpora�ng ECGS (Experimental GNU Compiler System), with improve op�miza�on.
GCC version 4 (2005):
GCC version 5 (2015):
GCC Version 6 (2016):
GCC Version 7 (2017):
The default mode is C++98 for GCC versions prior to 6.1, and C++14 for GCC 6.1 and above. You can use command-line flag -std to explicitly specify the C++
standard. For example,
-std=c++98, or -std=gnu++98 (C++98 with GNU extensions)
-std=c++11, or -std=gnu++11 (C++11 with GNU extensions)
-std=c++14, or -std=gnu++14 (C++14 with GNU extensions), default mode for GCC 6.1 and above.
1 of 11 22/03/2020, 19:56
GCC and Make - A Tutorial on how to compile, link and build C/C++ app... https://www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html
$ gcc --version
......
Target: x86_64-apple-darwin14.5.0 // 64-bit target codes
Thread model: posix
Notes:
I suggest you install "mingw64-x86_64-gcc-core" and "mingw64-x86_64-gcc-g++" to provide na�ve 64-bit Windows codes, but skip
"mingw64-i686-gcc-core" and "mingw64-i686-gcc-g++", unless you need to produce 32-bit Windows applica�ons.
For JNI (Java Na�ve Interface) in 64-bit Java, you need to use "x86_64-w64-mingw32-gcc" or "x86_64-w64-mingw32-g++" to produce 64-bit
na�ve Windows code.
$ x86_64-w64-mingw32-gcc -v
Using built-in specs.
COLLECT_GCC=x86_64-w64-mingw32-gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-w64-mingw32/6.4.0/lto-wrapper.exe
Target: x86_64-w64-mingw32
Configured with: .....
Thread model: posix
gcc version 6.4.0 (GCC)
$ x86_64-w64-mingw32-g++ --version
x86_64-w64-mingw32-g++ (GCC) 6.4.0
2 of 11 22/03/2020, 19:56
GCC and Make - A Tutorial on how to compile, link and build C/C++ app... https://www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html
$ i686-w64-mingw32-gcc --version
i686-w64-mingw32-gcc (GCC) 6.4.0
$ i686-w64-mingw32-g++ --version
i686-w64-mingw32-g++ (GCC) 6.4.0
Versions
You could display the version of GCC via --version op�on:
$ gcc --version
gcc (GCC) 6.4.0
$ g++ --version
g++ (GCC) 6.4.0
$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-cygwin/6.4.0/lto-wrapper.exe
Target: x86_64-pc-cygwin
Configured with: ......
Thread model: posix
gcc version 6.4.0 (GCC)
$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-cygwin/6.4.0/lto-wrapper.exe
Target: x86_64-pc-cygwin
Configured with: ......
Thread model: posix
gcc version 6.4.0 (GCC)
Help
You can get the help manual via the --help op�on. For example,
$ gcc --help
Man Pages
You can read the GCC manual pages (or man pages) via the man u�lity:
$ man gcc
// or
$ man g++
// Press space key for next page, or 'q' to quit.
Reading man pages under CMD or Bash shell can be difficult. You could generate a text file via:
The col u�lity is needed to strip the backspace. (For Cygwin, it is available in "U�ls", "u�l-linux" package.)
Alterna�vely, you could look for an online man pages, e.g., h�p://linux.die.net/man/1/gcc.
$ whereis gcc
gcc: /usr/bin/gcc.exe /usr/lib/gcc /usr/share/man/man1/gcc.1.gz
3 of 11 22/03/2020, 19:56
GCC and Make - A Tutorial on how to compile, link and build C/C++ app... https://www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html
1 // hello.c
2 #include <stdio.h>
3
4 int main() {
5 printf("Hello, world!\n");
6 return 0;
7 }
The default output executable is called "a.exe" (Windows) or "a.out" (Unixes and Mac OS X).
You need to use g++ to compile C++ program, as follows. We use the -o op�on to specify the output file name.
4 of 11 22/03/2020, 19:56
GCC and Make - A Tutorial on how to compile, link and build C/C++ app... https://www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html
However, we usually compile each of the source files separately into object file, and link them together in the later stage. In this case, changes in one file does
not require re-compila�on of the other files.
GCC compiles a C/C++ program into executable in 4 steps as shown in the above diagram. For example, a "gcc -o hello.exe hello.c" is carried out as
follows:
1. Pre-processing: via the GNU C Preprocessor (cpp.exe), which includes the headers (#include) and expands the macros (#define).
The resultant intermediate file "hello.i" contains the expanded source code.
2. Compila�on: The compiler compiles the pre-processed source code into assembly code for a specific processor.
The -S op�on specifies to produce assembly code, instead of object code. The resultant assembly file is "hello.s".
3. Assembly: The assembler (as.exe) converts the assembly code into machine code in the object file "hello.o".
5 of 11 22/03/2020, 19:56
GCC and Make - A Tutorial on how to compile, link and build C/C++ app... https://www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html
4. Linker: Finally, the linker (ld.exe) links the object code with the library code to produce an executable file "hello.exe".
1.8 Headers (.h), Static Libraries (.lib, .a) and Shared Library (.dll, .so)
There are two types of external libraries: sta�c library and shared library.
1. A sta�c library has file extension of ".a" (archive file) in Unixes or ".lib" (library) in Windows. When your program is linked against a sta�c library, the
machine code of external func�ons used in your program is copied into the executable. A sta�c library can be created via the archive program "ar.exe".
2. A shared library has file extension of ".so" (shared objects) in Unixes or ".dll" (dynamic link library) in Windows. When your program is linked against
a shared library, only a small table is created in the executable. Before the executable starts running, the opera�ng system loads the machine code needed
for the external func�ons - a process known as dynamic linking. Dynamic linking makes executable files smaller and saves disk space, because one copy of
a library can be shared between mul�ple programs. Furthermore, most opera�ng systems allows one copy of a shared library in memory to be used by all
running programs, thus, saving memory. The shared library codes can be upgraded without the need to recompile your program.
Because of the advantage of dynamic linking, GCC, by default, links to the shared library if it is available.
For each of the headers used in your source (via #include direc�ves), the compiler searches the so-called include-paths for these headers. The include-paths
are specified via -Idir op�on (or environment variable CPATH). Since the header's filename is known (e.g., iostream.h, stdio.h), the compiler only
needs the directories.
The linker searches the so-called library-paths for libraries needed to link the program into an executable. The library-path is specified via -Ldir op�on
(uppercase 'L' followed by the directory path) (or environment variable LIBRARY_PATH). In addi�on, you also have to specify the library name. In Unixes,
the library libxxx.a is specified via -lxxx op�on (lowercase le�er 'l', without the prefix "lib" and ".a" extension). In Windows, provide the full name
such as -lxxx.lib. The linker needs to know both the directories as well as the library names. Hence, two op�ons need to be specified.
> cpp -v
......
#include "..." search starts here:
#include <...> search starts here:
/usr/lib/gcc/x86_64-pc-cygwin/6.4.0/include
/usr/include
/usr/lib/gcc/x86_64-pc-cygwin/6.4.0/../../../../lib/../include/w32api
Try running the compila�on in verbose mode (-v) to study the library-paths (-L) and libraries (-l) used in your system:
6 of 11 22/03/2020, 19:56
GCC and Make - A Tutorial on how to compile, link and build C/C++ app... https://www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html
Eclipse CDT: In Eclipse CDT, you can set the include paths, library paths and libraries by right-click on the project ⇒ Proper�es ⇒ C/C++ General ⇒ Paths and
Symbols ⇒ Under tabs "Includes", "Library Paths" and "Libraries". The se�ngs are applicable to the selected project only.
$ gcc -c hello.c
$ gcc -o hello.exe hello.o
$ file hello.c
hello.c: C source, ASCII text, with CRLF line terminators
$ file hello.o
hello.o: data
$ nm hello.o
0000000000000000 b .bss
0000000000000000 d .data
0000000000000000 p .pdata
0000000000000000 r .rdata
0000000000000000 r .rdata$zzz
0000000000000000 t .text
0000000000000000 r .xdata
U __main
0000000000000000 T main
U puts
"nm" is commonly-used to check if a par�cular func�on is defined in an object file. A 'T' in the second column indicates a func�on that is defined, while a 'U'
indicates a func�on which is undefined and should be resolved by the linker.
2. GNU Make
The "make" u�lity automates the mundane aspects of building executable from source code. "make" uses a so-called makefile, which contains rules on how
7 of 11 22/03/2020, 19:56
GCC and Make - A Tutorial on how to compile, link and build C/C++ app... https://www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html
You can issue "make --help" to list the command-line op�ons; or "man make" to display the man pages.
1 // hello.c
2 #include <stdio.h>
3
4 int main() {
5 printf("Hello, world!\n");
6 return 0;
7 }
Create the following file named "makefile" (without any file extension), which contains rules to build the executable, and save in the same directory as the
source file. Use "tab" to indent the command (NOT spaces).
all: hello.exe
hello.exe: hello.o
gcc -o hello.exe hello.o
hello.o: hello.c
gcc -c hello.c
clean:
rm hello.o hello.exe
> make
gcc -c hello.c
gcc -o hello.exe hello.o
Running make without argument starts the target "all" in the makefile. A makefile consists of a set of rules. A rule consists of 3 parts: a target, a list of pre-
requisites and a command, as follows:
The target and pre-requisites are separated by a colon (:). The command must be preceded by a tab (NOT spaces).
When make is asked to evaluate a rule, it begins by finding the files in the prerequisites. If any of the prerequisites has an associated rule, make a�empts to
update those first.
In the above example, the rule "all" has a pre-requisite "hello.exe". make cannot find the file "hello.exe", so it looks for a rule to create it. The rule
"hello.exe" has a pre-requisite "hello.o". Again, it does not exist, so make looks for a rule to create it. The rule "hello.o" has a pre-requisite
"hello.c". make checks that "hello.c" exists and it is newer than the target (which does not exist). It runs the command "gcc -c hello.c". The rule
"hello.exe" then run its command "gcc -o hello.exe hello.o". Finally, the rule "all" does nothing.
More importantly, if the pre-requisite is not newer than than target, the command will not be run. In other words, the command will be run only if the target is
out-dated compared with its pre-requisite. For example, if we re-run the make command:
> make
make: Nothing to be done for `all'.
You can also specify the target to be made in the make command. For example, the target "clean" removes the "hello.o" and "hello.exe". You can
then run the make without target, which is the same as "make all".
> make
gcc -c hello.c
gcc -o hello.exe hello.o
NOTES:
If the command is not preceded by a tab, you get an error message "makefile:4: *** missing separator. Stop."
If there is no makefile in the current directory, you get an error message "make: *** No targets specified and no makefile found. Stop."
The makefile can be named "makefile", "Makefile" or "GNUMakefile", without file extension.
8 of 11 22/03/2020, 19:56
GCC and Make - A Tutorial on how to compile, link and build C/C++ app... https://www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html
A comment begins with a # and lasts �ll the end of the line. Long line can be broken and con�nued in several lines via a back-slash (\).
Syntax of Rules
A general syntax for the rules is:
The rules are usually organized in such as way the more general rules come first. The overall rule is o�en name "all", which is the default target for make.
Variables
A variable begins with a $ and is enclosed within parentheses (...) or braces {...}. Single character variables do not need the parentheses. For example,
$(CC), $(CC_FLAGS), $@, $^.
Automatic Variables
Automa�c variables are set by make a�er a rule is matched. There include:
$@: the target filename.
$*: the target filename without the file extension.
$<: the first prerequisite filename.
$^: the filenames of all the prerequisites, separated by spaces, discard duplicates.
$+: similar to $^, but includes duplicates.
$?: the names of all prerequisites that are newer than the target, separated by spaces.
all: hello.exe
hello.o: hello.c
gcc -c $<
clean:
rm hello.o hello.exe
# Search for dependencies and targets from "src" and "include" directories
# The directories are separated by space
VPATH = src include
You can also use vpath (lowercase) to be more precise about the file type and its search directory. For example,
Pattern Rules
A pa�ern rule, which uses pa�ern matching character '%' as the filename, can be applied to create a target, if there is no explicit rule. For example,
# Applicable for create executable (without extension) from object .o object file
# $^ matches all the pre-requisites (no duplicates)
9 of 11 22/03/2020, 19:56
GCC and Make - A Tutorial on how to compile, link and build C/C++ app... https://www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html
%: %.o
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
# A sample Makefile
# This Makefile demonstrates and explains
# Make Macros, Macro Expansions,
# Rules, Targets, Dependencies, Commands, Goals
# Artificial Targets, Pattern Rule, Dependency Rule.
# Here is a Make Macro that uses the backslash to extend to multiple lines.
OBJS = \
Test1.o \
Test2.o \
Main.o
# There are two standard Targets your Makefile should probably have:
# "all" and "clean", because they are often command-line Goals.
# Also, these are both typically Artificial Targets, because they don't typically
# correspond to real files named "all" or "clean".
# There is no required order to the list of rules as they appear in the Makefile.
# Make will build its own dependency tree and only execute each rule only once
# its dependencies' rules have been executed successfully.
# Here is a Rule that uses some built-in Make Macros in its command:
# $@ expands to the rule's target, in this case "test_me.exe".
# $^ expands to the rule's dependencies, in this case the three files
# main.o, test1.o, and test2.o.
$(LINK_TARGET) : $(OBJS)
g++ -g -o $@ $^
# These are Dependency Rules, which are rules without any command.
# Dependency Rules indicate that if any file to the right of the colon changes,
# the target to the left of the colon should be considered out-of-date.
# The commands for making an out-of-date target up-to-date may be found elsewhere
# (in this case, by the Pattern Rule above).
# Dependency Rules are often used to capture header file dependencies.
Main.o : Main.h Test1.h Test2.h
Test1.o : Test1.h Test2.h
Test2.o : Test2.h
10 of 11 22/03/2020, 19:56
GCC and Make - A Tutorial on how to compile, link and build C/C++ app... https://www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html
Feedback, comments, corrections, and errata can be sent to Chua Hock-Chuan (ehchua@ntu.edu.sg) | HOME
11 of 11 22/03/2020, 19:56