Предисловие
Вы используете $(CPP)
и $(CPPFLAGS)
... это для препроцессора .То, что вы хотите использовать, это $(CXX)
и $(CXXFLAGS)
для компилятора C ++.
В следующем предполагается, что GNU make и GCC-совместимый компилятор (clang сделает).
Шаг первый
Используйте общие правила, а не одно на исходный файл - последний очень быстро станет громоздким и очень подвержен ошибкам.
Либо перечислите свои исходные файлы вручную...
SOURCES := parking.cpp utils.cpp InputStateContext.cpp InputState.cpp InputStateA.cpp
... или автоматически перечислить все исходные файлы:
SOURCES := $(wildcard *.cpp)
Вам также необходим список объектных файлов (по одному .o на .cpp):
OBJECTS := $(patsubst %.cpp,%.o,$(SOURCES))
Теперь предоставьте правило для исполняемого файла, в зависимости от всех объектных файлов ...
parking: $(OBJECTS)
$(CXX) $(CXXFLAGS) $^ -o $@
... и универсальное правило о том, какчтобы превратить отдельный исходный файл в объектный файл:
%.o: %.cpp Makefile
$(CXX) $(CXXFLAGS) &< -o $@
Зависимость этого правила также от Makefile гарантирует, что, например, изменения в $(CXXFLAGS)
также инициируют перекомпиляцию.$<
разрешает зависимость first (исходный файл).
Мы расширим это правило позже.
Шаг второй
У нас будет файл зависимости для каждого исходного файла .(Смирись со мной здесь.) Мы можем создать список этих файлов ...
DEPENDS := $(patsubst %.cpp,%.d,$(SOURCES))
... и включить их в Makefile:
-include $(DEPENDS)
-
там означает, что make
не будет жаловаться, если эти файлы не существуют - потому что их нет, на данный момент.
Шаг третий (Основная часть ответа на ваш вопрос)
Пусть компилятор сгенерирует эти файлы зависимостей для us - потому что он знает лучше.Для этого мы расширим наше правило сборки:
%.o: %.cpp Makefile
$(CXX) $(CXXFLAGS) -MMD -MP -c $< -o $@
Флаг -MMD
создает файл зависимостей (%.d
), который будет содержать (в синтаксисе Makefile) правила, создающие сгенерированный файл (%.o
)в этом случае) зависит от исходного файла и любых несистемных заголовков, в которые он входит .Это означает, что объектный файл воссоздается автоматически при каждом касании соответствующих источников.Если вы также хотите зависеть от системных заголовков (т. Е. Проверять их наличие обновлений при каждой компиляции), используйте вместо этого -MD
.
Опция -MP
добавляет пустые фиктивные правила, которые позволяют избежать ошибок при удалении заголовочных файлов из файловой системы.
При первом запуске компиляции информация о зависимостях отсутствует - но посколькуобъектные файлы тоже не существуют, компилятор должен работать в любом случае.Для каждого последующего запуска make
будет включать автоматически созданные файлы зависимостей и «делать правильные вещи».
All-In-One (с некоторыми более синтаксическимисахар добавлен):
SOURCES := $(wildcard *.cpp)
OBJECTS := $(patsubst %.cpp,%.o,$(SOURCES))
DEPENDS := $(patsubst %.cpp,%.d,$(SOURCES))
# ADD MORE WARNINGS!
WARNING := -Wall -Wextra
# .PHONY means these rules get executed even if
# files of those names exist.
.PHONY: all clean
# The first rule is the default, ie. "make",
# "make all" and "make parking" mean the same
all: parking
clean:
$(RM) $(OBJECTS) $(DEPENDS) parking
# Linking the executable from the object files
parking: $(OBJECTS)
$(CXX) $(WARNING) $(CXXFLAGS) $^ -o $@
-include $(DEPENDS)
%.o: %.cpp Makefile
$(CXX) $(WARNING) $(CXXFLAGS) -MMD -MP -c $< -o $@