Heim > System-Tutorial > LINUX > Hauptteil

Dos and Don'ts für Linux-Makefiles: So vermeiden Sie häufige Fehler und Fallstricke

WBOY
Freigeben: 2024-02-11 12:12:12
nach vorne
849 Leute haben es durchsucht

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.

Linux Makefile 的注意事项:如何避免常见的错误和陷阱


Falle 1: Das Kommentarzeichen „#“ wird nach dem Leerzeichen nach der Anweisung verwendet, die die Variable definiert

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)
Nach dem Login kopieren
make之后其结果为 : 
/Source  |||||||      (注意:/Source与|之间的空格,其实是属于TmpDir变量的)
They are not equal

若把 
ifeq ($(TmpDir), /Source) 
改为
ifeq ($(TmpDir), /Source  )  
说明:/Source后面的空格需要跟定义TmpDir与注释符之间的空格数相等

如此一来,再次make,结果为:They are equal
Nach dem Login kopieren

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 $$@ 
Nach dem Login kopieren

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.


Falle 2: Verwenden Sie keine Leerzeichen willkürlich in den Klammern der ifeq-Anweisung

Ergebnis: Das Makefile behandelt die Leerzeichen nach den Parametern als Teil der Vergleichsparameter, was dazu führt, dass die Ergebnisse Ihren Wünschen widersprechen.

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
Nach dem Login kopieren

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.


Falle 3: Fallen bei der Verwendung von Pfaden in einer Mingw-Umgebung

Details: Bei korrekter Verwendung und Möglichkeit zur Generierung von .d-Abhängigkeitsdateien kann theoretisch jede Änderung einer .h- oder .c-Datei automatisch kompiliert werden. Das Ergebnis ist jedoch, dass die .h-Datei nach der Änderung nicht kompiliert werden kann Datei, d. h. es wurden keine Dateiaktualisierungen erkannt und die Kompilierung wurde daher nicht durchgeführt. Nach sorgfältiger Betrachtung des Inhalts des Makefiles sind die Hinweise nicht leicht zu erkennen. Tatsächlich steckt dahinter eine Falle, die nicht leicht zu erkennen ist.

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) $
Nach dem Login kopieren

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文件
Nach dem Login kopieren

解决方法:
既然知道了陷阱所在,就可以利用如下命令来解决该问题:

#通过增加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
Nach dem Login kopieren

通过本文,你应该对 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!

Quelle:lxlinux.net
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage