Makefile ist ein häufig verwendetes Dateiformat in Linux-Systemen. Es kann zur Beschreibung des Kompilierungsprozesses und der Abhängigkeiten eines Programms verwendet werden, sodass Benutzer den Befehl make problemlos zum Erstellen und Verwalten von Programmen verwenden können. Die Syntax und die Regeln von Makefile sind relativ einfach, es gibt jedoch einige Details und Sonderfälle, die beachtet werden müssen, da sonst die Kompilierung fehlschlagen oder unerwartete Ergebnisse auftreten können. Dieser Artikel stellt Ihnen einige häufige Fehler und Fallen in Linux-Makefiles vor und zeigt Ihnen, wie Sie diese vermeiden und lösen können, damit Sie Makefiles unter Linux besser verwenden und schreiben können.
Ergebnis: Der Wert der Variablen entspricht nicht dem, den Sie ihr zugewiesen haben, aber das Leerzeichen zwischen dem Wert und dem Kommentarzeichen wird der Variablen zugewiesen, wodurch die Ausführung gegen Ihren Willen erfolgt und nicht leicht zu erkennen ist.
Die Beispielbeschreibung lautet wie folgt (Makefile-Version: GNU MAKE 3.81):
TmpDir = /Source #此处随意定义了一个目录, #为了验证此陷阱,特意在赋值语句后空几格并进行注释, ifeq ($(TmpDir), /Source) Result = They are equal else Result = They are not equal endif all: @echo $(TmpDir)||||||| @echo $(Result)
make之后其结果为 : /Source ||||||| (注意:/Source与|之间的空格,其实是属于TmpDir变量的) They are not equal 若把 ifeq ($(TmpDir), /Source) 改为 ifeq ($(TmpDir), /Source ) 说明:/Source后面的空格需要跟定义TmpDir与注释符之间的空格数相等 如此一来,再次make,结果为:They are equal
Erweiterung 1: Tatsächlich führt der Überprüfungsprozess auch zu einer anderen Falle, der Falle in der ifeq()-Anweisung, siehe Falle 2
Erweiterung 2: Die Variablenzuweisungsanweisung hat diese Falle, was ist mit der Makrodefinitionsanweisung? ? und Sätze ähnlich den folgenden
CFLAGS += -DTMP=1 #注释语句 INCFLAGS += -I$(APP_COMMON_SRC_DIR)/Include #注释语句 main:mian.o gcc $$@
Tatsächlich zeigen tatsächliche Tests, dass dies keinen Einfluss auf den Wert der Makrodefinition „TMP“ in der Quelldatei sowie den Pfadwert von „INCFLAGS“ hat.
Erfahrung: Durch die obige Überprüfung wirkt sich die Annotation auf den Wert der in der Makefile-Datei definierten Variablen aus, jedoch nicht auf die Werte nach -D und -I. Daher wird empfohlen, Kommentare im Makefile nicht nach der Anweisung, sondern in der Zeile vor der Anweisung zu schreiben, um ähnliche Probleme zu vermeiden.
Die Beispielbeschreibung lautet wie folgt (Makefile-Version: GNU MAKE 3.81):
TmpDir = /Source #下方的/Source后面空了几格 ifeq ($(TmpDir), /Source ) Result = They are equal else Result = They are not equal endif all: @echo $(Result) make之后其结果为 : They are not equal 若把 ifeq ($(TmpDir), /Source ) 改为 ifeq ($(TmpDir), /Source) 如此一来,再次make,结果为:They are equal
Laut tatsächlichen Tests hat sich gezeigt, dass einige Leerzeichen nach $(TmpDir) keine Auswirkung haben, Leerzeichen nach /Source jedoch eine Auswirkung haben
Erfahrung:In Makefile ist es am besten, die Konsistenz der Parameter sicherzustellen, ob Leerzeichen usw. vorhanden sind. Es ist nicht so locker wie die Programmierung in Sprachen wie der C-Sprache.
Das Beispiel sieht ungefähr wie folgt aus:
TARGET = Temp # abspath 函数:获取其参数中的文件或者目录的绝对路径 APP_BASE = $(abspath ../..) DEV_BLD_DIR = $(APP_BASE)/$(TARGET)/Build TEMP = $(APPSRC:.c=.o) APPOBJS_TMP = $(TEMP:.S=.o) # addprefix 函数:把 APPOBJS_TMP 中的文件一一添加前缀 $(DEV_BLD_DIR)/ APPOBJS := $(addprefix $(DEV_BLD_DIR)/,$(APPOBJS_TMP)) APPDEPS_TMP = $(APPOBJS_TMP:.o=.d) APPDEPS := $(addprefix $(DEV_BLD_DIR)/,$(APPDEPS_TMP)) all: Tmp.bin -include $(APPDEPS) ...... #省略了若干内容 ...... # subst 函数:把$@中的 Source 替换成 Build # 该编译的命令,在编译源文件的同时,也生成了.d 依赖文件 $(DEV_BLD_DIR)/%.o: %.c $(info Compiling $$@) $(CFLAGS) $(INCFLAGS) $
Bitte klicken Sie hier, um zur Einführung in den Inhalt der .d-Abhängigkeitsdatei zu gelangen
Tatsächlich können wir aus den Ergebnissen grob schließen, dass ein Problem mit der .d-Abhängigkeitsdatei vorliegt, da das Umschreiben jeder Datei eine Neukompilierung erfordert, was die Funktion ist, die die .d-Abhängigkeitsdatei bieten soll.
陷阱:目标路径的问题,即同一文件目标的引用时要保持路径一致。mingw环境下,windows路径(e.g. c:\agc.o) 和 mingw路径(/c/agc.o)都能够识别,对于make而言, c:\abc.o 和 /c/abc.o 是两个不同的目标。若要是不知道这一知识要点,很难发现 .d 文件开头 c:\ 和 /c/ 的区别。(个人疑点:同一环境,不同工程,有些生成的.d依赖文件中.o目标路径和make中引用的路径是一样的,目前也不知是什么原因,总之这个陷阱还是存在的。)
实例陷阱说明:
#以下行将导入所有的.d依赖文件的内容,即以 /c/...开头的内容 -include $(APPDEPS) #而以下目标依赖关系中,指明目标的路径则是以 c:\...开头的路径 $(DEV_BLD_DIR)/%.o: %.c #其结果就是导致了因路径表示的不同,而认为不是同一目标的情况出现 #使得make不能找到.o目标文件依赖的所有依赖源文件,其中包括.h头文件 #自然而然,也就不能因为.h文件的更新,而重新编译对应的.c文件来生成.o文件
解决方法:
既然知道了陷阱所在,就可以利用如下命令来解决该问题:
#通过增加sed命令,把生成的.d依赖文件中的.o目标路径改写就可以了。 $(DEV_BLD_DIR)/%.o: %.c $(info Compiling $$@) $(CFLAGS) $(INCFLAGS) $'s,.*\.o[ :]*,$@:,g' $(DEV_BLD_DIR)/$*.d;\ rm -f $(DEV_BLD_DIR)/$*.d.tmp @echo
通过本文,你应该对 Linux Makefile 中的一些注意事项有了一个基本的了解,知道了如何避免和解决一些常见的错误和陷阱,如变量赋值、条件判断、目标文件、伪目标、自动变量等。你也应该明白了 Makefile 的作用和优点,以及如何在 Linux 下正确地使用和编写 Makefile。我们建议你在使用 Makefile 时要遵循一些规范和习惯,如使用缩进、注释、通配符等,以提高 Makefile 的可读性和可维护性。同时,我们也提醒你在使用 Makefile 时要注意一些潜在的问题和挑战,如跨平台、并行编译、递归调用等。希望本文能够帮助你更好地使用 Linux 系统,让你在 Linux 下编写出高效和优雅的 Makefile。
Das obige ist der detaillierte Inhalt vonDos and Don'ts für Linux-Makefiles: So vermeiden Sie häufige Fehler und Fallstricke. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!