Build code with GCC

Transform source code into executable code. Compile source files, link object code, and understand the relationship between different code forms. Optimize, harden, and debug your applications by using GCC.

Relationship between code forms

The C and C++ languages have three forms of code that are created through different stages of the build process. Understanding these relationships helps you work effectively with the GNU Compiler Collection (GCC).

The code forms of C and C++ languages:

  • Source code written in the C or C++ language, present as plain text files.

    The files typically use extensions such as .c, .cc, .cpp, .h, .hpp, .i, .inc. For a complete list of supported extensions and their interpretation, see the gcc manual pages:

    $ man gcc
  • Object code, created by compiling the source code with a compiler. This is an intermediate form.

    The object code files use the .o extension.

  • Executable code, created by linking object code with a linker.

    Linux application executable files do not use any file name extension. Shared object (library) executable files use the .so file name extension.

Note

Library archive files for static linking also exist. This is a variant of object code that uses the .a file name extension. Do not use static linking.

Producing executable code from source code is performed in two steps, which require different applications or tools:

  1. Source files are compiled to object files.
  2. Object files and libraries are linked (including the previously compiled sources).

GCC can be used as an intelligent driver for both compilers and linkers. This allows you to use a single gcc command for any of the required actions (compiling and linking). GCC automatically selects the actions and their sequence.

You can run GCC to compile only, link only, or perform both steps. This is determined by the types of inputs and requested type of output.

Because larger projects require a build system that usually runs GCC separately for each action, it is better to always consider compilation and linking as two distinct actions, even if GCC can perform both at once.

Compile source files to object code

To create object code files from source files without creating an executable file immediately, instruct GCC to create only object code files as its output. This is a basic operation of the build process for larger projects.

Before you begin

  • C or C++ source code file(s)
  • GCC installed on the system. For details, see Installing development tools for C and C++. .Procedure
    1. At the command line, change to the directory containing the source code file(s).
    2. Run gcc with the -c option:
      $ gcc -c source.c another_source.c

      Object files are created, with their file names reflecting the original source code files: source.c results in source.o.

      Note

      With C++ source code, replace the gcc command with g++ for convenient handling of C++ Standard Library dependencies.

Code optimization with the GCC

Compiler optimization transforms your code for efficiency. Use GCC options to balance compilation time with execution speed or binary size suitable for your deployment. Selecting the appropriate optimization level helps you achieve faster execution or smaller binaries for your application.

With GCC, you can set the optimization level by using the -Olevel option. This option accepts a set of values in place of the level.

Level Description

0

Optimize for compilation speed - no code optimization (default).

1, 2, 3

Optimize to increase code execution speed (the larger the number, the greater the speed).

s

Optimize for file size.

fast

Same as a level 3 setting, plus fast disregards strict standards compliance to allow for additional optimizations.

g

Optimize for debugging experience.

For release builds, use the optimization option -O2.

During development, the -Og option is useful for debugging the program or library in some situations. Because some bugs manifest only with certain optimization levels, test the program or library with the release optimization level.

GCC offers a large number of options to enable individual optimizations. For more information, see gcc man page for more details.

Options to harden code with the GCC

To add security checks during code compilation, you can use GNU Compiler Collection (GCC) compiler options. This helps produce more secure programs and libraries without changing source code.

Release version options

The following list of options is the recommended minimum for developers targeting Red Hat Enterprise Linux:

$ gcc ... -O2 -g -Wall -Wl,-z,now,-z,relro -fstack-protector-strong -fstack-clash-protection -D_FORTIFY_SOURCE=3 ...
  • For programs, add the -fPIE and -pie Position Independent Executable options.
  • For dynamically linked libraries, the mandatory -fPIC (Position Independent Code) option indirectly increases security.
Development options

Use the following options to detect security flaws during development. Use these options in conjunction with the options for the release version:

$ gcc ... -Walloc-zero -Walloca-larger-than -Wextra -Wformat-security -Wvla-larger-than ...
-fhardened
GCC 14 provides a new flag, -fhardened, which in turn enables several other flags to improve the security of generated code without impacting the ABI.
-fanalyzer
GCC provides a flag, -fanalyzer, which triggers warnings about potential issues in the source code, including security-related issues. Because -fanalyzer frequently has false positives and negatives, it should be used to locate potential bugs that should be investigated further and not as a formal analysis tool. This flag greatly increases the time and memory taken during compilation. Use only on C code.

Link code to create executable files

To create an executable file, linking combines all object files and libraries. This is the final step when building a C or C++ application.

Before you begin

  • One or more object file(s)
  • GCC must be installed on the system. For details, see Installing development tools for C and C++. .Procedure
    1. Change to the directory containing the object code file(s).
    2. Run gcc:
      $ gcc ... objfile.o another_object.o ... -o executable-file

      An executable file named executable-file is created from the supplied object files and libraries. To link additional libraries, add the required options after the list of object files.

      Note
      With C++ source code, replace the gcc command with g++ for convenient handling of C++ Standard Library dependencies.

      For more information, see Using libraries with GCC.

Example: Build a C program with the GCC (compile and link in one step)

To build a basic C program, use GCC to compile source code directly into an executable. This single-step compilation command creates a foundation for developing simple applications on Red Hat Enterprise Linux.

Procedure

  1. Create a directory hello-c:
    $ mkdir hello-c
  2. Change to the created directory:
    $ cd hello-c
  3. Create file hello.c with the following contents:
    #include <stdio.h>
    
    int main() {
      printf("Hello, World!\n");
      return 0;
    }
  4. Compile and link the code with GCC:
    $ gcc hello.c -o helloworld

    This compiles the code, creates the object file hello.o, and links the executable file helloworld from the object file.

  5. Run the resulting executable file:
    $ ./helloworld
    Hello, World!

Example: Build a C program with the GCC (compile and link in two steps)

To build a simple C program, compile a source file into an object file and then link it to create an executable. This two-step process demonstrates the fundamentals of how to use the GNU Compiler Collection (GCC) compiler workflow for C development.

Procedure

  1. Create a directory hello-c:
    $ mkdir hello-c
  2. Change to the created directory:
    $ cd hello-c
  3. Create file hello.c with the following contents:
    #include <stdio.h>
    
    int main() {
      printf("Hello, World!\n");
      return 0;
    }
  4. Compile the code with GCC:
    $ gcc -c hello.c

    The object file hello.o is created.

  5. Link an executable file helloworld from the object file:
    $ gcc hello.o -o helloworld
  6. Run the resulting executable file:
    $ ./helloworld
    Hello, World!
  7. Optional: Change back to the parent directory:
    $ cd ..
  8. Optional: Remove the hello-c directory:
    $ rm -r hello-c

Example: Build a C++ program with the GCC (compile and link in one step)

To build a minimal C++ program by compiling and linking in one step, create a source file and run g++ to produce an executable.

Procedure

  1. Create a directory hello-cpp:
    $ mkdir hello-cpp
  2. Change to the created directory:
    $ cd hello-cpp
  3. Create file hello.cpp with the following contents:
    #include <iostream>
    
    int main() {
      std::cout << "Hello, World!\n";
      return 0;
    }
  4. Compile and link the code with g++:
    $ g++ hello.cpp -o helloworld

    This compiles the code, creates the object file hello.o, and links the executable file helloworld from the object file.

  5. Run the resulting executable file:
    $ ./helloworld
    Hello, World!
  6. Optional: Change back to the parent directory:
    $ cd ..
  7. Optional: Remove the hello-cpp directory:
    $ rm -r hello-cpp

Example: Build a C++ program with the GCC (compile and link in two steps)

To build a minimal C++ program by using a two-step process, first compile the source into an object file, and then link it to create the executable. This approach demonstrates modular building with the GNU Compiler Collection (GCC) compiler.

Procedure

  1. Create a directory hello-cpp:
    $ mkdir hello-cpp
  2. Change to the created directory:
    $ cd hello-cpp
  3. Create file hello.cpp with the following contents:
    #include <iostream>
    
    int main() {
      std::cout << "Hello, World!\n";
      return 0;
    }
  4. Compile the code with g++:
    $ g++ -c hello.cpp

    The object file hello.o is created.

  5. Link an executable file helloworld from the object file:
    $ g++ hello.o -o helloworld
  6. Run the resulting executable file:
    $ ./helloworld
    Hello, World!
  7. Optional: Change back to the parent directory:
    $ cd ..
  8. Optional: Remove the hello-cpp directory:
    $ rm -r hello-cpp