日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Makefile札记

發布時間:2023/11/30 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Makefile札记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Makefile:= ?= += =的區別


Makefile中我們經常看到 = := ?= +=這幾個賦值運算符,那么他們有什么區別呢?我們來做個簡單的實驗

新建一個Makefile,內容為:

ifdef DEFINE_VRE

??? VRE = “Hello World!”

else

endif

ifeq ($(OPT),define)

??? VRE ?= “Hello World! First!”

endif

ifeq ($(OPT),add)

??? VRE += “Kelly!”

endif

ifeq ($(OPT),recover)

??? VRE := “Hello World! Again!”

endif

all:

??? @echo $(VRE)

敲入以下make命令:

make DEFINE_VRE=true OPT=define 輸出:Hello World!

make DEFINE_VRE=true OPT=add 輸出:Hello World! Kelly!

make DEFINE_VRE=true OPT=recover? 輸出:Hello World! Again!

make DEFINE_VRE= OPT=define?輸出:Hello World! First!

make DEFINE_VRE= OPT=add 輸出:Kelly!

make DEFINE_VRE= OPT=recover 輸出:Hello World! Again!

從上面的結果中我們可以清楚的看到他們的區別了

= 是最基本的賦值

:= 是覆蓋之前的值

?= 是如果沒有被賦值過就賦予等號后面的值

+= 是添加等號后面的值

之前一直糾結makefile“=”“:=”的區別到底有什么區別,因為給變量賦值時,兩個符號都在使用。網上搜了一下,有人給出了解答,但是本人愚鈍,看不懂什么意思。幾尋無果之下,也就放下了。今天看一篇博客,無意中發現作者對于這個問題做了很好的解答。解決問題之余不免感嘆,有時候給個例子不就清楚了嗎?為什么非要說得那么學術呢。^_^

????? 1“=”

????? make會將整個makefile展開后,再決定變量的值。也就是說,變量的值將會是整個makefile中最后被指定的值。看例子:

????????????x = foo
??????????? y = $(x) bar
??????????? x = xyz

??????在上例中,y的值將會是?xyz bar?,而不是?foo bar?

????? 2“:=”

????? “:=”表示變量的值決定于它在makefile中的位置,而不是整個makefile展開后的最終值。

????????????x := foo
??????????? y := $(x) bar
??????????? x := xyz

????? 在上例中,y的值將會是?foo bar?,而不是?xyz bar?了。



makefile宏定義:EXTRA_CFLAGS += -DCONFIG_ =y


EXTRA_CFLAGS += -D CONFIG_ =y

1.

假如定義一個宏CONFIG_DEBUG

.c里面定義為:#define?CONFIG_DEBUG

makefile里定義為: CONFIG_DEBUG=y

假如說我們想在makefile里為.c文件進入一個宏定義,就用EXTRA_CFLAGS += DCONFIG_DEBUG(等價于在.c文件里定義#define?CONFIG_DEBUG)

這時CONFIG_DEBUG=yEXTRA_CFLAGS += DCONFIG_DEBUG的區別應該你已經看出來的,前者是對makefile編譯時用的,比如說obj-(CONFIG_DEBUG) += test.o,而后者則是對.c源文件里的用的,比如說:

#if defined(CONFIG_DEBUG)?

...

#else

...

#endif

2.


假如定義一個宏CONFIG_DEBUG = 3

.c里面定義為:#define?CONFIG_DEBUG 3

假如說我們想在makefile里為.c文件進入一個宏定義,就用EXTRA_CFLAGS += -DCONFIG_DEBUG=3

此時兩者的定義完全相同。



Makefile中通配符*%的區別是什么?

此兩者均為通配符,但更準確的講,%Makefile規則通配符,一般用于規則描述,如

%.o:%c

? ? $(CC)? $< -o $@

表示所有的目標文件及其依賴文件,或者

$(filter %.c ,SOURCES)

此處SOURCES表示包含.c .cc .cpp等多類型源文件,該過濾器函數將c文件過濾出來,而%.c即為此過濾器規則。

通配符*則不具備上述功能。尤其是在Makefile,當變量定義或者函數調用時,該通配符的展開功能就失效了,即不能正常使用了,此時需要借助wildcard函數。二者應用范圍不同。



Makefile有三個非常有用的變量。分別是$@$^$<代表的意義分別是:

# 這是上面那個程序的Makefile文件:?

mainmain.o?mytool1.o?mytool2.o?


gcc?-o?main?main.o?mytool1.o?mytool2.o?


main.omain.c?mytool1.h?mytool2.h?


gcc?-c?main.c?


mytool1.omytool1.c?mytool1.h?


gcc?-c?mytool1.c?


mytool2.omytool2.c?mytool2.h?


gcc?-c?mytool2.c

有了這個Makefile文件,不論我們什么時候修改了源程序當中的什么文件,我們只要執行make命令,我們的編譯器都只會去編譯和我們修改的文件有關的文件,其它的文件它連理都不想去理的。?下面我們學習Makefile是如何編寫的。?Makefile中也#開始的行都是注釋行.Makefile中最重要的是描述文件的依賴關系的說明。一般的格式是:?

targetcomponents?

TAB rule?

第一行表示的是依賴關系。第二行是規則。?


比如說我們上面的那個Makefile文件的第二行。?

mainmain.o mytool1.o mytool2.o?

表示我們的目標(target)main的依賴對象(components)main.o mytool1.omytool2.o當倚賴的對象在目標修改后修改的話,就要去執行規則一行所指定的命令。

就象我們的上面那個Makefile第三行所說的一樣要執行 gcc-o main main.o mytool1.o mytool2.o注意規則一行中的TAB表示那里是一個TAB?Makefile有三個非常有用的變量。

分別是$@$^$<代表的意義分別是:?

$@--目標文件,$^--所有的依賴文件,$<--第一個依賴文件。?如果我們使用上面三個變量,

那么我們可以簡化我們的Makefile文件為:?

# 這是簡化后的Makefile?

mainmain.o mytool1.o mytool2.o?

gcc -o $@ $^?


main.omain.c mytool1.h mytool2.h?

gcc -c $<?


mytool1.omytool1.c mytool1.h?

gcc -c $<


mytool2.omytool2.c mytool2.h?

gcc -c $<?


經過簡化后,我們的Makefile是簡單了一點,不過人們有時候還想簡單一點。這里我們學習一個Makefile的缺省規則?.c.o?gcc -c $<?這個規則表示所有的 .o文件都是依賴與相應的.c文件的。例如mytool.o依賴于mytool.c這樣Makefile還可以變為:?


# 這是再一次簡化后的Makefile?

mainmain.o mytool1.o mytool2.o?

gcc -o $@ $^?

.c.o?

gcc -c $<?


好了,我們的Makefile 也差不多了,如果想知道更多的關于Makefile的規則,可以查看相應的文檔。





makefilePHONY的相關介紹

PHONY 目標并非實際的文件名:只是在顯式請求時執行命令的名字。有兩種理由需要使用PHONY目標:避免和同名文件沖突,改善性能。

如果編寫一個規則,并不產生目標文件,則其命令在每次make該目標時都執行。例如:
  clean:
  rm *.o temp
因為"rm"命令并不產生"clean"文件,則每次執行"make clean"的時候,該命令都會執行。如果目錄中出現了"clean"文件,則規則失效了:沒有依賴文件,文件"clean"始終是最新的,命令永遠不會執行;為避免這個問題,可使用".PHONY"指明該目標。如:
  .PHONY : clean
  這樣執行"make clean"會無視"clean"文件存在與否。

已知phony 目標并非是由其它文件生成的實際文件,make會跳過隱含規則搜索。這就是聲明phony目標會改善性能的原因,即使你并不擔心實際文件存在與否。
  完整的例子如下:
  .PHONY : clean
  clean :
  rm *.o temp

phony 目標可以有依賴關系。當一個目錄中有多個程序,將其放在一個makefile中會更方便。因為缺省目標是makefile中的第一個目標,通常將這個phony目標叫做"all",其依賴文件為各個程序:
  all : prog1 prog2 prog3
  .PHONY : all
  prog1 : prog1.o utils.o
   ? ? ? ? cc -o prog1 prog1.o utils.o
  prog2 : prog2.o
   ? ? ? ? cc -o prog2 prog2.o
  prog3 : prog3.o sort.o utils.o
   ? ? ? ? cc -o prog3 prog3.o sort.o utils.o

假設你的一個項目最后需要產生兩個可執行文件。你的主要目標是產生兩個可執行文件,但這兩個文件是相互獨立的——如果一個文件需要重建,并不影響另一個。你可以使用假象目的達到這種效果。一個假象目的跟一個正常的目的幾乎是一樣的,只是這個目的文件是不存在的。因此, make總是會假設它需要 被生成,當把它的依賴文件更新后,就會執行它的規則里的命令行。

如果在我們的 makefile 開始處輸入:

all : exec1 exec2

其中 exec1 exec2是我們做為目的的兩個可執行文件。 make把這個 'all' 做為它的主要目的,每次執行時都會嘗試把 'all'更新。但既然這行規則里沒有哪個命令來作用在一個叫 'all'實際文件(事實上 all并不會在磁碟上實際產生),所以這個規則并不真的改變 'all'的狀態。可既然這個文件并不存在,所以 make會嘗試更新 all 規則,因此就檢查它的依靠 exec1, exec2是否需要更新,如果需要,就把它們更新,從而達到我們的目的。

假象目的也可以用來描述一組非預設的動作。例如,你想把所有由 make產生的文件刪除,你可以在 makefile里設立這樣一個規則:

veryclean :
rm *.o
rm myprog

前提是沒有其它的規則依靠這個 'veryclean'目的,它將永遠不會被執行。但是,如果你明確的使用命令 'make veryclean' make會把這個目的做為它的主要目標,執行那些 rm命令。

如果你的磁碟上存在一個叫 veryclean文件,會發生什么事?這時因為在這個規則里沒有任何依靠文件,所以這個目的文件一定是最新的了(所有的依靠文件都已經是最新的了),所以既使用戶明確命令 make重新產生它,也不會有任何事情發生。解決方法是標明所有的假象目的(用 .PHONY),這就告訴 make不用檢查它們是否存在于磁碟上,也不用查找任何隱含規則,直接假設指定的目的需要被更新。在 makefile里加入下面這行包含上面規則的規則:

.PHONY : veryclean

就可以了。注意,這是一個特殊的 make規則,make知道 .PHONY是一個特殊目的,當然你可以在它的依靠里加入你想用的任何假象目的,而 make知道它們都是假象目的。






?Makefileshell腳本區別


Makefile可以調用shell腳本,但是Makefileshell腳本是不同的。本文試著歸納一下Makefileshell腳本的不同。
1 shell中所有引用以$打頭的變量其后要加{},而在Makefile中的變量是以$打頭的后加()。實例如下:
Makefile
PATH="/data/"
SUBPATH=$(PATH)

Shell
PATH="/data/"
SUBPATH=${PATH}

2Makefile中所有以$打頭的單詞都會被解釋成Makefile中的變量。如果你需要調用shell中的變量(或者正則表達式中錨定句位$),都需要加兩個$符號($$)。實例如下:

PATH="/data/"

all:
? ? echo ${PATH}
? ? echo $$PATH

?例子中的第一個${PATH}引用的是Makefile中的變量,而不是shell中的PATH環境變量,后者引用的事Shell中的PATH環境變量。


3
、通配符區別
shell
中通配符*表示所有的字符
Makefile
中通配符%表示所有的字符

4、在Makefile中只能在某一個target下的命令中調用Shell腳本,其他地方是不能輸出的。比如如下代碼就是沒有任何輸出:

VAR="Hello"
echo "$VAR"

all:
?? .....
以上代碼任何時候都不會輸出,沒有在任何target下得命令內,如果上述代碼改為如下:

VAR="Hello"

all:
? ? echo "$VAR"
? ? .....以上代碼,在make all的時候將會執行echo命令。

5、在Makefile中執行shell命令,一行創建一個進程來執行。這也是為什么很多Makefile中有很多行的末尾都是“;? \”,以此來保證代碼是一行而不是多行,這樣Makefile可以在一個進程中執行,例如:

SUBDIR=src example
all:
? ? @for subdir in $(SUBDIR); \
? ? do\
? ? ? ? echo "building "; \
? ? done上述可以看出for循環中每行都是以”; \”結尾的。

6、獲取當前目錄

PATH=`pwd` 注意是``,不是’'







?Makefile中的shell2009-12-24 09:27:05

分類:


一下摘錄Makefile中調用shell的一段


install:

? ? ? ? -if [ ! -e xxx ]; then sudo mkdir xxx; fi


注意,將上面的if語句寫到一行的話,必須在fi前面加上分號,否則會出現下面錯誤

unexpected end of file


下面轉一個相關文章

MakefileShell的問題

?

大概只要知道Makefile的人,都知道Makefile可以調用Shell腳本。但是在實際使用時,并不那么簡單,一些模棱兩可的地方可能會讓你抓狂。你若不信,可以先看幾個例子,想象一下這些這些例子會打印什么內容,記下你想象的結果,然后在計算機上運行這些例子,對照看一下。

?

?

示例一:

if [ "$(BUILD)" = "debug" ]; then? echo "build debug"; else echo "build release"; fi

all:

? ? echo "done"

示例二:

all:

? ? @CC=arm-linux-gcc

? ? @echo $(CC)

示例三:

CC=arm-linux-gcc

all:

? ? @echo $(CC)

示例四:

SUBDIR=src example

all:

? ? @for subdir in $(SUBDIR); \

? ? do\

? ? ? ? echo "building " $(subdir); \

? ? done

?

?

說明:

1. ? ? ? ? Shell腳本在target里才有效,其它地方都被忽略掉了。所以示例一中,”build debug”之類的字符串根本打印不出來。示例一的正確寫法是:

?

示例一:

all:

? ? if [ "$(BUILD)" = "debug" ]; then? echo "build debug"; else echo "build release"; fi

? ? echo "done"

?

2. ? ? ? ? make把每一行Shell腳本當作一個獨立的單元,它們在單獨的進程中運行。示例二中,兩行Shell腳本在兩個莫不相干的進程里運行,第一個進程把CC設置為arm-linux-gcc,第二個進程是不知道的,所以打印的結果自然不是arm-linux-gcc了。示例二的正確寫法是:

?

示例二:

all:

? ? @CC=arm-linux-gcc; echo $(CC)

或者:

all:

@CC=arm-linux-gcc; \

echo $(CC)

?

3. ? ? ? ? make在調用Shell之前先進行預處理,即展開所有Makefile的變量和函數。這些變量和函數都以$開頭。示例三中,Shell拿的腳本實際上是echo arm-linux-gcc,所以打印結果正確。

?

4. ? ? ? ? make預處理時,所有以$開頭的,它都不會放過。要想引用Shell自己的變量,應該以$$開頭。另外要注意,Shell自己的變量是不需要括號的。示例四的正確寫法是:

?

示例四:

SUBDIR=src example

all:

? ? @for subdir in $(SUBDIR); \

? ? do\

? ? ? ? echo "building " $$subdir; \

? ? done

感謝,Thanks




?linux Makefile obj-m obj-y ..

分類: Linux

2013-02-20 14:01 1773人閱讀 評論(0) 收藏 舉報

目標定義是Kbuild Makefile的主要部分,也是核心部分。主要是定義了要編 譯的文件,所有的選項,以及到哪些子目錄去執行遞歸操作。 最簡單的Kbuild makefile 只包含一行: 例子: obj-y += foo.o 該例子告訴Kbuild在這目錄里,有一個名為foo.o的目標文件。foo.o將從foo.c foo.S文件編譯得到。 如果foo.o要編譯成一模塊,那就要用obj-m了。所采用的形式如下: 例子: obj-$(CONFIG_FOO) += foo.o $(CONFIG_FOO)可以為y(編譯進內核) m(編譯成模塊)。如果CONFIG_FOO不是y m,那么該文件就不會被編譯聯接了


Linux各級內核源代碼的子目錄下都有Makefile,大多數Makefile要嵌入主目錄下的Rule.makeRule.make將識別各個Makefile中所定義的一些變量。變量obj-y表示需要編繹到內核中的目標文件名集合,定義O_TARGET表示將obj-y連接為一個O_TARGET名稱的目標文件,定義L_TARGET表示將obj-y合并為一個L_TARGET名稱的庫文件。同樣obj-m表示需要編繹成模塊的目標文件名集合。如果還需進行子目錄make,則需要定義subdir-ysubdir-m。在Makefile中,用"obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o"和"subdir-$(CONFIG_EXT2_FS) += ext2"這種形式自動為obj-yobj-msubdir-ysubdir-m添加文件名。有時,情況沒有這么單純,還需要使用條件語句個別對待。Makefile中還有其它一些變量,如mod-subdirs定義了subdir-m以外的所有模塊子目錄。?


Rules.make是如何使make進入子目錄的呢? 先來看subdir-y是如何處理的,在Rules.make中,先對subdir-y中的每一個文件名加上前綴"_subdir_"再進行排序生成subdir-list集合,再以它作為目標集,對其中每一個目標產生一個子make,同時將目標名的前綴去掉得到子目錄名,作為子make的起始目錄參數。subdir-msubdir-y類似,但情況稍微復雜一些。由于subdir-y中可能有模塊定義,因此利用mod-subdirs變量將subdir-y中模塊目錄提取出來,再與subdir-m合成一個大的MOD_SUB_DIRS集合。subdir-m的目標所用的前綴是"_modsubdir_"。?


一點說明,子目錄中的MakefileRules.make都沒有嵌入.config文件,它是通過主Makefile向下傳遞MAKEFILES變量完成的。MAKEFILESmake自已識別的一個變量,在執行新的Makefile之前,make會首先加載MAKEFILES所指的文件。在主Makefile中它即指向.config?

總結

以上是生活随笔為你收集整理的Makefile札记的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。