El proceso de compilación del compilador gcc en Linux

1. ¿Qué es GCC?

GCC es un software gratuito publicado bajo la licencia GPL y también es una parte clave del proyecto GNU. La intención original de GCC era escribir un compilador para el sistema operativo GNU, y ha sido adoptado como un compilador estándar por la mayoría de los sistemas operativos similares a Unix (como Linux, BSD, MacOS X, etc.), e incluso puede ser utilizado en Microsoft Windows GCC. GCC admite una variedad de chips de arquitectura de computadora, como x86, ARM, MIPS, etc., y se ha adaptado a una variedad de otras plataformas de hardware. Aquí primero explicamos principalmente el uso del lenguaje C gcc en Linux.

1. Cómo usar gcc

gcc [选项] 文件名
在linux下我们可以使用 gcc --help 查看gcc的各个选项

2. Opciones comunes de gcc

Inserte la descripción de la imagen aquí

El proceso de compilación de gcc

El proceso de compilación de gcc se puede dividir en 4 pasos principales:

Procesamiento previo (Procesamiento previo)
Compilación (Compilación)
Ensamblaje (Ensamblaje)
Vinculación (Vinculación)

Inserte la descripción de la imagen aquí

Hablemos de los pasos específicos de la compilación de gcc.

1. Pretratamiento

El preprocesamiento consiste en leer el programa fuente cy "reemplazar" las pseudoinstrucciones y los símbolos especiales que contiene; después de este procesamiento, se genera un archivo de salida sin definiciones de macro, sin instrucciones de compilación condicionales y sin símbolos especiales. El significado de este archivo es el mismo que el del archivo fuente que no ha sido preprocesado. Sigue siendo un archivo C, pero el contenido es diferente. Las pseudoinstrucciones incluyen principalmente los siguientes tres aspectos:
(1) Instrucciones de definición de macros, como #define NAME TokenString, #undef y algunas macros integradas en el compilador, como __DATE__, FILE, LINE, TIME, __FUNCTION__, etc. .
(2) Instrucciones de compilación condicional, como #ifdef, #ifndef, #else, #elif, #endif, etc.
(3) El archivo de encabezado contiene instrucciones, como #include "FileName" o #include, etc.

El proceso de pretratamiento incluye principalmente los siguientes procesos:

  • Elimine todas las #defines y expanda todas las definiciones de macros
  • Procese todas las instrucciones de precompilación condicionales, como #if, #ifdef, #elif, #else, #endif, etc.
  • Procese la directiva #include precompilada e inserte el archivo incluido en la posición de la directiva precompilada.
  • Eliminar todos los comentarios "//" y "/ * * /"
  • Agregue números de línea e identificadores de archivo para que los números de línea de depuración y los números de línea de advertencia de error de compilación se puedan generar durante la compilación.
  • Mantenga todas las directivas del compilador #pragma, porque el compilador necesita usarlas

El siguiente comando se usa generalmente para el preprocesamiento El parámetro -E significa solo preprocesamiento:
gcc -E hola.c -o hola.i
También puede usar el siguiente comando para completar el proceso de preprocesamiento, donde cpp es el preprocesador:
cpp hola. c> hola.

El resultado preprocesado hello.i sigue siendo el código fuente del lenguaje c, podemos usar el comando cat o vim para ver su código
vim hello.i

2. Compilar

El trabajo que debe hacer el compilador es pasar el análisis léxico y el análisis gramatical, luego de confirmar que todas las instrucciones cumplen con las reglas gramaticales, traducirlas en representaciones de código intermedio equivalentes o códigos ensambladores . Si desea saber más sobre el proceso de compilación, puede consultar otros blogs.

Podemos usar el siguiente comando para compilar y generar un archivo ensamblador:
gcc -S hello.i> hello.s
Podemos usar el comando cat para ver su código:
cat hello.s

3. Compilación

El proceso de ensamblaje en realidad traduce el código en lenguaje ensamblador en instrucciones de la máquina de destino . Para cada programa fuente de lenguaje c procesado por el sistema de traducción, el archivo de destino correspondiente se obtendrá finalmente a través de un proceso.

Podemos usar el siguiente comando para ensamblar:
gcc -c hello.s -o hello.o

4. Enlace

El archivo objeto generado por el ensamblador no se puede ejecutar inmediatamente y puede haber muchos problemas sin resolver. Por ejemplo, una función en un archivo fuente puede hacer referencia a un símbolo definido en otro archivo fuente (como una variable o llamada a función, etc.); una función en un archivo de biblioteca puede ser llamada en un programa, etc., todos estos problemas deben estar vinculados para ser resueltos. El trabajo principal del vinculador es conectar los archivos de objetos relevantes entre sí, es decir, vincular los símbolos a los que se hace referencia en un archivo con la definición del símbolo en otro archivo, de modo que todos estos . archivos de objetos se convierten en un todo unificado que puede ser cargado y ejecutado por el sistema operativo, es decir, programas ejecutables de acuerdo con los diferentes métodos de vinculación de las funciones de biblioteca especificados por el desarrollador, el proceso de vinculación se puede dividir en dos tipos: enlace ①Static ② Enlace dinámico.

Para la llamada a la función en el archivo ejecutable, los métodos de vinculación dinámica o vinculación estática se pueden adoptar respectivamente. El uso de enlaces dinámicos puede hacer que el archivo ejecutable final sea más corto y ahorrar algo de memoria cuando el objeto compartido es utilizado por múltiples procesos, porque solo se necesita almacenar una copia del código del objeto compartido en la memoria . Sin embargo, no es necesariamente que el uso de enlaces dinámicos sea mejor que el uso de enlaces estáticos. En algunos casos, los enlaces dinámicos pueden dañar el rendimiento .

Supongo que te gusta

Origin blog.csdn.net/KingRing_/article/details/115051281
Recomendado
Clasificación