1. 程式人生 > 實用技巧 >GCC編譯,庫的編譯使用及Makefile

GCC編譯,庫的編譯使用及Makefile

https://www.cnblogs.com/stewarttzy/p/3932507.html?utm_source=tuicool
將持續更新

一,gcc和g++編譯命令基礎

gcc/g++在執行編譯工作的時候,總共需要4步

1.預處理,生成.i的檔案[前處理器cpp]
2.將預處理後的檔案不轉換成組合語言,生成檔案.s[編譯器egcs]
3.有彙編變為目的碼(機器程式碼)生成.o的檔案[彙編器as]
4.連線目的碼,生成可執行程式[連結器ld]

[引數詳解]
-x language filename
   設定檔案所使用的語言,使字尾名無效,對以後的多個有效.也就是根
   據約定C語言的字尾名稱是.c的,而C++的字尾名是.C或者.cpp,如果
   你很個性,決定你的C程式碼檔案的字尾名是.pig 哈哈,那你就要用這
   個引數,這個引數對他後面的檔名都起作用,除非到了下一個引數
   的使用。
   可以使用的引數嗎有下面的這些
     c',

objective-c', c-header', c++', cpp-output',      assembler', and `assembler-with-cpp'.
   看到英文,應該可以理解的。
   例子用法:
   gcc -x c hello.pig
  
-x none filename
  關掉上一個選項,也就是讓gcc根據檔名字尾,自動識別檔案型別
  例子用法:
  gcc -x c hello.pig -x none hello2.c
  
-c
  只啟用預處理,編譯,和彙編,也就是他只把程式做成obj檔案
  例子用法:
  gcc -c hello.c
  他將生成.o的obj檔案

-S
  只啟用預處理和編譯,就是指把檔案編譯成為彙編程式碼。
  例子用法
  gcc -S hello.c
  他將生成.s的彙編程式碼,你可以用文字編輯器察看

-E
  只啟用預處理,這個不生成檔案,你需要把它重定向到一個輸出檔案裡
  面.
  例子用法:
  gcc -E hello.c > pianoapan.txt
  gcc -E hello.c | more
  慢慢看吧,一個hello word 也要與處理成800行的程式碼

-o
  指定目標名稱,預設的時候,gcc 編譯出來的檔案是a.out,很難聽,如果
  你和我有同感,改掉它,哈哈
  例子用法
  gcc -o hello.exe hello.c (哦,windows用習慣了)
  gcc -o hello.asm -S hello.c

-pipe
  使用管道代替編譯中臨時檔案,在使用非gnu彙編工具的時候,可能有些問
  題
  gcc -pipe -o hello.exe hello.c

-ansi
  關閉gnu c中與ansi c不相容的特性,啟用ansi c的專有特性(包括禁止一
  些asm inline typeof關鍵字,以及UNIX,vax等預處理巨集,

-fno-asm
  此選項實現ansi選項的功能的一部分,它禁止將asm,inline和typeof用作
  關鍵字。
    
-fno-strict-prototype
  只對g++起作用,使用這個選項,g++將對不帶引數的函式,都認為是沒有顯式
  的對引數的個數和型別說明,而不是沒有引數.
  而gcc無論是否使用這個引數,都將對沒有帶引數的函式,認為城沒有顯式說
  明的型別
  
-fthis-is-varialble
  就是向傳統c++看齊,可以使用this當一般變數使用.
  
-fcond-mismatch
  允許條件表示式的第二和第三引數型別不匹配,表示式的值將為void型別
  
-funsigned-char
-fno-signed-char
-fsigned-char
-fno-unsigned-char
  這四個引數是對char型別進行設定,決定將char型別設定成unsigned char(前
  兩個引數)或者 signed char(後兩個引數)
  
-include file
  包含某個程式碼,簡單來說,就是便以某個檔案,需要另一個檔案的時候,就可以
  用它設定,功能就相當於在程式碼中使用#include
  例子用法:
  gcc hello.c -include /root/pianopan.h
  
-imacros file
  將file檔案的巨集,擴充套件到gcc/g++的輸入檔案,巨集定義本身並不出現在輸入檔案
  中
  
-Dmacro
  相當於C語言中的#define macro
  
-Dmacro=defn
  相當於C語言中的#define macro=defn
  
-Umacro
  相當於C語言中的#undef macro

-undef
  取消對任何非標準巨集的定義
  
-Idir
  在你是用#include"file"的時候,gcc/g++會先在當前目錄查詢你所制定的頭
  檔案,如果沒有找到,他回到預設的標頭檔案目錄找,如果使用-I制定了目錄,他
  回先在你所制定的目錄查詢,然後再按常規的順序去找.
  對於#include,gcc/g++會到-I制定的目錄查詢,查詢不到,然後將到系
  統的預設的標頭檔案目錄查詢
  
-I-
  就是取消前一個引數的功能,所以一般在-Idir之後使用
  
-idirafter dir
  在-I的目錄裡面查詢失敗,講到這個目錄裡面查詢.
  
-iprefix prefix
-iwithprefix dir
  一般一起使用,當-I的目錄查詢失敗,會到prefix+dir下查詢
  
-nostdinc
  使編譯器不再系統預設的標頭檔案目錄裡面找標頭檔案,一般和-I聯合使用,明確
  限定標頭檔案的位置
  
-nostdin C++
  規定不在g++指定的標準路經中搜索,但仍在其他路徑中搜索,.此選項在建立
  libg++庫使用
  
-C
  在預處理的時候,不刪除註釋資訊,一般和-E使用,有時候分析程式,用這個很
  方便的
  
-M
  生成檔案關聯的資訊。包含目標檔案所依賴的所有原始碼
  你可以用gcc -M hello.c來測試一下,很簡單。
  
-MM
  和上面的那個一樣,但是它將忽略由#include造成的依賴關係。
  
-MD
  和-M相同,但是輸出將匯入到.d的檔案裡面
  
-MMD
  和-MM相同,但是輸出將匯入到.d的檔案裡面
  
-Wa,option
  此選項傳遞option給彙編程式;如果option中間有逗號,就將option分成多個選
  項,然後傳遞給會彙編程式
  
-Wl.option
  此選項傳遞option給連線程式;如果option中間有逗號,就將option分成多個選
  項,然後傳遞給會連線程式.
  

-llibrary
  制定編譯的時候使用的庫
  例子用法
  gcc -lcurses hello.c
  使用ncurses庫編譯程式
  
-Ldir
  制定編譯的時候,搜尋庫的路徑。比如你自己的庫,可以用它制定目錄,不然
  編譯器將只在標準庫的目錄找。這個dir就是目錄的名稱。
  
-O0
-O1
-O2
-O3
  編譯器的優化選項的4個級別,-O0表示沒有優化,-O1為預設值,-O3優化級別最
  高  
  
-g
  只是編譯器,在編譯的時候,產生條是資訊。
  
-gstabs
  此選項以stabs格式聲稱除錯資訊,但是不包括gdb除錯資訊.
  
-gstabs+
  此選項以stabs格式聲稱除錯資訊,並且包含僅供gdb使用的額外除錯資訊.
  
-ggdb
  此選項將盡可能的生成gdb的可以使用的除錯資訊.
-static
  此選項將禁止使用動態庫,所以,編譯出來的東西,一般都很大,也不需要什麼
動態連線庫,就可以執行.
-share
  此選項將盡量使用動態庫,所以生成檔案比較小,但是需要系統由動態庫.
-traditional
  試圖讓編譯器支援傳統的C語言特性

二,靜態庫,共享庫的編譯與使用

1.靜態庫建立及使用

示例:

複製程式碼
  base.h->a.cpp , baes.h->b.cpp

  g++ -c a.cpp
  g++ -c b.cpp
  ar -r libsay.a a.o b.o  # 編譯靜態庫:將所有目標檔案打包入庫中

  g++ main.cpp libsay.a -o run
複製程式碼

2.共享庫(動態庫)建立及使用

示例:

1   g++ -shared -fpic avg.cpp -o avg.so (編譯動態庫)
2
3   g++ main.cpp avg.so -o run

三,makefile的編寫

1.makefile的規則

target (目標檔案或label) : prerequisites (生成target所需要的東西)
command (執行的命令)
解釋:

  最終要生成的目標(run.bin) :中間的目標檔案(a1.o a2.o a3.o)

      編譯命令

2.makefile中常用函式表

(一)、字串處理函式
1.$(subst FROM,TO,TEXT)
函式名稱:字串替換函式—subst。
函式功能:把字串“TEXT”中的“FROM”字元替換為“TO”。
返回值:替換後的新字串。

2.$(patsubst PATTERN,REPLACEMENT,TEXT)
函式名稱:模式替換函式—patsubst。
函式功能:搜尋“TEXT”中以空格分開的單詞,將否符合模式“TATTERN”替換為“REPLACEMENT”。引數“PATTERN”中可以使用模
式萬用字元“%”來代表一個單詞中的若干字元。如果引數“REPLACEMENT”中也包含一個“%”,那麼“REPLACEMENT”中的“%”將是
“TATTERN”中的那個“%”所代表的字串。在“TATTERN”和“REPLACEMENT”中,只有第一個“%”被作為模式字元來處理,後續的作為字元本上來處理。在兩個引數中當使用第一個“%”本是字元本身時,可使用反斜槓“\”對它進行轉義處理。
返回值:替換後的新字串。
函式說明:引數“TEXT”單詞之間的多個空格在處理時被合併為一個空格,但前導和結尾空格忽略。

3.$(strip STRINT)
函式名稱:去空格函式—strip。
函式功能:去掉字串(若干單詞,使用若干空字元分割)“STRINT”開頭和結尾的空字元,並將其中多個連續空字符合併為一個空字元。
返回值:無前導和結尾空字元、使用單一空格分割的多單詞字串。
函式說明:空字元包括空格、[Tab]等不可顯示字元。

4.$(findstring FIND,IN)
函式名稱:查詢字串函式—findstring。
函式功能:搜尋字串“IN”,查詢“FIND”字串。
返回值:如果在“IN”之中存在“FIND”,則返回“FIND”,否則返回空。
函式說明:字串“IN”之中可以包含空格、[Tab]。搜尋需要是嚴格的文字匹配。

5.$(filter PATTERN…,TEXT)
函式名稱:過濾函式—filter。
函式功能:過濾掉字串“TEXT”中所有不符合模式“PATTERN”的單詞,保留所有符合此模式的單詞。可以使用多個模式。模式中一般需要包含模式字元“%”。存在多個模式時,模式表示式之間使用空格分割。
返回值:空格分割的“TEXT”字串中所有符合模式“PATTERN”的字串。
函式說明:“filter”函式可以用來去除一個變數中的某些字串,我們下邊的例子中就是用到了此函式。

6.$(filter-out PATTERN...,TEXT)
函式名稱:反過濾函式—filter-out。
函式功能:和“filter”函式實現的功能相反。過濾掉字串“TEXT”中所有符合模式“PATTERN”的單詞,保留所有不符合此模式的單詞。可以有多個模式。存在多個模式時,模式表示式之間使用空格分割。。
返回值:空格分割的“TEXT”字串中所有不符合模式“PATTERN”的字串。
函式說明:“filter-out”函式也可以用來去除一個變數中的某些字串,(實現和“filter”函式相反)。

7.$(sort LIST)
函式名稱:排序函式—sort。
函式功能:給字串“LIST”中的單詞以首字母為準進行排序(升序),並取掉重複的單詞。
返回值:空格分割的沒有重複單詞的字串。
函式說明:兩個功能,排序和去字串中的重複單詞。可以單獨使用其中一個功能。

8.$(word N,TEXT)
函式名稱:取單詞函式—word。
函式功能:取字串“TEXT”中第“N”個單詞(“N”的值從1開始)。
返回值:返回字串“TEXT”中第“N”個單詞。
函式說明:如果“N”值大於字串“TEXT”中單詞的數目,返回空字串。如果“N”為0,出錯!

9.$(wordlist S,E,TEXT)
函式名稱:取字串函式—wordlist。
函式功能:從字串“TEXT”中取出從“S”開始到“E”的單詞串。“S”和“E”表示單詞在字串中位置的數字。
返回值:字串“TEXT”中從第“S”到“E”(包括“E”)的單詞字串。
函式說明:“S”和“E”都是從1開始的數字。
當“S”比“TEXT”中的字數大時,返回空。如果“E”大於“TEXT”字數,返回從“S”開始,到“TEXT”結束的單詞串。如果“S”大於“E”,返回空。

10.$(words TEXT)
函式名稱:統計單詞數目函式—words。
函式功能:字算字串“TEXT”中單詞的數目。
返回值:“TEXT”字串中的單詞數。

11.$(firstword NAMES…)
函式名稱:取首單詞函式—firstword。
函式功能:取字串“NAMES…”中的第一個單詞。
返回值:字串“NAMES…”的第一個單詞。
函式說明:“NAMES”被認為是使用空格分割的多個單詞(名字)的序列。函式忽略“NAMES…”中除第一個單詞以外的所有的單詞。

(二)、檔名處理函式
1.$(dir NAMES…)
函式名稱:取目錄函式—dir。
函式功能:從檔名序列“NAMES…”中取出各個檔名目錄部分。檔名的目錄部分就是包含在檔名中的最後一個斜線(“/”)(包括斜線)之前的部分。
返回值:空格分割的檔名序列“NAMES…”中每一個檔案的目錄部分。
函式說明:如果檔名中沒有斜線,認為此檔案為當前目錄(“./”)下的檔案。

2.$(notdir NAMES…)
函式名稱:取檔名函式——notdir。
函式功能:從檔名序列“NAMES…”中取出非目錄部分。目錄部分是指最後一個斜線(“/”)(包括斜線)之前的部分。刪除所有檔名中的目錄部分,只保留非目錄部分。
返回值:檔名序列“NAMES…”中每一個檔案的非目錄部分。
函式說明:如果“NAMES…”中存在不包含斜線的檔名,則不改變這個檔名。以反斜線結尾的檔名,是用空串代替,因此當“NAMES…”中存在多個這樣的檔名時,返回結果中分割各個檔名的空格數目將不確定!這是此函式的一個缺陷。

3.$(suffix NAMES…)
函式名稱:取字尾函式—suffix。
函式功能:從檔名序列“NAMES…”中取出各個檔名的字尾。字尾是檔名中最後一個以點“.”開始的(包含點號)部分,如果檔名中不包含一個點號,則為空。
返回值:以空格分割的檔名序列“NAMES…”中每一個檔案的字尾序列。
函式說明:“NAMES…”是多個檔名時,返回值是多個以空格分割的單詞序列。如果檔名沒有後綴部分,則返回空。

4.$(basename NAMES…)
函式名稱:取字首函式—basename。
函式功能:從檔名序列“NAMES…”中取出各個檔名的字首部分(點號之後的部分)。字首部分指的是檔名中最後一個點號之前的部分。
返回值:空格分割的檔名序列“NAMES…”中各個檔案的字首序列。如果檔案沒有字首,則返回空字串。
函式說明:如果“NAMES…”中包含沒有後綴的檔名,此檔名不改變。如果一個檔名中存在多個點號,則返回值為此檔名的最後一個點號之前的檔名部分。

5.$(addsuffix SUFFIX,NAMES…)
函式名稱:加字尾函式—addsuffix。
函式功能:為“NAMES…”中的每一個檔名新增字尾“SUFFIX”。引數“NAMES…”為空格分割的檔名序列,將“SUFFIX”追加到此序列的每一個檔名的末尾。
返回值:以單空格分割的添加了字尾“SUFFIX”的檔名序列。

6.$(addprefix PREFIX,NAMES…)
函式名稱:加字首函式—addprefix。
函式功能:為“NAMES…”中的每一個檔名新增字首“PREFIX”。引數“NAMES…”是空格分割的檔名序列,將“SUFFIX”新增到此序列的每一個檔名之前。
返回值:以單空格分割的添加了字首“PREFIX”的檔名序列。

7.$(join LIST1,LIST2)
函式名稱:單詞連線函式——join。
函式功能:將字串“LIST1”和字串“LIST2”各單詞進行對應連線。就是將“LIST2”中的第一個單詞追加“LIST1”第一個單詞字後合併為一個單詞;將“LIST2”中的第二個單詞追加到“LIST1”的第一個單詞之後併合併為一個單詞,……依次列推。
返回值:單空格分割的合併後的字(檔名)序列。
函式說明:如果“LIST1”和“LIST2”中的字數目不一致時,兩者中多餘部分將被作為返回序列的一部分。

8.$(wildcard PATTERN)
函式名稱:獲取匹配模式檔名函式—wildcard
函式功能:列出當前目錄下所有符合模式“PATTERN”格式的檔名。
返回值:空格分割的、存在當前目錄下的所有符合模式“PATTERN”的檔名。
函式說明:“PATTERN”使用shell可識別的萬用字元,包括“?”(單字元)、“*”(多字元)等。

(三)、其它函式
1.$(foreach VAR,LIST,TEXT)
函式功能:函式“foreach”不同於其它函式。它是一個迴圈函式。類似於Linux的shell中的迴圈(for語句)。這個函式的工作過程是這樣
的:如果必要(存在變數或者函式的引用),首先展開變數“VAR”和“LIST”;而表示式“TEXT”中的變數引用不被展開。執行時把“LIST”中使
用空格分割的單詞依次取出賦值給變數“VAR”,然後執行“TEXT”表示式。重複直到“LIST”的最後一個單詞(為空時結束)。“TEXT”中的變數
或者函式引用在執行時才被展開,因此如果在“TEXT”中存在對“VAR”的引用,那麼“VAR”的值在每一次展開式將會到的不同的值。
返回值:空格分割的多次表示式“TEXT”的計算的結果。

2.$(if CONDITION,THEN-PART[,ELSE-PART])
函式功能:函式“if”提供了一個在函式上下文中實現條件判斷的功能。就像make所支援的條件語句—ifeq。第一個引數“CONDITION”,在函
數執行時忽略其前導和結尾空字元並展開。“CONDITION”的展開結果非空,則條件為真,就將第二個引數“THEN_PATR”作為函式的計算表達
式,函式的返回值就是第二表示式的計算結果;“CONDITION”的展開結果為空,將第三個引數
“ELSE-PART”作為函式的表示式,返回結果為第三個表示式的計算結果。
返回值:根據條件決定函式的返回值是第一個或者第二個引數表示式的計算結果。當不存在第三個引數“ELSE-PART”,並且“CONDITION”展開為空,函式返回空。
函式說明:函式的條件表示式“CONDITION”決定了,函式的返回值只能是“THEN-PART”或者“ELSE-PART”兩個之一的計算結果。

3.\((call VARIABLE,PARAM,PARAM,...) 函式功能:“call”函式是唯一一個可以建立定製引數化的函式的引用函式。我們可以將一個變數定義為一個複雜的表示式,用“call”函式根據不同的引數對它進行展開來獲得不同的結果。 在執行時,將它的引數“PARAM”依次賦值給臨時變數“\)(1)”、“\((2)”(這些臨時變數定義在“VARIABLE”的值中,參考下邊的例 子)…… call函式對引數的數目沒有限制,也可以沒有引數值,沒有引數值的“call”沒有任何實際存在的意義。執行時變數“VARIABLE”被展開為在函式 上下文有效的臨時變數,變數定義中的“\)(1)”作為第一個引數,並將函式引數值中的第一個引數賦值給它;變數中的“\((2)”一樣被賦值為函式的第二個 引數值;依此類推(變數\)(0)代表變數“VARIABLE”本身)。之後對變數“VARIABLE” 表示式的計算值。
返回值:引數值“PARAM”依次替換“\((1)”、“\)(2)”…… 之後變數“VARIABLE”定義的表示式的計算值。
函式說明:1.
函式中“VARIBLE”是一個變數名,而不是對變數的引用。因此,通常“call”函式中的“VARIABLE”中不包含“$”(當然,除了此變數名是
一個計算的變數名)。2.
當變數“VARIBLE”是一個make內嵌的函式名時(如“if”、“foreach”、“strip”等),對“PARAM”引數的使用需要注意,因
為不合適或者不正確的引數將會導致函式的返回值難以預料。3. 函式中多個“PARAM”之間使用逗號分割。4.
變數“VARIABLE”在定義時不能定義為直接展開式!只能定義為遞迴展開式。

4.value函式
\((value VARIABLE) 函式功能:不對變數“VARIBLE”進行任何展開操作,直接返回變數“VARIBALE”代表的值。這裡“VARIABLE”是一個變數名,一般不包含“\)”(當然,除了計算的變數名),
返回值:變數“VARIBALE”所定義文字值(不展開其中的變數或者函式應用)。

5.eval函式
函式功能:函式“eval”是一個比較特殊的函式。使用它我們可以在我們的Makefile中構造一個可變的規則結構關係(依賴關係鏈),其中可以使用其
它變數和函式。函式“eval”對它的引數進行展開,展開的結果作為Makefile的一部分,make可以對展開內容進行語法解析。展開的結果可以包含
一個新變數、目標、隱含規則或者是明確規則等。也就是說此函式的功能主要是:根據其引數的關係、結構,對它們進行替換展開。
返回值:函式“eval”的返回值時空,也可以說沒有返回值。
函式說明:“eval”函式執行時會對它的引數進行兩次展開。第一次展開過程發是由函式本身完成的,第二次是函式展開後的結果被作為Makefile內容
時由make解析時展開的。明確這一點對於使用“eval”函式非常重要。在理解了函式“eval”二次展開的過程後。實際使用時,當函式的展開結果中存
在引用(格式為:\((x))時,那麼在函式的引數中應該使用“\)\(”來代替“\)”。因為這一點,所以通常它的引數中會使用函式“value”來取一個變數
的文字值。

6.origin函式
\((origin VARIABLE) 函式功能:函式“origin”查詢引數“VARIABLE”(通常是一個變數名)的出處。 函式說明:“VARIABLE”是一個變數名而不是一個變數的引用。因此通常它不包含“\)”(當然,計算的變數名例外)。
返回值:返回“VARIABLE”的定義方式。用字串表示。
. undefined
變數“VARIABLE”沒有被定義。
. default
變數“VARIABLE”是一個預設定義(內嵌變數)。如“CC”、“MAKE”、“RM”等變數。如果在Makefile中重新定義這些變數,函式返回值將相應發生變化。
. environment
變數“VARIABLE”是一個系統環境變數,並且make沒有使用命令列選項“-e”(Makefile中不存在同名的變數定義,此變數沒有被替代)。
. environment override
變數“VARIABLE”是一個系統環境變數,並且make使用了命令列選項“-e”。Makefile中存在一個同名的變數定義,使用“make -e”時環境變數值替代了檔案中的變數定義。
. file
變數“VARIABLE”在某一個makefile檔案中定義。
. command line
變數“VARIABLE”在命令列中定義。
. override
變數“VARIABLE”在makefile檔案中定義並使用“override”指示符宣告。
. automatic
變數“VARIABLE”是自動化變數。

7.shell函式
不同於除“wildcard”函式之外的其它函式。make可以使用它來和外部通訊。
函式功能:函式“shell”所實現的功能和shell中的引用(``)相同。實現了命令的擴充套件。意味著需要一個shell
命令作為它的引數,而返回的結果是此命令在shell中的執行結果。make僅僅對它的回返結果進行處理;make將函式的返回結果中的所有換行符
(“\n”)或者一對“\n\r”替換為單空格;並去掉末尾的回車符號(“\n”)或者“\n\r”。函式展開式時,它所呼叫的命令(它的引數)得到執
行。除了對它的引用出現在規則的命令列中和遞迴的變數定義引用以外,其它決大多數情況下,make在讀取Makefile時函式shell就被擴充套件。
返回值:函式“shell”的引數在shell中的執行結果。
函式說明:函式本身的返回值是其引數的執行結果,沒有進行任何處理。對結果的處理是由make進行的。當對函式的引用出現在規則的命令列中,命令列在執行
時函式引用才被展開。展開過程函式引數的執行時在另外一個shell程序中完成的,因此對於出現在規則命令列的多級“shell”函式引用需要謹慎處理,
否則會影響效率(每一級的“shell”函式的引數都會有各自的shell程序)。

8.error 函式
$(error TEXT…)
函式功能:產生致命錯誤,並提示“TEXT…”資訊給使用者,之後退出make的執行。需要說明的是:“error”函式是在函式展開式(函式被呼叫時)才
提示資訊並結束make程序。因此如果函數出現在命令中或者一個遞迴的變數定義中時,在讀取Makefile時不會出現錯誤。而只有包含
“error”函式引用的命令被執行,或者定義中引用此函式的遞迴變數被展開時,才會提示致命資訊“TEXT…”同時make退出執行。
返回值:空字元
函式說明:“error”函式一般不出現在直接展開式的變數定義中,否則在make讀取Makefile時將會提示致命錯誤。

  1. warning 函式
    $(warning TEXT…)
    函式功能:函式“warning”類似於函式“error”,區別在於它不會導致致命錯誤(make不退出),而只是提示“TEXT…”,make的執行過程繼續。
    返回值:空字元
    函式說明:用法和“error”類似,展開過程相同。

3.makefile模板

複製程式碼
GXX=g++
GCC=gcc
CXXFLAG=-fopenmp -march=core2 -O3 -fomit-frame-pointer -pipe
CFLAG=\((CXXFLAG) DIR_INC=./include DIR_SRC=./src DIR_OBJ=./obj DIR_BIN=./bin DIR_LIB=/home/your_dir/env/lib_dir1/ LDFLAG=-Wl,--rpath=\)(DIR_LIB)/lib,--rpath=/home/your_dir/env/lib,--rpath=$(PWD)/lib,-O3 -fopenmp

指定include的路徑

INCLUDE=-I$(DIR_INC) -I./lib/include -I \((DIR_LIB)/include -I\)(DIR_LIB)/include/h_file_dir

指定lib的路徑

LIBS=-L $(DIR_LIB)/lib -lxxx1 -lxxx2 -lxxx3 -L/home/your_dir/env/lib -L $(PWD)/lib -lxxx4

TARGET=\((DIR_BIN)/exe_name DEF= -DLINUX #-DPATH #-DDEBUG SRC=\)(wildcard \({DIR_SRC}/*.cpp) OBJS=\)(SRC:\((DIR_SRC)/%.cpp=\)(DIR_OBJ)/%.o)

\((TARGET):\)(OBJS)
$(GXX) \((GXXFLAG)\)(LDFLAG) -o $@ $(OBJS) $(LIBS)

\((TARGET):\)(OBJS)

ar cru $(TARGET) $(OBJS)

\((DIR_OBJ)/%.o:\)(DIR_SRC)/%.cpp
$(GXX) -o $@ -c $< $(CXXFLAG) $(INCLUDE) $(DEF)

clean:
rm -fr $(OBJS) $(TARGET);
複製程式碼

說明:(1)利用自動化變數“$@”,這個變量表示著目前規則中所有的目標的集合。

    (2)\(<是第一個"prerequisite", 不知道怎麼翻譯,就是target:後面的列表裡的第一個. (Often the prerequisites include header files as well, which you do not want to mention in the recipe. The automatic variable `\)<' is just the first prerequisite:)
  示例:

 VPATH = src:../headers
 foo.o : foo.c defs.h hack.h
         cc -c $(CFLAGS) $< -o $@

  這裡$<就是foo.c

四,其他問題

1.rpath連結選項

SDK庫的名稱為liba.so, 其依賴於libb.so和libc.so,那麼在編譯應用程式的時候使用以下命令:

+++++++++++++++++++++++++++++++++++++++++++++

gcc -o test test.c -I. -L. -la -lb -lc

+++++++++++++++++++++++++++++++++++++++++++++

將SDK庫即liba.so交給其他的開發人員,其他的開發人員可不想編譯的時候,顯示的連結liba.so所依賴的庫。他們更願意編譯的時候,只顯示地連結liba.so。

rpath連結選項主要有兩個功能:

(1)程式執行時,優先到rpath指定的目錄去尋找依賴庫

(2)程式連結時,在指定的目錄中,隱式的連結那些動態庫所需要的連結庫。

往往我們都熟知第一個功能,忽略第二個功能。而第二個功能正是現在所需要的。

我們將liba.so,libb.so 和libc.so拷貝的同一個目錄中,然後利用rpath連結應用程式,這樣編譯便不需要顯示的去連結liba.so所依賴的庫了。

+++++++++++++++++++++++++++++++++++++++++++++

gcc -o test test.c -I. -L. -la -Wl,-rpath=.

+++++++++++++++++++++++++++++++++++++++++++++