簡體   English   中英

Makefile每次編譯

[英]Makefile compiling every time

我剛剛開始在我的大學學習C編程語言。 我們有一個任務是創建一個使用可執行程序的Makefile(在我的情況下是戰斗),並且僅在必要時編譯。 我的問題是,每次我使用make命令時它都會編譯,並且它不會像我想的那樣顯示“是最新的”。 我有兩個要編譯的對象(quest.o和thorgrim.o,只有quest.o必須創建,因為我們已經有thorgrim.o已經進入“戰斗”)。 這是我的代碼:

CC=gcc
EXE=battle
CFLAGS=-Wall

build: run
run: quest.o
     $(CC) $^ thorgrim.o -o $(EXE)
     ./$(EXE)
quest.o: quest.c
     $(CC) -c $^ -o $@
clean: rm -rf quest.o $(EXE)

我究竟做錯了什么? 如果我不接觸quest.c,我希望它編譯一次,然后顯示最新版本。

看到你是新手,我將引導你完成它,這樣你就可以學會在第一時間做到這一點。 有很多小細節,很多人最終都失蹤了,所以希望這會給你一個很好的參考:

首先,讓我們從定義對象開始

OBJS := quest.o thorgrim.o

您現在可以創建一個模式規則:

%.o: %.c
     $(CC) $(CFLAGS) -MD -MP $< -c -o $@

此規則的第一行%.o:%.c表示以.o結尾的任何內容都取決於具有以.c結尾的相同名稱的文件。 這樣做可以防止您為每個目標文件編寫單獨的規則。 請注意,此效果有一個默認模式規則,但我們不會在此處討論。

接下來,用$(CFALGS)調用$(CC) $(CFALGS) 請注意, $@ now表示要生成的.o文件的名稱, $<表示對象的第一個依賴項(在本例中為.c文件)。

-MD-MP用於自動生成依賴文件 - 對於每個.c文件,它還將創建一個.d文件,該文件列出了源需要構建的依賴項( .h文件)。 你必須-include的相關文件為它工作。 (有關這些內容的更多詳細信息,請參閱https://gcc.gnu.org/onlinedocs/gcc-4.3.1/gcc/Preprocessor-Options.html )。 這樣,如果修改頭文件,它將自動重建必要的.o文件。 話雖如此,您必須在makefile中包含這些.d文件:

-include $(OBJS:.o=.d)

這將包括.d文件,就像有人將代碼剪切並粘貼到您的makefile中一樣。 $(OBJS:.o=.d)只是告訴make獲取變量OBJS並用.d替換所有.o 請注意-在包含之前。 這告訴不要擔心文件是否不存在(就像你第一次構建的情況一樣......)。

好的,既然您已經構建了.o文件,那么您需要構建您的程序:

$(EXE): $(OBJS)
    $(CC) $^ -o $@

添加默認規則和評論,您就完成了。 因此,總之,您的makefile將類似於:

CC:=gcc
EXE:=battle
CFLAGS:=-Wall
OBJS:=quest.o thorgrim.o

%.o: %.c
     $(CC) $(CFLAGS) -MD -MP $< -c -o $@

$(EXE): $(OBJS)
    $(CC) $^ -o $@

clean:
    rm -f $(OBJS) $(EXE)

-include $(OBJS:.o=.d)

編輯:忘了干凈的規則 - 添加。

運行目標依賴於文件,但構建規則不會生成名為“run”的文件。 更好的想法是沿着這些方向做一些事情:

run: $(EXE)
     ./$(EXE)

$(EXE): $(OBJ)
       $(CC) $(CFLAGS) -o $@ $+ 

你做得不好。
這是一個“Makefile模板”:

CC=gcc
none: prog  #`make` -> `make prog`

#make's default rules are fine here.
prog: foo.o bar.o

foo.o: foo.c head.h

bar.o: bar.c head.h

編輯 :您需要使用whatever.o沒有 whatever的目標文件,所以要知道通過-c

編輯:添加$(EXE)作為run目標的依賴項

以下makefile顯示了它應該如何編寫

生成任何宏時,那些結果內容不會改變,總是使用:=而不是=所以宏只被評估一次

為可執行文件生成宏時,始終包含可執行文件的完整路徑,因此無論系統和/或環境“PATH”的其他更改如何,都始終執行正確的可執行文件。

注意:但是,要在可執行文件中包含多個文件,為了能夠在文件之間進行通信,每個源文件應該有一個頭文件,這些內容需要公開(數據和函數以及數據類型)那么這些頭文件需要在編譯時列在依賴項中。

CC := /usr/lib/gcc
RM := /usr/lib/rm -f -r

EXE := battle
CFLAGS := -Wall -Wextra -Wconversion -std=gnu99 -c

# macro with all the source names
SRCS := thorgrim.c quest.c

# macro with all the object file names
OBJS := $(SRCS:.c=.o)

# always include a .PHONY statement for any targets
# that do not produce a file of the same name
.PHONY : all clean run

# 'all' is the typical first target
all: run

# implied compile rule/recipe
%.o:%.c
<tab>$(CC) $(CFLAGS) -o $@ $<

# the macro 'LFLAGS' is part of the default macros
# link the objects into an executable
$(EXE): $(OBJS)
<tab>$(CC) $^ -o $@ $(LFLAGS)

# execute the executable
run: $(EXE)
<tab>./$(EXE)


clean: 
<tab>$(RM) quest.o $(EXE)

注意:將<tab>替換為實際的制表符

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM