使用Makefile构建:即使明确指定,也选择file.c而不是file.cpp

时间:2015-11-16 13:42:12

标签: c++ c makefile

摘要:

我在同一个父文件夹中有一个.c文件和一个同名的.cpp文件。我不再希望编译.c文件,但也不想将其从文件夹中删除。

即使我明确指定编译.cpp文件,makefile也在使用.c文件。我该如何解决这个问题?

在将 file3.c 重命名为其他名称时, file3.cpp 将被编译。

详细信息:

' src '中存在的文件文件夹是:

file1.c
file2.c
file3.c
file3.cpp
file4.cpp

makefile的重要摘录:

SOURCE_FILES := ./src/file1.c \
        ./src/file2.c \
        ./src/file3.cpp \
        ./src/file4.cpp

OBJS = $(patsubst %.cpp,%.o,$(filter %.cpp, $(SOURCE_FILES))) \
    $(patsubst %.c,%.o,$(filter %.c, $(SOURCE_FILES)))

all : $(OBJS)
    $(CXX) $(CFLAGS) $(INCLUDES) -o $(PROJECT).bin $(OBJS) $(LDFLAGS) $(LIBRARIES) 

.cpp.o: 
    $(CXX) $(CFLAGS) $(INCLUDES) -c $< -o $@
    @echo 'CPP FILE : ' $<

.c.o:
    $(CXX) $(CFLAGS) $(INCLUDES) -c $<  -o $@
    @echo 'C FILE : ' $<

在做&#39; make&#39;时,echo命令的日志给出:

C FILE : ./src/file1.c
C FILE : ./src/file2.c
C FILE : ./src/file3.c
CPP FILE : ./src/file4.cpp

问题:

  1. 如何解决上述问题?
  2. 是否有更简单的方法来获取 OBJS 变量的值?

2 个答案:

答案 0 :(得分:3)

方法make用于选择使用两种可能的匹配规则中的哪一种取决于您使用的make版本。 (它在3.81和3.82之间变化,我认为稍微调整了4.0+,但我不确定。)

我认为make 3.81使用了最后一个匹配规则,并使3.82+使用匹配规则和最短的词干(匹配%的位),然后使用具有相似词干长度的规则之间的第一个匹配规则。

所以看起来你现在正在使用make 3.81。

在这种情况下,应该可以简单地交换两个规则的顺序来获得你想要的行为(假设你总是想要.cpp个文件来赢得&#34;)。

或者,您可以尝试为file3.o目标提供显式先决条件,而不是让它猜测。 (即file3.o: file3.cpp

这表示您的显式后缀规则都不是必需的,因为make已包含从.o.c文件构建.cpp文件的默认规则。 (我不知道它们之间的相对顺序,因此您可能需要明确的先决条件,假设有效,内置规则才能正常工作。)

此外,您可能希望使用Pattern Rules代替Old-Fashioned Suffix Rules作为当前实践的一点。

填充我可以看到的OBJS变量的唯一改进就是过滤结果,因此只需过滤一次。

OBJS = $(filter %.o,$(patsubst %.cpp,%.o,$(SOURCE_FILES)) \
    $(patsubst %.c,%.o,$(SOURCE_FILES)))

也就是说你也可以使用Substitution References而不是显式调用$(patsubst)来缩短这一点。

OBJS = $(filter %.o,$(SOURCE_FILES:.cpp=.o) $(SOURCE_FILES:.c=.o))

答案 1 :(得分:0)

您有.c ==&gt;的规则。 .o和.cpp ==&gt;的.o。 在您的情况下,首先运行file3.c的规则,因为新创建的file3.o文件现在存在。由于目标file3.o文件存在,因此没有理由编译file3.cpp。

查看at the make manual,如果同一目标有2条规则,则使用最后一条规则。