Rumah > Tutorial sistem > LINUX > Linux Makefile Dos and Don't: Cara Mengelakkan Kesilapan dan Kesalahan Biasa

Linux Makefile Dos and Don't: Cara Mengelakkan Kesilapan dan Kesalahan Biasa

WBOY
Lepaskan: 2024-02-11 12:12:12
ke hadapan
898 orang telah melayarinya

Makefile ialah format fail yang biasa digunakan dalam sistem Linux. Ia boleh digunakan untuk menerangkan proses penyusunan dan kebergantungan program, membolehkan pengguna menggunakan arahan make dengan mudah untuk membina dan mengurus program. Sintaks dan peraturan Makefile agak mudah, tetapi terdapat beberapa butiran dan kes khas yang perlu diberi perhatian, jika tidak, kompilasi mungkin gagal atau hasil yang tidak dijangka mungkin berlaku. Artikel ini akan memperkenalkan anda kepada beberapa ralat dan perangkap biasa dalam Linux Makefiles, dan cara mengelakkan dan menyelesaikannya, supaya anda boleh menggunakan dan menulis Makefiles dengan lebih baik di bawah Linux.

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


Perangkap 1: Watak komen ‘#’ digunakan selepas ruang selepas pernyataan yang mentakrifkan pembolehubah

Keputusan: Nilai pembolehubah bukanlah apa yang anda tetapkan, tetapi ruang antara nilai dan aksara ulasan diperuntukkan kepada pembolehubah, menjadikan pelaksanaan bertentangan dengan kehendak anda dan tidak mudah dikesan.

Penerangan contoh adalah seperti berikut (versi Makefile: 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)
Salin selepas log masuk
make之后其结果为 : 
/Source  |||||||      (注意:/Source与|之间的空格,其实是属于TmpDir变量的)
They are not equal

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

如此一来,再次make,结果为:They are equal
Salin selepas log masuk

Sambungan 1: Malah, proses pengesahan juga membawa kepada perangkap lain, perangkap dalam pernyataan ifeq(), lihat perangkap 2
Sambungan 2: Pernyataan penugasan berubah mempunyai perangkap ini, bagaimana pula dengan pernyataan definisi makro ? dan ayat yang serupa dengan yang berikut

CFLAGS  += -DTMP=1   #注释语句
INCFLAGS += -I$(APP_COMMON_SRC_DIR)/Include   #注释语句

main:mian.o
    gcc $$@ 
Salin selepas log masuk

Malah, ujian sebenar menunjukkan bahawa ini tidak akan menjejaskan nilai definisi makro "TMP" dalam fail sumber, serta nilai laluan "INCFLAGS".

Pengalaman: Melalui pengesahan di atas, anotasi akan mempengaruhi nilai pembolehubah yang ditakrifkan di dalam fail Makefile, tetapi tidak akan menjejaskan nilai selepas -D dan -I. Oleh itu, adalah disyorkan bahawa ulasan dalam Makefile tidak harus ditulis selepas pernyataan, tetapi dalam baris sebelum pernyataan, untuk mengelakkan masalah yang sama.


Perangkap 2: Jangan gunakan ruang dalam kurungan pernyataan ifeq

Keputusan: Makefile akan menganggap ruang selepas parameter sebagai sebahagian daripada parameter untuk perbandingan, menyebabkan keputusan bertentangan dengan kehendak anda.

Penerangan contoh adalah seperti berikut (versi Makefile: 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
Salin selepas log masuk

Menurut ujian sebenar, telah ditunjukkan bahawa beberapa ruang selepas $(TmpDir) tidak mempunyai kesan, tetapi ruang selepas /Source akan memberi kesan

Pengalaman:

Dalam Makefile, yang terbaik adalah memastikan ketekalan parameter, sama ada terdapat ruang, dll. Ia tidak longgar seperti pengaturcaraan dalam bahasa seperti bahasa C.


Perangkap 3: Perangkap apabila menggunakan laluan dalam persekitaran mingw

Butiran: Apabila digunakan dengan betul dan dapat menjana fail kebergantungan .d, secara teori, pengubahsuaian mana-mana fail .h atau .c boleh dikompil secara automatik, tetapi hasilnya ialah fail .h tidak boleh disusun selepas pengubahsuaian .c fail, iaitu, tiada kemas kini fail dikesan, dan oleh itu kompilasi tidak dilakukan. Selepas melihat dengan teliti kandungan Makefile, petunjuk tidak dapat dilihat dengan mudah. Sebenarnya, ada perangkap di sebalik ini yang tidak mudah untuk dikesan.

Contohnya lebih kurang seperti berikut:

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) $
Salin selepas log masuk

Sila klik untuk memasukkan pengenalan kandungan berkaitan fail dependency .d

Malah, daripada keputusan, kita boleh membuat kesimpulan secara kasar bahawa terdapat masalah dengan fail dependency .d, kerana menulis semula mana-mana fail memerlukan penyusunan semula, iaitu fungsi yang sepatutnya diberikan oleh fail dependency .d.

陷阱:目标路径的问题,即同一文件目标的引用时要保持路径一致。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文件
Salin selepas log masuk

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

#通过增加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
Salin selepas log masuk

通过本文,你应该对 Linux Makefile 中的一些注意事项有了一个基本的了解,知道了如何避免和解决一些常见的错误和陷阱,如变量赋值、条件判断、目标文件、伪目标、自动变量等。你也应该明白了 Makefile 的作用和优点,以及如何在 Linux 下正确地使用和编写 Makefile。我们建议你在使用 Makefile 时要遵循一些规范和习惯,如使用缩进、注释、通配符等,以提高 Makefile 的可读性和可维护性。同时,我们也提醒你在使用 Makefile 时要注意一些潜在的问题和挑战,如跨平台、并行编译、递归调用等。希望本文能够帮助你更好地使用 Linux 系统,让你在 Linux 下编写出高效和优雅的 Makefile。

Atas ialah kandungan terperinci Linux Makefile Dos and Don't: Cara Mengelakkan Kesilapan dan Kesalahan Biasa. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:lxlinux.net
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan