簡體   English   中英

Makefile 每次都重新編譯

[英]Makefile recompiles every time

我是 C 的初學者,一直在嘗試解決一些與 makefile 有關的大學任務。這是一個多文件項目,想法是編譯nave.c porto.c meteo.c master.c

除最后一個外,其他都需要與common_ipcsutils鏈接,並單獨編譯。 也就是說,這一切似乎都工作正常,但我的問題是,如果我多次運行兩個目標(調試或發布)中的任何一個,即使沒有任何修改,它們也會從頭開始編譯所有內容。

有任何想法嗎? 這是我的 makefile,刪除了不相關的目標。 dbg也被刪除,因為它與rls相同。


# basic rules
CC      = gcc
LDFLAGS = -lm
COMMON  = common_ipcs.c utils.c
TARGET  = master
SOURCE  = master.c nave.c porto.c meteo.c
 
# directories
DIRSRC  = source
DIRHDR  = headers
DIRDBG  = debug
DIRRLS  = release
 
# compiling flags
CFLAGS  = -std=c89
DCFLAGS = $(CFLAGS) -g -O0 -pedantic -DDEBUG
RCFLAGS = $(CFLAGS) -O2 -Wall -Wextra -DNDEBUG
 
# $< is the first prerequisite
# $@ is the target
# $^ is all the prerequisites
 
.PHONY: all prep rls dbg drun run clean
 
# build all the prerequisites for compiling the project
all: clean prep rls
 
prep:
    @mkdir -p $(DIRDBG) $(DIRRLS)
 
rls: $(addprefix $(DIRSRC)/, $(SOURCE))
    $(CC) $(RCFLAGS) $(addprefix $(DIRSRC)/, $(COMMON)) $(DIRSRC)/nave.c -o $(DIRRLS)/nave.o $(LDFLAGS)
    $(CC) $(RCFLAGS) $(addprefix $(DIRSRC)/, $(COMMON)) $(DIRSRC)/porto.c -o $(DIRRLS)/porto.o $(LDFLAGS)
    $(CC) $(RCFLAGS) $(addprefix $(DIRSRC)/, $(COMMON)) $(DIRSRC)/meteo.c -o $(DIRRLS)/meteo.o $(LDFLAGS)
    $(CC) $(RCFLAGS) $(addprefix $(DIRSRC)/, $(COMMON)) $(DIRSRC)/master.c -o $(DIRRLS)/$(TARGET) $(LDFLAGS)


幾天來我一直在弄亂這個 makefile,它經歷了難以想象的重寫,此時我什至不確定該嘗試什么。 與此迭代相關,我還嘗試刪除.PHONY ,但重新編譯沒有任何變化,因為我已經解釋過.PHONY還會強制重新編譯所有文件。 我查看了不同的類似問題,但似乎沒有一個真正適用於這個特定的 makefile 問題。

我認為您對makefile 規則是什么感到困惑。 規則由三部分組成:一個或多個目標、零個或多個先決條件以及要運行的命令配方

Make 會將每個目標的時間戳與其列出的所有先決條件進行比較,如果任何先決條件比目標更新,它將啟動一個 shell 來運行預計會使目標更新的配方

你有這個規則:

rls: $(addprefix $(DIRSRC)/, $(SOURCE))
        $(CC) $(RCFLAGS) $(addprefix $(DIRSRC)/, $(COMMON)) $(DIRSRC)/nave.c -o $(DIRRLS)/nave.o $(LDFLAGS)
        $(CC) $(RCFLAGS) $(addprefix $(DIRSRC)/, $(COMMON)) $(DIRSRC)/porto.c -o $(DIRRLS)/porto.o $(LDFLAGS)
        $(CC) $(RCFLAGS) $(addprefix $(DIRSRC)/, $(COMMON)) $(DIRSRC)/meteo.c -o $(DIRRLS)/meteo.o $(LDFLAGS)
        $(CC) $(RCFLAGS) $(addprefix $(DIRSRC)/, $(COMMON)) $(DIRSRC)/master.c -o $(DIRRLS)/$(TARGET) $(LDFLAGS)

我們暫時忽略編譯器的錯誤調用(您正在構建程序但將它們命名為.o文件,這是不正確的,或者至少不是一個好主意)。

這條規則是怎么說的? 它告訴 make 有一個名為rls的目標,它具有先決條件source/master.csource/nave.csource/porto.csource/meteo.c ,如果目標rls已過期它應該運行一個由編譯器的四次調用組成的配方,編譯器將創建四個不同的程序:三個名為release/nave.orelease/porto.orelease/meteo.o ,最后一個名為release/master

因此,make 盡職盡責地檢查磁盤上名為rls的文件的時間戳,該文件不存在,因此永遠不會被認為是最新的,並且由於它已過時,它會運行調用所有四個編譯行的配方。 每次。

當您編寫makefile規則時,您應該遵循以下規則:(a) 每個配方都應該只構建一個目標,不能超過一個; (b) 規則的目標名稱必須是配方創建的文件的確切名稱:如果配方創建了一個名為blahblah.o的文件,那么規則的目標必須是blahblah.o 如果配方創建了一個名為some/other/dir/foo的文件,那么規則的目標必須是some/other/dir/foo

當您在 makefile 方面做得更好時,您會意識到有時違反這些規則是有用的,也是個好主意。 但這些都是一個很好的起點。

暫無
暫無

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

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