Makefile在C文件上运行两次

时间:2013-11-23 10:45:02

标签: gcc makefile

我有两个文件:assign1.c和ports.h。

仅供参考:我使用的是avr-gcc。

我构建了以下makefile,我也用它来处理其他项目(和其他TARGET)。

TARGET = assign2
LIB=
INCLUDE=ports.h
CFLAGS =-mmcu=atmega32 -Wall
CC = avr-gcc
SRC= $(TARGET).c
OBJ= $(SRC:.c=.o)

OBJCOPY = avr-objcopy
FORMAT  = ihex

MSG_COMPILING = Compiling:
MSG_LINKING = Linking:
MSG_FLASH = Creating load file for flash:

all:elf hex

elf: $(TARGET).elf
hex: $(TARGET).hex

%.hex: %.elf
    @echo $(MSG_FLASH) $@
    @echo 
    $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
    $(RM) *.elf $(TARGET)
    @echo 

%.elf: $(OBJ) $(LIB)
    @echo $(MSG_LINKING) $@
    @echo 
    $(CC)  $(CFLAGS)  $^ -o $@
    @echo 

%.o: $(SRC) $(INCLUDE)
    @echo $(MSG_COMPILING) $<
    @echo 
    $(CC)  $(CFLAGS) -c $<
    @echo 

.PHONY : clean

clean:
    $(RM) *.o *.hex *.elf $(TARGET)

终端打印以下输出。

C:\Project>make
Compiling: assign2.c

avr-gcc  -mmcu=atmega32 -Wall -c assign2.c
In file included from assign2.c:8:
c:/winavr-20100110/lib/gcc/../../avr/include/util/delay.h:90:3: warning: #warnin
g "Compiler optimizations disabled; functions from <util/delay.h> won't work as
designed"

Linking: assign2.elf

avr-gcc  -mmcu=atmega32 -Wall  assign2.o -o assign2.elf

Compiling: assign2.c

avr-gcc  -mmcu=atmega32 -Wall -c assign2.c
In file included from assign.c:8:
c:/winavr-20100110/lib/gcc/../../avr/include/util/delay.h:90:3: warning: #warnin
g "Compiler optimizations disabled; functions from <util/delay.h> won't work as
designed"

avr-gcc   elf.o assign2.elf   -o elf
avr-gcc: elf.o: No such file or directory
make: *** [elf] Error 1
rm assign2.o

C:\Project>

出于某种原因,似乎第二次编译第一个文件并且崩溃了。

任何人都可以纠正我的错误吗?

1 个答案:

答案 0 :(得分:3)

问题是你的模式规则。您正在编写这样的模式规则(在make扩展变量之后):

%.o: assign2.c ports.h

此规则告诉make的是,要构建的任何匹配%.o模式的目标都可以通过编译assign2.c来构建。这显然不正确:此规则只构建一个目标:assign2.o

因此make会读取你的makefile并希望构建一个名为elf的文件。它看到elf依赖于$(TARGET).elf,所以它构建了它(这是第一个编译和链接,它有效)。然后make想要自己构建elf。你没有宣称它是.PHONY,所以make假设它可能是一个真正的目标。

查看其内置规则,找到一个允许它构建elf的规则,并找到一个内置规则:% : %.o,它可用于从{编译程序{1}}具有相同前缀的文件。现在,对于目标.o,make想要尝试构建文件elf。啊哈!它看到有一个模式规则允许它基于elf.o源文件构建任何.o文件,因此它运行该规则(这是第二次编译),期望它构建assign2.c ..它显然没有。

然后使用不存在的elf.o运行内置链接配方,然后失败。

解决问题的方法有两点:

首先,你应该总是声明你实际上不想构建的所有makefile目标.PHONY所以make不会尝试构建它们:

elf.o

其次,你不应该使用模式规则,前提条件也不是模式(这在某些特定情况下很有用,但一般情况下不是这样)。您应该将这些模式规则更改为明确的规则:

.PHONY: all elf hex

或者通过使用先决条件列表中的模式将它们变为完整模式规则:

assign2.elf: $(OBJ) $(LIB)
        ...

$(OBJ): $(SRC) $(INCLUDE)
        ...