Ⅰ linux的makefile中":="與"="有什麼區別
:= 就是簡單的賦值, 比如
foo := $(bar)
將bar的值賦給foo
?= 是條件賦值, 比如
foo ?= $(bar)
只有當foo變數還沒有被定義的時候,才會將bar的值賦給foo。 注意,如果foo已經被定義過,但是是空值了話,?=不會給他賦值。比方說你的makefile是
foo = hello
foo ?= new
則最終foo的值是hello
如果你的makefile是
foo =
foo ?= new
foo的值是空
Ⅱ makefile有哪些環境變數
MakeFile中的變數定義
一般在我們書寫Makefile時,各部分變數引用的格式我們建議如下:
1. make變數(Makefile中定義的或者是make的環境變數)的引用使用「$(VAR)」格式。
2. 出現在規則命令行中shell變數(一般為執行命令過程中的臨時變數,它不屬於Makefile變數,而是一個shell變數)引用使用shell的「$tmp」格式。
3. 對出現在命令行中的make變數我們同樣使用「$(CMDVAR)」 格式來引用。
MakeFile中給變數賦值有以下兩種方式
1.遞歸展開式,使用=直接定義,例子如下:
foo = $(bar)
bar = $(ugh)
ugh = Huh?
all:;echo $(foo)
執行「make」將會列印出「Huh?」。整個變數的替換過程時這樣的:首先「$(foo)」被替換為「$(bar)」,接下來 「$(bar)」被替換為「$(ugh)」,最後「$(ugh)」被替換為「Hug?」。整個替換的過程是在執行「echo $(foo)」是進行的。
這種方式的缺點是
缺點1:使用此風格的變數定義,可能會由於出現變數遞歸定義而導致make陷入到無限的變數展開過程中,最終使make執行失敗.
缺點2:這種風格的變數定義中如果使用了函數,那麼包含在變數值中的函數總會在變數被引用的地方執行(變數被展開時)。
2.直接展開式
這種風格的變數使用「:=」來定義變數。在使用「:=」定義變數時,變數值中對另外變數的引用或者函數的引用在定義時被展開(對變數進行替換)。
x := foo
y := $(x) bar
x := later
就等價於:
y := foo bar
x := later
需要CFLAGS := $(include_dirs) -O
include_dirs := -Ifoo -Ibar
由於在變數「include_dirs」的定義出現在「CFLAGS」定義之後。因此在「CFLAGS」的定義中,「include_dirs」的值為空。「CFLAGS」的值為「-O」而不是「-Ifoo -Ibar -O」。注意的是:此風格變數在定義時就完成了對所引用的變數的展開,因此它不能實現對其後定義變數的引用。
變數的替換引用,格式為「$(VAR:A=B)」(或者「${VAR:A=B}」),
意思是,替換變數「VAR」中所有「A」字元結尾的字為「B」結尾的字。
「結尾」的含義是空格之前(變數值多個字之間使用空格分開)。
而對於變數其它部分的「A」字元不進行替換。
自動化變數
$@
代表規則中的目標文件名。如果目標是一個文檔(Linux中,一般稱.a文件為文檔),那麼它代表這個文檔的文件名。在多目標的模式規則中,它代表的是哪個觸發規則被執行的目標文件名。
$%
規則的目標文件是一個靜態庫文件時,代表靜態庫的一個成員名。例如,規則的目標是「foo.a(bar.o)」,那麼,「$%」的值就為「bar.o」,「$@」的值為「foo.a」。如果目標不是函數庫文件,其值為空。
$<
規則的第一個依賴文件名。如果是隱含規則,則它代表通過目標指定的第一個依賴文件。
$?
所有比目標文件更新的依賴文件列表,空格分割。如果目標是靜態庫文件名,代表的是庫成
員(.o文件)的更新情況。
$^
規則的所有依賴文件列表,使用空格分隔。如果目標是靜態庫文件名,它所代表的只能是所有庫成員(.o文件)名。一個文件可重復的出現在目標的依賴中,變數「$^」只記錄它的一次引用情況。就是說變數「$^」會去掉重復的依賴文件。
$+
類似「$^」,但是它保留了依賴文件中重復出現的文件。主要用在程序鏈接時,庫的交叉引用場合。
$(@D)
代表目標文件的目錄部分(去掉目錄部分的最後一個斜杠)。如果「$@」是「dir/foo.o」,那麼「$(@D)」的值為「dir」。如果「$@」不存在斜杠,其值就是「.」(當前目錄)。注意它和函數「dir」的區別!
$(@F)
目標文件的完整文件名中除目錄以外的部分(實際文件名)。如果「$@」為「dir/foo.o」,那麼「$(@F)」只就是「foo.o」。「$(@F)」等價於函數「$(notdir $@)」。
$(%D)
$(%F)
當以如「archive(member)」形式靜態庫為目標時,分別表示庫文件成員「member」名中的目錄部分和文件名部分。它僅對這種形式的規則目標有效。
$(<D)
$(<F)
分別表示規則中第一個依賴文件的目錄部分和文件名部分。
$(^D)
$(^F)
分別表示所有依賴文件的目錄部分和文件部分(不存在同一文件)。
$(+D)
$(+F)
分別表示所有依賴文件的目錄部分和文件部分(可存在重復文件)。
$(?D)
$(?F)
分別表示被更新的依賴文件的目錄部分和文件部分。
Ⅲ linux shell: 幫我解釋下這個makefile每一行的意思嘛
CC=gcc //指定編譯器為gcc編譯器
CFLAGS //指定編譯選項
CFILES=$(wildcard*.c) //wildcard是擴展通配符,匹配當前目錄下所有.c文件(文件包含路徑)
OBJS=$(CFILES:%c=%o) //生成文件格式,把CFILES匹配的所有.c文件名改為.o文件名
all:hello //all 目標依賴於hello
hello : $(OBJS) //hello 目標依賴於$(OBJS)包含的文件,生成$(OBJS)的規則如下。
$(CC) ...... //展開就是用gcc生成可執行程序。gcc -o hello $(OBJS)
.c.o:
$(CC) -c $< //利用gcc編譯c源文件為.o格式的目標文件
clean:
rm -rf hello *.o //清理生成文件命令。
-----------------------------------------
實際上,makefile文件就是把手動編譯的過程寫入了這個文件。
Ⅳ Linux的makefile中有連接腳本和沒連接腳本的區別
在Makefile可以調用shell腳本,但是Makefile和shell腳本是不同的。本文試著歸納一下Makefile和shell腳本的不同。
1、
shell中所有引用以$打頭的變數其後要加{},而在Makefile中的變數是以$打頭的後加()。實例如下:
Makefile
PATH="/data/"
SUBPATH=$(PATH)
Shell
PATH="/data/"
SUBPATH=${PATH}
2、Makefile中所有以$打頭的單詞都會被解釋成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`
注意是``,不是''
推薦你看或者linux就該這么學,具體關於這一章地址3w(dot)linuxprobe(dot)com.
Ⅳ Linux下shell腳本怎麼實現運行某個文件的makefile
make工具就知道阿,makefile文件里描述了編譯參數等信息
Ⅵ Makefiel和shell的區別
一句2句說不清楚,他們是2樣東西,語法有相似之處,各有各的語法。bash shell script是/bin/bash這個工具可以理解並執行的命令的集合。一個腳本包括一個或者多個命令(並非全是一行一行簡單的命令,還有循環,分支,函數等等)
#!/bin/bash
date
cat a.txt
echo "hello world"
這是個簡單的bash shell 腳本。
看看下面最簡單的一個makefile文件sy1.mk,運行cat sy1.mk顯示一下它,注意echo的左邊必須是一個Tab鍵,不是8個空格:
$ cat sy1.mk
all:
echo "hello makefile"
運行命令make -f <文件名>:
$ make -f sy1.mk
echo "hello makefile"
hello makefile
makefile文件是被/usr/bin/make或者/bin/make (或者 /usr/bin/gmake)能理解並且運行(嚴格說,還不能完全說「運行」)的文本文件。
編譯大型軟體,例如Android (你可以下載andoid全套代碼,網上可以查到步驟),一般離不開makefile,也離不開shell;在linux/unix下做軟體開發(不管大型軟體還是很小的軟體),做linux系統維護,搭建linux使用和開發環境,一般離不開shell。
學會shell和makefile不是一天2天的事,網上免費的資料很多。
供參考,謝謝!
Ⅶ 在linux下如何執行另一個文件夾下的makefile
可以在主Makefile文件中直接寫
all:
cd /Path/To/src1 && make
cd /Path/To/src2 && make
......
注意命令直接要使用 「&&」符號連接,尤其是在聲明一些環境變數的時候,例如
export GNUMAKE=/bin/gmake && cd /Path/To/src && make
Ⅷ Linux makefile&shell的一個問題
ar 命令是用來將若干 .o 文件打包成(靜態)庫文件。 按照習慣,庫文件後綴名都是 .a
crv 分別是 ar 命令的三個參數,cr的意思是創建指定.a文件(如果不存在),並將.o文件加入到這個.a文件中。 v 的意思是讓 ar 命令在執行的時候列印更多的提示信息。
ar crv abc.a $(OBJ) 就是將 abc.o 打包到庫文件 abc.a 中的意思。
更多信息可以 man ar 來看到。
Ⅸ linux Makefile文件中 KERNELDIR = /lib/moles/$(shell uname -r)/build什麼意思
你說的是編譯內核模塊的Makefile是嗎?KERNELDIR指的是內核庫文件的路徑,你的代碼中使用的是內核提供的函數,而這些函數也是有具體實現的,在連接成一個內核模塊時要說明這些庫文件在哪裡,方便鏈接程序把它們連接成一個完成的模塊。「?=」:如果這個KERNELDIR為空說明你沒有指定內核庫文件的路徑,那麼它就會給KERNELDIR賦值,因為頂層Makefile通過這個環境變數知道內核庫文件在哪裡。KERNELDIR=/lib/moles/$(shell uname -r)/build;其中 shell uname -r 說的是調用shell里頭的uname指令 你可以uname -r看看呢是什麼,他表示的是內核版本號。一般來說我們構造內核樹時,它把內核庫統一保存在/lib/moles/內核版本號/build目下。還有不清楚的請提問,呵呵。Ⅹ Linux基礎中,shell腳本和makefile文件的差別是什麼啊,求詳細點嘛
你可以認為makefile是shell腳本「派生」出來的。最樸素的makefile可以完全通過gcc等語句實現,在這種情況下也就是shell腳本了。但是為了方便,makefile引入了大量的語法用來使編譯鏈接變得簡單,所以和shell腳本還是不同的。
可以參考:http://apps.hi..com/share/detail/31232485