如何将一个独立的Makefile目标设为另一个目标的依赖,并在选项改变时重新构建

编程语言 2026-07-11

我创建了一个有多个目标的makefile,将从另一个脚本调用。一个目标依赖于一个选项文件。选项文件依赖于一个空的FORCE目标,它的配方会检查传入的选项是否发生变化。只有在确实变化时,选项文件才会更新。其意图是在传入的选项发生变化时重新构建所有受影响的文件。

以下是表示主源文本的文件,main.asm

    section code  
incbin "help1.txt"  
incbin "help2.txt"  
incbin "help3.txt"

下面是三个帮助模块,help/help1.asm

%ifdef OPTION  
    db "Good",13,10  
%else  
    db "Bad",13,10  
%endif

help/help2.asm

%ifdef OPTION  
    db "Good quux",13,10  
%else  
    db "Bad quux",13,10  
%endif

以及help/help3.asm

%ifdef OPTION  
    db "Good baz",13,10  
%else  
    db "Bad baz",13,10  
%endif

这是我的两个独立目标的makefile,helptxtmain.bin

NASM?=nasm  

HELPSOURCES = $(wildcard help/*.asm)  
HELPTXT = $(patsubst help/%.asm,%.txt,$(HELPSOURCES))  

all: main.bin  

clean:  
    rm -f *.bin *.txt *.lst  

.SUFFIXES: .bin .asm .txt  

option: FORCE  
    @echo $(OPTIONS) > option.new  
    @diff -Nq option option.new \  
      || cp -a option.new option  

FORCE:  

helptxt: $(HELPTXT)  

%.txt: help/%.asm option  
    $(NASM) $(OPTIONS) help/$*.asm -o $*.txt -fbin  

%.bin: %.asm  
    $(NASM) $*.asm -l $*.lst -o $*.bin -fbin

以下是从干净状态重新构建的预期用法:

test$ make clean  
rm -f *.bin *.txt *.lst  
test$ make helptxt OPTIONS=-DOPTION  
Files option and option.new differ  
nasm -DOPTION help/help1.asm -o help1.txt -fbin  
nasm -DOPTION help/help2.asm -o help2.txt -fbin  
nasm -DOPTION help/help3.asm -o help3.txt -fbin  
test$ make  
nasm main.asm -l main.lst -o main.bin -fbin  
test$ cat main.bin  
Good  
Good quux  
Good baz

在本示例中,分别构建 helptxtall 目标可以正常工作。然而,如果我们修改其中一个帮助文件,但未检测到 main.bin 需要重新构建,效果就不会按预期进行:

test$ touch help/help1.asm  
test$ make helptxt OPTIONS=-DOPTION  
nasm -DOPTION help/help1.asm -o help1.txt -fbin  
test$ make  
make: Nothing to be done for 'all'.

现在 main.bin 已经过时。因此,我们希望将.txt文件添加为 main.bin 的依赖项。看起来很简单,在makefile中加入以下内容:

ifeq ($(EXTERNALHELPTARGET),helptxt)  
main.bin: $(HELPTXT)  
endif

因此现在我们重新尝试,设定变量使其依赖于.txt文件:

test$ touch help/help1.asm  
test$ make helptxt OPTIONS=-DOPTION  
nasm -DOPTION help/help1.asm -o help1.txt -fbin  
test$ EXTERNALHELPTARGET=helptxt make  
Files option and option.new differ  
nasm  help/help1.asm -o help1.txt -fbin  
nasm  help/help2.asm -o help2.txt -fbin  
nasm  help/help3.asm -o help3.txt -fbin  
nasm main.asm -l main.lst -o main.bin -fbin  
test$ cat main.bin  
Bad  
Bad quux  
Bad baz

发生了什么?第二次make运行重新构建了所有帮助文件,现在得到的是错误的内容。也就是说选项开关没有被正确传递。

这个问题在我把一些脚本转换为 [我的86-DOS调试器项目,lDebug](带一个小写字母L)时出现。新的makefile包含 [helptxt和 helphlz目标],它们等价于本例中的 helptxt。选项文件 [名为optionlz],并接收变量 $(LZEXEDAT_L_SWITCH),该变量在生成lzexedat压缩的帮助文件的配方中使用。需要依赖这些帮助文件的文件是 msg.obj

解决方案

解决方法是在调用 make 时,总是为 helptxt 目标传递选项开关。如果与 helptxt 相同的文件是 main.bin 的前提条件,那么在第二次 make 运行时也会执行强制选项检查;如果发现选项不同(例如为空字符串),它将导致以错误的选项状态重建所有.txt文件。

将.txt文件选项开关传递给第二次 make 调用即可解决。以下是在该问题最后一次运行之后的立即一次运行:

test$ make helptxt OPTIONS=-DOPTION  
Files option and option.new differ  
nasm -DOPTION help/help1.asm -o help1.txt -fbin  
nasm -DOPTION help/help2.asm -o help2.txt -fbin  
nasm -DOPTION help/help3.asm -o help3.txt -fbin  
test$ EXTERNALHELPTARGET=helptxt make OPTIONS=-DOPTION  
nasm main.asm -l main.lst -o main.bin -fbin  
test$ cat main.bin  
Good  
Good quux  
Good baz  
test$

为了证明只有 help1.txtmain.bin 在修改单个文件 help/help1.asm 时会重新构建,下面给出另一组传入正确选项的运行:

test$ touch help/help1.asm  
test$ make helptxt OPTIONS=-DOPTION  
nasm -DOPTION help/help1.asm -o help1.txt -fbin  
test$ EXTERNALHELPTARGET=helptxt make OPTIONS=-DOPTION  
nasm main.asm -l main.lst -o main.bin -fbin  
test$ cat main.bin  
Good  
Good quux  
Good baz  
test$

实现正确顺序的 make 命令的实际项目修订位于 https://hg.pushbx.org/ecm/ldebug/rev/df5bf9cf492a

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章