从 3.81 升级到 4.3 后,我遇到了奇怪的行为。 这个 makefile 描述了使用较旧的 GNU 语法构建静态库:
make
LIBNAME = testlib.a
OBJ_FILES = \
$(LIBNAME)(test1.o) \
$(LIBNAME)(test2.o)
all: $(LIBNAME)
$(LIBNAME): $(OBJ_FILES)
$(RANLIB) $@
4.3的行为是始终生成lib,无论源文件是否已更改。 在
make
的输出中,似乎 make -p
正在执行隐式规则并在目录中搜索 make
和 test1.o
,但由于它们不在那里,它会从源生成新的它们,并用 添加它们test2.o
命令,然后将它们从目录中删除。在版本3.81中,它直接在ar
中检查
testlib.a
,如果找到则不执行其他规则。那么这个 makefile 必须重写吗?还是有其他可能获得旧的行为?
编辑:
现在在另一个 Linux Mint 系统上进行测试,使用 GNU
test1.o
4.3,具有相同的行为。
make
的已清理输出:
make -p
这两种情况之间的唯一区别是cc -c -o test1.o test1.c
ar rv testlib.a test1.o
r - test1.o
cc -c -o test2.o test2.c
ar rv testlib.a test2.o
r - test2.o
rm test1.o test2.o
# GNU Make 4.3
# Gebaut für x86_64-pc-linux-gnu
# Copyright (C) 1988-2020 Free Software Foundation, Inc.
# Lizenz GPLv3+: GNU GPL Version 3 oder später <http://gnu.org/licenses/gpl.html>
# Dies ist freie Software: Sie können sie nach Belieben ändern und weiter verteilen.
# Soweit es die Gesetze erlauben gibt es KEINE GARANTIE.
# „Make“-Datenbank; erstellt am: Wed Jan 24 19:47:38 2024
testlib.a(test2.o): test2.o
# Die Suche nach impliziten Regeln wurde durchgeführt.
# Wurzel impliziter/statischer Muster: „test2.o“
# Die Datei existiert nicht.
# Datei wurde aktualisiert.
# Erfolgreich aktualisiert.
# automatisch
# @ := testlib.a
# automatisch
# * := test2.o
# automatisch
# < := test2.o
# automatisch
# + := test2.o
# automatisch
# % := test2.o
# automatisch
# ^ := test2.o
# automatisch
# ? := test2.o
# automatisch
# | :=
# Hashtabellen-Statistik für Variablen:
# Load=8/32=25%, Rehash=0, Kollisionen=2/24=8%
# Auszuführende Regel (eingebaut):
$(AR) $(ARFLAGS) $@ $<
test1.o: test1.c
# Die Suche nach impliziten Regeln wurde durchgeführt.
# Wurzel impliziter/statischer Muster: „test1“
# Datei ist ein Zwischenschritt in den Abhängigkeiten.
# Zuletzt geändert 2024-01-24 19:47:38.902846541
# Datei wurde aktualisiert.
# Erfolgreich aktualisiert.
# automatisch
# @ := test1.o
# automatisch
# * := test1
# automatisch
# < := test1.c
# automatisch
# + := test1.c
# automatisch
# % :=
# automatisch
# ^ := test1.c
# automatisch
# ? := test1.c
# automatisch
# | :=
# Hashtabellen-Statistik für Variablen:
# Load=8/32=25%, Rehash=0, Kollisionen=2/19=11%
# Auszuführende Regel (eingebaut):
$(COMPILE.c) $(OUTPUT_OPTION) $<
testlib.a(test1.o): test1.o
# Die Suche nach impliziten Regeln wurde durchgeführt.
# Wurzel impliziter/statischer Muster: „test1.o“
# Die Datei existiert nicht.
# Datei wurde aktualisiert.
# Erfolgreich aktualisiert.
# automatisch
# @ := testlib.a
# automatisch
# * := test1.o
# automatisch
# < := test1.o
# automatisch
# + := test1.o
# automatisch
# % := test1.o
# automatisch
# ^ := test1.o
# automatisch
# ? := test1.o
# automatisch
# | :=
# Hashtabellen-Statistik für Variablen:
# Load=8/32=25%, Rehash=0, Kollisionen=2/24=8%
# Auszuführende Regel (eingebaut):
$(AR) $(ARFLAGS) $@ $<
# Dies ist kein Ziel:
test2.c:
# Die Suche nach impliziten Regeln wurde durchgeführt.
# Zuletzt geändert 2024-01-24 19:41:32.093558001
# Datei wurde aktualisiert.
# Erfolgreich aktualisiert.
# Dies ist kein Ziel:
.a:
# Eingebaute Regel
# Die Suche nach impliziten Regeln wurde nicht durchgeführt.
# Zeit der letzten Änderung wurde nicht überprüft.
# Datei wurde nicht aktualisiert.
all: testlib.a
# Die Suche nach impliziten Regeln wurde durchgeführt.
# Die Datei existiert nicht.
# Datei wurde aktualisiert.
# Erfolgreich aktualisiert.
# Hashtabellen-Statistik für Variablen:
# Load=0/32=0%, Rehash=0, Kollisionen=0/28=0%
test2.o: test2.c
# Die Suche nach impliziten Regeln wurde durchgeführt.
# Wurzel impliziter/statischer Muster: „test2“
# Datei ist ein Zwischenschritt in den Abhängigkeiten.
# Zuletzt geändert 2024-01-24 19:47:38.930846181
# Datei wurde aktualisiert.
# Erfolgreich aktualisiert.
# automatisch
# @ := test2.o
# automatisch
# * := test2
# automatisch
# < := test2.c
# automatisch
# + := test2.c
# automatisch
# % :=
# automatisch
# ^ := test2.c
# automatisch
# ? := test2.c
# automatisch
# | :=
# Hashtabellen-Statistik für Variablen:
# Load=8/32=25%, Rehash=0, Kollisionen=2/19=11%
# Auszuführende Regel (eingebaut):
$(COMPILE.c) $(OUTPUT_OPTION) $<
# Dies ist kein Ziel:
test1.c:
# Die Suche nach impliziten Regeln wurde durchgeführt.
# Zuletzt geändert 2024-01-24 19:41:09.466140573
# Datei wurde aktualisiert.
# Erfolgreich aktualisiert.
testlib.a: testlib.a(test1.o) testlib.a(test2.o)
# Die Suche nach impliziten Regeln wurde durchgeführt.
# Zuletzt geändert 2024-01-24 19:47:38.93484613
# Datei wurde aktualisiert.
# Erfolgreich aktualisiert.
# Hashtabellen-Statistik für Variablen:
# Load=0/32=0%, Rehash=0, Kollisionen=0/28=0%
的版本吗?也就是说,您是在具有两个不同版本的
make
的同一系统上运行它,还是在具有不同版本的操作系统和/或编译器的两个不同系统上运行它?我敢打赌,除了使用不同版本的 make
之外,您还使用了不同版本的 binutils。
在过去 10 年左右的某个时刻,有人想到了一个令人惊讶的好主意(不是!),即make
程序的默认行为应该改变 50 年来的状态,并使其“确定性” 。现在,我完全支持可重现的构建,但这应该是一种选择加入功能,而不是选择退出功能,特别是因为在
ar
中启用“确定性模式”完全破坏了 make 管理档案的能力。如果您希望它起作用,您将必须手动禁用确定性模式。尝试添加:
ar
看看它是否能解决问题。
顺便说一句,在上面的 makefile 示例中,您忘记定义
ARFLAGS += -U
,因此它无法工作(该变量不是 GNU Make 的内置变量)。