compiler - ¿Cómo puedo vincular archivos de objeto en C? Falla con "Símbolos indefinidos para la arquitectura x86_64"
makefile c compiler (5)
Así que estoy tratando de usar una función definida en otro archivo C (archivo1.c) en mi archivo (archivo2.c). Incluyo el encabezado del archivo1 (archivo1.h) para hacer esto.
Sin embargo, sigo recibiendo el siguiente error cada vez que intento compilar mi archivo usando gcc:
Undefined symbols for architecture x86_64:
"_init_filenames", referenced from:
_run_worker in cc8hoqCM.o
"_read_list", referenced from:
_run_worker in cc8hoqCM.o
ld: symbol(s) not found for architecture x86_64
Me han dicho que necesito "vincular los archivos objeto juntos" para usar las funciones del archivo1 en el archivo2, pero no tengo idea de lo que eso significa :(
Agregue foo1.c, foo2.c, foo3.c y makefile en una carpeta del tipo make in bash
si no desea utilizar el archivo MAKE, puede ejecutar el comando
gcc -c foo1.c foo2.c foo3.c
entonces
gcc -o output foo1.o foo2.o foo3.o
foo1.c
#include <stdio.h>
#include <string.h>
void funk1();
void funk1() {
printf ("/nfunk1/n");
}
int main(void) {
char *arg2;
size_t nbytes = 100;
while ( 1 ) {
printf ("/nargv2 = %s/n" , arg2);
printf ("/n:> ");
getline (&arg2 , &nbytes , stdin);
if( strcmp (arg2 , "1/n") == 0 ) {
funk1 ();
} else if( strcmp (arg2 , "2/n") == 0 ) {
funk2 ();
} else if( strcmp (arg2 , "3/n") == 0 ) {
funk3 ();
} else if( strcmp (arg2 , "4/n") == 0 ) {
funk4 ();
} else {
funk5 ();
}
}
}
foo2.c
#include <stdio.h>
void funk2(){
printf("/nfunk2/n");
}
void funk3(){
printf("/nfunk3/n");
}
foo3.c
#include <stdio.h>
void funk4(){
printf("/nfunk4/n");
}
void funk5(){
printf("/nfunk5/n");
}
makefile
outputTest: foo1.o foo2.o foo3.o
gcc -o output foo1.o foo2.o foo3.o
make removeO
outputTest.o: foo1.c foo2.c foo3.c
gcc -c foo1.c foo2.c foo3.c
clean:
rm -f *.o output
removeO:
rm -f *.o
Las respuestas existentes ya cubren el "cómo", pero solo quería dar más detalles sobre "qué" y "por qué" para otros que podrían estar preguntándose.
Qué hace un compilador (gcc): el término "compilar" es un término algo sobrecargado porque se usa en un nivel alto para significar "convertir el código fuente a un programa", pero más técnicamente significa "convertir el código fuente a código de objeto". Un compilador como gcc en realidad realiza dos funciones relacionadas, pero discutiblemente distintas, para convertir su código fuente en un programa: compilar (como en la última definición de convertir fuente a código objeto) y vincular (el proceso de combinar los archivos de código objeto necesarios en un ejecutable completo).
El error original que vio es técnicamente un "error de enlace", y lo lanza "ld", el enlazador. A diferencia de los errores de tiempo de compilación (estrictos), no hay ninguna referencia a las líneas de código fuente, ya que el vinculador ya está en el espacio de objetos.
De forma predeterminada, cuando a gcc se le da el código fuente como entrada, intenta compilar cada uno y luego vincularlos todos juntos. Como se señaló en las otras respuestas, es posible usar indicadores para indicarle a gcc que solo compile primero, luego use los archivos del objeto más tarde para vincular en un paso por separado. Este proceso de dos pasos puede parecer innecesario (y probablemente sea para programas muy pequeños), pero es muy importante cuando se administra un programa muy grande, donde compilar todo el proyecto cada vez que realiza un pequeño cambio podría desperdiciar una cantidad considerable de tiempo.
Puede compilar y vincular en un comando:
gcc file1.c file2.c -o myprogram
Y corre con:
./myprogram
Pero para responder la pregunta tal como se lo solicitó, simplemente pase los archivos del objeto a gcc
:
gcc file1.o file2.o -o myprogram
Supongo que estás usando gcc
, para simplemente vincular los archivos de objeto haz:
$ gcc -o output file1.o file2.o
Para obtener los archivos de objetos, simplemente compile usando
$ gcc -c file1.c
esto produce file1.o y así sucesivamente.
Si desea vincular sus archivos a un archivo ejecutable
$ gcc -o output file1.c file2.c
Ya que no se menciona cómo compilar un archivo .c junto con un grupo de archivos .o, y este comentario lo solicita:
¿Dónde está el main.c en esta respuesta? : / si file1.c es el principal, ¿cómo lo vincula con otros archivos .o ya compilados? - Tom Brito 12 de octubre de 14 a 19:45
$ gcc main.c lib_obj1.o lib_obj2.o lib_objN.o -o x0rbin
Aquí, main.c es el archivo C con la función main () y los archivos objeto (* .o) están precompilados. GCC sabe cómo manejarlos juntos, e invoca el enlazador en consecuencia y da como resultado un ejecutable final, que en nuestro caso es x0rbin.
Podrá utilizar funciones no definidas en main.c pero usando una referencia externa a las funciones definidas en los archivos de objeto (* .o).
También puede vincular con .obj u otras extensiones si los archivos del objeto tienen el formato correcto (como COFF).