2017-09-30 90 views
0

對不起,重複,但我找不到解決方案。 以下是我希望Makefile完成的命令序列。Makefile自動編譯,彙編和鏈接目錄中的許多文件

gcc-elf-gcc -S -combine loadStoreByte.c string.c lib_uart.c bubble_uart.c -o bubble_uart.s 

gcc-elf-as -o startup.o startup.s; 
gcc-elf-as -o handler.o handler.s; 
gcc-elf-as -o bubble_uart.o bubble_uart.s; 

gcc-elf-ld -o bubble_uart -T browtb.x bubble_uart.o startup.o handler.o; 

也就是說,我想所有的C文件編譯成一個單一的S檔,然後assemeble所有s文件轉換成相應的目標文件和鏈接所有對象文件爲一個可執行文件。

我試過下面的makefile。單個目標可以正常工作,但無法使用「全部製造」同時運行所有目標。 請指導如何解決它。

CC = brownie32-elf-gcc 
AS = brownie32-elf-as 
LK = brownie32-elf-ld 
SFILE = $(wildcard *.s) 
OFILE = $(patsubst %.s,%,$(SFILE)) 
CFILE = $(wildcard *.c) 
OBJ = $(wildcard *.o) 

APP = bubble_uart 

all: compile assemble link 

link: $(OBJ) 
     $(LK) -o $(APP) -T browtb.x $^ 

assemble: $(OFILE) 

%: %.s compile 
     $(AS) -o [email protected] $< 

compile: $(CFILE) 
     $(CC) -S -combine $^ -o $(APP).s 

clean: 
     rm -f $(OBJ) $(APP) $(APP).s *.o 

感謝

+0

我糾正你的問題,我覺得它有一個錯誤。 –

回答

1

Makefile中沒有與「最佳實踐」的書面正因爲這樣很容易讓你犯錯。我將在這裏重新編寫您的makefile文件,並提供解決所有問題的最佳實踐。請藉助GNU Make手冊進行研究。

最大的問題是你有「程序/動作」,比如「彙編」作爲目標。這使makefile成爲一種「程序」程序。 GNU Make的設計不是一種程序性語言,而是一種聲明性語言。 「目標」不應該是行爲,而應該是實際文件的集合,即實際文件或「假冒」文件。

在makefiles中使用wildcard是一個壞主意 - 最好是顯式列出您的文件,如我所示。

請參考我的回答 makefile enforce library dependency ordering 關於良好實踐的討論,包括假冒和真實目標。

MAKEFILE := $(lastword $(MAKEFILE_LIST)) 

CFILES := \ 
    loadStoreByte.c \ 
    string.c \ 
    lib_uart.c \ 
    bubble_uart.c 

SFILE_OUTPUT := bubble_uart.s 

SFILES := $(SFILE_OUTPUT) \ 
    startup.s \ 
    handler.s 

OFILES := $(SFILES:s=o) 

APP := bubble_uart 

.PHONY: all 
all: $(APP) 

$(APP): browtb.x $(OFILES) $(MAKEFILE) 
    gcc-elf-ld -o [email protected] -T $< $(OFILES) 

$(OFILES): %o : %s $(MAKEFILE) 
    gcc-elf-as -o [email protected] $< 

$(SFILE_OUTPUT): $(CFILES) $(MAKEFILE) 
    gcc-elf-gcc -S -combine $(CFILES) -o [email protected] 
+0

感謝@Mark Galeck的解釋,但c文件列表不是固定的。它可能是任何數量的c文件 – Sajjad

+1

@Sajjad是的,我知道,無所謂 - 你應該總是有一個列表,而不是使用「通配符」。如果所有c文件都是源文件,請列出它們。當你添加一個新的源時,你更新列表。如果某些c文件不是來源,而是在構建過程中生成的,則可以計算列表 - 就像我上面爲「SFILES」所做的那樣。 –

+0

說說最佳實踐:在一行中定義Makefile變量爲空,然後在每個「foo.c」中添加一個「VAR + = foo.c」行來添加它們比在diff中混合反斜槓線要方便得多,合併。 – ndim

0

It is usually best if the target of a rule is the name of the file the rule produces.

所以compile規則:

compile: $(CFILE) 
    $(CC) -S -combine $^ -o $(APP).s 

應該是這樣的:

$(APP).s: $(CFILE) 
    $(CC) -S -combine $^ -o [email protected] 

同樣的對象規則:

%: %.s compile 
    $(AS) -o [email protected] $< 

應該是這樣的:

%.o: %.s 
    $(AS) -o [email protected] $< 

(沒有理由爲它依賴於compile$(APP).s,因爲bubble_uart.s是無關緊要的大多數對象文件)

然後目標文件的列表應該包括bubble_uart.o

SFILES = $(sort $(wildcard *.s) $(APP).s) 
OFILES = $(patsubst %.s,%.o,$(SFILES)) 

(該sort是刪除重複。)請注意,這是OBJE名單可執行文件構建所需的ct文件,而不是碰巧存在於構建過程開始時的對象文件列表。

最後,可執行文件:

$(APP): $(OFILES) 
    $(LK) -o [email protected] -T browtb.x $^ 
+0

感謝您的好解釋。 – Sajjad

+0

@Beta只是一件事,'$(APP)'也應該依賴於'browtb.x'。當然,我認爲,所有具有不平凡食譜的目標應該依賴於Makefile(s) - 但這只是我的看法,幾乎沒有人會這樣做。當改變Makefile時,人們只是乾淨和重建,這很愚蠢,但這就是我的用戶所做的,這就是他們一直所做的:) –