proceso de compilación del programa GCC

En este trabajo, la herramienta gcc compilador para el proceso de compilación para grabar el programa


Compilación (total)

Cuando escribimos un programa sencillo helloword, necesidad de programa en un archivo ejecutable, es necesario pasar por el siguiente paso es compilar.

hello.c
-----------------------------------------------
#include <stdio.h>

#define X 1

int main()
{
        int i=0;
        printf("hello world X = %d i=%d !\n",X,i);
        return 0;
}

Si está utilizando la herramienta de compilador es gcc, necesitará hola.c gcc sólo una salida puede ser compilado a.out. Pero la simple recopilación contiene varios pasos - pre-compilación, compilar, ensamblar, enlace (el enlace no es estrictamente hablando una parte del proceso de construcción, aquí para hablar directamente entre sí), la comprensión de estos pasos ayuda a profundizar en la comprensión del proceso.

precompilado

lenguaje C con un '#' al comienzo de las instrucciones previas, incluyendo #ifdef, # include # define y pertenecen a la pre-compilador Directiva. etapa precompilado, compilador gcc Directiva hará será utilizado un tratamiento previo para colocar la definición #define macro ampliado en valor real, asignar a los archivos de cabecera #include archivo de media, pero no comprueba correctamente después de copiar, a la corrección flujo posterior del proceso.

gcc -E -o hello.i hello.c

Como el anterior, de modo que sólo la aplicación de gcc precompila procesos necesitan añadir -E opción, mientras archivo general de salida precompilado .i sufijo. Los resultados de este extracto partes del archivo, ver las declaraciones pertinentes y ficheros de cabecera se copian en el archivo después de # include se expanden, mientras que la función principal del uso de la #define X se sustituye por los lugares reales 1.

# 1 "hello.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "hello.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 27 "/usr/include/stdio.h" 3 4
# 1 "/usr/include/features.h" 1 3 4
# 367 "/usr/include/features.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 1 3 4
# 410 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4
# 411 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 2 3 4
# 368 "/usr/include/features.h" 2 3 4
# 391 "/usr/include/features.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 1 3 4
# 10 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs-64.h" 1 3 4
# 11 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 2 3 4
# 392 "/usr/include/features.h" 2 3 4
# 28 "/usr/include/stdio.h" 2 3 4

...
...


extern int fprintf (FILE *__restrict __stream,
      const char *__restrict __format, ...);


extern int printf (const char *__restrict __format, ...);

...
...

# 5 "hello.c"
int main()
{
 int i=0;
 printf("hello world X = %d i=%d !\n",1,i);
 return 0;
}

Compilar

En el documento sobre la base del siguiente proceso se va a realizar, recopilar y compilar el principio de este artículo aquí no es la misma cosa, se compila en el principio de este trabajo es explicar varios procesos para abreviar. Compilado en este documento se refiere a la pre-compilador para compilar, en el que sólo un proceso. Compilador genera código ensamblador correspondiente a la máquina, así mismo hello.c precompilado completó ejemplo hello.i, el uso -S  parámetros del proceso de compilación.

gcc -S -o hello.s hello.i
        .file   "hello.c"
        .section        .rodata
.LC0:
        .string "hello world X = %d i=%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
        subq    $16, %rsp
        movl    $0, -4(%rbp)
        movl    -4(%rbp), %eax
        movl    %eax, %edx
        movl    $1, %esi
        movl    $.LC0, %edi
        movl    $0, %eax
        call    printf
        movl    $0, %eax
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
        .ident  "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609"
        .section        .note.GNU-stack,"",@progbits

Ensamblar, enlace

etapa de compilación que hacer es compilar el proceso de salida de código de montaje se convierte en código binario de la máquina, pero no se ejecuta directamente dependiente de la necesidad de vincular la biblioteca o archivo con el fin de obtener el archivo ejecutable final. Asamblea procesar mediante el  -c parámetro, el vínculo que enlace directamente los archivos .o se pueden ejecutar directamente gcc.

gcc -c -o hello.o hello.s
gcc -o hello hello.o

listas de enlaces sólo el ejemplo de nuestra propia hola.o, no vi las otras bibliotecas dependientes, pero aún así ser capaz de enlazar con éxito y se realizan normal, ya que el sistema es bibliotecas dependientes en este proceso se carga por defecto, aquí directamente en el gcc en el enlace -v parámetro se puede observar,

 gcc -v -o hello  hello.o
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 5.4.0-6ubuntu1~16.04.12' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.12)
COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/5/:/usr/lib/gcc/x86_64-linux-gnu/5/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/5/:/usr/lib/gcc/x86_64-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/5/:/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/5/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/5/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-o' 'hello' '-mtune=generic' '-march=x86-64'
 /usr/lib/gcc/x86_64-linux-gnu/5/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/5/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper -plugin-opt=-fresolution=/tmp/ccLdFZul.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --sysroot=/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o hello /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/5/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/5 -L/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/5/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/5/../../.. hello.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/5/crtend.o /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crtn.o

Utilice los parámetros de salida -v anteriores, el uso Ctrl + F -lc de búsqueda puede ver aparecen los parámetros, que está vinculado libc sistema de bibliotecas, el uso directo de comando ldd puede también ver el archivo ejecutable hola resultante depende biblioteca.

CryptonymAMS$: ldd hello
        linux-vdso.so.1 =>  (0x00007ffc397a6000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4a8ed33000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f4a8f0fd000)

Hola aquí utiliza una librería de enlace dinámico vinculado al sistema, puede utilizar el comando file para ver el, es decir, la vinculación dinámica vinculada de forma dinámica.

hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.32, BuildID[sha1]=ac17e411d6f0b61087de124ee029056f09f4c990, not stripped

Hasta ahora, todo el proceso se ha completado compilador gcc, la salida del archivo ejecutable.

 

suplemento

gcc parámetros utilizados comúnmente

-E :执行到预编译流程就停止,不执行后续编译、汇编等流程
-S :只执行到编译流程,不执行后续汇编等流程
-c :只执行到汇编流程,不执行链接流程

-o :指定输出文件的名字

-I :指定头文件路径
-L :指定库文件路径
-l :指定需要链接的库(如libc.so,只需要 -lc 即可)

-static :静态链接方式(可执行文件包含执行需要的所有信息,但是文件大小会比较大)
-nostdlib :不链接标准库

-v :查看gcc版本信息,编译过程使用时用于打印编译过程的输出

Más parámetros pueden ser directa o hombre gcc gcc vista --help.

Se han publicado 19 artículos originales · ganado elogios 7 · vistas 6927

Supongo que te gusta

Origin blog.csdn.net/G_METHOD/article/details/104163168
Recomendado
Clasificación