为什么这个makefile不适用于所有对象?

时间:2011-07-05 20:41:48

标签: c makefile cygwin cross-compiling

这个makefile的行为与我的预期不符。我希望它为当前目录和子目录中的每个.c文件构建.o文件,并将它们放在静态库中。但是,它会在第一个或第二个文件后停止应用我的$(INCS)。当它试图构建第二个.o文件时,我没有在构建行中看到-I路径,并且它抱怨没有在其中找到头文件。名称已被通用化以简化事物。我在Windows XP上使用cygwin。我正在使用不在cygwin树下的ARM交叉编译器。我根据答案here创建了这个makefile。只有大约24个.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路径时,目标文件已成功构建。

3 个答案:

答案 0 :(得分:3)

在这里处理头文件有两种不同的机制:

编译器尝试从foo.o构建foo.c时,在foo.c遇到#include "foo.h"时,它会寻找{{} 1}}。 foo.h标志告诉它在哪里看。如果在没有标志的情况下调用它,它需要找到-I,它会抱怨并死亡。

Make 尝试构建foo.h并考虑使用哪个规则时,它会查看先决条件。您的规则的先决条件是foo.o,因此它会寻找这些先决条件。 如何知道foo.c foo.d foo.h的位置?请注意,其中一个命令中的编译器标志没有用 - 它不会对此进行任何推断。如果它找不到(并且不知道如何制作)先决条件,它将拒绝该规则并寻找另一个规则,例如对$(INCS)变量一无所知的隐式foo.h规则,这会引导您解决上述问题。

如果这是问题(您可以通过查看标题的位置并进行一些实验来检查),您有几个选择:

A)您可以使用隐式规则及其变量。只需将%.o添加到INCS,您就可以获得所需的结果。这告诉编译器要做什么,但是它仍然让关于依赖的黑暗,所以你可能需要仔细检查你的依赖处理是否正确。

B)你可以告诉Make在哪里找到头文件:

CFLAGS

(您可能会注意到这对于您的vpath %.h inc my/inc/path 变量来说是多余的,冗余也很糟糕 - 您可以消除这种冗余,但我建议您首先使用它。)

答案 1 :(得分:2)

我猜你有文件名为firstfile.h,secondfile.h,但没有名为thirdfile.h的文件?

我会假设make不能使用你给它的规则,因为无法找到或构建.h文件。因此它决定使用默认的隐式规则。

答案 2 :(得分:1)

我可以想象的是,对于“thirdfile”,你的depfile会以某种方式过时或损坏。也许它已经足够糟糕,因为调用其他默认目标会令人困惑。