Как использовать фильтр с * F в Makefile? - PullRequest
0 голосов
/ 23 апреля 2020

В моем файле Makefile есть эта строка:

$(CC) $(CFLAGS) -o $@ -c $(filter %$(*F).cpp, $(SOURCES))

Предположим, у меня есть 2 cpp файл типа "docinfo. cpp" и "info. cpp", когда g ++ build "docinfo. . cpp "в" docinfo.o ", это работает.

g++ -I ... -o docinfo.o -c docinfo.cpp

Но когда g ++ создает" info. cpp "в" info.o ", возникает ошибка.

g++ -I ... -o info.o -c docinfo.cpp info.cpp

Как мне заставить это работать?

Это мой Makefile:

CC        := gcc
RM        := rm -rf

WORKSPACE := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))

TARGET    := $(WORKSPACE)test.so

SOURCES   := $(foreach dir,$(WORKSPACE),$(wildcard $(dir)source/*.c))

INCLUDE   := -I$(WORKSPACE)include/

CFLAGS    := $(INCLUDE) -O0 -Wall -fPIC 
#CFLAGS    += -g
#CFLAGS    += -D__DEBUG__

OBJS      := $(notdir $(SOURCES:.c=.o))
OBJ_PATH  := $(WORKSPACE)object/
OBJS_O    := $(addprefix $(OBJ_PATH), $(OBJS))

LIB_PATH  := $(WORKSPACE)lib
LIBS      := -ldl -shared

.PHONY: all clean

all: $(OBJ_PATH) $(LIB_TAG) $(TARGET)

$(OBJ_PATH):
    mkdir -p $@

$(TARGET): $(OBJS_O)
    $(CC) $(CFLAGS) -o $@ $^ -L$(LIB_PATH) $(LIBS)
    @echo "$@"

$(OBJS_O): $(SOURCES)
    $(CC) $(CFLAGS) -o $@ -c $(filter %$(*F).c,$(SOURCES))

clean:
    -$(RM) $(OBJS_O) $(OBJ_PATH) $(TARGET)

1 Ответ

0 голосов
/ 23 апреля 2020

Во-первых, почему бы вам просто не использовать $< вместо попытки отфильтровать что-либо из $ (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, поскольку каждый объектный файл зависит только от исходного файла, а не от всех исходных файлов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...