首页 > 解决方案 > 为什么makefile强制覆盖目标

问题描述

我需要通过这种方式调用 make:

bin ?= bar                                                                      

all: ${bin}                                                                     

objects := 1.o 2.o                                                              

$(objects): %.o: ./%.cpp                                                        
▸   g++ -c  $< -o $@                                                            

foo: FORCE                                                                      
▸   bin=foo\                                                                    
▸   ▸   $(MAKE)·                                                                

${bin}: ${objects}                                                              
▸   g++  ${objects} -o ${bin}                                                  

FORCE:

即默认目标是 bar,但 foo 目标再次调用 make 并使用 bin=foo 变量。问题是当目标 foo 被覆盖时(在第二次调用期间)它总是运行(链接)如果我使用另一个目标名称可以避免这种情况:

foo_bla_bla: FORCE                                                                      
▸   bin=foo\                                                                    
▸   ▸   $(MAKE)

在这种情况下, foo 文件将仅在目标文件发生变化时才被链接(对,我需要)。但是我需要为此目标使用相同的名称来调用 make foo 并通过这种方式获取 foo bin。那么为什么覆盖 foo 目标需要伪造链接呢?

标签: c++makefile

解决方案


您不会通过丢弃有关目标的完整信息来覆盖目标。您正在覆盖目标的配方:丢弃旧配方并用新配方替换它。您将收到关于此的警告(最好在您的问题中显示这一点)。

目标的先决条件foo仍然保留,因此FORCE第一个目标的先决条件foo仍然存在。因此,foo目标总是被重建。

这不是处理这个问题的好方法。更好一点的是检查的值,bin如果不是,则只定义递归目标foo

ifneq ($(bin),foo)
foo: FORCE
▸   $(MAKE) bin=foo
endif

但比这更好的是根本不使用递归。你为什么需要它?为什么不直接说:

bar foo: ${objects}
▸   g++  ${objects} -o ${bin}

推荐阅读