2015-05-15 130 views
0

我想編譯和彙編,然後鏈接一些源文件。據我所知,它沒有告訴鏈接器使用VPATH中的路徑,直到我第二次運行它。 這裏的Makefile文件:第二次運行時只使用VPATH?

#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/[email protected] $^ 

.c.o: 
    $(CC) $(CFLAGS) $(CINC) -DHWCLASS=$(HWDEF) -o obj/[email protected] -c $^ 

.s.o: 
    $(CC) $(CFLAGS) $(CINC) -DHWCLASS=$(HWDEF) -o obj/[email protected] -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/

謝謝!

+0

.SUFFIXES已過時,它定義了處理文件的順序。在/ SUFFIXES語句中,它表示在.c文件之前處理.o文件。這將是一個問題。 make中的默認.SUFFIXES正確列出了所有文件名的結尾,所以.SUFFIXES不應該在'本地'makefile中 – user3629249

回答

4

VPATH是當開始做相關的搜索來源,沒有目標,所以只有在VPATH存在的文件的路徑。自第一次運行make以來,您的.o文件都不存在,make也找不到它們。你也在用你的後綴規則說謊 - 像.c.o:這樣的規則告訴make「這是如何在當前目錄下從.c文件製作.o文件」,但是然後該動作使文件在obj子目錄中。

如果您使用GNU製造或BSD化妝,你可以使用模式規則,包括目錄:

elf/%.elf: obj/%.o: 
     $(LD) $(LDFLAGS) -o [email protected] $^ 

obj/%.o: %.c 
     $(CC) $(CFLAGS) $(CINC) -DHWCLASS=$(HWDEF) -o [email protected] -c $^ 

obj/%.o: %.s 
     $(CC) $(CFLAGS) $(CINC) -DHWCLASS=$(HWDEF) -o [email protected] -c $^ 

模式規則完全歸入的後綴規則的所有用途 - 與GNU或BSD令你應該從不使用後綴規則,而是使用模式規則。

+0

完美,謝謝! –

0

而不是

kernel.elf: bootstrap.o kernel.o 

嘗試

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

在Makefile中我使用'$ ^'來指定輸入文件,所以我不能做那。 (看看recipie .o.elf)我試過'obj/$ ^',但是這會導致'obj/bootstrap.o kernel.o',它仍然不起作用。 –

+0

如果它僅在第二次運行時讀取VPATH,則還可以嘗試「VPATH:=」而不是「VPATH =」 – rost0031

+0

這不起作用。我仍然有同樣的錯誤。無論如何,我的VPATH中沒有變量,它只是'src /:obj /' –

0

我已經改變我的.o.elf規則固定的:

.o.elf: 
    cd obj/ && \ 
    $(LD) $(LDFLAGS) -o ../elf/[email protected] $^ 

即目錄切換到/ OBJ目錄。這是一個愚蠢的黑客,我不喜歡它,但它的工作原理。

相關問題