如何在Makefile中对* F使用过滤器?

问题描述 投票:0回答:1

我的Makefile中有此行:

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

[假设我有2个cpp文件,例如“ docinfo.cpp”和“ info.cpp”,当g ++将“ 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)
c makefile
1个回答
0
投票

首先,为什么不只使用$<而不是尝试从$(SOURCES)中过滤掉某些内容?

$(CC) $(CFLAGS) -o $@ -c $<

[如果出于某种奇怪的原因,您确实需要过滤器,那么如果您不希望为以$(* F).cpp结尾的任何值返回匹配项,那么就不要在其前面加上模式匹配项字符(%):

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

但是,这很奇怪,因为$(*F)应该扩展为foo.cpp,这意味着它将解析为foo.cpp.cpp

所以,我认为您的makefile有点不寻常(或可能不正确)……但是由于您仅提供了配方,没有向我们展示整个规则,所以我们无法确定。

ETA

现在我们可以看到您的makefile,果然有问题。这条规则是错误的:

$(OBJS_O): $(SOURCES)
        $(CC) ...

解析变量后,这将扩展为什么?假设您有SOURCES解析为source/foo.c source/bar.cOBJS_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) ...

也就是说,每个对象都依赖于[[all源文件,因此,如果更改了任何源文件,则将重建每个对象。

如果要使其正常工作并将所有目标文件放在一个目录中,无论它们位于哪个源目录下,那么您都必须将vpath与一个模式规则一起使用,如下所示:

vpath %.c $(sort $(dir $(SOURCES))) $(OBJ_PATH)%.o : %.c $(CC) $(CFLAGS) -o $@ -c $<

现在您可以使用$<而不是filter函数,因为每个目标文件都完全依赖于它的源文件,而不是所有的源文件。
© www.soinside.com 2019 - 2024. All rights reserved.