只在第二次运行时使用VPATH?

时间:2015-05-15 16:57:46

标签: c assembly makefile

我正在尝试编译和汇编,然后链接一些源文件。据我所知,它不会告诉链接器在VPATH中使用该路径,直到我第二次运行它。 这是Makefile:

#Makefile for SWS ARMKern

CC=arm-linux-gnueabi-gcc
LD=arm-linux-gnueabi-ld
CFLAGS=-g -Wall -Wextra -std=gnu11 -ffreestanding -march=armv6 -msoft-float -fPIC -mapcs-frame
LDFLAGS=-N -Ttext=0x10000
HWDEF=versatilepb #The set of hardware quirks to use.

#Paths
VPATH=src/:obj/
CINC=-Isrc/include/

kernel.elf: bootstrap.o kernel.o

.PHONY: clean test

clean:
    rm -f obj/*.o elf/*.elf

test:
    qemu-system-arm -M versatilepb -cpu arm1176 -nographic -soundhw none -kernel elf/kernel.elf

.SUFFIXES: .s .o .c .elf

.o.elf:
    $(LD) $(LDFLAGS) -o elf/$@ $^

.c.o:
    $(CC) $(CFLAGS) $(CINC) -DHWCLASS=$(HWDEF) -o obj/$@ -c $^

.s.o:
    $(CC) $(CFLAGS) $(CINC) -DHWCLASS=$(HWDEF) -o obj/$@ -c $^

这就是:

> ls
elf  isosrc  Makefile  Makefile~  obj  README.md  README.md~  src
> make kernel.elf
arm-linux-gnueabi-gcc -g -Wall -Wextra -std=gnu11 -ffreestanding -march=armv6 -msoft-float -fPIC -mapcs-frame -Isrc/include/ -DHWCLASS=versatilepb  -o obj/kernel.o -c src/kernel.c
arm-linux-gnueabi-gcc -g -Wall -Wextra -std=gnu11 -ffreestanding -march=armv6 -msoft-float -fPIC -mapcs-frame -Isrc/include/ -DHWCLASS=versatilepb  -o obj/bootstrap.o -c src/bootstrap.s
arm-linux-gnueabi-ld -N -Ttext=0x10000 -o elf/kernel.elf kernel.o bootstrap.o
arm-linux-gnueabi-ld: cannot find kernel.o: No such file or directory
arm-linux-gnueabi-ld: cannot find bootstrap.o: No such file or directory
Makefile:26: recipe for target 'kernel.elf' failed
make: *** [kernel.elf] Error 1
> make kernel.elf
arm-linux-gnueabi-ld -N -Ttext=0x10000 -o elf/kernel.elf obj/kernel.o obj/bootstrap.o

我确定这只是我的Makefile的一个问题,但我很难过。如何确保链接器使用VPATH路径?或者甚至只是强迫它查看obj /

谢谢!

3 个答案:

答案 0 :(得分:4)

VPATH是搜索来源而非目标的路径,因此只有在启动时VPATH上存在的文件才有效。自从第一次运行make以来,没有任何.o文件存在,make无法找到它们。您也可以使用后缀规则 - 像.c.o:这样的规则告诉make“这是如何在.o文件的当前目录中创建.c文件”,但是然后该操作将文件放在obj子目录中。

如果您正在使用GNU make或BSD make,您可以使用包含目录的模式规则:

elf/%.elf: obj/%.o:
        $(LD) $(LDFLAGS) -o $@ $^

obj/%.o: %.c
        $(CC) $(CFLAGS) $(CINC) -DHWCLASS=$(HWDEF) -o $@ -c $^

obj/%.o: %.s
        $(CC) $(CFLAGS) $(CINC) -DHWCLASS=$(HWDEF) -o $@ -c $^

模式规则完全包含后缀规则的所有使用 - 使用GNU或BSD,你应该从不使用后缀规则,而是使用模式规则。

答案 1 :(得分:0)

而不是

kernel.elf: bootstrap.o kernel.o

尝试

kernel.elf: obj/bootstrap.o obj/kernel.o

答案 2 :(得分:0)

我已通过将.o.elf规则更改为:

来解决此问题
.o.elf:
    cd obj/ && \
    $(LD) $(LDFLAGS) -o ../elf/$@ $^

即。将目录更改为/ obj目录。这是一个愚蠢的黑客,我不喜欢它,但它有效。