偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

利用Makfile給多文件、多目錄C源碼建立工程

系統(tǒng) Linux
我們將該項目的所有功能函數(shù)放到以該函數(shù)名命名的c文件,同時放到對應名稱的子目錄中。比如函數(shù)allfree(),存放到 allfree/allfree.c中。

[[429525]]

0. 前言

粉絲留言,想知道如何使用Makefile給多個文件和多級目錄建立一個工程,必須安排!

關(guān)于Makefile的入門參考文章,可以先看這篇文章:

《Makefile入門教程》

為了讓大家有個更加直觀的感受,一口君將之前寫的一個小項目,本篇在該項目基礎上進行修改。

該項目詳細設計和代碼,見下文:

《從0寫一個《電話號碼管理系統(tǒng)》的C入門項目【適合初學者】》

一、文件

好了,開始吧!

我們將該項目的所有功能函數(shù)放到以該函數(shù)名命名的c文件,同時放到對應名稱的子目錄中。

比如函數(shù)allfree(),存放到 allfree/allfree.c中

最終目錄結(jié)構(gòu)如下圖所示:

  1.  peng@ubuntu:/mnt/hgfs/code/phone$ tree . 
  2. ├── allfree 
  3. │   ├── allfree.c 
  4. │   └── Makefile 
  5. ├── create 
  6. │   ├── create.c 
  7. │   └── Makefile 
  8. ├── delete 
  9. │   ├── delete.c 
  10. │   └── Makefile 
  11. ├── display 
  12. │   ├── display.c 
  13. │   └── Makefile 
  14. ├── include 
  15. │   ├── Makefile 
  16. │   └── phone.h 
  17. ├── init 
  18. │   ├── init.c 
  19. │   └── Makefile 
  20. ├── login 
  21. │   ├── login.c 
  22. │   └── Makefile 
  23. ├── main 
  24. │   ├── main.c 
  25. │   └── Makefile 
  26. ├── Makefile 
  27. ├── menu 
  28. │   ├── Makefile 
  29. │   └── menu.c 
  30. ├── scripts 
  31. │   └── Makefile 
  32. └── search 
  33.     ├── Makefile 
  34.     └── search.c 
  35.  
  36. 11 directories, 22 files 

直接看下編譯結(jié)果吧:

  1. peng@ubuntu:/mnt/hgfs/code/phone$ make 
  2. make[1]: Entering directory '/mnt/hgfs/code/phone/allfree' 
  3. make[1]: Nothing to be done for 'all'
  4. make[1]: Leaving directory '/mnt/hgfs/code/phone/allfree' 
  5. make[1]: Entering directory '/mnt/hgfs/code/phone/create' 
  6. make[1]: Nothing to be done for 'all'
  7. make[1]: Leaving directory '/mnt/hgfs/code/phone/create' 
  8. make[1]: Entering directory '/mnt/hgfs/code/phone/delete' 
  9. make[1]: Nothing to be done for 'all'
  10. make[1]: Leaving directory '/mnt/hgfs/code/phone/delete' 
  11. make[1]: Entering directory '/mnt/hgfs/code/phone/display' 
  12. make[1]: Nothing to be done for 'all'
  13. make[1]: Leaving directory '/mnt/hgfs/code/phone/display' 
  14. make[1]: Entering directory '/mnt/hgfs/code/phone/init' 
  15. make[1]: Nothing to be done for 'all'
  16. make[1]: Leaving directory '/mnt/hgfs/code/phone/init' 
  17. make[1]: Entering directory '/mnt/hgfs/code/phone/login' 
  18. make[1]: Nothing to be done for 'all'
  19. make[1]: Leaving directory '/mnt/hgfs/code/phone/login' 
  20. make[1]: Entering directory '/mnt/hgfs/code/phone/menu' 
  21. make[1]: Nothing to be done for 'all'
  22. make[1]: Leaving directory '/mnt/hgfs/code/phone/menu' 
  23. make[1]: Entering directory '/mnt/hgfs/code/phone/search' 
  24. make[1]: Nothing to be done for 'all'
  25. make[1]: Leaving directory '/mnt/hgfs/code/phone/search' 
  26. make[1]: Entering directory '/mnt/hgfs/code/phone/main' 
  27. make[1]: Nothing to be done for 'all'
  28. make[1]: Leaving directory '/mnt/hgfs/code/phone/main' 
  29. gcc -Wall -O3 -o phone allfree/*.o create/*.o delete/*.o display/*.o init/*.o login/*.o menu/*.o search/*.o main/*.o -lpthread 
  30. phone make done!  

運行結(jié)果如下:

二、Makefile常用基礎知識點

[0] 符號'@' '$' '$$' '-' '-n '的說明

1.'@'

通常makefile會將其執(zhí)行的命令行在執(zhí)行前輸出到屏幕上。如果將‘@’添加到命令行前,這個命令將不被make回顯出來。例如:

  1. @echo  --compiling module----;  // 屏幕輸出  --compiling module---- 
  2. echo  --compiling module----;  // 沒有@ 屏幕輸出echo  --compiling module----    

2.' - '

通常刪除,創(chuàng)建文件如果碰到文件不存在或者已經(jīng)創(chuàng)建,那么希望忽略掉這個錯誤,繼續(xù)執(zhí)行,就可以在命令前面添加 -,

  1. -rm dir; 
  2. -mkdir aaadir; 

3.' $ '美元符號$,主要擴展打開makefile中定義的變量

4.' $$ '$$ 符號主要擴展打開makefile中定義的shell變量

[1] wildcard

說明: 列出當前目錄下所有符合模式“ PATTERN”格式的文件名,并且以空格分開。“ PATTERN”使用shell可識別的通配符,包括“ ?”(單字符)、“ *”(多字符)等。示例:

  1. $(wildcard *.c)  

返回值為當前目錄下所有.c 源文件列表。

[2] patsubst

說明:把字串“ x.c.c bar.c”中以.c 結(jié)尾的單詞替換成以.o 結(jié)尾的字符。示例:

  1. $(patsubst %.c,%.o,x.c.c bar.c) 

函數(shù)的返回結(jié)果 是

  1. x.c.o bar.o 

[3] notdir

說明:去除文件名中的路徑信息 示例:

  1. SRC = ( notdir ./src/a.c )  

去除文件a . c 的路徑信息 , 使用 (notdir ./src/a.c) 去除文件a.c的路徑信息,使用 (notdir./src/a.c)去除文件a.c的路徑信息,使用(SRC)得到的是不帶路徑的文件名稱,即a.c。

[4] 包含頭文件路徑

使用-I+頭文件路徑的方式可以指定編譯器的頭文件的路徑 示例:

  1. INCLUDES = -I./inc 
  1. $(CC) -c $(INCLUDES) $(SRC) 

[5] addsuffix

函數(shù)名稱:加后綴函數(shù)—addsuffix。語法:

  1. $(addsuffix SUFFIX,NAMES…)  

函數(shù)功能:為“NAMES…”中的每一個文件名添加后綴“SUFFIX”。參數(shù)“NAMES…” 為空格分割的文件名序列,將“SUFFIX”追加到此序列的每一個文件名 的末尾。返回值:以單空格分割的添加了后綴“SUFFIX”的文件名序列。函數(shù)說明:示例:

  1. $(addsuffix .c,foo bar)  

返回值為

  1. foo.c bar.c 

[6] 包含另外一個文件:include

在Makefile使用include關(guān)鍵字可以把別的Makefile包含進來,這很像C語言的#include,被包含的文件會原模原樣的放在當前文件的包含位置。比如命令

  1. include file.dep 

即把file.dep文件在當前Makefile文件中展開,亦即把file.dep文件的內(nèi)容包含進當前Makefile文件

在 include前面可以有一些空字符,但是絕不能是[Tab]鍵開始。

[7] foreach

foreach函數(shù)和別的函數(shù)非常的不一樣。因為這個函數(shù)是用來做循環(huán)用的 語法是:

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

這個函數(shù)的意思是,把參數(shù)中的單詞逐一取出放到參數(shù)所指定的變量中,然后再執(zhí)行所包含的表達式。

每一次會返回一個字符串,循環(huán)過程中,的所返回的每個字符串會以空格分隔,最后當整個循環(huán)結(jié)束時,所返回的每個字符串所組成的整個字符串(以空格分隔)將會是foreach函數(shù)的返回值。

所以,最好是一個變量名,可以是一個表達式,而中一般會使用這個參數(shù)來依次枚舉中的單詞。

舉例:

  1. names := a b c d 
  2. files := $(foreach n,$(names),$(n).o) 

上面的例子中,$(name)中的單詞會被挨個取出,并存到變量“n”中,“$(n).o”每次根據(jù)“$(n)”計算出一個值,這些值以空格分隔,最后作為foreach函數(shù)的返回,所以,$(files)的值是“a.o b.o c.o d.o”。

注意,foreach中的參數(shù)是一個臨時的局部變量,foreach函數(shù)執(zhí)行完后,參數(shù)的變量將不在作用,其作用域只在foreach函數(shù)當中。

[8] call

“ call”函數(shù)是唯一一個可以創(chuàng)建定制化參數(shù)函數(shù)的引用函數(shù)。使用這個函數(shù)可以實現(xiàn)對用戶自己定義函數(shù)引用。我們可以將一個變量定義為一個復雜的表達式,用“ call”函數(shù)根據(jù)不同的參數(shù)對它進行展開來獲得不同的結(jié)果。

函數(shù)語法:

  1. $(call variable,param1,param2,...) 

函數(shù)功能:在執(zhí)行時,將它的參數(shù)“ param”依次賦值給臨時變量“ $(1)”、“ $(2)” call 函數(shù)對參數(shù)的數(shù)目沒有限制,也可以沒有參數(shù)值,沒有參數(shù)值的“ call”沒有任何實際存在的意義。執(zhí)行時變量“ variable”被展開為在函數(shù)上下文有效的臨時變量,變量定義中的“ $(1)”作為第一個參數(shù),并將函數(shù)參數(shù)值中的第一個參數(shù)賦值給它;變量中的“ $(2)”一樣被賦值為函數(shù)的第二個參數(shù)值;依此類推(變量**$(0)**代表變量“ variable”本身)。之后對變量“ variable” 表達式的計算值。

返回值:參數(shù)值“ param”依次替換“ $(1)”、“ $(2)”…… 之后變量“ variable”定義的表達式的計算值。

函數(shù)說明:

  1. 函數(shù)中“ variable”是一個變量名,而不是變量引用。因此,通常“ call”函數(shù)中的“ variable”中不包含“ $”(當然,除非此變量名是一個計算的變量名)。
  2. 當變量“ variable”是一個 make 內(nèi)嵌的函數(shù)名時(如“ if”、“ foreach”、“ strip”等),對“ param”參數(shù)的使用需要注意,因為不合適或者不正確的參數(shù)將會導致函數(shù)的返回值難以預料。
  3. 函數(shù)中多個“ param”之間使用逗號分割。
  4. 變量“ variable”在定義時不能定義為直接展開式!只能定義為遞歸展開式。

函數(shù)示例:

  1. reverse = $(2)$(1) 
  2. foo = $(call reverse,a,b) 
  3. all
  4.  @echo "foo=$(foo)" 

執(zhí)行結(jié)果:

  1. foo=ba 

即a替代了替代了(2)

三、編譯詳細說明

我們在根目錄下執(zhí)行make命令后,詳細步驟如下:

1.include scripts/Makefile :將文件替換到當前位置,

2.使用默認的目標all,該目標依賴于$(Target)$(Target) 在scripts/Makefile中定義了,即phone

3.而$(Target)依賴于mm

4.mm這個目標會執(zhí)行

  1. @ $(foreach n,$(Modules),$(call modules_make,$(n))) 

Modules是所有的目錄名字集合, foreach 會遍歷字符串$(Modules)中每個詞語, 每個詞語會賦值給n, 同時執(zhí)行語句:

  1. call modules_make,$(n) 

5.modules_make 被$(MAKE) -C $(1)所替代,

$(MAKE) 有默認的名字make -C:進入子目錄執(zhí)行make$(1) :是步驟4中$(n),即每一個目錄名字

最終步驟4的語句就是進入到每一個目錄下,執(zhí)行每一個目錄下的Makefile

6.進入某一個子目錄下,執(zhí)行Makefile 默認目標是all,依賴Objs

  1. Objs := $(patsubst %.c,%.o,$(Source)) 

patsubst 把字串$ource中以.c 結(jié)尾的單詞替換成以.o 結(jié)尾的字符 而

  1. Source := $(wildcard ./*.c) 

wildcard 會列舉出當前目錄下所有的.c文件

所以第6步最終就是將子目錄下的所有的.c文件,編譯生成對應文件名的.o文件

  1. $(CC) $(CFLAGS) -o $(Target) $(AllObjs) $(Libs) 

這幾個變量都在文件scripts/Makefile中定義$(CC) :替換成gcc,制定編譯器$(CFLAGS) :替換成-Wall -O3,即編譯時的優(yōu)化等級-o $(Target):生成可執(zhí)行程序phone$(AllObjs) :

  1. AllObjs := $(addsuffix /*.o,$(Modules)) 

addsuffix 會將 /*.o追加到$(Modules)中所有的詞語后面,也就是我們之前在子目錄下編譯生成的所有的.o文件$(Libs) :替換為-lpthread,即所需要的動態(tài)庫

大家可以根據(jù)這個步驟,來分析一下執(zhí)行make clean時,執(zhí)行步驟

本文轉(zhuǎn)載自微信公眾號「一口Linux」

 

責任編輯:姜華 來源: 一口Linux
相關(guān)推薦

2020-03-17 17:49:58

C語言編程語言

2020-03-18 12:23:49

C語言編程語言

2024-08-20 07:55:03

2024-01-16 11:43:38

C++HashMap

2010-08-26 13:17:27

DHCP服務器

2022-04-08 07:52:00

架構(gòu)多機房多活

2021-12-15 11:30:04

無人駕駛智能技術(shù)

2009-02-03 09:48:00

DHCPVlAN

2009-06-16 10:20:05

多繼承C#

2021-04-12 18:14:56

鴻蒙HarmonyOS應用開發(fā)

2010-01-15 18:06:58

CentOS文件

2024-12-06 15:11:34

Python文件夾目錄

2019-07-04 14:40:28

FacebookRAT惡意軟件

2012-05-08 13:24:45

負載均衡帶寬銳捷網(wǎng)絡

2009-08-07 13:38:18

C#文件相對路徑

2018-08-20 16:00:23

MySQL并發(fā)控制MVCC

2020-10-23 10:10:59

Promise前端代碼

2009-05-26 12:23:56

Linux變量文件命名

2022-03-28 10:25:27

前端文件編譯器

2009-07-21 17:39:50

iBATIS的多對多映
點贊
收藏

51CTO技術(shù)棧公眾號