Compiling and linking are the two phases that transform your C source code into an executable program

are phases:

  • main and fundamental
  • differents

They cannot be skipped, as each phase solves a different type of problem in the code


compilation phase

Compilation converts human-written code (.c) into intermediate binary code called object code (.o)

At this stage, the compiler knows which external function is going to be used thanks to the .h file, but it doesn’t know where the actual code is to execute it

This option tells GCC to compile, but to stop before the linking phase:

  • -c
  • Compile Only
  • Tells GCC to run the preprocessing, compilation, and assembly phases, but NOT to run the link phase
gcc -c file.c

file.o is the Implicit Output, GCC generates an output file with the same name, but with the extension .o (e.g. file.o)

If you want the resulting object file to be saved with a different name or path, you must combine the -c and -o options

gcc -c file.c -o build/math_constants.o

This .o file is the one you then package with ar rcs to create the static library (.a)


There are 4 types of files:

  • .h (interface, has the definitions/signatures/signatures/domain and image of the functions, It’s like a contract that the compiler must fulfill) (Contains the declarations (prototypes) of functions, structures, and constants) (Tells the compiler (GCC) what functions exist, what arguments they expect, and what type of value they return)
  • .c (human-readable font c)
  • .o (Incomplete binary files, they are not executable, they lack code to become executable)
  • executable (complete binary and executable)
  • In C, when we talk about “importing” or using code from other modules or libraries, we always include the .h files and not the .c files

It only needs the library contract (the .h file) to know which functions exist and what arguments they expect. It leaves “holes” where external function calls go

The source file (.c) contains the actual implementation or definition of the functions

The compiler reads the .h to check the call syntax

The linker uses the .c binary (the implementation) to fill the hole and create the executable.


linking pase

The link takes the object codes (.o) and the binary libraries (.a or .so) to connect them and create the final executable binary.

  • input: Object files (.o), static (.a) and dynamic (.so) libraries
  • output: Executable File (the final binary)
  • Resolves External References. The linker fills in the gaps left by the compiler, searching for the actual executable code for each external function
  • You need the library implementation binary code (the .a or .so file) to connect the code
  • gcc main.o libutils.a -o program

The linker converts the program into something that the operating system can load and run.


the diagram is:

first in library/librarys

library files (.c) -> compiler (gcc) -> object files (.o) -> single file .a (with ar rcs) (.o files packaged into a single .a file)

second, in the file that use the library

source code (.c) -> (compiler gcc) object code (.o) -> linker (.a file) -> executable

after

./executable

Here is a real example:

https://gitlab.com/com.leibnix/examplelibraric