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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

make工具和Makefile基础语法(含有交叉编译、pthread_create()的处理)

發布時間:2023/12/10 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 make工具和Makefile基础语法(含有交叉编译、pthread_create()的处理) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

  • 含有交叉編譯、pthread_create()處理
  • 初次使用
    • 1、編寫Makefile文件
    • 2、make
    • 3、make clean
  • Makefile基本語法
    • 1、Makefile規則格式
    • 2、變量
    • 3、變量賦值符(=、:=、?=、+=)
    • 4、模式規則(通配符)
    • 5、自動化變量
    • 6、偽目標
    • 7、條件判斷
    • 8、函數使用
      • 1、函數 subst
      • 2、函數 patsubst
      • 3、函數 dir
      • 4、函數 notdir
      • 5、函數 foreach
      • 6、函數 wildcard

含有交叉編譯、pthread_create()處理

摘自:使用makefile編譯含有pthread_create()函數時報錯:對‘pthread_create’未定義的引用

交叉編譯的話直接將Makefile里面的gcc替換成arm-linux-gnueabihf-gcc即可。

在linux應用程序中使用了多線程編程,但是makefile編譯卻報如下錯誤:

/tmp/cc5i6uH7.o:在函數‘main’中: tcpSever.c:(.text+0x62):對‘modRegInit’未定義的引用 tcpSever.c:(.text+0x76):對‘ryS’未定義的引用 tcpSever.c:(.text+0xc0):對‘ryS’未定義的引用 tcpSever.c:(.text+0x10a):對‘ryS’未定義的引用 tcpSever.c:(.text+0x14e):對‘ryS’未定義的引用 collect2: error: ld returned 1 exit status

網上查找解決方案,發現修改makefile即可。如下

test: rySys.o tcpSever.ogcc -o test rySys.o tcpSever.o -lpthread rySys.o: rySys.c rySys.hgcc -c rySys.c -lpthread tcpSever.o: tcpSever.c rySys.c rySys.hgcc -c tcpSever.c -lpthread clean:rm *.orm test

初次使用

當文件有幾十、上百甚至上萬個的時候用終端輸入 gcc 命令的方法顯然是不現實的,為此提出了一個解決大工程編譯的工具:make,描述哪些文件需要編譯、哪些需要 重新編譯 的文件就叫做 Makefile。使用的時候只需要一個 make 命令即可完成整個工程的自動編譯,極大的提高了軟件開發的效率。

使用make工具可以自動完成編譯工作,這些工作包括:

  • 如果修改了某幾個源文件,則只重新編譯這幾個源文件;
  • 如果某個頭文件被修改了,則重新編譯所有包含該頭文件的源文件。

1、編寫Makefile文件

在工程目錄下創建Makefile文件:

Makefile 里面是由一系列的規則組成的,這些規則格式如下:

目標…... : 依賴文件集合……命令1命令2……

Makefile 和 .c 文件是處于同一個目錄的,在Makefile文件中輸入如下代碼:

main: main.o fun1.o fun2.ogcc -o main main.o fun1.o fun2.o main.o: main.cgcc -c main.c fun1.o: fun1.cgcc -c fun1.c fun2.o: fun2.cgcc -c fun2.cclean:rm *.orm main

上述代碼中所有行首需要空出來的地方一定要使用 “TAB” 鍵!不要使用空格鍵!這是 Makefile 的語法要求

2、make

Makefile 編寫好以后我們就可以使用make命令來編譯我們的工程了,直接在命令行中輸入make即可,make 命令會在當前目錄下查找是否存在 “Makefile” 這個文件,如果存在的話就會按照 Makefile 里面定義的編譯方式進行編譯:

make


此時我們修改一下 fun1.c 的文件源碼,再make:

可以看出因為我們修改了fun1.c這個文件,所以fun1.c和最后的可執行文件main重新編譯了,其它沒有修改過的文件就沒有編譯,而且我們只需要輸入make命令即可,非常方便。

3、make clean

make clean

Makefile基本語法

1、Makefile規則格式

目標...: 依賴文件集合...命令1命令2......

!!命令列表中的每條命令必須以 TAB 鍵開始,不能使用空格!

  • 比如:
main: main.o fun1.o fun2.ogcc -o main main.o fun1.o fun2.o

這條規則的目標是main,main.o、fun1.o、fun2.o是生成main的依賴文件,如果要更新目標main,就必須先更新它的所有依賴文件,如果依賴文件中的任何一個有更新(更改時間),那么目標也必須更新,“更新”就是執行一遍規則中的命令列表。make命令會為Makefile中的每個以 TAB 開始的命令創建一個 Shell 進程去執行。

  • 示例:
main: main.o fun1.o fun2.ogcc -o main main.o fun1.o fun2.o main.o: main.cgcc -c main.c fun1.o: fun1.cgcc -c fun1.c fun2.o: fun2.cgcc -c fun2.cclean:rm *.orm main

make命令在執行這個Makefile的時候其執行步驟如下:

首先更新第一條規則中的main,第一條規則的目標成為默認目標,只要默認目標更新了那么就認為Makefile的工作完成。在第一次編譯的時候由于main還不存在,因此第一條規則會執行,第一條規則依賴于文件main.o、fun1.o和fun2.o這個三個.o文件,這三個.o文件目前還都沒有,因此必須先更新這三個文件。make 會查找以這三個.o文件為目標的規則并執行。

以main.o為例,發現更新main.o的是第二條規則,因此會執行第二條規則,第二條規則里面的命令為“gcc –c main.c”,這行命令就是不鏈接編譯main.c,生成main.o。

最后一個規則目標是clean,它沒有依賴文件,因此會默認為依賴文件都是最新的,所以其對應的命令不會執行,當我們想要執行clean的話可以直接使用命令make clean,執行以后就會刪除當前目錄下所有的.o文件以及main,因此clean的功能就是完成工程的清理工作。

  • 總結make執行過程:

① make命令會在當前目錄下查找以 Makefile(或makefile) 命名的文件。

② 當找到 Makefile 文件以后就會按照 Makefile 中定義的規則去編譯生成最終的目標文件。

③ 當發現目標文件不存在,或者目標所依賴的文件比目標文件新(也就是最后修改時間比目標文件晚)的話就會執行后面的命令來更新目標。

!!注意: 除了 Makefile 的“終極目標”所在的規則以外,其它規則的順序在 Makefile中是沒有意義的,“終極目標”就是指在使用 make 命令的時候沒有指定具體的目標時,make 默認的那個目標,它是 Makefile 文件中第一條規則的目標,如果 Makefile 中的第一個規則有多個目標,那么這些目標中的第一個目標就是 make 的“終極目標”

2、變量

跟 C 語言一樣 Makefile 也是支持變量的,如前面的例子:

main: main.o fun1.o fun2.ogcc -o main main.o fun1.o fun2.o

上述 Makefile 語句中,main.o、fun1.o、fun2.o 這三個依賴文件,我們輸入了兩遍,我們這個 Makefile 比較小,如果 Makefile 復雜的時候這種重復輸入的工作就會非常費時間,Makefile 加入了變量支持,類似 C 語言中的宏。使用變量將上面的代碼修改:

# Makefile 變量的使用 objects = main.o fun1.o fun2.o main: $(objects)gcc -o main $(objects)

Makefile 的注釋用#。
我們定義了一個變量objects,并且給這個變量進行了賦值,其值為字符串main.o fun1.o fun2.o,Makefile 中變量的引用方法是 $(變量名),如本例中: $(objects)。

我們在定義變量objects 的時候使用“=”對其進行了賦值,Makefile
變量的賦值符還有其它兩個“:=”和“?=”,我們來看一下這三種賦值符的區別:

3、變量賦值符(=、:=、?=、+=)

使用“=”在給變量的賦值的時候,不一定要用已經定義好的值,也可以使用后面定義的值,比如如下代碼:

① 賦值符=:

name = lcx curname = $(name) name = licxprint:@echo curname: $(curname)

第一行定義了一個變量name,值為lcx,第二行定義了變量curname,值也為lcx,第三行變量name的值改為licx,第五、六行是輸出變量curname的值。在 Makefile 要輸出一串字符的話使用echo。(第六行中的echo前面加了個 @符號,因為 Make 在執行的過程中會自動輸出命令執行過程,在命令前加上@就不會輸出命令執行過程)執行結果:

可以看出,curname的值不是lcx,而是變量name最后一次賦值的結果。

② 賦值符:=:

name = lcx curname := $(name) name = licxprint:@echo curname: $(curname)

執行結果:

顯然,此時curname值為lcx,因為賦值符:=只能使用前面定義的值。

③ 賦值符?=

curname ?= licx

上述代碼的意思是,如果變量curname前面沒有被賦值,那么此變量就是licx,如果前面已經賦過值了,那么就使用前面賦的值。

④ 變量追加符+=

Makefile 中的變量是字符串,有時候我們需要給前面已經定義好的變量添加一些字符串,此時就要使用變量追加符號+=,如:

objects = main.o fun1.o objects += fun2.oprint:@echo objects: $(objects)


可以看出,objects最后的值為main.o fun1.o fun2.o。

4、模式規則(通配符)

如下示例代碼:

objects = main.o fun1.o fun2.o main: $(objects)gcc -o main $(objects)main.o: main.cgcc -c main.c fun1.o: fun1.cgcc -c fun1.c fun2.o: fun2.cgcc -c fun2.cclean:rm *.orm main

顯然,如果工程中.c文件很多,這樣做就很不方便,我們可以使用 Makefile 中的模式規則,使用一條規則來將所有的.c文件編譯為對應的.o文件。

模式規則中,至少在規則的目標定義中要包含%,否則就是一般規則,目標中的%表示對文件名的匹配,%表示長度任意的非空字符串,比如%.c就是所有的以.c結尾的文件,類似于通配符

示例可以改成如下形式:

objects = main.o fun1.o fun2.o main: $(objects)gcc -o main $(objects)%.o: %.c#命令clean:rm *.orm main

第六行的命令我們需要借助下面的自動化變量 ↓↓↓

5、自動化變量

上面講的模式規則中,目標和依賴都是一系列的文件,每一次對模式規則進行解析的時候都會是不同的目標和依賴文件,而命令只有一行,那么如何通過一行命令來從不同的依賴文件中生成對應的目標?自動化變量就是完成這個功能的!

自動化變量就是這種變量會把模中所定義的一系列的文件自動的挨個取出,直至所有的符合模式的文件都取完,自動化變量只應該出現在規則的命令中,常用的自動化變量如下:

常用的三種: $@、 $< 和 $^

那么上述代碼我們可以完善:

objects = main.o fun1.o fun2.o main: $(objects)gcc -o main $(objects)%.o: %.cgcc -c $<clean:rm *.orm main

6、偽目標

偽目標的主要是為了避免 Makefile 中定義的執行命令的目標和工作目錄下的實際文件出現名字沖突,有時候我們需要編寫一個規則用來執行一些命令,但是這個規則不是用來創建文件的,比如文章示例有如下代碼用來完成清理工程的功能:

clean:rm *.orm main

上述規則中并沒有創建clean文件的命令,因此工作目錄下永遠都不會存在文件clean,當我們輸入make clean以后,后面的rm *.o和rm main總是會執行。如果我們在工作目錄下創建一個名為clean(重名)的文件,當執行make clean的時候,規則因為沒有依賴文件,所以目標被認為是最新的 (剛創建了一個clean文件,是最新的),因此后面的rm命令也就不會執行,如圖所示:

為了避免這個問題,我們可以將clean聲明為偽目標,聲明方式如下:

.PHONY:clean

那么我們可以將示例代碼修改為:

.PHONY : cleanclean:rm *.orm main

7、條件判斷

在 C 語言中我們通過條件判斷語句來根據不同的情況來執行不同的分支,Makefile 也支持條件判斷,語法有兩種如下:

<條件關鍵字> <條件為真時執行的語句> endif

以及:

<條件關鍵字> <條件為真時執行的語句> else <條件為假時執行的語句> endif

其中條件關鍵字有 4 個:ifeq、ifneq、ifdef 和 ifndef,這四個關鍵字其實分為兩對、ifeq 與ifneq、ifdef 與 ifndef,先來看一下 ifeq 和 ifneq,ifeq 用來判斷是否相等,ifneq 就是判斷是否不相等,ifeq 用法如下:

ifeq (<參數 1>, <參數 2>) ifeq ‘<參數 1 >,<參數 2>’ ifeq “<參數 1>,<參數 2>” ifeq “<參數 1>,<參數 2>’ ifeq ‘<參數 1>,<參數 2>

上述用法中都是用來比較“參數 1”和“參數 2”是否相同,如果相同則為真,“參數 1”和“參數 2”可以為函數返回值。ifneq 的用法類似,只不過 ifneq 是用來了比較“參數 1”和“參數 2”是否不相等,如果不相等的話就為真。

ifdef 和 ifndef 的用法如下:

ifdef <變量名>

如果“變量名”的值非空,那么表示表達式為真,否則表達式為假。“變量名”同樣可以是一個函數的返回值。ifndef 用法類似,但是含義用戶 ifdef 相反。

8、函數使用

Makefile 支持函數,類似 C 語言一樣,Makefile 中的函數是已經定義好的,我們直接使用,不支持我們自定義函數。make 所支持的函數不多,函數的用法如下:

$(函數名 參數集合)

或者:

${函數名 參數集合}

可以看出,調用函數和調用普通變量一樣,使用符號 “$ ” 來標識。參數集合是函數的多個參數,參數之間以逗號“,”隔開,函數名和參數之間以“空格”分隔開,函數的調用以“$”開頭。

接下來我們介紹幾個常用的函數,來保證后面的學習。其它的函數大家可以參考《跟我一起寫 Makefile》這份文檔。

1、函數 subst

函數 subst 用來完成字符串替換,調用形式如下:

$(subst <from>,<to>,<text>)

此函數的功能是將字符串< text>中的內容替換為< to>,函數返回被替換以后的字符串,比如如下示例:

$(subst zzk,ZZK,my name is zzk

把字符串“my name is zzk”中的“zzk”替換為“ZZK”,替換完成以后的字符串為“my name is ZZK”。

2、函數 patsubst

函數 patsubst 用來完成模式字符串替換,使用方法如下:

$(patsubst <pattern>,<replacement>,<text>)

此函數查找字符串< text>中的單詞是否符合模式< pattern>,如果匹配就用< replacement>來替換掉,< pattern>可以使用通配符“%”,表示任意長度的字符串,函數返回值就是替換后的字符串。如果< replacement>中也包涵“%”,那么< replacement>中的“%”將是< pattern>中的那個“%”所代表的字符串,比如:

$(patsubst %.c,%.o,a.c b.c c.c)

將字符串“a.c b.c c.c”中的所有符合“%.c”的字符串,替換為“%.o”,替換完成以后的字符串為“a.o b.o c.o”。

3、函數 dir

函數 dir 用來獲取目錄,使用方法如下:

$(dir <names…>)

此函數用來從文件名序列< names>中提取出目錄部分,返回值是文件名序列< names>的目錄部分,比如:

$(dir </src/a.c>)

提取文件“/src/a.c”的目錄部分,也就是“/src”。

4、函數 notdir

函數 notdir 看名字就是知道去除文件中的目錄部分,也就是提取文件名,用法如下:

$(notdir <names…>)

此函數用與從文件名序列< names>中提取出文件名非目錄部分,比如:

$(notdir </src/a.c>)

提取文件“/src/a.c”中的非目錄部分,也就是文件名“a.c”。

5、函數 foreach

foreach 函數用來完成循環,用法如下:

$(foreach <var>, <list>,<text>)

此函數的意思就是把參數中的單詞逐一取出來放到參數 < var> 中, 然后再執行 < text > 所包含的表達式。每次 < text > 都會返回一個字符串,循環的過程中,< text > 中所包含的每個字符串會以空格隔開,最后當整個循環結束時,< text > 所返回的每個字符串所組成的整個字符串將會是函數 foreach 函數的返回值。

6、函數 wildcard

通配符“%”只能用在規則中,只有在規則中它才會展開,如果在變量定義和函數使用時,通配符不會自動展開,這個時候就要用到函數 wildcard,使用方法如下:

$(wildcard PATTERN…)

比如:

$(wildcard *.c)

上面的代碼是用來獲取當前目錄下所有的.c 文件,類似“%”。

總結

以上是生活随笔為你收集整理的make工具和Makefile基础语法(含有交叉编译、pthread_create()的处理)的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 亚洲做受高潮 | 日韩精品中文字幕一区二区三区 | 91视频毛片 | 与子敌伦刺激对白播放的优点 | 日韩高清在线观看一区 | 在线播放91| 激情网页| 国产亚洲性欧美日韩在线观看软件 | 亚洲一区二区三区免费看 | 免费看日批视频 | 婷婷在线免费 | 粉嫩在线 | 亚洲综合久久婷婷 | 国产精品无码中文 | 丁香六月婷婷综合 | av网站在线看 | 国产一区久久久 | 少妇野外性xx老女人野外性xx | 久久综合伊人77777麻豆最新章节 | 国产亚洲一区二区不卡 | 国产无码精品久久久 | 色网导航站 | 91影院在线免费观看 | 99久久免费看精品国产一区 | 国产精品一区二区三区四区视频 | 亚洲一区亚洲二区 | 嫩模被强到高潮呻吟不断 | 国产区一区二区三区 | 国产露出视频 | 一级特黄肉体裸片 | 深夜免费视频 | 91福利在线播放 | 精品久久蜜桃 | 国产av成人一区二区三区高清 | 999在线视频| 中文写幕一区二区三区免费观成熟 | 天操夜夜操 | 久久国产麻豆 | 制服丝袜中文字幕在线 | 91中文视频 | 波多野吉衣av无码 | 欧美日韩成人网 | 天堂网视频在线 | 成人一二三| 91黄色入口 | a视频免费观看 | 午夜欧美精品久久久久久久 | 亚洲国产经典 | 国产理论影院 | 黑丝袜av | 久久久久黄色 | 国产精品久久久午夜夜伦鲁鲁 | 国产色网址 | 西西久久 | 色五夜| 亚洲免费观看高清 | 主人性调教le百合sm | 在线看av的网址 | 天天干天天舔 | 日韩中文字幕国产 | 色咪咪网站| 在线看黄色网址 | 亚洲激情婷婷 | 亚洲中文字幕无码一区二区三区 | 亚洲三级国产 | 国产精品自产拍高潮在线观看 | 久草资源站 | 久久久九九九九 | 玖玖久久 | 午夜性影院 | 777奇米视频 | 青青草原免费观看 | 日本韩国在线播放 | 欧美videos另类极品 | 奇米综合| 国产免费av网址 | 女人下部全棵看视频 | 亚洲第一av网站 | a毛片大片 | 狠狠插狠狠操 | 亚洲精品乱码久久久久久黑人 | jjzz日本女人 | 狂野欧美性猛交xxxx777 | 午夜一本 | 色狠狠一区二区三区香蕉 | 久久精品久久久久 | 隣の若妻さん波多野结衣 | 成年人爱爱视频 | 妹子色综合 | av福利在线播放 | 欢乐谷在线观看免费播放高清 | 91精品国产综合久久久蜜臀九色 | 国产不卡av在线播放 | 国产一区二区三区在线观看免费 | 色图社区 | 亚洲视频小说 | 国产又粗又黄又爽视频 | 亚洲精品国产成人 | 私库av在线 |