此生成文件的行为与我预期的不同。我希望它为当前目录和子目录中的每个.c文件构建.o文件,并将它们放在静态库中但是,它会在第一个或第二个文件之后停止应用我的$(INCS)当它试图构建第二个.o文件时,我在构建行中看不到-I路径,它抱怨没有在其中找到头文件。名字被泛化以简化事情我在Windows XP上使用cygwin我使用的是一个不在cygwin树下的ARM交叉编译器我根据一个答案制作了这个makefilehere只有大约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)
为什么生成后续的.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.o
构建foo.c
时,在foo.c
中遇到#include "foo.h"
,它会寻找foo.h
。-I
标志告诉它在哪里查找。如果调用它时没有找到foo.h
所需的标志,它会抱怨并死掉。
当Make试图构建foo.o
时,考虑使用哪个规则,它会查看先决条件规则的先决条件是foo.c foo.d foo.h
,因此它会查找这些先决条件。如何知道foo.h
在哪里注意,其中一个命令中的编译器标志没有任何用处——它不会对此做任何推断如果它找不到(也不知道如何创建)一个先决条件,它将拒绝该规则并寻找另一个规则,例如不知道$(INCS)变量的隐式%.o
规则,这将导致出现上述问题。
如果这是问题所在(您可以通过查看报头的位置并进行一些实验来进行检查),您有两个选项:
A)你可以使用隐式规则,它是变量。只需将INCS
添加到CFLAGS
中,您就可能得到所需的结果这告诉编译器该做什么,但它仍然让Make对依赖项一无所知,因此您可能需要重新检查依赖项处理是否正确。
B)您可以告诉Make在哪里找到头文件:
vpath %.h inc my/inc/path
(您可能会注意到这对于
INCS
变量是多余的,而且冗余是不好的——您可以消除这种冗余,但我建议您首先让它工作。)