这个makefile的行为与我预期的不一样。我希望它为当前目录和子目录中的每个.c文件构建.o文件,并将它们放在静态库中。但是,它会在第一个或第二个文件之后停止应用我的$(INCS(。当它试图构建第二个.o文件时,我在构建行中看不到-I路径,它抱怨在其中找不到头文件。为了简化事情,名字被通用化了。我在WindowsXP上使用cygwin。我使用的是一个不在cygwin树下的ARM交叉编译器。我根据这里的答案创建了这个makefile。只有大约20多个.c文件,因此以这种方式创建依赖文件的开销并不是什么大问题。
# Project specific options
CC = my-cross-gcc
INCS := -I. -Iinc
INCS += -Imy/inc/path
CFLAGS := -Wall -fPIC -static -cross-compiler-specific-options
OUT := bin/libmylib.a
MKDIR:=mkdir -p
### Generic C makefile items below:
# Add .d to Make's recognized suffixes.
SUFFIXES += .d
NODEPS:=clean
#Find all the C files in this directory, recursively
SOURCES:=$(shell find . -name "*.c")
#These are the dependency files
DEPFILES:=$(patsubst %.c,%.d,$(SOURCES))
OBJS:= $(patsubst %.c,%.o,$(SOURCES))
#Don't create dependencies when we're cleaning, for instance
ifeq (0, $(words $(findstring $(MAKECMDGOALS), $(NODEPS))))
-include $(DEPFILES)
endif
#This is the rule for creating the dependency files
%.d: %.c
$(CC) $(INCS) $(CFLAGS) -MM -MT '$(patsubst %.c, %.o,$(patsubst %.c,%.o,$<))' $< > $@
#This rule does the compilation
%.o: %.c %.d %.h
$(CC) $(INCS) $(CFLAGS) -o $@ -c $<
# Now create a static library
all: $(OBJS)
@$(MKDIR) bin
ar rcsvq $(OUT) $(OBJS)
clean:
rm -rf $(OBJS) $(OUT) $(DEPFILES)
为什么这个makefile在生成后续的.o文件时不应用$(INCS(?我该如何修复它?输出类似于:
$ make all
my-cross-gcc -I. -Iinc -Imy/inc/path -<compiler options> -o firstfile.o -c firstfile.c
my-cross-gcc -I. -Iinc -Imy/inc/path -<compiler options> -o secondfile.o -c secondfile.c
my-cross-gcc -<compiler flags> -o thirdfile.o -c thirdfile.c
thirdfile.c:23:18: fatal error: myinc.h: No such file or directory
compilation terminated.
当我转到命令行并在gcc行中键入构建thirdfile.o并使用-I路径时,对象文件就成功构建了。
这里有两种不同的处理头文件的机制:
当编译器试图从foo.c
构建foo.o
,并且在foo.c
中遇到#include "foo.h"
时,它将查找foo.h
。-I
标志告诉它在哪里查找。如果在没有找到foo.h
所需的标志的情况下调用它,它将抱怨并死亡。
当Make尝试构建foo.o
并考虑使用哪个规则时,它会查看先决条件。您的规则的先决条件是foo.c foo.d foo.h
,因此它将查找这些先决条件<怎么知道foo.h
在哪里>请注意,其中一个命令中的编译器标志没有任何用处——它不会对此进行任何推导。如果它找不到(也不知道如何创建(先决条件,它将拒绝该规则并寻找另一个规则,例如隐式%.o
规则,它对您的$(INCS(变量一无所知,这会导致您出现上述问题。怎么知道CCD_10在哪里>
如果这是问题所在(你可以通过查看标题的位置并进行一些实验来检查(,你有几个选择:
A( 你可以使用隐式规则,它是变量。只需将INCS
添加到CFLAGS
中,您可能会得到您想要的结果。这告诉编译器该做什么,但它仍然让Make对依赖项一无所知,因此您可能必须仔细检查依赖项处理是否正确。
B( 你可以告诉Make在哪里可以找到头文件:
vpath %.h inc my/inc/path
(您可能会注意到,这对INCS
变量来说是多余的,而且冗余是不好的——您可以消除这种冗余,但我敦促您先让它工作起来。(
我猜您有名为firstfile.h、secondfile.h的文件,但没有名为thirdfile.h的任何文件?
然后我假设make不能使用你给它的规则,因为它找不到或无法构建.h文件。因此,它决定使用默认的隐式规则。
我所能想象的是,对于"thirdfile",您的depfile在某种程度上已经过时或损坏。也许这已经够糟糕的了,以至于调用其他默认目标会让make感到困惑。