programa proceso etapas ejecutar compilar compilacion como visual-c++ compiler-construction lua vc6

visual c++ - etapas - El proceso de compilación



proceso de compilacion en c (5)

¿Alguien puede explicar cómo funciona la compilación?

Parece que no puedo entender cómo funciona la compilación ...

Para ser más específico, he aquí un ejemplo. Estoy intentando escribir un código en MSVC ++ 6 para cargar un estado Lua.

Yo ya:

  • establecer los directorios adicionales para la biblioteca e incluir archivos en los directorios correctos
  • usado "C" externo (porque Lua solo es C o eso me dicen)
  • include''d los archivos de encabezado correctos

Pero sigo recibiendo algunos errores en MSVC ++ 6 sobre símbolos externos no resueltos (para las funciones Lua que utilicé).

Por mucho que me gustaría saber cómo resolver este problema y seguir adelante, creo que sería mucho mejor para mí si llegara a entender los procesos subyacentes involucrados, así que ¿alguien podría escribir una buena explicación para esto? Lo que estoy buscando saber es el proceso ... Podría verse así:

Paso 1:

  • Entrada: código (s) fuente
  • Proceso: Análisis (quizás agregue más detalles aquí)
  • Salida: lo que sea que se produzca aquí ...

Paso 2:

  • Entrada: ¿Cuál fue la salida del paso 1, y tal vez lo que sea necesario (bibliotecas? ¿DLL? .so? .lib?)
  • Proceso: todo lo que se hace con la entrada
  • Salida: lo que sea salida

y así..

Gracias..

Tal vez esto explique qué son los símbolos, qué es exactamente "vincular", qué código de "objeto" o lo que sea ...

Gracias ... Perdón por ser tan novato ...

PD. Esto no tiene que ser específico de un idioma. Pero no dude en expresarlo en el idioma en el que se sienta más cómodo ... :)

EDITAR : Entonces, de todos modos, pude resolver los errores, resulta que tengo que agregar manualmente el archivo .lib al proyecto; simplemente, especificar el directorio de la biblioteca (donde reside .lib) en la configuración IDE o la configuración del proyecto no funciona.

Sin embargo, las respuestas a continuación me han ayudado algo a comprender mejor el proceso. Muchas gracias! .. Si alguien todavía quiere escribir una guía completa, por favor hazlo ... :)

EDITAR : solo como referencia adicional, encontré dos artículos de un autor (Mike Diehl) para explicar esto bastante bien ... :) Examinando el proceso de compilación: Parte 1 Examinando el proceso de compilación: Parte 2


Debe ingresar a la configuración del proyecto y agregar un directorio donde tenga esa biblioteca LUA * .lib en algún lugar de la pestaña "vinculador". Configuración llamada "incluidas las bibliotecas" o algo, lo siento, no puedo buscarlo.

La razón por la que obtienes "símbolos externos no resueltos" es porque la compilación en C ++ funciona en dos etapas. Primero, el código se compila, cada archivo .cpp en su propio archivo .obj, luego "linker" se inicia y une todos los archivos .obj al archivo .exe. El archivo .lib es simplemente un conjunto de archivos .obj fusionados para hacer que la distribución de bibliotecas sea un poco más simple. Entonces, al agregar todas las declaraciones "#include" y extern le dijiste al compilador que en algún lugar sería posible encontrar el código con esas firmas, pero el enlazador no puede encontrar ese código porque no sabe dónde están esos archivos .lib con código real es colocado.

Asegúrese de haber leído REDME de la biblioteca, generalmente tienen una explicación bastante detallada de lo que debe hacer para incluirlo en su código.


Los dos pasos principales son la compilación y el enlace.

La compilación toma unidades de compilación individuales (que son simplemente archivos fuente, con todos los encabezados que incluyen) y crean archivos de objetos. Ahora, en esos archivos objeto, hay muchas funciones (y otras cosas, como datos estáticos) definidas en ubicaciones específicas (direcciones). En el próximo paso, vincular, también se necesita un poco de información adicional sobre estas funciones: sus nombres. Entonces estos también están almacenados. Un solo archivo de objeto puede referenciar funciones (porque quiere llamarlas cuando se ejecuta el código) que están realmente en otros archivos de objetos, pero dado que estamos tratando con un solo archivo de objeto aquí, solo referencias simbólicas (sus ''nombres'') para esas otras funciones se almacenan en el archivo de objeto.

Luego viene el enlace (limitémonos a enlaces estáticos aquí). Enlazar es donde los archivos de objetos que se crearon en el primer paso (ya sea directamente, o después de haber sido arrojados juntos en un archivo .lib) se toman juntos y se crea un ejecutable. En el paso de vinculación, todas las referencias simbólicas de un archivo de objeto o lib a otro se resuelven (si pueden), buscando los nombres en el objeto correcto, buscando la dirección de la función y colocando las direcciones en la derecha. lugar.

Ahora, para explicar algo sobre el "exterior" C "''que necesita:

C no tiene sobrecarga de funciones. Una función siempre es reconocible por su nombre. Por lo tanto, cuando compila código como código C, solo el nombre real de la función se almacena en el archivo objeto.

C ++, sin embargo, tiene algo llamado ''sobrecarga de función / método''. Esto significa que el nombre de una función ya no es suficiente para identificarlo. Por lo tanto, los compiladores de C ++ crean ''nombres'' para las funciones que incluyen los prototipos de la función (ya que el nombre más el prototipo identificará de manera única una función). Esto se conoce como ''name mangling''.

La especificación ''Extern'' C '''' es necesaria cuando desea utilizar una biblioteca que ha sido compilada como código ''C'' (por ejemplo, los binarios Lua precompilados) de un proyecto C ++.

Para su problema exacto: si todavía no funciona, estas sugerencias podrían ayudar: * ¿los binarios de Lua se han compilado con la misma versión de VC ++? * ¿puede simplemente compilar Lua usted mismo, ya sea dentro de su solución de VC, o como un proyecto separado como código de C ++? * ¿estás seguro de que tienes todas las cosas "externas" C "''correctas?


Paso 1 - Compilador:

  • Entrada: archivo de código fuente [s]
  • Proceso: analizar el código fuente y traducirlo al código máquina
  • Salida: archivo (s) de objeto, que consta [s] de:
    • Los nombres de los símbolos que se definen en este objeto y que este archivo de objeto "exporta"
    • El código de máquina asociado a cada símbolo que está definido en este archivo de objeto
    • Los nombres de los símbolos que no están definidos en este archivo de objeto, pero de los que depende el software en este archivo de objeto y con los que debe vincularse posteriormente, es decir, los nombres que este archivo de objeto "importa"

Paso 2 - Enlazando:

  • Entrada:
    • Archivo (s) de objeto del paso 1
    • Bibliotecas de otros objetos (por ejemplo, de O / S y otro software)
  • Proceso:
    • Para cada objeto que quieras vincular
    • Obtener la lista de símbolos que importa este objeto
    • Encuentra estos símbolos en otras bibliotecas
    • Enlace las bibliotecas correspondientes a sus archivos de objetos
  • Salida: un único archivo ejecutable, que incluye el código de máquina de todos sus objetos, más los objetos de las bibliotecas que fueron importados (vinculados) a sus objetos.


De fuente a ejecutable generalmente es un proceso de dos etapas para C y lenguajes asociados, aunque el IDE probablemente presente esto como un proceso único.

1 / Usted codifica su fuente y la ejecuta a través del compilador. El compilador en esta etapa necesita su fuente y los archivos de encabezado de las otras cosas con las que va a vincular (ver a continuación).

La compilación consiste en convertir sus archivos fuente en archivos objeto. Los archivos de objeto tienen su código compilado y suficiente información para saber qué otras cosas necesitan, pero no dónde encontrar esas otras cosas (por ejemplo, las bibliotecas de LUA).

2 / Linking, la etapa siguiente, combina todos los archivos de objeto con bibliotecas para crear un ejecutable. No cubriré la vinculación dinámica aquí ya que eso complicará la explicación con poco beneficio.

No solo necesita especificar los directorios donde el vinculador puede encontrar el otro código, debe especificar la biblioteca real que contiene ese código. El hecho de que esté recibiendo elementos externos no resueltos indica que no ha hecho esto.

Como ejemplo, considere el siguiente código simplificado C ( xx.c ) y comando.

#include <bob.h> int x = bob_fn(7); cc -c -o xx.obj xx.c

Esto compila el archivo xx.obj a xx.obj . El bob.h contiene el prototipo de bob_fn() para que la compilación tenga éxito. El -c indica al compilador que genere un archivo de objeto en lugar de un ejecutable y -o xx.obj establece el nombre del archivo de salida.

Pero el código real para bob_fn() no está en el archivo de encabezado, sino en /bob/libs/libbob.so , por lo que para vincular, necesita algo como:

cc -o xx.exe xx.obj -L/bob/libs;/usr/lib -lbob

Esto crea xx.exe desde xx.obj , usando librerías (buscadas en las rutas dadas) de la forma libbob.so (la lib y .so son generalmente agregadas por el enlazador). En este ejemplo, -L establece la ruta de búsqueda para las bibliotecas. El -l especifica una biblioteca para buscar para su inclusión en el ejecutable si es necesario. El vinculador generalmente toma el "bob" y encuentra el primer archivo de biblioteca relevante en la ruta de búsqueda especificada por -L .

Un archivo de biblioteca es realmente una colección de archivos de objeto (más o menos cómo un archivo zip contiene muchos otros archivos, pero no necesariamente comprimidos): cuando se encuentra la primera aparición relevante de un elemento externo indefinido, el archivo objeto se copia de la biblioteca y se agrega al ejecutable al igual que su archivo xx.obj . Esto generalmente continúa hasta que no haya más elementos externos sin resolver. La biblioteca ''relevante'' es una modificación del texto "bob", puede buscar libbob.a , libbob.dll , libbob.so , bob.a , bob.dll , bob.so , etc. La relevancia es decidida por el vinculador y debe documentarse.

Cómo funciona depende del enlazador, pero esto es básicamente eso.

1 / Todos los archivos de objeto contienen una lista de elementos externos no resueltos que deben resolverse. El vinculador reúne todos estos objetos y corrige los enlaces entre ellos (resuelve tantos elementos externos como sea posible).

2 / Luego, por cada elemento externo aún no resuelto, el vinculador peina los archivos de la biblioteca buscando un archivo de objeto que pueda satisfacer el enlace. Si lo encuentra, lo atrae hacia adentro; esto puede resultar en más elementos externos no resueltos, ya que el objeto puede tener su propia lista de elementos externos que deben ser satisfechos.

3 / Repita el paso 2 hasta que no haya más elementos externos sin resolver o ninguna posibilidad de resolverlos desde la lista de la biblioteca (aquí es donde estaba su desarrollo, ya que no había incluido el archivo de la biblioteca LUA).

La complicación que mencioné anteriormente es la vinculación dinámica. Ahí es donde se vincula con un trozo de una rutina (una especie de marcador) en lugar de la rutina real, que luego se resuelve en el momento de la carga (cuando se ejecuta el ejecutable). Cosas como los controles comunes de Windows están en estos archivos DLL para que puedan cambiar sin tener que volver a vincular los objetos en un nuevo ejecutable.