国产毛片a精品毛-国产毛片黄片-国产毛片久久国产-国产毛片久久精品-青娱乐极品在线-青娱乐精品

迅為IMX6ULL開發板Ubuntu下C編程入門(二)

發布時間:2020-5-25 13:16    發布者:落風
本文是介紹3.3 初識 Makefile+3.4Makefile語法
3.3  初識  Makefile
3.3.1  什么是 Makefile
3.2 章節我們了解了在 Ubuntu 系統下通過 gcc 編譯器來編譯 C 程序,在我們演示的歷程中只有一個C 文件,我們直接在終端輸入 gcc 的編譯命令,就完成了 C 程序的編譯。我們在實際開發過程中,如果我們的工程有幾十個,或者幾百幾千個 C 文件,我們通過在終端輸入 gcc 命令來編譯,這顯然是不現實的。為了解決這個問題我們可以使用“make”命令,它會解析 Makefile 文件中的指令(應該說是規則)來編譯整個工程。在 Makefile 文件中描述了整個工程的所有文件的編譯順序,編譯規則。
作為一個專業的程序員,一定要掌握 Makefile 的,我們可以通過 Makefile 能了解到整個工程的處理過程的。
由于Makefile涉及到很多的知識點,以至于可以單獨寫本書來講述,所以本章我們只是講解下Makefile的基礎入門,如果詳細的研究 Makefile,可以給大家推薦《跟我一起寫 Makefile》這個電子文檔,該文檔已經放在了:i.MX6UL 終結者光盤資料\09_其它參考資料里面了。
3.3.2  第一個 Makefile在本節我們建立這樣一個工程,計算兩個整形數的和,并將結果在終端顯示出來。在這個工程中一共有main.c、calc.c 兩個 C 文件和 calc.h 這個頭文件。其中 main.c 是主文件,calc.c 負責接收 main.c 傳過來的數據,然后進行相加。main.c 文件的內用如下:
#include
include "calc.h"
int main(int argc, char *argv[])
{
int a = 3, b = 6, sum;
sum = calc(a, b);
printf("%d + %d = %d\n", a, b, sum);
return 0;
}
calc.c 文件內容如下:
#include
int calc(int a, ing b)
{
return (a+b);
}
文件 calc.h 內容如下:
#ifndef _CALC_H
#define _CALC_H
int calc(int a, int b);
#endif
上面就是我們這個工程的所有源文件,我們在終端使用 gcc 編譯這個工程,在終端輸入“gcc main.ccalc.c -o main”,該命令的意思是用 gcc 對 main.c、calc.c 進行編譯,然后輸出可執行文件 main,運行結果如下圖所示:
通過上圖可以看到生成了可執行文件 main,我們在終端運行 main 執行文件,運行結果如下圖所示:
我們可以看到上圖的運行結果和我們設計的結果是一致的。由于我們的這個工程是有三個文件,如果工程有幾百個,幾千個的文件,或者如果有一個文件被修改,使用上面的命令將會編譯所有的文件,如果我們的工程有上萬個文件,編譯完一次工程所需要的時間就很可怕。最優的方法就是編譯過一次以后,如果后面在編譯,只編譯修改的文件,這樣就會節約很多時間,因此我們修改下編譯方法,命令如下:
gcc -c main.c
gcc -c calc.c
gcc main.o calc.o -o main
我們在終端輸入上面的命令,結果如下圖所示:
上圖的第一條和第二條命令里面使用了參數“-c”是把 main.c 和 calc.c 編譯成對應的.o 文件,最后一條命令是把編譯生成的.o 文件鏈接成可執行文件 main。假如我們修改了 main.c 這個文件。只需將 main.c這個一個文件重新編譯下,然后在把所有的.o 文件重新鏈接成可執行文件,對應的命令如下:
gcc -c main.c
gcc main.o calc.o -o main
可是這樣還有一個問題,如果需要修改的文件有很多,這樣工作量也會不小,所以我們需要一個工具:
1.如果工程沒有編譯過,就會把工程中的.c 文件全部編譯并連接成可執行文件
2.如果工程中有某些文件修改了,只編譯修改的文件并連接成可執行文件
3.如果工程中的頭文件修改了,那么就要編譯所有引用這個頭文件的.c 文件,并且連 接成可執行文件
我們開頭說的 Makefile 就是完成這個功能的,下面我們在工程中建立一個 Makefile 文件來實現這樣的功能(注意:文件名字必須為 Makefile,大小寫是區分的)。我們使用 vim 創建 Makefile 文件(Makefile和我們的 main.c、calc.c 在同一級目錄下),然后輸入下面的腳本:
main:main.o calc.o
gcc -o main main.o calc.o
main.o:main.c
gcc -c main.c
calc.o:calc.c
gcc -c calc.c
clean
rm -rf *.o
rm -rf main
上面腳本縮進的行需要使用“Tab”鍵縮進,不要使用空格,這是 Makefile 的語法要求,編寫完成的腳本如下圖所示:

編寫好 Makefile,保存并退出,然后我們在終端輸入“make”命令來編譯我們的工程,make 命令會在當前目錄下查找“Makefile”文件,如果存在的話就按照 Makefile 里面的規則進行編譯,如下圖所示:
通過上圖可以看到編譯產生了 main.o、calc.o 和 main 執行文件,說明編譯成功了。接下來我們修改下 main.c 這個文件,如下圖所示:
然后保存并退出,然后在終端輸入“make”再次編譯下工程,如下圖所示:
通過上圖我們可以看到只重新編譯了修改的 main.c,并最終重新鏈接生成可執行文件 main,我們在終端運行可執行文件 main,如下圖所示:
3.4 e Makefile 語法
3.4.1  初識 Makefile
Makefile 文件是由一些列的規則組合而成的,格式如下:
target(目標文件) ...: prerequisites(依賴的文件) ...
command(命令)
...
...
比如 3.3.2 中寫的 Makefile 的規則:
main.o:main.c
gcc -c main.c
這條規則的 main.o 是目標文件(將要生成的文件),main.c 是依賴的文件(生成 main.o 需要的文件),“gcc -c main.c”是生成 main.o 需要運行的命令。e Makefile  中每行的腳本如果有縮進的情況,必須使用“ Tab ” 鍵縮進,切記不能使用空格縮進(這是 e Makefile  的語法要求),大家一定要切記!下面我們來分析一下圖 3.3.2 章節中寫的 Makefile 文件,腳本如下:
1 main:main.o calc.o
2 2 gcc -o main main.o calc.o
3 3 main.o:main.c
4 4 gcc -c main.c
5 5 calc.o:calc.c
6 6 gcc -c calc.c
7 7
8 8 clean:
9 9 rm -rf *.o
10 rm -rf main
從上圖的運行結果可以看到最后的結果等于 10 了,和我們程序的設計結果是一樣的。
該腳本一共有 4 條規則,1、2 行是第一條規則,3、4 行是第二條規則,5、6 是第三條規則 8、9、10是第四條規則。我們在運行 make 命令的時候,會解析當前目錄下的這個 Makefile 文件里面的規則,首先解析第一條規則,第一條規則中的目標文件是 main,只要完成了該目標文件的更新,整個 Makefile 的功能
就完成了。在第一次編譯的時候,由于目標文件 main 不存在,則會解析第一條規則,第一條規則依賴文件main.o、calc.o,make 命令會檢查當前目錄下是否有這兩個.o 文件,經過檢查發現沒有,然后 make 會在Makefile 中查找分別以 main.o、calc.o 為目標的規則(第二條,第三條規則)。執行第二條規則依賴的文件是 main.c,make 命令檢查發現當前目錄下有這個文件,然后執行第二條規則的命令“gcc -c main.c”生成 main.o 文件。然后執行第三條規則,第三條規則的目標文件是 calc.o,依賴的文件是 calc.c,make命令檢查發現當前目錄下存在該文件,然后執行第三條規則的命令“gcc -c calc.c”生成 calc.o 文件,至此第一條規則依賴的 main.o、calc.o;兩個文件已經生成了,然后運行第一條規則的命令“gcc -o mainmain.o calc.o”生成 main 文件。因為 make 命令運行的時候會從 Makefile 的第一條規則開始解析,然后根據第一條規則的依賴文件去遍歷文件中的“對應規則”,然后在根據“對應規則”的依賴文件去遍歷“對應的規則”,采用這樣遞歸的方式會遍歷出完成第一條規則所需要的所有規則。下面我們來看看第四條規則的目標文件是 clean,我們通過查看發現該規則與第一條規則沒有關聯,所以我們在運行 make 命令的時候,不會遍歷到該規則。我們可以在終端輸入“make clean”命令來運行第四條規則,第四條規則沒有依賴的文件,所以執行運行命令“rm -rf *.o”和“rm -rf main”,這兩條命令的功能是刪除以.o 問結尾的所有文件,刪除文件 main,運行如下圖所示:
通過上圖可以看到 main.o、mcalc.o 和 main 三個文件已經刪除了。通過該規則我們可以清除編譯產生的文件,實現工程的清理。
我們再來總結一下 make 命令的執行過程:
1.make 命令會在當前目錄下查找以 Makefile 命名的文件
2.找到 Makefile 文件,就會按照 Makefile 里面的規則去編譯,并生成最終文件
3.當發現目標文件不存在或者所依賴的文件比目標文件新(修改時間),就會執行規則對應的命令來更新。我們可以看到 make 是一個工具,他會通過 Makefile 文件里面的內容來執行具體的編譯過程。
3.4.2 Makefile  的變量
在 3.3.2 章節中的 Makefile 第一條規則:
main:main.o calc.o
gcc -o main main.o calc.o
在該規則中 main.o、calc.o 這兩個文件我們輸入了兩次,由于我們的額 Makefile 文件內容比較少,如果 Makefile 復雜的情況下,這種重復的輸入就會非常占用時間,而且修改起來也會很麻煩,為了解決這個問題,Makefile 可以使用變量。Makefile 的變量是一個字符串。比如上面的規則我們聲明一個變量,叫objects,objs 或者是 OBJ,反正不管是什么,只要能夠表示 main.o、calc.o 就行了,我們修改上面的規則
1 objects = main.o calc.o
2 2 main( objects)
3 3 gcc -o main $( objects)
我們來分析下修改后的規則,首先第一行是我們定義了一個變量 objects,并給賦值“main.o calc.o”,第二行、第三行用到了變量 objects。Makefile 中的變量引用方式是“$(變量名)”,變量 objects 的賦值使用“=”,Makefile 中變量的賦值還可以使用“:=”、“?=”、“+=”,這四種賦值的區別如下:
1. “= = ” 賦值符
我們先在用戶根目錄的 work 目錄下創建一個 Makefile 腳本,輸入下面的內容:
1 ceshi1 = test
2 ceshi2 = $(ceshi1)
3 ceshi1 = temp
4
5 out:
6 @echo ceshi2(ceshi2)
第一行我們定義了變量并賦值“test”,第二行定義了變量 ceshi2 并賦值變量 ceshi1,第三行修改變量ceshi1 的值為“temp”,第五行、第六行是輸出變量 ceshi2 的值。我們在終端輸入“make out”命令,如下圖所示:
在上圖可以看到變量 ceshi2 的值是 temp,也就是變量 ceshi1 最后一次的賦值。
2. “ := ” 賦值符
我們修改“=”賦值符中的代碼,第二行的“=”改成“:=”,代碼如下:
1 ceshi1 = test
2 ceshi2 := $(ceshi1)
3 ceshi1 = temp
4
5 out:
6 @echo ceshi2(ceshi2)
我們在終端輸入“make out”命令,如下圖所示:
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml10068\wps4.png
我們可以看到上圖的運行結果輸出變量 ceshi2 的值是 test,雖然在第三行我們修改了變量 ceshi1 的
值,通過本實驗我們可以看到“:=”賦值符的功能了。
3. “ ?= ” 賦值符
ceshi ?= test
“?=”賦值符的作用是如果前面沒有給變量 ceshi 賦值,那么變量就賦值“test”,如果前面已經賦值了,就使用前面的賦值。
4. “ += ” 賦值符
objs = main.o
objs += calc.o
上面的腳本最后變量 objs 的值是“main.o calc.o”,“+=”賦值符的功能是實現變量的追加。
3.4.3  條件判斷
使用條件判斷,可以讓 make 根據運行時的不同情況選擇不同的執行分支。條件表達式可以是比較變量的值,或是比較變量和常量的值。其語法有下面兩種:
1.
<條件比較>
[條件為真時執行的腳本]
endif
2.
<條件比較>
[條件為真時執行的腳本]
else
[條件為假時執行的腳本]
endif
條件比較用到的比較關鍵字有:ifeq、ifneq、ifdef、ifndef。
ifeq 表示如果比較相等,語法如下:
ifeq(<參數 1>, <參數 2>)
ifneq 表示如果不相等,語法如下:
ifneq(<參數 1>, <參數 2>)
ifdef 表示如果定義了變量,語法如下:
ifdef <變量名>
ifndef 表示如果沒有定義變量,語法如下:
ifndef <變量名>
3.4.4  使用函數
在 Makefile 中可以使用函數來處理變量,從而讓我們的命令或是規則更為的靈活和具有智能。make 所支持的函數也不算很多,不過已經足夠我們的操作了。函數調用后,函數的返回值可以當做變量來使用。
函數的調用很像變量的使用,也是以“$”來標識的,語法如下:
$(<函數名> <參數集合>)
或者:
${<函數名> <參數集合>}
函數名和參數集合之間以空格分隔,參數集合的參數通過逗號分隔。函數調用以“$”開頭,以圓括號或花括號把函數名和參數括起。感覺很像一個變量。函數中的參數可以使用變量。為了風格的統一,函數和變量的括號最好一樣,如使用“$(subst a,b,$(x))”這樣的形式,而不是“$(subst a,b,${x})”的形式。
因為統一會更清楚,也會減少一些不必要的麻煩。
接下來我們介紹幾個常用的函數,其它的函數可以參考文檔《跟我一起寫 Makefile》。
t 1.subst  函數
$(subst ,,)
此函數的功能是把字串中的字符串替換成,函數返回被替換過后的字符串。如下示例:
$(subst ee,EE,feet on the street)
以上腳本實現把字符串“feet on the street”中的“ee”字符串替換成“EE”字符串,替換后的字符串
為“feet on the strEEt”。
. 2. t patsubst  函數
$(patsubst ,,)
此函數的功能是查找中的單詞(單詞以“空格”、“Tab”或“回車”“換行”分隔)是否符合模式,如果匹配的話,則以替換。這里可以包括通配符“%”,表示任意長度的字串。如果中也包含“%”,那么中的這個“%”將是中的那個“%”所代表的字串。(可以用“\”來轉義,以“\%” 來表示真實含義的“%”字符)。函數返回被替換過后的字符串。如下示例:
$(patsubst %.c,%.o,x.c bar.c)
以上腳本實現把字串“x.c bar.c”符合模式[%.c]的單詞替換成[%.o],返回結果是“x.o bar.o”
3.strip  函數
$(strip )
此函數的功能是去掉字串中開頭和結尾的空字符,函數返回被去掉空格的字符串值。如下示例:
$(strip a b c )
以上腳本實現把字串“a b c ”去掉開頭和結尾的空格,結果是“a b c”。
. 4. g findstring  函數
$(findstring ,)
此函數的功能是在字串中查找字串,如果找到,那么返回,否則返回空字符串,如下示
例:
$(findstring a,a b c)
$(findstring a,b c)
以上腳本,第一個返回“a”字符串,第二個返回空字符串。
r 5.dir  函數
$(dir )
此函數的功能是從文件名序列中取出目錄部分。目錄部分是指最后一個反斜杠(“/”)之前的部
分。如果沒有反斜杠,那么返回“./”。返回文件名序列的目錄部分,如下示例:
$(dir src/foo.c hacks)
以上腳本運行結果返回“src/”。
. 6. r notdir  函數
$(notdir )
此函數的功能是從文件名序列中取出非目錄部分。非目錄部分是指最后一個反斜杠(“/”)之后
的部分,返回文件名序列的非目錄部分,如下示例:
$(notdir src/foo.c)
以上腳本返回字符串“foo.c”
. 7. h foreach  函數
$(foreach ,,)
此函數的功能是把參數中的單詞逐一取出放到參數所指定的變量中,然后再執行所包含的表達式。每一次會返回一個字符串,循環過程中,的所返回的每個字符串會以空格分隔,最后當整個循環結束時,所返回的每個字符串所組成的整個字符串(以空格分隔)將會是 foreach 函數的返回值。所以,最好是一個變量名,可以是一個表達式,而中一般會使用這個參數來依次枚舉中的單詞。如下示例:
names := a b c d
files := $(foreach n,$(names),$(n).o)
以上腳本實現$(name)中的單詞會被挨個取出,并存到變量“n”中,“$(n).o”每次根據“$(n)”計算出一個值,這些值以空格分隔,最后作為 foreach 函數的返回,所以$(files)的值是“a.o b.o c.o d.o”。(注意,foreach 中的參數是一個臨時的局部變量,foreach 函數執行完后,參數的變量將不在作用,其作用域只在 foreach 函數當中)。
3.4.5  在規則中使用通配符
如果我們想定義一系列比較類似的文件,我們很自然地就想起使用通配符。make 命令支持三種通配符:“*”,“?”和“[...]”,這是和 Unix 的 B-Shell 是相同的。“~”字符在文件名中也有比較特殊的用途。如果是“~/test”,這就表示當前用戶根目錄下的 test 文件。而“~admin/test”則表示用戶 admin 根目錄下的 test 文件。通配符代替了一系列的文件,如“*.c”表示所有后綴為 .c 的文件。一個需要我們注意的是,如果我們的文件名中有通配符,如:“*”,那么可以用轉義字符“\”,如“\*” 來表示真實的“*”字符,而不是任意長度的字符串。
下面我們來看幾個具體的示例:
clean:
rm -rf *.o
上面這個示例說明通配符可以在規則的命令中使用。
print: *.c
上面這個示例說明通配符可以在規則的依賴中使用
objects = *.o
上面這個示例表示了,通符同樣可以用在變量中。并不是說[*.o]會展開,objects 的值就是“*.o”。Makefile中的變量其實就是 C/C++中的宏。如果你要讓通配符在變量中展開,也就是讓 objects 的值是所有[.o]的文件名的集合,那么,你可以這樣:
objects := $(wildcard *.o)
這種用法由關鍵字“wildcard”指出,關于 Makefile 的關鍵字可以參考文檔《跟我一起寫 Makefile》。
關于 Makefile 的相關內容我們就介紹到這里,本節只是對 Makefile 做了基本的講解,Mkaefile 還有大量
完結,更多內容關注:
https://item.taobao.com/item.htm?spm=a2oq0.12575281.0.0.34851debJbM0Ye&ft=t&id=614020183147&qq-pf-to=pcqq.c2c
本文地址:http://m.qingdxww.cn/thread-589981-1-1.html     【打印本頁】

本站部分文章為轉載或網友發布,目的在于傳遞和分享信息,并不代表本網贊同其觀點和對其真實性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問題,我們將根據著作權人的要求,第一時間更正或刪除。
您需要登錄后才可以發表評論 登錄 | 立即注冊

廠商推薦

  • Microchip視頻專區
  • 利用SAM E54 Xplained Pro評估工具包演示CAN轉USB橋接器以及基于CAN的主機和自舉程序應用程序
  • 使用SAM-IoT Wx v2開發板演示AWS IoT Core應用程序
  • 使用Harmony3加速TCP/IP應用的開發培訓教程
  • 集成高級模擬外設的PIC18F-Q71家族介紹培訓教程
  • 貿澤電子(Mouser)專區
關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯系我們
電子工程網 © 版權所有   京ICP備16069177號 | 京公網安備11010502021702
快速回復 返回頂部 返回列表
主站蜘蛛池模板: 黄页网站在线播放 | 91在线高清 | 色婷婷综合缴情综六月 | 麻豆久久婷婷综合五月国产 | 第一福利在线观看 | 国产麻豆a一级毛片爽爽影院 | 羞羞免费网站 | 99热这里有精品 | 2018精品国产一区二区 | 一区高清| 免费国产99久久久香蕉 | 黄色一级片黄色一级片 | 亚洲精品网站在线观看不卡无广告 | 国产精品久久久久久久毛片 | 亚洲xx视频 | 大乳女子一级毛片 | 亚洲高清在线观看看片 | 国产va欧美va在线观看 | 免费香蕉成视频成人网 | 和阿同居的日子hd | 欧美日本一道免费一区三区 | 欧美一区欧美二区 | 四虎最新网站 | 精品卡一卡卡2卡3网站 | 日韩久久精品一区二区三区 | 欧美日本韩国一区二区 | 91亚洲人成手机在线观看 | 看片天堂| 中文字幕视频二区 | 国产偷久久 | 国产精彩对白综合视频 | 久久综合结合久久很很很97色 | 日本一区二区三区精品 | 全部免费的毛片在线看美国 | 香蕉视频网站免费观视频 | 免费人成在线观看网站 | 91精品国产一区 | 亚洲va国产日韩欧美精品色婷婷 | 亚洲91在线视频 | 日韩一级片在线 | 亚洲综合校园春色 |