Это очень просто, с использованием VPATH .Во-первых, вы должны убедиться, что ваша переменная OBJS
содержит то, что вы хотите построить.В настоящее время у вас есть это:
OBJ=$(patsubst %.c, $(OBJDIR)/%.o, $(SRC))
, что неверно, потому что SRC
содержит пути типа ./../../folder0/folder02/src/foobar.c
, что означает, что после patsubst
вы получите пути типа ./build/obj/./../../folder0/folder02/src/foobar.o
, что явно не то, что выхочу.Используйте вместо этого:
OBJ = $(patsubst %.c, $(OBJDIR)/%.o, $(notdir $(SRC)))
, который для каждого исходного файла somepath/foobar.c
, независимо от значения somepath , даст вам ./build/obj/foobar.o
, что вам нужно.
Затем сохраните правило, которое создает этот .o из файла .c.Наконец, используйте VPATH, чтобы указать make, где искать исходные файлы, если они не существуют в локальном каталоге:
VPATH = $(SRCDIRS)
Это все, что вам нужно сделать.
Я должен отметить, чтоваш INCLUDES
немного сломан: у вас будет огромное количество дубликатов каталогов, добавленных с -I
.Вместо этого:
INCLUDE=$(foreach d, $(DEP),-I $(dir $d))
Вы должны использовать:
INCLUDE = $(addprefix -I,$(sort $(dir $(DEP)))
Функция sort
также будет уникальной, и вам не понадобится foreach
, потому что большинство функций ввозьмите несколько слов и оперируйте всеми ними.
В качестве последнего замечания вы должны использовать :=
вместо =
, это будет намного более эффективным.То, как вы пишете здесь каждый раз, когда эти переменные раскрываются, будет перезапускать операции find
и т. Д. Вставьте echo find 1>&2;
в вызовы shell
функций перед find
и посмотрите, сколько раззапустите ...
О, тогда действительно последнее замечание: при настройке этого параметра теперь каждый отдельный исходный файл будет перестраиваться при каждом изменении любого заголовочного файла (вы добавили $(DEPS)
в качестве предварительного условия для$(OBJDIR)/%.o
цель).Может быть, это то, что вы хотите, но это необычно.