Monday, November 9, 2015

Compilation steps in C

Before generating any executable file, program has to travel many stages of compilation. each stage of compilation has its own significance. If it fails at any step it may not lead to further. So it is programmer responsibility to make compiler happy.

Stages are -

1) Pre-processing
2) Compilation
3) Assembler
4) Linker

Pre-processing

This is the very first stage of compilation. at this all stage all includes files, macro defines get expended and if any issue with include file it will display here itself. it is better illustrated with following example hello.c

 #include <stdio.h>  
 #define MAX 100  
 int main()  
 {  
      printf("MAX : %d\n",MAX); return 0;  
 }  

Now compile the above code, to see just Pre-processing stage, compile with following options
$ gcc -E Hello_world.c  

-E options expand all macros, but it will display all expansion on terminal itself. A better way to keep all into a single file is redirect to a file with extension .i.
$ gcc -E Hello_world.c > hello.i   
$ ls  
 hello.c hello.i

or
 $ gcc -save-temps hello.c   
 $ ls  
 a.out hello.c hello.i hello.o hello.s  
 
If -save-temps option is used in compilation, then all stage file generate in one shot. that we dont want now..

Compilation

 All code here after will convert into machine language(low level language) hello.s. To illustrate this -S option can be used which produce hello.s file
 $ gcc -S hello.i   
 $ ls  
 hello.c hello.s  

And hello.s file will look like

$ cat hello.s  
     .file    "hello.c"  
     .section    .rodata  
 .LC0:  
     .string    "MAX : %d\n"  
     .text  
     .globl    main  
     .type    main, @function  
 main:  
 .LFB0:  
     .cfi_startproc  
     pushq    %rbp  
     .cfi_def_cfa_offset 16  
     .cfi_offset 6, -16  
     movq    %rsp, %rbp  
     .cfi_def_cfa_register 6  
     movl    $100, %esi  
     movl    $.LC0, %edi  
     movl    $0, %eax  
     call    printf  
     movl    $0, %eax  
     popq    %rbp  
     .cfi_def_cfa 7, 8  
     ret  
     .cfi_endproc  
 .LFE0:  
     .size    main, .-main  
     .ident    "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"  
     .section    .note.GNU-stack,"",@progbits  

Assembler 

Here is the stage where all syntax used in c program is checked. If any syntax error or function prototype mismatch or unused variable, undefined variable, redefine variables preset in the code, will be thrown as error or warning by the compiler .In this stage all code converts from machine code to object code and one object file is generated with extension of hello.o. That can be seen separately by using following command.
 $ gcc -Wall -c hello.s  
 $ ls  
 hello.c hello.o hello.s  

-Wall gcc option will throw all kind of warning that was found during compilation. If everything goes smooth the an object file will be generated which is nothing but complied file only that contains all symbols (all global variables, functions etc.. ) used in code.

Linker

This is last and final stage of compilation where all the linker combine all symbol objects together and form an executable file. if any Static library used in code that also linked at this stage only by using -l<lib name> option.
 $ gcc -o run hello.s  
 or  
 $ gcc -o run hello.c  
 or  
 $ gcc -o run hello.o  
 or  
 $ gcc -o run hello.i  
 $ ls  
 hello.c hello.i hello.o hello.s run  

an executable file 'run' is generated.  Now run the 'run'.
 $ ./run   
 MAX : 100  

Note. you can notice that #define MAX 100 replace second argument of printf(), but not in first one because first argument is treated as control string or like string. that is why out put looks like
MAX : 100  







2 comments: