开发者

Why does this makefile not apply includes to all objects?

This makefile does not behave as I expect. I want it to build .o files for each .c file in the current directory and subdirectories, and put them in a static library. However, it stops applying my $(INCS) after the first or second file. When it tries to build the second .o file, I don't see the -I paths in the build line and it complains about not finding a header file therein. Names have been genericized to simplify things. I'm using cygwin on Windows XP. I'm using an ARM cross compiler that is not under the cygwin tree. I based this makefile off an answer here. There are only about two dozen .c files so the overhead of creating the dependency files this way isn't a big deal.

# 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)
开发者_StackOverflowendif

#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)

Why does this makefile not apply $(INCS) when building subsequent .o files? How do I fix it? Output resembles this:

$ 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.

When I go to the command line and type in the gcc line to build thirdfile.o and use the -I paths, the object file is successfully built.


There are two different mechanisms for handling header files at work here:

When the compiler is trying to build foo.o from foo.c, and in foo.c it encounters #include "foo.h", it goes looking for foo.h. The -I flags tell it where to look. If it is invoked without the flags it needs to find foo.h, it will complain and die.

When Make is trying to build foo.o, and considering which rule to use, it looks at the prerequisites. The prerequisites for your rule are foo.c foo.d foo.h, so it goes looking for those prerequisites. How is it to know where foo.h is? Note that the compiler flag inside one of its commands is of no use-- it won't make any deductions about that. If it can't find (and doesn't know how to make) a prerequisite, it will reject that rule and look for another one, such as the implicit %.o rule which knows nothing about your $(INCS) variable, and that leads you to the problem described above.

If this is the problem (and you can check by looking at the locations of the headers and doing some experiments) you have a couple of options:

A) You can use the implicit rule, and it's variables. Just add INCS to CFLAGS and you'll probably get the results you want. This tells the compiler what to do, but it still leaves Make in the dark about the dependencies, so you'll probably have to double-check that your dependency handling is correct.

B) You can tell Make where to find the header files:

vpath %.h inc my/inc/path

(You may notice that this is redundant with your INCS variable, and redundancy is bad-- you can eliminate this redundancy, but I urge you to get it working first.)


I'm going to guess that you have files named firstfile.h, secondfile.h, but no file named thirdfile.h?

I would then suppose that make cannot use the rule you gave it because and can't find or build the .h file. So it decides to use the default implicit rule instead.


All I can imagine is that for "thirdfile" your depfile is somehow out-of-date or corrupt. Perhaps it is bad enough that it's confusing make into calling some other default target.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜