Основная проблема заключается в том, что некоторые ваши рецепты для связи не хватает выходного файла и что ваша компиляция отсутствует -c
.
В случае, если вы используете GNU сделать следующее Makefile
будет достаточно, чтобы делать то, что вы хотите сделать:
CFLAGS:=-Wall -std=c11
CPPFLAGS:=-DNDEBUG
.PHONY: all
all: caltool
caltool: caltool.o calutil.o
.PHONY: clean
clean::
$(RM) *.o
Объяснение:
- Когда вы не используете target- конкретные переменные, вы должны использовать
:=
вместо =
для назначения переменных, чтобы они были расширены при назначении, а не при оценке.
- Когда ваш
Makefile
растет, и вы его разделяете, вы можете захотеть иметь несколько целей под названием clean
, которые будут выполнены. В этом случае используйте clean::
вместо clean:
.
- Там в предопределенную переменную для вызова
rm
, это $(RM)
и включает в себя -f
флаг, чтобы предотвратить Makefile
от сбоя в случае, если один или несколько файлов, подлежащих удалению, не существует в первую очередь.
- Шаблон для
clean
должен быть *.[adios]
(что очень легко запомнить, прощай испанский для свидания), так что она удаляет промежуточные архивы (.a
при создании собственных статических библиотек), файлы зависимостей (.d
), выход препроцессора (.i
) и ассемблерных файлов (.s
), если вы используете -save-temps
, чтобы узнать, что делает компилятор.
- GNU сделать имеет встроенные правила для компиляции и компоновки, см http://git.savannah.gnu.org/cgit/make.git/tree/default.c?id=3.81
- Встроенный правило для компиляции вызывает
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o [email protected] $<
так что вам не нужно писать собственное правило.
- Встроенный правило для связи вызывает
$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o [email protected]
- Цели, которые не сами файлы должны быть объявлены
.PHONY
, чтобы избежать путаницы, когда пользователь создает файл с таким же именем, как all
или clean
.
- Я не вижу, как любая из ваших команд создаст файл, соответствующий шаблону glob
*.out
, поэтому я удалил эту часть правила clean
.
- Флаги для препроцессора должны быть отправлены в
CPPFLAGS
вместо CFLAGS
. Флаги препроцессора, как правило, представляют собой все эти -D
и -I
флаги, а также передаются другим инструментам, использующим препроцессор C в том же проекте, например splint
или PC-Lint
.
Когда Makefile
запускается, он ищет, как сделать all
, и он считает, что для all
он должен сделать caltool
. Для caltool
он находит, что он должен сначала сделать calutil.o
и caltool.o
. Когда он пытается сделать calutil.o
и caltool.o
, он находит, что он может сделать их от calutil.c
и caltool.c
и сделает это. Затем он свяжет caltool.o
и calutil.o
в caltool
.
От вашего имени я догадался, что это caltool.c
, который содержит функцию main()
. Полезно поместить объект, содержащий main()
, первый раз, когда вы используете статические библиотеки ссылок.
Редактировать: Вот еще волшебство для вас. Я предполагаю, что у вас есть файл заголовка calutil.h
, который включен caltool.c
для доступа к внешним символам, предоставленным calutil.c
. Вы хотите перестроить все объекты, которые зависят от этих файлов заголовков. В этом случае, добавьте следующие строки в Makefile:
CPPFLAGS+=-MMD
-include caltool.d calutil.d
Для того, чтобы не иметь список объектов несколько раз, вы можете добавить переменную objects
так:
objects:=caltool.o calutil.o
Вы бы тогда построить приложение с этим правилом:
caltool: $(objects)
И включать файлы зависимостей, как это:
-include $(objects:.o=.d)
В случае, если вы держите ваше рабочее дерево «чистым», то есть не «загрязняет» его с «чужим» кодом, то есть вы всегда хотите включить все .c
файлов в вашем проекте, вы можете изменить определение objects
как следующим образом:
sources:=$(wildcard *.c)
objects:=$(sources:.c=.o)
в случае, если вы удивляетесь, почему это CPPFLAGS
(в верхнем регистре), но objects
(в нижнем регистре): он обычно используется верхний регистр для всех переменных, которые настроить рецепты правил и контроля встроенного поведения make
, инструменты, построенные поверх него, и классические переменные окружения, а также переменные нижнего регистра для всего остального.
Какую версию 'make' вы используете? Для того, что вы хотите достичь, ваш 'Makefile' может быть слишком сложным, особенно когда вы используете GNU make. –
Эй, пользуюсь 3.81. Любые упрощения были бы удивительными. – MortalMan
Отсутствует второе правило '-c', поэтому' caltool.o' является * полной программой *, а не объектным файлом. – immibis