Linux Makefile 中的陷阱【轉】

轉自:https://blog.csdn.net/QQ1452008/article/details/52247944

版權聲明:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/QQ1452008/article/details/52247944

前言

每個編寫過Makefile的程序員都可能遇見過Makefile中內含的陷阱,本博文旨在展現陷阱,提醒自己,也供大家一起學習。

本博文會隨所遇見的Makefile陷阱有關的問題而進行后續的更新。


陷阱一:在定義變量的語句后面空格之后使用了‘#’注釋符

結果:導致變量的值并不是你所賦值的,而是把值與注釋符之間的空格一起賦值給了變量,使得執行違背自己的意愿,而不容易察覺。

實例說明如下(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)

?

make之后其結果為 : 
/Source  |||||||      (注意:/Source與|之間的空格,其實是屬于TmpDir變量的)
They are not equal若把 
ifeq ($(TmpDir), /Source) 
改為
ifeq ($(TmpDir), /Source  )  
說明:/Source后面的空格需要跟定義TmpDir與注釋符之間的空格數相等如此一來,再次make,結果為:They are equal

擴展一:其實驗證的過程中也引申出了另一個陷阱,ifeq()語句中的陷阱,見陷阱二
擴展二 : 變量賦值語句存在這個陷阱,那宏定義語句呢?及類似于如下語句

CFLAGS  += -DTMP=1   #注釋語句
INCFLAGS += -I$(APP_COMMON_SRC_DIR)/Include #注釋語句 main:mian.o gcc $< $(CFLAGS) $(INCFLAGS) -o $@ 

?

其實經過實測表明,這樣并不會影響宏定義“TMP”在源文件中的值, 以及“INCFLAGS ”所在的路徑值。

心得: 通過以上求證,注釋符會影響到Makefile文件內部定義使用的變量的值,而不會影響到諸如 -D , -I 后面的值。所以建議Makefile中注釋都不要寫在語句后面,而是語句的前一行,來避免類似的問題出現


陷阱二:ifeq語句的括號里面,不要隨意使用空格

結果:makefile會吧參數后面的空格也當作參數的一部分來進行比較,導致結果違背自己的意愿。

實例說明如下(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

經過實測表明,$(TmpDir)后面空幾格沒有影響,唯獨/Source后面空格就會有影響了

心得 : 在Makefile中,最好保證參數的一致性,是否空格等,不像C語言等語言編程一樣,那么寬松。


陷阱三:在mingw環境下使用路徑時的陷阱

詳情:在正確使用并能生成.d依賴文件,理論上使得修改任一 .h 或者 .c 文件都能自動進行編譯的情況下,其結果偏偏就是在修改了.h文件而不能編譯與之相關的.c文件,即沒有檢查到有文件更新,從而沒有進行編譯。待仔細查看Makefile的內容,也不能輕易看出端倪。其實這背后存在一個不易察覺的陷阱。

例子大概如下:

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 $< ...) $(CC) -c -o $(subst Source,Build,$@) $(CFLAGS) $(INCFLAGS) $< -MD -MF $(DEV_BLD_DIR)/$*.d -MP

?

請點擊進入 .d依賴文件 相關內容介紹

其實從結果上便能大致推測是.d依賴文件部分出現了問題,因為改寫任一文件都要能重新編譯,本身就是.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文件

?

解決方法:
既然知道了陷阱所在,就可以利用如下命令來解決該問題:

#通過增加sed命令,把生成的.d依賴文件中的.o目標路徑改寫就可以了。
$(DEV_BLD_DIR)/%.o: %.c$(info Compiling $< ...) $(CC) -c -o $(subst Source,Build,$@) $(CFLAGS) $(INCFLAGS) $< -MD -MF $(DEV_BLD_DIR)/$*.d.tmp -MP sed 's,.*\.o[ :]*,$@:,g' < $(DEV_BLD_DIR)/$*.d.tmp > $(DEV_BLD_DIR)/$*.d;\ rm -f $(DEV_BLD_DIR)/$*.d.tmp @echo

?

心得:以后出現類似該情況,即表面上 makefile 中沒有什么問題,但在使用了依賴文件,并修改.h 文件后,不重新編譯的情況,這個時候要考慮路徑問題。不同路徑的表示方法,所表示的目標文件在make中會認為不是同一文件。

--------------------- 本文來自 Jerry_yl_ 的CSDN 博客 ,全文地址請點擊:https://blog.csdn.net/QQ1452008/article/details/52247944?utm_source=copy?

轉載于:https://www.cnblogs.com/sky-heaven/p/9735196.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/277168.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/277168.shtml
英文地址,請注明出處:http://en.pswp.cn/news/277168.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

html錨點

設置錨點的兩種方式 1.設置一個錨點鏈接<a href"#wang">去找汪星人</a> 在頁面中需要的位置設置錨點<a name"wang">汪星人基地</a> 2.設置一個錨點鏈接<a href"#miao">去找喵星人</a> 在頁面中需要的位置設…

大學生計算機課程考試試題,大學生計算機基礎課程考試系統研究與實現

摘要&#xff1a;本文主要針對教學評測領域中的主觀題評測等難點展開研究.過去在教育評測領域雖然廣泛使用測試系統,但由于無法對主觀題進行準確有效的判斷,造成了以客觀題為主的測試局限性.本課題引入智能的算法以實現全自動教學評測,對于教育測試工作有著深遠的現實意義. 本系…

初學Vue.js--數據綁定與文本插值

(一)數據雙向綁定 數據的雙向綁定是Vue.js的核心功能在上一篇記錄中已經簡單創建了一個Vue實例如下 var myVuenew Vue({ el:#myvue//myvue是已經存在的div&#xff0c;其id值為myvue }) 使用選項el掛載成功后&#xff0c;我們可以通過myVue.$el來訪問該元素&#xff0c;如果需要…

網頁色彩搭配的內涵

網頁的色彩搭配往往是網友們感到頭疼的問題&#xff0c;尤其是那些完全沒有美術基礎的網友。到底用什么色彩搭配好看呢&#xff1f;讓我們來看看網友54雨寒的高見吧&#xff01; 一、紅色的色感溫暖&#xff0c;性格剛烈而外向&#xff0c;是一種對人刺激性很強的色。紅色容易引…

VS歷程簡單記錄

當時一開始裝VS2015&#xff0c;是用了很長時間了。裝了之后是可以用的&#xff0c;打了不少代碼的。 后來很長一段時間沒用它了&#xff0c;時隔良久&#xff0c;雙擊快捷方式竟然打開不了&#xff0c;讓我“重裝”。 其實也不用重裝&#xff0c;本機用的Win10&#xff0c;去控…

計算機考研分數2019,2019考研分數線和國家線有什么關系

2019考研學校分數線和國家線有什么區別。國家線即全國碩士研究生考生進入復試基本分數要求&#xff0c;是基礎分數線&#xff0c;要有資格參加復試必須過了這條線。國家線今天大概在3月中旬公布。學校分數線(簡稱學校線)是各招生單位在國家線的基礎上&#xff0c;根據本校有關專…

記錄一次react項目配置過程

1.為什么要配置react而不是腳手架 因為要知其然,最好還要知其所以然&#xff01; 2.配置對象 webpack webpack-dev-server babel eslint 3.配置過程 1.webpack 第一步:引入必須文件 const path require("path"); const webpack require("webpack");//為了…

智能文件名排序

默認排序問題 windows排序 Windows的資源管理中&#xff0c;提供了文件名的智能排序功能&#xff0c;可以識別出文件名中數字&#xff08;數字位數不相同&#xff09;&#xff0c;然后比較數字大小進行排序&#xff0c;如下圖&#xff1a; 代碼默認排序 但在C#中的列表排序中則…

VS2005 Web Application Project啟用WSE(Ver 3.0)的方法

使用過WSE的朋友都知道&#xff0c;若要啟用Server端Projects的WSE功能&#xff0c;需要選中如下所示的兩個單選框:Enable this project for Web Services Enhancements和Enable Microsoft Web Services Enhancement Soap Protocol Factory.但是在WSE3.0中對于Web Application …

計算機英語課程背景,專家講座第十五講:信息化背景下高質量大學英語課程建設與教學設計...

11月27日下午&#xff0c;南京大學王海嘯教授應邀到我院開展題為“信息化背景下高質量大學英語課程建設與教學設計”學術講座。講座由外國語言文學學院胡元江副院長和鮑貴教授共同主持&#xff0c;學院全體教師和研究生參加了本次學術活動。王海嘯教授目前兼任教育部高等學校大…

ORA-28001: the password has expired

原創文章地址:https://blog.csdn.net/zdw_wym/article/details/38066745 Oracle提示錯誤消息 ORA-28001: the password has expired&#xff0c;是由于Oracle11G的新特性所致&#xff0c;Oracle11G創建用戶時缺省密碼過期限制是180天&#xff08;即6個月&#xff09;&#xff0…

使用c#操作IBM WebSphere MQ

IBM WebSphere MQ 5.3升級到CSD05之后&#xff0c;提供了使用.net操作MQ的類庫&#xff0c;安裝完成之后&#xff0c;會在MQ的安裝目錄的bin文件夾下面多出一個amqmdnet.dll文件&#xff0c;把這個DLL作為引用添加到你的.net工程中&#xff0c;你的.net程序中就可以操作IBM Web…

【SpringBoot】在IOC之外的類中使用IOC內部的Bean

某些時候&#xff0c;某些類是不歸IOC管的&#xff0c;如我們的一些Util&#xff0c;如何使用IOC中的Bean&#xff1f; 1、寫一個SpringUtil類&#xff0c;該類用于操縱Spring的ApplicationContext Component的注解是需要的&#xff0c;該Util是要被Spring管理的。 Component p…

計算機office二級app,計算機二級office

計算機二級office是一款為用戶提供各種計算機二級知識的軟件&#xff0c;用戶可以在應用中快速的學習計算機二級office知識&#xff0c;順利通過二級考試&#xff1b;應用擁有海量的精選計算機二級考試題庫&#xff0c;不放過每一個考題&#xff0c;讓用戶全面的學習二級知識&a…

Obj-C 實現設計模式 -- Observer

觀察者模式&#xff0c;采用氣象站的例子來說明&#xff0c;本質上跟Java來實現差不多。只不過是針對協議&#xff08;Delegate&#xff09;來編程。 簡單說下需求&#xff0c;氣象顯示版向氣象站注冊成功訂閱者&#xff08;觀察者&#xff09;&#xff0c;氣象站監測到氣溫發生…

影響員工敬業度的三大因素

敬業的員工通常業績比較突出&#xff0c;對企業做的貢獻很大。經理人當然希望自己的員工個個都是敬業的員工&#xff0c;但實際上&#xff0c;在中國只有8%的員工具有敬業精神&#xff0c;相比全球的平均水平14%還有很大的差距。 是什么因素造成員工不敬業呢&#xff1f;根據世…

cf914D. Bash and a Tough Math Puzzle(線段樹)

題意 題目鏈接 Sol 直接在線段樹上二分 當左右兒子中的一個不是\(x\)的倍數就繼續遞歸 由于最多遞歸到一個葉子節點&#xff0c;所以復雜度是對的 開始時在糾結如果一段區間全是\(x\)的兩倍是不是需要特判&#xff0c;實際上是不需要的。 可以這么想&#xff0c;如果能成功的話…

計算機答辯答不上來怎么回答,答辯答不上來怎么辦

論文答辯成為了不少同學的最后一次考試&#xff0c;從開題報告、論文定稿到格式排版大家一定都花費了大量的時間和精力&#xff0c;然而有時也會有一點小錯誤。所以&#xff0c;答辯前怎么準備&#xff0c;答辯的時候應該怎么靈活表現才能讓自己最有可能通過答辯呢&#xff1f;…

urllib2.urlopen超時問題

urllib2.urlopen超時問題 沒有設置timeout參數&#xff0c;結果在網絡環境不好的情況下&#xff0c;時常出現read()方法沒有任何反應的問題&#xff0c;程序卡死在read()方法里&#xff0c;搞了大半天&#xff0c;才找到問題&#xff0c;給urlopen加上timeout就ok了&#xff0c…

git 關聯遠程分支

問題解析&#xff1a; git本地新建一個分支后&#xff0c;必須要做遠程分支關聯。如果沒有關聯&#xff0c; git 會在下面的操作中提示你顯示的添加關聯。關聯目的是如果在本地分支下操作&#xff1a; git pull, git push &#xff0c;不需要指定在命令行指定遠程的分支&#x…