Подтвердить что ты не робот

Как связать файлы объектов в C? Ошибка с символами Undefined для архитектуры x86_64 "

Итак, я пытаюсь использовать функцию, определенную в другом файле C (file1.c) в моем файле (file2.c). Для этого я использую заголовок file1 (file1.h).

Тем не менее, я все время получаю следующую ошибку, когда пытаюсь скомпилировать мой файл с помощью 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

Мне сказали, что мне нужно "связать объектные файлы вместе", чтобы использовать функции из файла1 в файле2, но я не знаю, что это значит: (

4b9b3361

Ответ 1

Я предполагаю, что вы используете gcc, чтобы просто связать файлы объектов:

$ gcc -o output file1.o file2.o

Чтобы получить объектные файлы, просто скомпилируйте с помощью

$ gcc -c file1.c

это дает файл file1.o и т.д.

Если вы хотите связать свои файлы с исполняемым файлом, выполните

$ gcc -o output file1.c file2.c

Ответ 2

Существующие ответы уже охватывают "как", но я просто хотел рассказать о том, "что" и "почему" для других, которым может быть интересно.

Что делает компилятор (gcc): термин "компиляция" является немного перегруженным термином, потому что он используется на высоком уровне для обозначения "конвертировать исходный код в программу", но более технически означает "конвертировать" исходный код для объектного кода ". Компилятор, такой как gcc, фактически выполняет две связанные, но, возможно, различные функции, чтобы превратить ваш исходный код в программу: компиляция (как в последнем определении преобразования источника в объектный код) и связывание (процесс объединения необходимых файлов объектных кодов в один полный исполняемый файл).

Исходная ошибка, которую вы видели, технически является "ошибкой связывания" и вызывается "ld", компоновщиком. В отличие от (строгих) ошибок времени компиляции, ссылка на строки исходного кода отсутствует, поскольку компоновщик уже находится в пространстве объектов.

По умолчанию, когда gcc предоставляется исходный код в качестве ввода, он пытается скомпилировать каждый, а затем связать все вместе. Как отмечено в других ответах, возможно использовать флаги, чтобы дать команду gcc просто скомпилировать сначала, а затем использовать объектные файлы позже, чтобы связать их на отдельном шаге. Этот двухэтапный процесс может показаться излишним (и, вероятно, для очень маленьких программ), но очень важно при управлении очень большой программой, когда компиляция всего проекта каждый раз, когда вы делаете небольшое изменение, будет тратить значительное количество времени.

Ответ 3

Вы можете скомпилировать и связать одну команду:

gcc file1.c file2.c -o myprogram

И запустите с помощью:

./myprogram

Но чтобы ответить на заданный вопрос, просто передайте объектные файлы в gcc:

gcc file1.o file2.o -o myprogram

Ответ 4

Добавьте foo1.c, foo2.c, foo3.c и makefile в одну папку тип make в bash

если вы не хотите использовать make файл, вы можете запустить команду

gcc -c foo1.c foo2.c foo3.c

затем

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

Ответ 5

Так как нет упоминания о том, как скомпилировать файл .c вместе с кучей файлов .o, и этот комментарий требует:

где main.c в этом ответе?:/if file1.c является основным, как сделать вы связываете его с другими уже скомпилированными файлами .o? - Том Брито 12 октября '14 в 19:45

$gcc main.c lib_obj1.o lib_obj2.o lib_objN.o -o x0rbin

Здесь main.c - это файл C с функцией main(), и файлы объектов (*.o) предварительно скомпилированы. GCC знает, как обрабатывать их вместе, и соответственно ссылается на компоновщик и выводит окончательный исполняемый файл, который в нашем случае является x0rbin.

Вы сможете использовать функции, не определенные в main.c, но используя внешнюю ссылку на функции, определенные в объектных файлах (*.o).

Вы также можете ссылаться на .obj или другие расширения, если объектные файлы имеют правильный формат (например, COFF).