所以,我有一个GNU make的项目。有时,如果我执行make all
,它会构建,但在此之后,再次构建调试符号文件 ,有时它只能正常工作并报告Nothing to be done for 'all'
。
按预期工作:
[cad@cordev kernel32]$ make clean
make -C boot clean
make[1]: Entering directory '/home/cad/Desktop/kernel/kernel32/boot'
rm -f main.o boot.o floppy_errs.o install_ints.o drivers/i8259A.o drivers/i8042o drivers/vga.o *.ld.m4
make[1]: Leaving directory '/home/cad/Desktop/kernel/kernel32/boot'
make -C kernel clean
make[1]: Entering directory '/home/cad/Desktop/kernel/kernel32/kernel'
make[1]: Nothing to be done for 'clean'.
make[1]: Leaving directory '/home/cad/Desktop/kernel/kernel32/kernel'
rm -f *.out *.img *.sym
[cad@cordev kernel32]$ make all
make -C boot all
make[1]: Entering directory '/home/cad/Desktop/kernel/kernel32/boot'
m4 ../m4/global.m4 m4/boot.m4 m4/asm.m4 ../m4/asm.m4 main.S | \
as -o main.o --32 -g
m4 ../m4/global.m4 m4/boot.m4 m4/asm.m4 ../m4/asm.m4 boot.S | \
as -o boot.o --32 -g
m4 ../m4/global.m4 m4/boot.m4 m4/asm.m4 ../m4/asm.m4 floppy_errs.S | \
as -o floppy_errs.o --32 -g
m4 ../m4/global.m4 m4/boot.m4 m4/asm.m4 ../m4/asm.m4 install_ints.S | \
as -o install_ints.o --32 -g
m4 ../m4/global.m4 m4/boot.m4 m4/asm.m4 ../m4/asm.m4 drivers/i8259A.S | \
as -o drivers/i8259A.o --32 -g
m4 ../m4/global.m4 m4/boot.m4 m4/asm.m4 ../m4/asm.m4 drivers/i8042.S | \
as -o drivers/i8042.o --32 -g
m4 ../m4/global.m4 m4/boot.m4 m4/asm.m4 ../m4/asm.m4 drivers/vga.S | \
as -o drivers/vga.o --32 -g
m4 ../m4/global.m4 m4/boot.m4 boot.ld > boot.ld.m4
ld -T boot.ld.m4 main.o boot.o floppy_errs.o install_ints.o drivers/i8259A.o drvers/i8042.o drivers/vga.o -melf_i386
make[1]: Leaving directory '/home/cad/Desktop/kernel/kernel32/boot'
objcopy --only-keep-debug boot.out boot.sym
objcopy --strip-debug --strip-unneeded boot.out
objcopy -O binary boot.out boot.img
[cad@cordev kernel32]$ make all
make: Nothing to be done for 'all'.
奇怪地工作:
[cad@cordev kernel32]$ make clean
make -C boot clean
make[1]: Entering directory '/home/cad/Desktop/kernel/kernel32/boot'
rm -f main.o boot.o floppy_errs.o install_ints.o drivers/i8259A.o drivers/i8042o drivers/vga.o *.ld.m4
make[1]: Leaving directory '/home/cad/Desktop/kernel/kernel32/boot'
make -C kernel clean
make[1]: Entering directory '/home/cad/Desktop/kernel/kernel32/kernel'
make[1]: Nothing to be done for 'clean'.
make[1]: Leaving directory '/home/cad/Desktop/kernel/kernel32/kernel'
rm -f *.out *.img *.sym
[cad@cordev kernel32]$ make all
make -C boot all
make[1]: Entering directory '/home/cad/Desktop/kernel/kernel32/boot'
m4 ../m4/global.m4 m4/boot.m4 m4/asm.m4 ../m4/asm.m4 main.S | \
as -o main.o --32 -g
m4 ../m4/global.m4 m4/boot.m4 m4/asm.m4 ../m4/asm.m4 boot.S | \
as -o boot.o --32 -g
m4 ../m4/global.m4 m4/boot.m4 m4/asm.m4 ../m4/asm.m4 floppy_errs.S | \
as -o floppy_errs.o --32 -g
m4 ../m4/global.m4 m4/boot.m4 m4/asm.m4 ../m4/asm.m4 install_ints.S | \
as -o install_ints.o --32 -g
m4 ../m4/global.m4 m4/boot.m4 m4/asm.m4 ../m4/asm.m4 drivers/i8259A.S | \
as -o drivers/i8259A.o --32 -g
m4 ../m4/global.m4 m4/boot.m4 m4/asm.m4 ../m4/asm.m4 drivers/i8042.S | \
as -o drivers/i8042.o --32 -g
m4 ../m4/global.m4 m4/boot.m4 m4/asm.m4 ../m4/asm.m4 drivers/vga.S | \
as -o drivers/vga.o --32 -g
m4 ../m4/global.m4 m4/boot.m4 boot.ld > boot.ld.m4
ld -T boot.ld.m4 main.o boot.o floppy_errs.o install_ints.o drivers/i8259A.o drvers/i8042.o drivers/vga.o -melf_i386
make[1]: Leaving directory '/home/cad/Desktop/kernel/kernel32/boot'
objcopy --only-keep-debug boot.out boot.sym
objcopy --strip-debug --strip-unneeded boot.out
objcopy -O binary boot.out boot.img
[cad@cordev kernel32]$ make all
objcopy --only-keep-debug boot.out boot.sym # HERE
[cad@cordev kernel32]$ make all
make: Nothing to be done for 'all'.
(我用# HERE
标记了相关的行。我还插入了空行以提高可读性。)
这里的事情是,这似乎是随机发生的。事实上,我给出的这两个例子是先后发生的
我注意到make clean
,make all
和make all
有时之间的较长时间导致了冗余构建步骤,而紧密地执行命令从不< / em>造成了这个。不过,我只是尝试了10倍。
makefile如下:
# Parameters passed to GNU make.
# `dbg=y|n': decides whether debugging mode is on or not.
# `sep_boot=y|n': decides whether bootloader and kernel should be seperate
# images or not.
# TODO: add functionality for these parameters
SHELL = /bin/bash
%.sym: %.out
objcopy --only-keep-debug $< $@
%.img: %.out
objcopy --strip-debug --strip-unneeded $<
objcopy -O binary $< $@
%.out:
make -C $* all
# TODO: merge run and debug targets and decide to debug or not using the dbg
# parameter.
boot_debug: boot.sym boot.img
qemu-system-i386 -fda boot.img -s -S &
gdb -x dbg.gdb
all: boot.sym boot.img #kernel.img kernel.sym
boot.sym boot.img: boot.out
kernel.sym kernel.img: kernel.out
clean:
make -C boot clean
make -C kernel clean
rm -f *.out *.img *.sym
.PHONY: boot_debug all clean
如果您想自己复制,可以下载git clone here。
那么,这里的问题是什么?附加构建步骤与命令之间传递的时间之间的相关性在哪里(或者只是错误观察)? GNU make依赖于时间戳来确定文件的最新版本......也许这与某种程度有关?
答案 0 :(得分:2)
嗯,这条规则的第一行:
%.img: %.out
objcopy --strip-debug --strip-unneeded $<
objcopy -O binary $< $@
正在修改其先决条件(boot.out
),后者会更新其时间戳。根据具体发生的时间,您拥有的文件系统类型(例如,它是否支持亚秒级时间戳等),可能是在此规则完成后,boot.out
的时间戳现在具有更新的时间戳比之前创建的boot.sym
,所以当你重新运行make时,它将决定重建boot.sym
。
您需要以不修改先决条件的方式重写此规则;也许:
%.img: %.out
objcopy --strip-debug --strip-unneeded $< $<.tmp
objcopy -O binary $<.tmp $@
rm -f $<.tmp
我不确定objcopy是否会从stdin写入stdout / read,但如果是这样,你可以使用管道代替。