Во-первых, почему бы вам просто не использовать $<
вместо попытки отфильтровать что-либо из $ (SOURCES)?
$(CC) $(CFLAGS) -o $@ -c $<
Если по какой-то странной причине вам нужен фильтр, тогда, если вы не хотите возвращать совпадение для любого значения, заканчивающегося $ (* F). cpp, просто не ставьте перед ним префикс с символом совпадения шаблона (%
):
$(CC) $(CFLAGS) -o $@ -c $(filter $(*F).cpp, $(SOURCES))
Это странно, потому что $(*F)
должно расшириться до foo.cpp
, что означает, что это разрешится до foo.cpp.cpp
.
Так что, я думаю, что-то довольно необычное (или, возможно, неправильное) в вашем makefile ... но так как вы только предоставили рецепт и не показали нам полное правило, мы не можем сказать наверняка.
ETA
Теперь, когда мы посмотрите свой make-файл, конечно, у него есть проблема. Это правило неверно:
$(OBJS_O): $(SOURCES)
$(CC) ...
На что это распространяется после разрешения переменных? Скажем, у вас есть SOURCES
разрешение source/foo.c source/bar.c
и OBJS_O
разрешение object/foo.o object/bar.o
. Тогда приведенное выше правило разрешается так:
object/foo.o object/bar.o: source/foo.c source/bar.c
$(CC) ...
Что здесь делает? Он волшебным образом не выполняет какое-то поэтапное сопоставление целей с предварительными условиями. Он интерпретирует это правило так, как если бы вы написали следующее:
object/foo.o: source/foo.c source/bar.c
$(CC) ...
object/bar.o: source/foo.c source/bar.c
$(CC) ...
То есть каждый объект зависит от всех исходных файлов, поэтому, если любой исходный файл изменяется, каждый объект перестраивается .
Если вы хотите, чтобы это работало правильно и поместили все объектные файлы в один каталог, независимо от того, в каком каталоге они находятся, то вам нужно будет использовать vpath
с правилом шаблона, например, так: :
vpath %.c $(sort $(dir $(SOURCES)))
$(OBJ_PATH)%.o : %.c
$(CC) $(CFLAGS) -o $@ -c $<
Теперь вы можете использовать $<
вместо функции filter
, поскольку каждый объектный файл зависит только от исходного файла, а не от всех исходных файлов.