2017-01-25 2 views
0

примечание: это заключительное упражнение в книге Head First C.Allegro5 makefile error

У меня есть следующая проблема. Я пытаюсь сделать игру, используя библиотеки allegro5.2. Я хочу использовать несколько файлов .c, чтобы упорядочить все аккуратно. Однако у меня проблемы с компиляцией моих программ с использованием make-файла. Я пытаюсь скомпилировать эту простую программу:

#include <stdio.h> 
#include <allegro5/allegro.h> 

const int disp_h = 640; 
const int disp_w = 480; 

int main(int argc, char **argv) { 

ALLEGRO_DISPLAY *display; 

if(!al_init()) { 
    fprintf(stderr, "failed to initialize allegro!\n"); 
    return -1; 
} 

display = al_create_display(disp_h,disp_w); 
if(!display) { 
    fprintf(stderr, "failed to create display!\n"); 
    return -1; 
} 

al_rest(0.4); 
al_destroy_display(display); 

printf("bye bye!!!\n"); 

return 0; 
} 

Makefile, является:

Blasteroids.o: allegro.h Blasteroids.c 
    gcc -Wall -c Blasteroids.c 

Blasteroids: Blasteroids.o allegro.h 
    gcc -Wall -I/usr/include/allegro5 -L/usr/lib -lallegro -lallegro_main Blasteroids.o -o Blasteroids 

Теперь, когда я использую терминал это компилируется нормально, но теперь я, кажется, есть проблема. Ошибка определяется с помощью терминала (с помощью команды сделать Blasteroids) является:

cc Blasteroids.o -o Blasteroids 
Undefined symbols for architecture x86_64: 
    "_al_create_display", referenced from: 
     __al_mangled_main in Blasteroids.o 
    "_al_destroy_display", referenced from: 
     __al_mangled_main in Blasteroids.o 
    "_al_install_system", referenced from: 
     __al_mangled_main in Blasteroids.o 
    "_al_rest", referenced from: 
     __al_mangled_main in Blasteroids.o 
    "_main", referenced from: 
    implicit entry/start for main executable 
    (maybe you meant: __al_mangled_main) 
ld: symbol(s) not found for architecture x86_64 
clang: error: linker command failed with exit code 1 (use -v to see invocation) 
make: *** [Blasteroids] Error 1 

Я не знаю, что я делаю неправильно, и я очень новой для этих вещей. Я искал примеры в make-файлах, но они дают мне код, как я использую сейчас. Теперь я могу использовать только одну строку для вышеуказанной программы, но идея состоит в том, что я хочу создать свои собственные .c-файлы, сделать их в .o-файлы, а затем связать их вместе. Отсюда make-файл.

+0

Я действительно сомневаюсь, что _exact_ же команда работает с терминалом. Вы должны переместить флаги библиотеки '-lallegro -lallegro_main' в конец линии ссылок после файлов' .o'. – MadScientist

+0

Это действительно работает. Я получаю открытый экран на мгновение всякий раз, когда я запускаю программу – PJS

+1

Я имею в виду, что команда связи не является выходной программой. В любом случае ваши библиотеки должны появляться после объектных файлов в линии ссылок. – MadScientist

ответ

0

make программа ищет файлы с именем makefile или Makefile, без расширения. Если вы назовете ваш make-файл чем-то другим, например makefile.txt, то make не может найти его, и он просто будет использовать свои собственные встроенные правила, которые ничего не знают о дополнительных библиотеках флагов, которые могут понадобиться.

Так что либо переименовать Makefile в makefile или Makefile, либо указать имя вашего Makefile явно в командной строке при запуске сделать, например, make -f makefile.txt Blasteroids.

Во-вторых, если вы не укажете цель в командной строке, тогда make всегда будет строить первую цель. Таким образом, если вы переупорядочиваете свои цели так, чтобы тот, который вы обычно хотите создать (в данном случае Blasteroids), сначала, тогда вы можете просто запустить make без аргументов и построить эту цель.

В отличие от языка программирования, порядок определения цели не имеет значения: например, вам не нужно определять правила для всех объектных файлов перед линией связи. Make читает весь файл и строит внутренний график необходимых отношений, а узлы и ребра в этом графе могут быть добавлены в любом порядке.

+0

Спасибо за помощь .. – PJS

0

что-то вроде следующего содержания Makefile должен сделать работу

Примечания:

  1. заголовочные файлы нужны только во время стадии компиляции
  2. файлы библиотек требуется только во время стадии ссылка
  3. лучше всего, чтобы первая «цель» была «все», поэтому make-файл можно успешно выполнить без необходимости включать параметр «Blasteroids»
  4. , имеющий 'target' 'clean' позволяет легко удалить предметы, которые будут перестроены.
  5. Любая «цель», которая не создает файл с таким же именем, должна быть указана оператором «.PSEUDO».
  6. компоновщик обрабатывает элементы командной строки компоновщика в порядке, указанном в командной строке. Поэтому перечислите объекты, затем каталоги, затем короткие «имена» библиотеки
  7. введите заголовочные файлы в конце командной строки компиляции
  8. используйте макросы (например, CC и RM), содержащие полный путь к исполняемый файл, поэтому используется правильный исполняемый файл, а другой - первый элемент, найденный в $ PATH, который соответствует имени.
  9. $^является встроенный макрос, который расширяется к рецепту зависимостей
  10. $ < является встроенный макрос, который расширяется к первой зависимости
  11. $ @ встроенный в макрос, который расширяется в рецепте «мишень»
  12. в $(SRC:.c=?) заявления делать замену символов на расширение имен файлов, содержащихся в $(SRC) макро
  13. %.o:%.c рецепт говорит для каждого исходного файла для компиляции в объектный файл, используйте этот рецепт
  14. «-ggdb ' является поэтому максимальная информация об отладке будет доступна для отладчика «gdb».
  15. Этот шаблон «makefile» может быть широко использован для других проектов с незначительными вариациями.Для большей гибкости можно также вставить рецепт для автоматического создания зависимостей файла заголовка, поэтому не нужно будет перечислять их отдельно в рецепте компиляции, но в настоящее время следующее содержимое файла makefile будет делать то, что вы в настоящее время пытаетесь выполнить

и теперь Makefile

CC := /bin/gcc 
RM := /bin/rm 

CFLAGS := -Wall -Wextra -pedantic -std=gnu99 -ggdb -c 
LFLAGS := -L/usr/lib -lallegro -lallegro_main 

SRC := Blasteroids.c 
#OBJ := $(SRC:.c=.0) 
OBJ := $(SRC:.c=.o) 
NAME := $(SRC:.c=) 

.PSEUDO: all clean 

all: $(NAME) 

%.o:%.c 
    #$(CC) $(CFLAGS) $^ -o [email protected] -I/usr/include/allegro5 
    $(CC) $(CFLAGS) $< -o [email protected] -I/usr/include/allegro5 

$(NAME): $(OBJ) 
    $(CC) -ggdb $^ -o [email protected] $(LFLAGS) 

.clean: 
    $(RM) -f $(NAME) $(OBJ) 
+0

Вы не должны использовать '$ ^' в своем правиле компиляции, вы должны использовать '$ <'. Кроме того, ваша настройка 'OBJ' неверна (вы добавляете' .0' не '.o'). Я рекомендую использовать стандартные переменные, что означает 'LDFLAGS' для компоновщиков, таких как' -L' и 'LDLIBS' для библиотек, таких как' -l'. Лично я рекомендую не использовать полностью определенные пути для 'CC' и' RM'. – MadScientist

+0

@MadScientist, я согласен с исправляющими ошибками ключевого слова, которые вы упомянули.Однако, если более одного исполняемого файла имеет одно и то же имя. Если исполняемый файл, который вы хотите использовать make-файл, не является первым, найденным в кеше или в списке $ PATH, тогда будет выполнен неправильный. Поэтому всегда следует использовать «полностью квалифицированные» пути для любых функций ОС, таких как gcc и rm и mv, chgrp и chmod и ... стандартные макросы: «LDFLAGS» и «LDLIBS» могут быть не такими, какие вы хотите ваш файл. Так что вы все равно их замените. Лучше всего заменить уникальными именами макросов. – user3629249

+0

Игнорировать мой ответ, чтобы отразить поправки к ошибкам keypunch. Примечание: ведущая строка '#' в строке makefile означает, что строка является только комментариями. – user3629249

Смежные вопросы