¿Por qué Compilar Primero a un Archivo Objeto?


En el último año he empezado a programar en Fortran trabajando en una universidad de investigación. La mayor parte de mi experiencia previa es en lenguajes web como PHP o ASP antiguo, así que soy un novato en compilar sentencias.

Tengo dos códigos diferentes que estoy modificando.

One tiene una instrucción explícita creating .o archivos de módulos (por ejemplo, archivo gfortran-c.f90) antes de crear el ejecutable.

Otros son creando el archivo ejecutable directamente (a veces creando .archivos mod, pero no .o archivos, por ejemplo, gfortran-o archivo ejecutable.f90 fileb.f90 mainfile.f90).

  • ¿Hay alguna razón (que no sea, tal vez, Makefiles) por la que se prefiera un método sobre el otro?
Author: Tony, 2011-03-12

5 answers

Compilar primero a archivos objeto se llama compilación separada. Hay muchas ventajas y algunos inconvenientes.

Ventajas:

  • fácil de transformar los archivos objeto (.o) a las bibliotecas y enlazar a ellas más tarde
  • muchas personas pueden trabajar en diferentes archivos fuente al mismo tiempo
  • compilación más rápida (no compila los mismos archivos una y otra vez cuando la fuente no ha cambiado)
  • los archivos objeto se pueden hacer a partir de diferentes fuentes de lenguaje y enlazados juntos en algún momento posterior. Para ello, los archivos objeto solo tienen que utilizar el mismo formato y convenciones de llamada compatibles.
  • la compilación separada permite la distribución de bibliotecas de todo el sistema (ya sea bibliotecas de SO, bibliotecas estándar de lenguaje o bibliotecas de terceros) ya sea estática o compartida.

Inconvenientes:

  • Hay algunas optimizaciones (como optimizar funciones de distancia) que el compilador no puede realizar, y el enlazador no se preocupa por; sin embargo, muchos los compiladores ahora incluyen la opción de realizar "optimización del tiempo de enlace", lo que en gran medida niega este inconveniente. Pero esto sigue siendo un problema para las bibliotecas del sistema y las bibliotecas de terceros, especialmente para las bibliotecas compartidas (imposible optimizar partes de un componente que pueden cambiar en cada ejecución, sin embargo, otras técnicas como la compilación JIT pueden mitigar esto).
  • en algunos lenguajes, el programador tiene que proporcionar algún tipo de encabezado para el uso de otros que enlazarán con este objeto. Para ejemplo en C tienes que proporcionar .h archivos para ir con tus archivos objeto. Pero es una buena práctica de todos modos.
  • en lenguajes con inclusión basada en texto como C o C++, si cambias un prototipo de función, tienes que cambiarlo en dos lugares. Una vez en el archivo de encabezado, una vez en el archivo de implementación.
 28
Author: kriss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-20 08:16:03

Cuando tienes un proyecto con unos 100 archivos fuente, no quieres recompilar todos de ellos cada vez que uno cambia. Al compilar cada archivo de origen en un archivo de objeto separado y solo recompilar los archivos de origen que se ven afectados por un cambio, se pasa la cantidad mínima de tiempo desde el cambio de código fuente a un nuevo ejecutable.

make es la herramienta común utilizada para rastrear dichas dependencias y recrear su binario cuando algo cambia. Por lo general, configura lo que cada fuente file depends on (estas dependencias pueden ser generadas típicamente por su compilador - en un formato adecuado para make), y deje que make maneje los detalles de la creación de un binario actualizado.

 14
Author: Erik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-12 16:46:59

El.o archivo es el archivo Objeto. Es una representación intermedia del programa final.

Específicamente, típicamente, el .o el archivo tiene código compilado, pero lo que no tiene son direcciones finales para todas las diferentes rutinas o datos.

Una de las cosas que un programa necesita antes de poder ejecutarse es algo similar a una imagen de memoria.

Por ejemplo.

Si tienes tu programa principal y llama a una rutina A. (Esto es faux fortran, no he tocado en décadas, así que trabaja conmigo aquí.)

PROGRAM MAIN
INTEGER X,Y
X = 10
Y = SQUARE(X)
WRITE(*,*) Y
END

Entonces tienes la función SQUARE.

FUNCTION SQUARE(N)
SQUARE = N * N
END

Son unidades compiladas individualmente. Puede ver que cuando se compila MAIN no SABE dónde está "SQUARE", en qué dirección está. Necesita saber que cuando llama a la instrucción de la SUBRUTINA DE SALTO de microprocesadores (JSR), la instrucción tiene un lugar para ir.

El.o el archivo ya tiene la instrucción JSR, pero no tiene el valor real. Que viene más adelante en el enlace o fase de carga (dependiendo de su aplicación).

Entonces, MAINS .o archivo tiene todo el código para main, y una lista de referencias que quiere resolver (notablemente SQUARE). SQUARE es básicamente independiente, no tiene ninguna referencia, pero al mismo tiempo, no tenía ninguna dirección en cuanto a dónde existe en la memoria todavía.

El enlazador quitará todo el .o archivos y combinarlos en un solo exe. En los viejos tiempos, el código compilado sería literalmente una imagen de memoria. El programa comenzaría en alguna dirección y simplemente cargado en RAM al por mayor, y luego ejecutado. Por lo tanto, en el escenario, se puede ver el enlazador tomando los dos .o archivos, concatenándolos juntos (para obtener la dirección real de cuadrados), luego volvería y encontraría la referencia CUADRADA en PRINCIPAL, y completaría la dirección.

Los enlazadores modernos no van tan lejos, y posponen gran parte de ese procesamiento final hasta cuando el programa está realmente cargado. Pero el concepto es similar.

Compilando a .o archivos, terminas con unidades de lógica reutilizables que luego se combinan posteriormente por los procesos de enlace y carga antes de la ejecución.

El otro aspecto agradable es que el .o los archivos pueden provenir de diferentes idiomas. Siempre y cuando los mecanismos de llamada sean compatibles (es decir, cómo se pasan los argumentos a y desde funciones y procedimientos), una vez compilados en a .o, el lenguaje fuente se vuelve menos relevante. Puede vincular, combinar, código C con código FORTRAN, por ejemplo.

En PHP et all, el proceso es diferente porque todo el código se carga en una sola imagen en tiempo de ejecución. Puedes considerar los FORTRANs .o archivos similares a cómo usaría PHPs include mechanism para combinar archivos en un todo grande y cohesivo.

 5
Author: Will Hartung,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-12 17:00:57

Otra razón, aparte del tiempo de compilación, es que el proceso de compilación es un proceso de múltiples pasos .

El proceso de múltiples partes.

Los archivos objeto son solo una salida intermedia de ese proceso. Eventualmente serán utilizados por el enlazador para producir el archivo ejecutable.

 2
Author: Peter K.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-12 16:51:10

Compilamos archivos objeto para poder vincularlos entre sí para formar ejecutables más grandes. Esa no es la única manera de hacerlo.

También hay compiladores que no lo hacen de esa manera, sino que compilan en memoria y ejecutan el resultado inmediatamente. Anteriormente, cuando los estudiantes tenían que usar mainframes, esto era estándar. Turbo Pascal también lo hizo de esta manera.

 1
Author: Bo Persson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-12 17:58:29