Chapter 3. Compiling and Building
3.1. GNU Compiler Collection (GCC)
gcc
and g++
), run-time libraries (like libgcc
, libstdc++
, libgfortran
, and libgomp
), and miscellaneous other utilities.
3.1.1. Language Compatibility
- Calling conventions. These specify how arguments are passed to functions and how results are returned from functions.
- Register usage conventions. These specify how processor registers are allocated and used.
- Object file formats. These specify the representation of binary object code.
- Size, layout, and alignment of data types. These specify how data is laid out in memory.
- Interfaces provided by the runtime environment. Where the documented semantics do not change from one version to another they must be kept available and use the same name at all times.
- Name mangling and demangling
- Creation and propagation of exceptions
- Formatting of run-time type information
- Constructors and destructors
- Layout, alignment, and padding of classes and derived classes
- Virtual function implementation details, such as the layout and alignment of virtual tables
The following is a list of known incompatibilities between the Red Hat Enterprise Linux 6 and 5 toolchains.
- Passing/returning structs with flexible array members by value changed in some cases on Intel 64 and AMD64.
- Passing/returning of unions with long double members by value changed in some cases on Intel 64 and AMD64.
- Passing/returning structs with complex float member by value changed in some cases on Intel 64 and AMD64.
- Passing of 256-bit vectors on x86, Intel 64 and AMD64 platforms changed when
-mavx
is used. - There have been multiple changes in passing of _Decimal{32,64,128} types and aggregates containing those by value on several targets.
- Packing of packed char bitfields changed in some cases.
The following is a list of known incompatibilities between the Red Hat Enterprise Linux 5 and 4 toolchains.
- There have been changes in the library interface specified by the C++ ABI for thread-safe initialization of function-scope static variables.
- On Intel 64 and AMD64, the medium model for building applications where data segment exceeds 4GB, was redesigned to match the latest ABI draft at the time. The ABI change results in incompatibility among medium model objects.
-Wabi
can be used to get diagnostics indicating where these constructs appear in source code, though it will not catch every single case. This flag is especially useful for C++ code to warn whenever the compiler generates code that is known to be incompatible with the vendor-neutral C++ ABI.
-fabi-version=1
option. This practice is not recommended. Objects created this way are indistinguishable from objects conforming to the current stable ABI, and can be linked (incorrectly) amongst the different ABIs, especially when using new compilers to generate code to be linked with old libraries that were built with tools prior to Red Hat Enterprise Linux 4.
Warning
3.1.2. Object Compatibility and Interoperability
ld
(distributed as part of the binutils
package) or in the dynamic loader (ld.so
, distributed as part of the glibc
package) can subtly change the object files that the compiler produces. These changes mean that object files moving to the current release of Red Hat Enterprise Linux from previous releases may lose functionality, behave differently at runtime, or otherwise interoperate in a diminished capacity. Known problem areas include:
ld
--build-id
In Red Hat Enterprise Linux 6 this is passed told
by default, whereas Red Hat Enterprise Linux 5ld
doesn't recognize it.as
.cfi_sections
supportIn Red Hat Enterprise Linux 6 this directive allows.debug_frame
,.eh_frame
or both to be omitted from.cfi*
directives. In Red Hat Enterprise Linux 5 only.eh_frame
is omitted.as
,ld
,ld.so
, andgdb
STB_GNU_UNIQUE
and%gnu_unique_symbol
supportIn Red Hat Enterprise Linux 6 more debug information is generated and stored in object files. This information relies on new features detailed in theDWARF
standard, and also on new extensions not yet standardized. In Red Hat Enterprise Linux 5, tools likeas
,ld
,gdb
,objdump
, andreadelf
may not be prepared for this new information and may fail to interoperate with objects created with the newer tools. In addition, Red Hat Enterprise Linux 5 produced object files do not support these new features; these object files may be handled by Red Hat Enterprise Linux 6 tools in a sub-optimal manner.An outgrowth of this enhanced debug information is that the debuginfo packages that ship with system libraries allow you to do useful source level debugging into system libraries if they are installed. See Section 4.2, “Installing Debuginfo Packages” for more information on debuginfo packages.
prelink
.
3.1.3. Running GCC
gcc
command. This is the main driver for the compiler. It can be used from the command line to pre-process or compile a source file, link object files and libraries, or perform a combination thereof. By default, gcc
takes care of the details and links in the provided libgcc
library.
3.1.3.1. Simple C Usage
Example 3.1. hello.c
#include <stdio.h> int main() { printf ("Hello world!\n"); return 0; }
Procedure 3.1. Compiling a 'Hello World' C Program
- Compile Example 3.1, “hello.c” into an executable with:
~]$
gcc hello.c -o hello
Ensure that the resulting binaryhello
is in the same directory ashello.c
. - Run the
hello
binary, that is,./hello
.
3.1.3.2. Simple C++ Usage
Example 3.2. hello.cc
#include <iostream> using namespace std; int main() { cout << "Hello World!" << endl; return 0; }
Procedure 3.2. Compiling a 'Hello World' C++ Program
- Compile Example 3.2, “hello.cc” into an executable with:
~]$
g++ hello.cc -o hello
Ensure that the resulting binaryhello
is in the same directory ashello.cc
. - Run the
hello
binary, that is,./hello
.
3.1.3.3. Simple Multi-File Usage
Example 3.3. one.c
#include <stdio.h> void hello() { printf("Hello world!\n"); }
Example 3.4. two.c
extern void hello(); int main() { hello(); return 0; }
Procedure 3.3. Compiling a Program with Multiple Source Files
- Compile Example 3.3, “one.c” into an executable with:
~]$
gcc -c one.c -o one.o
Ensure that the resulting binaryone.o
is in the same directory asone.c
. - Compile Example 3.4, “two.c” into an executable with:
~]$
gcc -c two.c -o two.o
Ensure that the resulting binarytwo.o
is in the same directory astwo.c
. - Compile the two object files
one.o
andtwo.o
into a single executable with:~]$
gcc one.o two.o -o hello
Ensure that the resulting binaryhello
is in the same directory asone.o
andtwo.o
. - Run the
hello
binary, that is,./hello
.
3.1.3.4. Recommended Optimization Options
It is very important to choose the correct architecture for instruction scheduling. By default GCC produces code optimized for the most common processors, but if the CPU on which your code will run is known, the corresponding -mtune=
option to optimize the instruction scheduling, and -march=
option to optimize the instruction selection should be used.
-mtune=
optimizes instruction scheduling to fit your architecture by tuning everything except the ABI and the available instruction set. This option will not choose particular instructions, but instead will tune your program in such a way that executing on a particular architecture will be optimized. For example, if an Intel Core2 CPU will predominantly be used, choose -mtune=core2
. If the wrong choice is made, the program will still run, but not optimally on the given architecture. The architecture on which the program will most likely run should always be chosen.
-march=
optimizes instruction selection. As such, it is important to choose correctly as choosing incorrectly will cause your program to fail. This option selects the instruction set used when generating code. For example, if the program will be run on an AMD K8 core based CPU, choose -march=k8
. Specifying the architecture with this option will imply -mtune=
.
-mtune=
and -march=
commands should only be used for tuning and selecting instructions within a given architecture, not to generate code for a different architecture (also known as cross-compiling). For example, this is not to be used to generate PowerPC code from an Intel 64 and AMD64 platform.
-march=
and -mtune=
, see the GCC documentation available here: GCC 4.4.4 Manual: Hardware Models and Configurations
The compiler flag -O2
is a good middle of the road option to generate fast code. It produces the best optimized code when the resulting code size is not large. Use this when unsure what would best suit.
-O3
is preferable. This option produces code that is slightly larger but runs faster because of a more frequent inline of functions. This is ideal for floating point intensive code.
-Os
. This flag also optimizes for size, and produces faster code in situations where a smaller footprint will increase code locality, thereby reducing cache misses.
-frecord-gcc-switches
when compiling objects. This records the options used to build objects into objects themselves. After an object is built, it determines which set of options were used to build it. The set of options are then recorded in a section called .GCC.command.line
within the object and can be examined with the following:
$ gcc -frecord-gcc-switches -O3 -Wall hello.c -o hello $ readelf --string-dump=.GCC.command.line hello String dump of section '.GCC.command.line': [ 0] hello.c [ 8] -mtune=generic [ 17] -O3 [ 1b] -Wall [ 21] -frecord-gcc-switches
3.1.3.5. Using Profile Feedback to Tune Optimization Heuristics
- Inlining
- Branch prediction
- Instruction scheduling
- Inter-procedural constant propagation
- Determining of hot or cold functions
Procedure 3.4. Using Profile Feedback
- The application must be instrumented to produce profiling information by compiling it with
-fprofile-generate
. - Run the application to accumulate and save the profiling information.
- Recompile the application with
-fprofile-use
.
Procedure 3.5. Compiling a Program with Profiling Feedback
- Compile
source.c
to include profiling instrumentation:gcc source.c -fprofile-generate -O2 -o executable
- Run
executable
to gather profiling information:./executable
- Recompile and optimize
source.c
with profiling information gathered in step one:gcc source.c -fprofile-use -O2 -o executable
-fprofile-dir=DIR
where DIR
is the preferred output directory.
Warning
3.1.3.6. Using 32-bit compilers on a 64-bit host
glibc
and libgcc
, and libstdc++
if the program is a C++ program. On Intel 64 and AMD64, this can be done with:
yum install glibc-devel.i686 libgcc.i686 libstdc++-devel.i686
db4-devel
libraries to build, the 32-bit version of these libraries can be installed with:
yum install db4-devel.i686
Note
.i686
suffix on the x86 platform (as opposed to x86-64
) specifies a 32-bit version of the given package. For PowerPC architectures, the suffix is ppc
(as opposed to ppc64
).
-m32
option can be passed to the compiler and linker to produce 32-bit executables. Provided the supporting 32-bit libraries are installed on the 64-bit system, this executable will be able to run on both 32-bit systems and 64-bit systems.
Procedure 3.6. Compiling a 32-bit Program on a 64-bit Host
- On a 64-bit system, compile
hello.c
into a 64-bit executable with:gcc hello.c -o hello64
- Ensure that the resulting executable is a 64-bit binary:
$ file hello64 hello64: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped $ ldd hello64 linux-vdso.so.1 => (0x00007fff242dd000) libc.so.6 => /lib64/libc.so.6 (0x00007f0721514000) /lib64/ld-linux-x86-64.so.2 (0x00007f0721893000)
The commandfile
on a 64-bit executable will includeELF 64-bit
in its output, andldd
will list/lib64/libc.so.6
as the main C library linked. - On a 64-bit system, compile
hello.c
into a 32-bit executable with:gcc -m32 hello.c -o hello32
- Ensure that the resulting executable is a 32-bit binary:
$ file hello32 hello32: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped $ ldd hello32 linux-gate.so.1 => (0x007eb000) libc.so.6 => /lib/libc.so.6 (0x00b13000) /lib/ld-linux.so.2 (0x00cd7000)
The commandfile
on a 32-bit executable will includeELF 32-bit
in its output, andldd
will list/lib/libc.so.6
as the main C library linked.
$ gcc -m32 hello32.c -o hello32 /usr/bin/ld: crt1.o: No such file: No such file or directory collect2: ld returned 1 exit status
$ g++ -m32 hello32.cc -o hello32-c++ In file included from /usr/include/features.h:385, from /usr/lib/gcc/x86_64-redhat-linux/4.4.4/../../../../include/c++/4.4.4/x86_64-redhat-linux/32/bits/os_defines.h:39, from /usr/lib/gcc/x86_64-redhat-linux/4.4.4/../../../../include/c++/4.4.4/x86_64-redhat-linux/32/bits/c++config.h:243, from /usr/lib/gcc/x86_64-redhat-linux/4.4.4/../../../../include/c++/4.4.4/iostream:39, from hello32.cc:1: /usr/include/gnu/stubs.h:7:27: error: gnu/stubs-32.h: No such file or directory
-m32
will in not adapt or convert a program to resolve any issues arising from 32/64-bit incompatibilities. For tips on writing portable code and converting from 32-bits to 64-bits, see the paper entitled Porting to 64-bit GNU/Linux Systems in the Proceedings of the 2003 GCC Developers Summit.
3.1.4. GCC Documentation
man
pages for cpp
, gcc
, g++
, gcj
, and gfortran
.