Прежде всего, вы не можете создать Makefile для чего-либо, если вы не знаете, как сделать это вручную.Итак, давайте сначала исправим ваши проблемы компиляции и компоновки.Чтобы скомпилировать тип вашей программы:
gcc -c game.c
Опция -c
сообщает gcc
, что вы просто хотите скомпилировать, а не ссылаться.Эта команда создает объектный файл с именем game.o
.Для автоматизации этого с make вам ничего не нужно: make уже знает, как это сделать.Без Makefile просто наберите:
make game.o CC=gcc
и make сделает эту работу.Обратите внимание, что мы сообщаем make, какой компилятор использовать, передавая ему в командной строке значение для его стандартной переменной make CC
.
Далее мы хотим связать все объектные файлы нашего проекта (только game.o
вв нашем случае, но у нас может быть несколько, соответствующих нескольким различным исходным файлам) и генерировать исполняемый файлЗдесь важно понимать, что вы используете библиотеку уже существующих функций (ncurses
), которая по умолчанию не связана ни с каким исполняемым файлом, поскольку большинство программ не используют ее.Вы должны указать gcc
связать ваши объектные файлы с этой библиотекой, используя параметр -lncurses
:
gcc game.o -o game -lncurses
Обратите внимание, что в очень простом примере, подобном этому, вы можете скомпилировать и связать в одномпозвоните по номеру gcc
:
gcc game.c -o game -lncurses
И снова, make уже знает, как все это сделать.Просто нужно передать параметр связывания -lncurses
благодаря другой стандартной переменной make LDLIBS
:
make game CC=gcc LDLIBS=-lncurses
И все, вы должны быть в состоянии играть в свою игру.Если вы хотите обрабатывать все детали в реальном Makefile, то все должно быть в порядке:
game: game.c
gcc game.c -o game -lncurses
Но гораздо более подходящим решением было бы:
CC := gcc
LDLIBS := -lncurses
game: game.c
$(CC) $^ -o $@ $(LDLIBS)
InЧтобы понять это, вам придется потратить некоторое время с GNU make manual , но вот краткое и минимальное объяснение.В обеих версиях:
<target>: <prerequisite>
<recipe>
говорит make, что для сборки <target>
необходимо иметь <prerequisite>
и запустить <recipe>
.Это также говорит make, что если <target>
новее <prerequisite>
, то нет необходимости перестраивать <target>
.В первой версии выше, с:
game: game.c
gcc game.c -o game -lncurses
make знает, что:
- , если
game.c
не существует, он не может собрать game
;если его так попросят, то возникнет ошибка - , если
game
существует и новее game.c
, то для сборки game
делать нечегоесли game
не существует или если он старше game.c
, он должен работать:
gcc game.c -o game -lncurses
Во второй версии:
VARNAME := <value>
это синтаксис make для установки переменной make с именем VARNAME
в значение <value>
, в то время как $(VARNAME)
является синтаксисом make для получения значения make variable VARNAME
.$@
и $^
- это две автоматические переменные , значения которых являются, соответственно, целью и списком всех предпосылок правила, в рецепте которых они появляются.