Makefile中的變量

Makefile中的變量
2007-11-03 12:03

Makefile中變量有以下幾個特征:

1. Makefile中變量和函數的展開(除規則命令行中的變量和函數以外),是在make讀取makefile文件時進行的,這里的變量包括了使用“=”定義和使用指示符“define”定義的。

2. 變量可以用來代表一個文件名列表、編譯選項列表、程序運行的選項參數列表、搜索源文件的目錄列表、編譯輸出的目錄列表和所有我們能夠想到的事物。

3. 變量名是不包括“:”、“#”、“=”、前置空白和尾空白的任何字符串。

4. 變量名是大小寫敏感的。推薦的做法是在對于內部定義定義的一般變量(例如:目標文件列表objects)使用小寫方式,而對于一些參數列表(例如:編譯選項CFLAGS)采用大寫方式。

5. 另外有一些變量名只包含了一個或者很少的幾個特殊的字符(符號)。稱它們為自動化變量。像“$<”、“$@”、“$?”、“$*”等。

(1) 變量的引用

??????Makefile中在對一些簡單變量的引用,我們也可以不使用“()”和“{}”來標記變量名,而直接使用“$x”的格式來實現,此種用法僅限于變量名為單字符的情況。另外自動化變量也使用這種格式。對于一般多字符變量的引用必須使用括號了標記,否則make將把變量名的首字母作為作為變量而不是整個字符串(“$PATH”在Makefile中實際上是“$(P)ATH”)。這一點和shell中變量的引用方式不同。shell中變量的引用可以是“${xx}”或者“$xx”格式。但在Makefile中多字符變量名的引用只能是“$(xx)”或者“${xx}”格式。

(2) 變量的定義

兩種風格:遞歸展開式變量和直接展開式變量。前者前者在引用的地方是嚴格的文本替換,后者用:=定義,變量值中對其他量或者函數的引用在定義變量時被展開(對變量進行替換),此風格變量在定義時就完成了對所引用變量和函數的展開,因此不能實現對其后定義變量的引用(前者是嫩購實現這個功能的)。如:
CFLAGS := $(include_dirs) -O
include_dirs := -Ifoo -Ibar
由于變量“include_dirs”的定義出現在“CFLAGS”定義之后。因此在“CFLAGS”的定義中,“include_dirs”的值為空。“CFLAGS”的值為“-O”而不是“-Ifoo -Ibar -O”。這一點也是直接展開式和遞歸展開式變量的不同點。

??? 在復雜的Makefile中,推薦使用直接展開式變量。因為這種風格變量的使用方式和大多數編程語言中的變量使用方式基本上相同。它可以使一個比較復雜的Makefile在一定程度上具有可預測性。而且這種變量允許我們利用之前所定義的值來重新定義它(比如使用某一個函數來對它以前的值進行處理并重新賦值),此方式在Makefile中經常用到。盡量避免和減少遞歸式變量的使用。

???????? 當定義不包含尾空格的變量時,就不能使用這種方式,將變量定義和注釋書寫在同一行并使用若干空格分開。否則,注釋之前的空格會被作為變量值的一部分。例如下邊的做法就是不正確的:
dir := /foo/bar # directory to put the frobs in
變量“dir”的值是“/foo/bar ”(后面有4個空格),這可能并不是想要實現的。如果一個文件以它作為路徑來表示“$(dir)/file”,
那么大錯特錯了。

“?=”操作符
GNU make中,還有一個被稱為條件賦值的賦值操作符“?=”。被稱為條件賦值是因為:只有此變量在之前沒有賦值的情況下才會對這個變量進行賦值。例如:
FOO ?= bar
其等價于:
ifeq ($(origin FOO), undefined)
FOO = bar
endif
含義是:如果變量“FOO”在之前沒有定義,就給它賦值“bar”。否則不改變它的值。

“+=”操作符

使用“+=”操作符,相當于:
objects = main.o foo.o bar.o utils.o
objects := $(objects) another.o

如果被追加值的變量之前沒有定義,那么,“+=”會自動變成“=”,此變量就被定義為一個遞歸展開式的變量。如果之前存在這個變量定義,那么“+=”就繼承之前定義時的變量風格。

variable := value
variable += more

就是
variable := value
variable := $(variable) more

variable = value
variable += more
相當于:
temp = value
variable = $(temp) more

(3) 變量的高級用法

1.?? 變量的替換引用

對于一個已經定義的變量,可以使用“替換引用”將其值中的后綴字符(串)使用指定的字符(字符串)替換。

例如:
foo := a.o b.o c.o
bar := $(foo:.o=.c)
在這個定義中,變量“bar”的值就為“a.c b.c c.c”。使用變量的替換引用將變量“foo”以空格分開的值中的所有的字的尾字符“o”替換為“c”,其他部分不變

又如:
foo := a.o b.o c.o
bar := $(foo:%.o=%.c)
這個例子同樣使變量“bar”的值為“a.c b.c c.c”。這種格式的替換引用方式比第一種方式更通用。

使用環境變量需要注意以下幾點:
1. 在Makefile中對一個變量的定義或者以make命令行形式對一個變量的定義,都將覆蓋同名的環境變量(注意:它并不改變系統環境變量定義,被修改的環境變量只在make執行過程有效)。而make使用“-e”參數時,Makefile和命令行定義的變量不會覆蓋同名的環境變量,make將使用系統環境變量中這些變量的定義值。
2. make的遞歸調用中,所有的系統環境變量會被傳遞給下一級make。默認情況下,只有環境變量和通過命令行方式定義的變量才會被傳遞給子make進程。在Makefile中定義的普通變量需要傳遞給子make時需要使用“export”指示符來對它聲明。

3. 一個比較特殊的是環將變量“SHELL”。在系統中這個環境變量的用途是用來指定用戶和系統的交互接口,顯然對于make是不合適的。因此make的執行環境變量“SHELL”沒有使用同名的環境變量定義,而是“/bin/sh”。make默認“/bin/sh”作為它的命令行解釋程序(make在執行之前將變量“SHELL”設置為“/bin/sh”)。


gcc -O2 -o $@ $< 意思

-O2表示優化選項,2表示最優優化,即編譯器會優化你的程序;-o表示后邊接的是文件名稱;$@是Makefile的通配符,代指你前面指定的文件名,例如有規則%.o:%.c,那么$@表示xxx.o文件(xxx是你的源代碼文件的名稱前綴)$<表示搜索到的第一個匹配的文件,對于規則%.o:%.c$<表示第一個找到的.c文件。簡而言之,假設在一個文件夾下有若干.c文件,那么下面的規則:
%.o:%.c
<TAB>gcc -O2 -o $@ $<??? #<TAB>表示Tab鍵
表示把所有的.c文件編譯成中間.o文件。
http://zhidao.baidu.com/question/246239567.html

四、嵌套執行make

在一些大的工程中,我們會把我們不同模塊或是不同功能的源文件放在不同的目錄中,我們可以在每個目錄中都書寫一個該目錄的Makefile,這有利于讓我們的Makefile變得更加地簡潔,而不至于把所有的東西全部寫在一個Makefile中,這樣會很難維護我們的Makefile,這個技術對于我們模塊編譯和分段編譯有著非常大的好處。

例如,我們有一個子目錄叫subdir,這個目錄下有個Makefile文件,來指明了這個目錄下文件的編譯規則。那么我們總控的Makefile可以這樣書寫:

subsystem:
cd subdir && $(MAKE)

其等價于:

subsystem:
$(MAKE) -C subdir

定義$(MAKE)宏變量的意思是,也許我們的make需要一些參數,所以定義成一個變量比較利于維護。這兩個例子的意思都是先進入“subdir”目錄,然后執行make命令。

我們把這個Makefile叫做“總控Makefile”,總控Makefile的變量可以傳遞到下級的Makefile中(如果你顯示的聲明),但是不會覆蓋下層的Makefile中所定義的變量,除非指定了“-e”參數。

如果你要傳遞變量到下級Makefile中,那么你可以使用這樣的聲明:

export <variable ...>


GNU組織建議把編譯器為每一個源文件的自動生成的依賴關系放到一個文件中,為每一個“name.c”的文件都生成一個“name.d”的Makefile文件[.d]文件中就存放對應[.c]文件的依賴關系。

于是,我們可以寫出[.c]文件和[.d]文件的依賴關系,并讓make自動更新或自成[.d]文件,并把其包含在我們的主Makefile中,這樣,我們就可以自動化地生成每個文件的依賴關系了。
這里,我們給出了一個模式規則來產生[.d]文件:
%.d: %.c
@set -e; rm -f $@; \
$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
這個規則的意思是,所有的[.d]文件依賴于[.c]文件,“rm -f $@”的意思是刪除所有的目標,也就是[.d]文件,第二行的意思是,為每個依賴文件“$<”,也就是[.c]文件生成依賴文件,“$@”表示模式“%.d”文件,如果有一個C文件是name.c,那么“%”就是“name”,“$$$$”意為一個隨機編號,第二行生成的文件有可能是“name.d.12345”,第三行使用sed命令做了一個替換,關于sed命令的用法請參看相關的使用文檔。第四行就是刪除臨時文件。
總而言之,這個模式要做的事就是在編譯器生成的依賴關系中加入[.d]文件的依賴,即把依賴關系:
main.o : main.c defs.h
轉成:
main.o main.d : main.c defs.h
于是,我們的[.d]文件也會自動更新了,并會自動生成了,當然,你還可以在這個[.d]文件中加入的不只是依賴關系,包括生成的命令也可一并加入,讓每個[.d]文件都包含一個完賴的規則。一旦我們完成這個工作,接下來,我們就要把這些自動生成的規則放進我們的主Makefile中。我們可以使用Makefile的“include”命令,來引入別的Makefile文件(前面講過),例如:
sources = foo.c bar.c
include $(sources:.c=.d)
上述語句中的“$(sources:.c=.d)”中的“.c=.d”的意思是做一個替換,把變量$(sources)所有[.c]的字串都替換成[.d],關于這個“替換”的內容,在后面我會有更為詳細的講述。當然,你得注意次序,因為include是按次來載入文件,最先載入的[.d]文件中的目標會成為默認目標。
書寫命令

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

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

相關文章

小技巧集錦

2019獨角獸企業重金招聘Python工程師標準>>> jackson JsonDeserialize 使用方法&#xff1a; 實現方法注解寫在set方法上。 public class CustomJsonDateDeserializer extends JsonDeserializer<Date> {private SimpleDateFormat datetimeFormat new SimpleD…

interface-C#接口-統一的標準

文章目錄接口的定義接口的實現實例1實例2接口的繼承博主寫作不容易&#xff0c;孩子需要您鼓勵 萬水千山總是情 , 先點個贊行不行 接口是面向對象編程的一個重要技術&#xff0c;在C#中負責實現多重繼承。一個接口定義一個協定&#xff0c;實現接口類或結構體必須遵守其協定…

JMeter入門(1):JMeter總體介紹及組件介紹

一、JMeter概述 JMeter就是一個測試工具&#xff0c;相比于LoadRunner等測試工具&#xff0c;此工具免費&#xff0c;且比較好用&#xff0c;但是前提當然是安裝Java環境&#xff1b;JMeter可以做(1)壓力測試及性能測試&#xff1b;(2)數據庫測試&#xff1b;(3)Java程序的測試…

二層交換機、三層交換機和路由器的基本工作原理和三者之間的主要區別

二層交換機:二層交換技術是發展比較成熟&#xff0c;二層交換機屬數據鏈路層設備&#xff0c;可以識別數據包中的MAC地址信息&#xff0c;根據MAC地址進行轉發&#xff0c;并將這些MAC地址與對應的端口記錄在自己內部的一個地址表中。 具體如下&#xff1a; &#xff08;1&…

Unity3D:視物有點眩暈的原因

設置Main Camera 的 Field of View 為100&#xff0c;看物體總覺得很不舒服。 設置為 60 就正常了。 根本原因&#xff0c;有待于分析 轉載于:https://www.cnblogs.com/makebetter/p/7063694.html

使用jQuery清空file文件域的解決方案

使用jQuery清空file文件域的解決方案 var file $("#file") file.after(file.clone().val("")); file.remove();

更改mysql最大連接數

方法一&#xff1a; 打開cmd&#xff0c;用"mysql -u root -p;"命令進入mysql, 輸入命令&#xff1a;show variables like "max_connections" 顯示最大連接數 更改最大連接數 : set global max_connections 5000 方法二&#xff1a; 在my.ini加上 max_co…

根據HTML5 獲取當前位置的經緯度【百度地圖】【高德地圖】

是想讓地圖的定位用戶位置更準確一些。 查看了介紹&#xff1a; http://www.w3school.com.cn/html5/html_5_geolocation.asp 看介紹中拿數據挺簡單。 <!DOCTYPE html> <html> <body> <p id"demo">點擊這個按鈕&#xff0c;獲得您的坐標&…

C#抽象類與密封類-abstract-sealed

文章目錄抽象類和抽象方法實現抽象方法接口、類和抽象類密封類博主寫作不容易&#xff0c;孩子需要您鼓勵 萬水千山總是情 , 先點個贊行不行 如果說繼承是面向對象設計理論的基石&#xff0c;那么抽象理論和方法就是繼承理論的頂梁柱。 抽象類和抽象方法 簡單的說&#x…

vs2010快捷鍵

Ctrl M O: 折疊所有方法 Ctrl M M: 折疊或者展開當前方法 Ctrl M L: 展開所有方法 1、強迫智能感知&#xff1a;CtrlJ&#xff1b;2、強迫智能感知顯示參數信息&#xff1a;Ctrl-Shift-空格&#xff1b;3、格式化整個塊&#xff1a;CtrlKF4、檢查括號匹配(在左右括號間切…

startup畢業論文

今天起得相對比較晚&#xff0c;為的是一個沒有目的面試&#xff0c;去了的結果。只是打擊一下自己的自信心&#xff0c;走的時候&#xff0c;面試官冷冷的說了一句&#xff0c;你的面試到此結束&#xff0c;是的&#xff0c;我并沒有很傷心&#xff0c;在門外等面試的時候&…

Javascript實現信息滾動效果的方法

<html><head><meta http-equiv"Content-Type" content"text/html; charsetutf-8" /><title>向上無縫滾動</title><style>body { font-size: 12px; line-height: 24px; text-algin: center; /* 頁面內容居中 */}* { ma…

C# delegate與event,委托與事件

文章目錄委托示例事件實例博主寫作不容易&#xff0c;孩子需要您鼓勵 萬水千山總是情 , 先點個贊行不行 委托和事件是C#中兩個比較復雜的概念&#xff0c;這篇文章介紹兩個概念與基本用法&#xff0c;讓大家理解C#中的事件處理機制。 委托 委托也叫代理&#xff0c;就是把…

路由器與交換機的工作原理

路由器與交換機的工作原理 計算機網絡往往由許多種不同類型的網絡互連連接而成。如果幾個計算機網絡只是在物理上連接在一起&#xff0c;它們之間并不能進行通信&#xff0c;那么這種“互連”并沒有什么實際意義。因此通常在談到“互連”時&#xff0c;就已經暗示這些相互連接的…

Java的四種引用,強弱軟虛,用到的場景(轉+補充)

Q1&#xff1a;引用隊列是什么&#xff1f;如何使用&#xff1f;使用的場景有哪些&#xff1f; A1:oracle的api文檔的描述&#xff1a; https://docs.oracle.com/javase/7/docs/api/java/lang/ref/ReferenceQueue.htmlReference queues, to which registered reference objects…

C# lambda表達式與匿名方法

文章目錄匿名方法Lambda表達式實例實例博主寫作不容易&#xff0c;孩子需要您鼓勵 萬水千山總是情 , 先點個贊行不行 C#中的匿名方法是在C#2.0引入的&#xff0c;它終結了聲明委托的唯一方法是使用命名方法的時代。在C#更高版本中&#xff0c;Lambda表達式取代了匿名方法&a…

LINUx打包命令匯總

.tar 解包&#xff1a;tar xvf FileName.tar 打包&#xff1a;tar cvf FileName.tar DirName &#xff08;注&#xff1a;tar是打包&#xff0c;不是壓縮&#xff01;&#xff09; ——————————————— .gz 解壓1&#xff1a;gunzip FileName.gz 解壓2&#xff1a;…

常用的相似度計算

在數據分析和數據挖掘的過程中&#xff0c;我們經常需要知道個體間差異的大小&#xff0c;進而評價個體的相似性和類別。最常見的是數據分析中的相關分析&#xff0c;數據挖掘中的分 類和聚類算法&#xff0c;如K最近鄰&#xff08;KNN&#xff09;和K均值&#xff08;K-Means&…

玩轉C#窗體-屬性、方法和事件詳細說明

文章目錄簡介Windows窗體的基本屬性一、布局屬性1、StartPosition屬性2、Location屬性3、尺寸屬性4、WindowsState屬性5、Autoscroll屬性6、AutoSize屬性二、樣式屬性1、ControlBox屬性2、MaximizeBox屬性3、MinimizeBox屬性4、HelpButton屬性5、ShowIcon屬性6、Icon屬性7、Sho…

for循環和數組練習

//公雞2文&#xff0c;母雞1文&#xff0c;小雞半文&#xff0c;每種至少一只&#xff0c;100文買100只雞有多少種可能var ci 0; for(var g1;g<50;g){for(var m1;m<100;m){for(var x1;x<100;x){if(g*2m*1x*(0.5)100&&gmx100){ci1;console.log("買公雞&qu…