简体   繁体   English

Makefile 每次都重新编译

[英]Makefile recompiles every time

I'm a beginner with C and have been trying to tackle a few university tasks in regards to the makefile. It's a multi-file project and the idea is to compile nave.c porto.c meteo.c .我是 C 的初学者,一直在尝试解决一些与 makefile 有关的大学任务。这是一个多文件项目,想法是编译nave.c porto.c meteo.c and master.c .master.c

All but the last need to be linked with common_ipcs and utils and are separately compiled.除最后一个外,其他都需要与common_ipcsutils链接,并单独编译。 That said this all seems to work fine and all but my issue is that if I run any of the two target (debug or release) multiple times, they keep compiling everything from scratch even though nothing had been modified.也就是说,这一切似乎都工作正常,但我的问题是,如果我多次运行两个目标(调试或发布)中的任何一个,即使没有任何修改,它们也会从头开始编译所有内容。

Any ideas?有任何想法吗? Here's my makefile with the not relevant targets removed.这是我的 makefile,删除了不相关的目标。 dbg is also removed as it is identical to rls . 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)


I've been messing with this makefile for days, it has gone through an inconceivable amount of rewrites and at this point I am not even sure what to try anymore.几天来我一直在弄乱这个 makefile,它经历了难以想象的重写,此时我什至不确定该尝试什么。 Relevant to this iteration, I've also tried to remove .PHONY , without any change in the recompilation as I had been explained that .PHONY also forces recompilation of all files.与此迭代相关,我还尝试删除.PHONY ,但重新编译没有任何变化,因为我已经解释过.PHONY还会强制重新编译所有文件。 I've looked at different similar questions posted and none really seem to be applicable to this specific makefile issue.我查看了不同的类似问题,但似乎没有一个真正适用于这个特定的 makefile 问题。

I think you're confused about what a makefile rule is.我认为您对makefile 规则是什么感到困惑。 A rule consists of three parts: one or more targets , zero or more prerequisites , and a recipe of commands to run.规则由三部分组成:一个或多个目标、零个或多个先决条件以及要运行的命令配方

Make will compare timestamps of each target to all its listed prerequisites , and if any prerequisite is newer than the target, it will start a shell to run the recipe which is expected to bring the target up to date. Make 会将每个目标的时间戳与其列出的所有先决条件进行比较,如果任何先决条件比目标更新,它将启动一个 shell 来运行预计会使目标更新的配方

You have this rule:你有这个规则:

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)

We will ignore, for the moment, the incorrect invocation of the compiler (you are building programs but naming them as .o files which is not right, or at least not a good idea).我们暂时忽略编译器的错误调用(您正在构建程序但将它们命名为.o文件,这是不正确的,或者至少不是一个好主意)。

What does this rule say?这条规则是怎么说的? It tells make that there is a target named rls and it has the prerequisites source/master.c , source/nave.c , source/porto.c , and source/meteo.c , and that if the target rls is out of date it should run a recipe consisting of four invocations of the compiler which will create four different programs: three named release/nave.o , release/porto.o , release/meteo.o , and finally one named release/master .它告诉 make 有一个名为rls的目标,它具有先决条件source/master.csource/nave.csource/porto.csource/meteo.c ,如果目标rls已过期它应该运行一个由编译器的四次调用组成的配方,编译器将创建四个不同的程序:三个名为release/nave.orelease/porto.orelease/meteo.o ,最后一个名为release/master

So, make dutifully checks the timestamp of a file on your disk named rls , which doesn't exist so it can never be considered up to date, and since it's out of date it runs the recipe which invokes all four of those compile lines.因此,make 尽职尽责地检查磁盘上名为rls的文件的时间戳,该文件不存在,因此永远不会被认为是最新的,并且由于它已过时,它会运行调用所有四个编译行的配方。 Every time.每次。

When you write a makefile rule you should follow these rules: (a) each recipe should build EXACTLY ONE target, never more than one;当您编写makefile规则时,您应该遵循以下规则:(a) 每个配方都应该只构建一个目标,不能超过一个; and (b) the target name of the rule must be the exact name of the file that the recipe creates: if the recipe creates a file named blahblah.o , then the target of the rule must be blahblah.o . (b) 规则的目标名称必须是配方创建的文件的确切名称:如果配方创建了一个名为blahblah.o的文件,那么规则的目标必须是blahblah.o If the recipe creates a file named some/other/dir/foo then the target of the rule must be some/other/dir/foo .如果配方创建了一个名为some/other/dir/foo的文件,那么规则的目标必须是some/other/dir/foo

When you get better at makefiles you'll realize that there are times when it's useful and a good idea to violate these rules.当您在 makefile 方面做得更好时,您会意识到有时违反这些规则是有用的,也是个好主意。 But these are a good starting point.但这些都是一个很好的起点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM