我希望我的Makefile接受不同的源文件类型。可以,但是当我更改包含文件时,它不会重新编译。这是Makefile:
C_SOURCES := $(wildcard *.c)
CPP_SOURCES := $(wildcard *.cpp)
CC_SOURCES := $(wildcard *.cc)
ALL_SOURCES := $(notdir $(C_SOURCES) $(CPP_SOURCES) $(CC_SOURCES))
C_OBJECTS := ${C_SOURCES:.c=.o}
CPP_OBJECTS := ${CPP_SOURCES:.cpp=.o}
CC_OBJECTS := ${CC_SOURCES:.cc=.o}
ALL_OBJECTS := $(notdir $(C_OBJECTS) $(CPP_OBJECTS) $(CC_OBJECTS))
#############################################################
all: a.out
a.out: $(ALL_OBJECTS)
g++ -o $@ -g $^
%.o: %.cpp
g++ -c $@ -g $^
%.o: %.cc
g++ -c $@ -g $^
%.o: %.c
g++ -c $@ -g $^
clean:
rm -f a.out
rm -f *.o
make.depend: $(ALL_SOURCES)
g++ -MM $^ > $@
-include make.depend
以* .o:开头的行是最近添加的内容-我想知道是否有帮助。没有效果。
make.depend正在执行其工作:我检查了一下,它的依赖关系是正确的。 (对于我的MCVE,我有一个源文件main.cpp,其中包含date.h。)
main.o: main.cpp date.h
$(info $(ALL_OBJECTS))
的输出为main.o
。
所以:我怎样才能识别包含的更改?
答案 0 :(得分:1)
显示问题时,显示运行命令和打印内容的示例将很有帮助。给定您提供的makefile,我会惊讶地发现make实际上除了生成依赖文件之外根本没有运行任何命令。
那是因为:
C_OBJECTS := ${C_SOURCES: .c =.o}
是无效的语法。或更确切地说,它不会执行您想要的操作。它用{{1}替换了_____.c__
中每个单词末尾的文字字符串_
(其中C_SOURCES
是空格...所以我不会只使用空格) }。当然,您没有任何这些,所以基本上您的.o
变量仅包含您的源文件(因为替换没有进行任何更改)。
您可以使用:
ALL_OBJECTS
看看这里会发生什么。
这需要写成:
$(info $(ALL_OBJECTS))
makefile中的空格非常棘手。您一定要小心放在哪里,也不能随意添加它。
我也不知道为什么要使用C_OBJECTS := ${C_SOURCES:.c=.o}
CPP_OBJECTS := ${CPP_SOURCES:.cpp=.o}
CC_OBJECTS := ${CC_SOURCES:.cc=.o}
,因为所有文件都在当前目录中。
从技术上讲,使用notdir
编译器前端编译.c
文件是不正确的。
ETA ,您的模式规则也不正确:您缺少编译器的g++
选项;它们都应该等同于:
-o
更好的方法是使用标准的make变量,然后您可以自定义行为而无需重写所有规则:
%.o: %.c
g++ -c -o $@ -g $^
答案 1 :(得分:0)
更新只需使用@MadScientist中描述的全面构建的自动依赖项文件http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/。这适用于GCC和clang(由于clang明确的目标是与GCC命令行兼容)。
出于完整性考虑,我的原始答案是:
生成的依赖关系规则必须依赖于依赖关系规则生成规则所确定的来源。这需要-MT
的{{1}}参数。
在您的gcc
的经过稍许清理的版本中,我已经将此作为示例:
GNUmakefile
#############################################################
ALL_CFLAGS = -g
ALL_CXXFLAGS = -g
#############################################################
.PHONY: all
all: all-local
#############################################################
bin_PROGRAMS += test-cxx
test_cxx_OBJECTS += main.o
test_cxx_OBJECTS += main-c.o
test-cxx: $(test_cxx_OBJECTS)
$(LINK.cc) $(ALL_CXXFLAGS) -o $@ $^
ALL_OBJECTS += $(test_cxx_OBJECTS)
#############################################################
%.o: %.cpp
$(COMPILE.cpp) $(ALL_CXXFLAGS) -o $@ -c $<
%.o: %.cc
$(COMPILE.cc) $(ALL_CXXFLAGS) -o $@ -c $<
%.o: %.c
$(COMPILE.c) $(ALL_CFLAGS) -o $@ -c $<
#############################################################
%.dep: %.cpp
$(COMPILE.cpp) -MM -MT "$*.o $@ " $< > $@.tmp
mv -f $@.tmp $@
%.dep: %.cc
$(COMPILE.cc) -MM -MT "$*.o $@ " $< > $@.tmp
mv -f $@.tmp $@
%.dep: %.c
$(COMPILE.c) -MM -MT "$*.o $@ " $< > $@.tmp
mv -f $@.tmp $@
ALL_DEPS = $(ALL_OBJECTS:.o=.dep)
-include $(ALL_DEPS)
#############################################################
.PHONY: all-local
all-local: $(bin_PROGRAMS)
.PHONY: clean
clean:
rm -f $(bin_PROGRAMS)
rm -f *.dep
rm -f *.o
#############################################################
生成规则将递归检查所有包含的源文件,并将它们全部列出在生成的*.dep
文件中。
为每个目标文件使用单独的*.dep
文件意味着,如果仅更改一个源文件,则实际上只会重新生成需要重新生成的*.dep
文件。
*.dep
生成规则首先创建一个*.dep
文件,并且仅在成功生成*.dep.tmp
文件的情况下才将其移动到*.dep
。因此,如果由于某种原因生成*.dep.tmp
文件失败(例如,您可能包括一个不存在的头文件),那么您将没有新生成的(因此被认为是最新的)空白*.dep.tmp
文件被*.dep
包含。