Во-первых, обратите внимание, что целью по умолчанию в Makefile является первая;следовательно, если у нас есть файлы зависимостей, и мы включаем их перед главной целью, то цель .o
в первом включенном правиле зависимости будет целью по умолчанию.Как правило, включайте зависимости где-то еще ниже, например, в самый конец.
Проблема сопоставления с образцом в этом Makefile вызвана тем, что файлы .o
не имеют префикса каталога из-заиспользование $(notdir ...)
в расширении, которое их генерирует, но файлы .cpp
делают.
make
пытается создать некоторый foo.o
, и правило %.o: %.cpp
заставляет его искать foo.cpp
.Но нет foo.cpp
;существует только src/dir/foo.cpp
.
Если вы действительно хотите, чтобы файлы .o
находились в одном каталоге, механизм VPATH
может оказаться возможным.Если src/dir
находится в VPATH
, то, когда make
ищет foo.cpp
для обновления foo.o
, он найдет его в src/dir
.
Если принудительно выполнить все .o
файлыиз дерева в один каталог, вы должны быть уверены, что нет двух .cpp
файлов с одинаковыми именами.
Если вы хотите поместить .o
файлы вне дерева исходных текстов (что полезно,потому что вы можете иметь, например, исходное дерево только для чтения), вероятно, лучше всего отобразить структуру исходного дерева в выходном дереве, например:
$(OUTPUT_DIR)/%.o: %.cpp: # where the % stem is src/dir/whatever/foo
Идея состоит в том, что объектфайл $(OUTPUT_DIR)/src/whatever/foo.o
, а исходный файл src/whatever/foo.cpp
.
Рецепт должен убедиться, что каталог $(OUTPUT_DIR)/src/whatever
существует;поэтому где-то понадобится команда mkdir -p
:
$(OUTPUT_DIR)/%.o: %.cpp:
$(info Compiling $< ...)
@mkdir -p $(dir $@)
@$(CXX) -c $(CFLAGS) $< -o $@ -MF $(@:%.o=%.d) -MT $@