Pregunta

¿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, aquí hay 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
  • usé "C" externa (porque Lua es solo C o eso escuché)
  • Incluye los archivos de encabezado correctos.

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

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 comprender los procesos subyacentes involucrados, entonces, ¿podría alguien escribir una buena explicación para esto?Lo que estoy buscando saber es el proceso..Podría verse así:

Paso 1:

  • Aporte:Código(s) fuente
  • Proceso:Análisis (quizás agregue más detalles aquí)
  • Producción:lo que sea que se genere aquí ...

Paso 2:

  • Aporte:Lo que se obtuvo en el paso 1, más tal vez cualquier otra cosa que sea necesaria (¿bibliotecas?¿DLL?.¿entonces?.lib?)
  • Proceso:lo que sea que se haga con la entrada
  • Producción:lo que sea que salga

etcétera..

Gracias..

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

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

PDEsto no tiene por qué ser específico del idioma.Pero siéntete libre de expresarlo en el idioma con el que te sientas más cómodo.:)

EDITAR: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 el .lib) en la configuración del IDE o en la configuración del proyecto no funciona.

Sin embargo, las respuestas a continuación me han ayudado de alguna manera a comprender mejor el proceso.¡Muchas gracias!..Si alguien todavía quiere escribir una guía completa, por favor hágalo.:)

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

¿Fue útil?

Solución

Desde el código fuente hasta el ejecutable es generalmente un proceso de dos etapas para C y los lenguajes asociados, aunque el IDE probablemente lo presente como un proceso único.

1/ Codificas tu fuente y la ejecutas a través del compilador.El compilador en esta etapa necesita su fuente y los archivos de encabezado de las otras cosas que va a vincular (ver más abajo).

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

2/ Vincular, la siguiente etapa, es combinar todos sus archivos objeto con bibliotecas para crear un ejecutable.No cubriré los enlaces dinámicos aquí ya que complicarán la explicación y generarán pocos beneficios.

No solo necesita especificar los directorios donde el vinculador puede encontrar el otro código, sino que también necesita especificar la biblioteca real que contiene ese código.El hecho de que tengas aspectos externos sin resolver indica que no lo has hecho.

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

#include <bob.h>
int x = bob_fn(7);

cc -c -o xx.obj xx.c

Esto compila el xx.c archivo 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 objeto en lugar de un ejecutable y el -o xx.obj establece el nombre del archivo de salida.

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

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

Esto crea xx.exe de xx.obj, utilizando bibliotecas (buscadas en las rutas indicadas) del formulario libbob.so (El vinculador generalmente agrega lib y .so).En este ejemplo, -L establece la ruta de búsqueda de bibliotecas.El -l especifica una biblioteca que se buscará para incluirla en el ejecutable si es necesario.El vinculador normalmente 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 en realidad una colección de archivos objeto (más o menos como un archivo zip contiene varios otros archivos, pero no necesariamente comprimidos): cuando se encuentra la primera aparición relevante de un externo indefinido, el archivo objeto se copia de la biblioteca y se agrega. al ejecutable como tu xx.obj archivo.Esto generalmente continúa hasta que no quedan más aspectos 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étera.La relevancia la decide el propio enlazador y debe documentarse.

El funcionamiento depende del vinculador, pero básicamente eso es todo.

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

2/ Entonces, por cada externo aún sin resolver, el vinculador peina los archivos de la biblioteca en busca de un archivo objeto que pueda satisfacer el vínculo.Si lo encuentra, lo atrae; esto puede dar como resultado más aspectos externos no resueltos, ya que el objeto atraído puede tener su propia lista de aspectos externos que deben satisfacerse.

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

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

Otros consejos

Paso 1 - Compilador:

  • Entrada: archivo de código fuente [s]
  • Proceso: el análisis de código fuente y traducir a código de máquina
  • Salida: file Object [s], que consisten [s] de:
    • Los nombres de los símbolos que se definen en este objeto y que este fichero objeto "exportaciones"
    • El código de máquina asociada a cada símbolo que se define en este fichero objeto
    • Los nombres de símbolos que no se definen en este archivo de objeto, pero en la que el software en este archivo objeto depende y al que posteriormente deben estar vinculados, nombres es decir que este archivo de objeto "importaciones"

Paso 2 - Vinculación:

  • Entrada:
    • file Object [s] desde el paso 1
    • Bibliotecas de otros objetos (por ejemplo, de la O / S y otro software)
  • Proceso:
    • Para cada objeto que desea vincular
    • Obtener la lista de símbolos que este objeto las importaciones
    • Para estos símbolos en otras bibliotecas
    • el nexo de las bibliotecas correspondientes a los archivos de objetos
  • Salida: un único archivo ejecutable, que incluye el código de máquina de todos los objetos, además de los objetos de las bibliotecas que fueron importados (vinculados) a los objetos
  • .

Los dos pasos principales son la compilación y la vinculación.

Compilación tiene unidades de compilación individuales (los que son simplemente archivos de origen, con todas las cabeceras se incluyen), y crear ficheros objeto. Ahora, en esos archivos de objetos, hay una gran cantidad de funciones (y otras cosas, como datos estáticos) definidos en lugares específicos (direcciones). En el siguiente paso, que une, también se necesita un poco de información adicional sobre estas funciones: sus nombres. Por lo que estos también se almacenan. Un archivo único objeto puede hacer referencia a funciones (porque quiere llamar a ellos cuando el código se ejecute) que son en realidad en otros archivos objeto, pero ya que estamos tratando con un único fichero objeto aquí, hace referencia único simbólicos (sus 'nombres') a aquellas otras funciones se almacenan en el fichero objeto.

A continuación viene la vinculación (vamos a limitarnos a la vinculación estática aquí). La vinculación es donde los archivos de objetos que se crearon en el primer paso (ya sea directamente, o después de que hayan sido lanzados juntos en un archivo .lib) se toman juntos y se crea un archivo ejecutable. En la etapa de vinculación, todas esas referencias simbólicas de archivo de un objeto o lib a otro se resuelven (si puede ser), por buscar los nombres en el objeto correcto, encontrar la dirección de la función, y poner las direcciones en la derecha lugar.

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

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

C ++, sin embargo, tiene algo que se llama 'función / sobrecarga de métodos'. Esto significa que el nombre de una función ya no es suficiente para identificarlo. por lo tanto, los compiladores de C ++ Crear 'nombres' para funciones que incluyen los prototipos de la función (ya que el nombre más el prototipo será identificar de forma exclusiva una función). Esto se conoce como 'renombrado de nombres'.

El 'extern 'C'' es necesaria la especificación cuando se quiere utilizar una biblioteca que ha sido compilado como código 'C' (por ejemplo, los binarios Lua precompilados) de un proyecto de C ++.

Para su problema exacto: si todavía no funciona, estos consejos podrían ayudar: * Han sido los binarios Lua compilado con la misma versión de VC ++? * Puede que simplemente compilar Lua ti mismo, ya sea dentro de su solución de VC, o como un proyecto independiente como código C ++? * ¿Está seguro de que tiene todos los 'extern 'C'' cosas correctas?

Se tiene que entrar en configuración de proyecto y añadir un directorio donde se tiene que la biblioteca LUA * .lib archivos en algún lugar de la pestaña "enlazador". Ajuste llamado "incluyendo bibliotecas" o algo así, lo siento, no puedo mirar hacia arriba.

La razón por la que se obtiene "símbolos externos no resueltos" se debe a que la compilación en C ++ funciona en dos etapas. En primer lugar, el código se compila, cada archivo .cpp en su propio archivo .obj, a continuación, comienza "enlazador" y uno a todos los que OBJ archivos en un archivo .exe. archivo .lib es sólo un montón de archivos .obj se fusionaron para hacer la distribución de las bibliotecas sólo un poco más simple bits. Así que mediante la adición de todos los "# include" y declaración externa que le dijo al compilador que en algún lugar que sería posible encontrar código con esas firmas pero enlazador no puede encontrar el código, ya que no sabe dónde esos archivos .lib con código real se coloca.

Asegúrese de haber leído REDME de la biblioteca, por lo general tienen una explicación más detallada de lo que había que hacer para incluirlo en el código.

También puede ser que desee comprobar esto: compilador, ensamblador, enlazador y PALA: UNA HISTORIA BREVE .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top