1. 如何用GCC在linux下編譯C語言程序
在Linux下面,如果要編譯一個C語言源程序,我們要使用GNU的gcc編譯器,假設我們有下面一個非常簡單的源程序(hello.c):
int main(int argc,char **argv)
{
printf("Hello Linux
");
}
要編譯這個程序,我們只要在命令行下執行:
gcc -o hello hello.c
gcc 編譯器就會為我們生成一個hello的可執行文件.執行./hello就可以看到程
序的輸出結果了
2. 怎樣調試GCC源碼
一、Linux程序gcc編譯步驟:
Gcc編譯過程主要的4個階段:
l 預處理階段,完成宏定義和include文件展開等工作;(.i)
l 根據編譯參數進行不同程度的優化,編譯成匯編代碼(.s.S)
l 用匯編器把匯編代碼進一步生成目標代碼(.o)
l 用連接器把生成的目標代碼和系統或用戶提供的庫連接起來,生成可執行文件
格式:
l gcc -E test.c//預處理階段
l Gcc -S test.c//編譯階段
l Gcc -c test.c//匯編階段
l Gcc -o test test.c//鏈接階段
二、Linux程序gdb調試步驟:
Gdb的功能:
l 設置斷點
l 監視程序變數的值
l 程序的單步執行
l 顯示、修改變數的值
l 顯示、修改寄存器
l 查看程序的堆棧情況
l 遠程調試
Gdb調試過程:
1、程序經過預處理後,即進入編譯階段,進入編譯階段,首先聲明編譯:
2、格式:gdb -o test test.c -g
3、進入編譯:gdb test
4、顯示需要編譯調試的源程序:l(list)//list filename
5、設置斷點:b(break)行號
6、查看設置的斷點:info b
7、運行調試程序:run
8、跳到下一個斷點:c(continue)
9、單步運行的話使用:n(next)/s(step into)跳到函數體 //區別在與:next執行函數體,而step不執行函數體
10、調試過程中查看某個變數的變化:print i (每次都要手動設置)//display i(設置一次一直尾隨,直到用「undisplay 變數標號」 停止)
11、退出當前的調試使用finish 跳出函數
12、清楚斷點 clear 行號
13、Delete 斷點信息序號// 刪除所有斷點或設置的要刪除的斷點
14、退出調試 q
15、b num if i==20 設置斷點的觸發條件
16、condition num i==50 改變斷點的觸發條件
3. gcc編譯器究竟怎麼打開我竟然在gcc的安裝文件夾中找不到gcc的打開文件
你先用vim 或者直接用gedit編寫好程序,然後直接輸入命令就可以了,比如你的程序是helloworld.c,那麼你可以輸入命令:
編譯命令:gcc -o helloworld helloworld.c
運行命令./helloworld
希望這樣的回答對你有幫助!
gcc的使用方法
1。gcc包含的c/c++編譯器
gcc,cc,c++,g++,gcc和cc是一樣的,c++和g++是一樣的,一般c程序就用gcc編譯,c++程序就用g++編譯
2。gcc的基本用法
gcc test.c這樣將編譯出一個名為a.out的程序
gcc test.c -o test這樣將編譯出一個名為test的程序,-o參數用來指定生成程序的名字
3。為什麼會出現undefined reference to 'xxxxx'錯誤?
首先這是鏈接錯誤,不是編譯錯誤,也就是說如果只有這個錯誤,說明你的程序源碼本身沒有問題,是你用編譯器編譯時參數用得不對,你沒有指定鏈接程序要用到得庫,比如你的程序里用到了一些數學函數,那麼你就要在編譯參數里指定程序要鏈接數學庫,方法是在編譯命令行里加入-lm。
4。-l參數和-L參數
-l參數就是用來指定程序要鏈接的庫,-l參數緊接著就是庫名,那麼庫名跟真正的庫文件名有什麼關系呢?
就拿數學庫來說,他的庫名是m,他的庫文件名是libm.so,很容易看出,把庫文件名的頭lib和尾.so去掉就是庫名了。
好了現在我們知道怎麼得到庫名了,比如我們自已要用到一個第三方提供的庫名字叫libtest.so,那麼我們只要把libtest.so拷貝到/usr/lib里,編譯時加上-ltest參數,我們就能用上libtest.so庫了(當然要用libtest.so庫里的函數,我們還需要與libtest.so配套的頭文件)。
放在/lib和/usr/lib和/usr/local/lib里的庫直接用-l參數就能鏈接了,但如果庫文件沒放在這三個目錄里,而是放在其他目錄里,這時我們只用-l參數的話,鏈接還是會出錯,出錯信息大概是:"/usr/bin/ld: cannot find -lxxx",也就是鏈接程序ld在那3個目錄里找不到libxxx.so,這時另外一個參數-L就派上用場了,比如常用的X11的庫,它放在/usr/X11R6/lib目錄下,我們編譯時就要用-L/usr/X11R6/lib -lX11參數,-L參數跟著的是庫文件所在的目錄名。再比如我們把libtest.so放在/aaa/bbb/ccc目錄下,那鏈接參數就是-L/aaa/bbb/ccc -ltest
另外,大部分libxxxx.so只是一個鏈接,以RH9為例,比如libm.so它鏈接到/lib/libm.so.x,/lib/libm.so.6又鏈接到/lib/libm-2.3.2.so,如果沒有這樣的鏈接,還是會出錯,因為ld只會找libxxxx.so,所以如果你要用到xxxx庫,而只有libxxxx.so.x或者libxxxx-x.x.x.so,做一個鏈接就可以了ln -s libxxxx-x.x.x.so libxxxx.so
手工來寫鏈接參數總是很麻煩的,還好很多庫開發包提供了生成鏈接參數的程序,名字一般叫xxxx-config,一般放在/usr/bin目錄下,比如gtk1.2的鏈接參數生成程序是gtk-config,執行gtk-config --libs就能得到以下輸出"-L/usr/lib -L/usr/X11R6/lib -lgtk -lgdk -rdynamic -lgmole -lglib -ldl -lXi -lXext -lX11 -lm",這就是編譯一個gtk1.2程序所需的gtk鏈接參數,xxx-config除了--libs參數外還有一個參數是--cflags用來生成頭文
件包含目錄的,也就是-I參數,在下面我們將會講到。你可以試試執行gtk-config --libs --cflags,看看輸出結果。
現在的問題就是怎樣用這些輸出結果了,最苯的方法就是復制粘貼或者照抄,聰明的辦法是在編譯命令行里加入這個`xxxx-config --libs --cflags`,比如編譯一個gtk程序:gcc gtktest.c `gtk-config --libs --cflags`這樣就差
不多了。注意`不是單引號,而是1鍵左邊那個鍵。
除了xxx-config以外,現在新的開發包一般都用pkg-config來生成鏈接參數,使用方法跟xxx-config類似,但xxx-config是針對特定的開發包,但pkg-config包含很多開發包的鏈接參數的生成,用pkg-config --list-all命令可以列出所支持的所有開發包,pkg-config的用法就是pkg-config pagName --libs --cflags,其中pagName是包名,是pkg-config--list-all里列出名單中的一個,比如gtk1.2的名字就是gtk+,pkg-config gtk+ --libs --cflags的作用跟gtk-config --libs --cflags是一樣的。比如:gcc gtktest.c `pkg-config gtk+ --libs --cflags`。
5。-include和-I參數
-include用來包含頭文件,但一般情況下包含頭文件都在源碼里用#include xxxxxx實現,-include參數很少用。-I參數是用來指定頭文件目錄,/usr/include目錄一般是不用指定的,gcc知道去那裡找,但是如果頭文件不在/usr/include里我們就要用-I參數指定了,比如頭文件放在/myinclude目錄里,那編譯命令行就要加上-I/myinclude參數了,如果不加你會得到一個"xxxx.h: No such file or directory"的錯誤。-I參數可以用相對路徑,比如頭文件在當前目錄,可以用-I.來指定。上面我們提到的--cflags參數就是用來生成-I參數的。
6。-O參數
這是一個程序優化參數,一般用-O2就是,用來優化程序用的,比如gcc test.c -O2,優化得到的程序比沒優化的要小,執行速度可能也有所提高(我沒有測試過)。
7。-shared參數
編譯動態庫時要用到,比如gcc -shared test.c -o libtest.so
8。幾個相關的環境變數
PKG_CONFIG_PATH:用來指定pkg-config用到的pc文件的路徑,默認是/usr/lib/pkgconfig,pc文件是文本文件,擴展名是.pc,裡面定義開發包的安裝路徑,Libs參數和Cflags參數等等。
CC:用來指定c編譯器。
CXX:用來指定cxx編譯器。
LIBS:跟上面的--libs作用差不多。
CFLAGS:跟上面的--cflags作用差不多。
CC,CXX,LIBS,CFLAGS手動編譯時一般用不上,在做configure時有時用到,一般情況下不用管。
環境變數設定方法:export ENV_NAME=xxxxxxxxxxxxxxxxx
9。關於交叉編譯
交叉編譯通俗地講就是在一種平台上編譯出能運行在體系結構不同的另一種平台上,比如在我們地PC平台(X86 CPU)上編譯出能運行在sparc CPU平台上的程序,編譯得到的程序在X86 CPU平台上是不能運行的,必須放到sparc CPU平台上才能運行。
當然兩個平台用的都是linux。
這種方法在異平台移植和嵌入式開發時用得非常普遍。
相對與交叉編譯,我們平常做的編譯就叫本地編譯,也就是在當前平台編譯,編譯得到的程序也是在本地執行。
用來編譯這種程序的編譯器就叫交叉編譯器,相對來說,用來做本地編譯的就叫本地編譯器,一般用的都是gcc,但這種gcc跟本地的gcc編譯器是不一樣的,需要在編譯gcc時用特定的configure參數才能得到支持交叉編譯的gcc。
為了不跟本地編譯器混淆,交叉編譯器的名字一般都有前綴,比如sparc-xxxx-linux-gnu-gcc,sparc-xxxx-linux-gnu-g++ 等等
10。交叉編譯器的使用方法
使用方法跟本地的gcc差不多,但有一點特殊的是:必須用-L和-I參數指定編譯器用sparc系統的庫和頭文件,不能用本地(X86)
的庫(頭文件有時可以用本地的)。
例子:
sparc-xxxx-linux-gnu-gcc test.c -L/path/to/sparcLib -I/path/to/sparcInclude
4. gcc 鏈接自定義庫文件的方法有幾種
-l 是直接加上某庫的名稱,如-lc是libc庫 -L 是庫的路徑,搜索的時候優先在-L目錄下搜索 你使用gcc --help就可以看到所有的選項以及用法
5. gcc的基本用法
在使用GCC編譯器的時候,我們必須給出一系列必要的調用參數和文件名稱。GCC編譯器的調用參數大約有100多個,這里只介紹其中最基本、最常用的參數。具體可參考GCC Manual。
GCC最基本的用法是∶gcc [options] [filenames]
其中options就是編譯器所需要的參數,filenames給出相關的文件名稱。
-c,只編譯,不鏈接成為可執行文件,編譯器只是由輸入的.c等源代碼文件生成.o為後綴的目標文件,通常用於編譯不包含主程序的子程序文件。
-o output_filename,確定輸出文件的名稱為output_filename,同時這個名稱不能和源文件同名。如果不給出這個選項,gcc就給出預設的可執行文件a.out。
-g,產生符號調試工具(GNU的gdb)所必要的符號資訊,要想對源代碼進行調試,我們就必須加入這個選項。
-O,對程序進行優化編譯、鏈接,採用這個選項,整個源代碼會在編譯、鏈接過程中進行優化處理,這樣產生的可執行文件的執行效率可以提高,但是,編譯、鏈接的速度就相應地要慢一些。
-O2,比-O更好的優化編譯、鏈接,當然整個編譯、鏈接過程會更慢。
-Idirname,將dirname所指出的目錄加入到程序頭文件目錄列表中,是在預編譯過程中使用的參數。C程序中的頭文件包含兩種情況∶
A)#include <myinc.h>
B)#include 「myinc.h」
其中,A類使用尖括弧(< >),B類使用雙引號(「 」)。對於A類,預處理程序cpp在系統預設包含文件目錄(如/usr/include)中搜尋相應的文件,而B類,預處理程序在目標文件的文件夾內搜索相應文件。
-v gcc執行時執行的詳細過程,gcc及其相關程序的版本號
原版gcc manual該選項英文解釋
Print (on standard error output) the commands executed to run the stages of compilation. Also print the version number of the compiler driver program and of the preprocessor and the compiler proper.
編譯程序時加上該選項可以看到gcc搜索頭文件/庫文件時使用的搜索路徑!
6. mac下的gcc如何使用。。
gcc常用命令行
gcc/g++在執行編譯工作的時候,總共需要以下幾步:
1.預處理,生成.i的文件[預處理器cpp]
2.將預處理後的文件轉換成匯編語言,生成文件.s[編譯器egcs]
3.由匯編變為目標代碼(機器代碼)生成.o的文件[匯編器as]
4.連接目標代碼,生成可執行程序[鏈接器ld]
/**********GCC能夠處理的後綴有:**********/
a. *.c *.C (C語言)
b. *.cxx *.cc (C++語言)
c. *.m (面向對象的C)
d. *.i (預處理後的C語言源文件)
e. *.ii (預處理後的C++語言源文件)
f. *.s *.S (匯編語言)
h. *.h (頭文件)
/**********目標文件可以是:**********/
a. *.o 編譯連接後的目標文件
b. *.a 庫文件
-o FILE 指定輸出文件名,在編譯為目標代碼時,這一選項不是必須的。如果FILE沒有指定,預設文件名是a.out.
-c 只編譯不鏈接
-IDIRNAME 將DIRNAME加入到頭文件的搜索目錄列表中
-LDIRNAME 將DIRNAME加入到庫文件的搜索目錄列表中,預設情況下gcc 只鏈接共享庫
-lFOO 鏈接名為libFOO的函數庫
-O 優化編譯過的代碼
-ON 指定代碼優化的級別為N,o<=N<=3
-v 顯示在編譯過程的每一步中用到的命令
-x language filename 設定文件所使用的語言,使後綴名無效,對以後的多個有效.也就是根據約定C語言的後綴名稱是.c的,而C++的後綴名是.C或者.cpp,
如果你很個性,決定你的C代碼文件的後綴名是.pig 哈哈,那你就要用這個參數,這個參數對他後面的文件名都起作用,
除非到了下一個參數的使用。例 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文件
-o 制定目標名稱,預設的時候,gcc 編譯出來的文件是a.out,很難聽,如果你和我有同感,改掉它!
例子用法
gcc -o hello.exe hello.c (哦,windows用習慣了)
gcc -o hello.asm -S hello.c
-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 使用curses庫編譯程序
-Ldir 制定編譯的時候,搜索庫的路徑。比如你自己的庫,可以用它制定目錄,不然編譯器將只在標准庫的目錄找。這個dir就是目錄的名稱。
-O0 -O1 -O2 -O3 編譯器的優化選項的4個級別,-O0表示沒有優化,-O1為預設值,-O3優化級別最高
-g 只是編譯器,在編譯的時候,產生調試信息。
-gstabs 此選項以stabs格式聲稱調試信息,但是不包括gdb調試信息.
-gstabs+ 此選項以stabs格式聲稱調試信息,並且包含僅供gdb使用的額外調試信息.
-ggdb 此選項將盡可能的生成gdb的可以使用的調試信息.
-static 此選項將禁止使用動態庫,所以,編譯出來的東西,一般都很大,也不需要什麼動態連接庫,就可以運行.
-share 此選項將盡量使用動態庫,所以生成文件比較小,但是需要系統有動態庫.
-traditional 試圖讓編譯器支持傳統的C語言特性
7. GCC的使用
http://blog.csdn.net/kkk8000/article/details/5998536
今天把cygwin下的bin目錄添加到PATH後,直接運行g++, gcc, 顯示「訪問被拒絕」 (access denied).
竟然那麼詭異,上網查資料,網上的解決方案說:
檢查g++.exe, gcc.exe是否只有1k大小,如果是,那麼文件是符號鏈接,那麼把文件重命名一下(備份)。
然後把g++-3.exe(或者g++-4.exe)拷貝一份,重命名為g++.exe。 把gcc-3.exe拷貝一份,重命名為gcc.exe。
試了一下,靠,根本不管用,這是哪門子方法,完全沒邏輯性.
初步認為訪問被拒絕是沒有許可權,於是右鍵點擊g++.exe和gcc.exe,選擇屬性---安全,Domain User許可權選擇完全控制,果然好了.
看來網上的山寨方法確實很多,還要靠自己.
8. 如何使用GCC生成動態庫和靜態庫
下面以工程libtest為例說明gcc創建和使用靜態庫、動態庫的過程,libtest目錄結構和內容如圖1所示,其中三個文件hello.h,hello.c和main.c的內容如下。
libtest/include/hello.h
#ifdef _HELLO_H_
#define _HELLO_H_
void hello();
#endif
libtest/lib/hello.c
#include "hello.h"
#include <stdio.h>
void hello()
{
printf("hello world!\n");
}
libtest/src/main.c
#include "hello.h"
int main()
{
hello();
}
靜態庫過程如下:
(1) 進入libtest/lib目錄,執行命令:
gcc -c -I../include hello.c
該命令生成目標文件hello.o,注意:參數-I添加頭文件搜索目錄,這里因為hello.c中有#include 「hello.h」,hello.h在libtest/include目錄中,這里需要指定該目錄通知gcc,否則出現錯誤提示「找不到頭文件hello.h」。
這一步將在libtest/lib目錄中生成一個hello.o文件。
(2) 在libtest/lib目錄,執行命令:
ar rc libhello.ahello.o
該命令將hello.o添加到靜態庫文件libhello.a,ar命令就是用來創建、修改庫的,也可以從庫中提出單個模塊,參數r表示在庫中插入或者替換模塊,c表示創建一個庫
這一步將在libtest/lib目錄中生成一個libhello.a文件。
(3) 進入libtest/src目錄,執行命令:
gcc main.c-I../include -L../lib -lhello -o main
該命令將編譯main.c並鏈接靜態庫文件libhello.a生成可執行文件main,注意:參數-L添加庫文件搜索目錄,因為libhello.a在libtest/lib目錄中,這里需要指定該目錄通知gcc,參數-l指定鏈接的庫文件名稱,名稱不用寫全名libhello.a,只用寫hello即可。
這一步將在libtest/src目錄中生成可執行文件main。
動態庫過程如下:
(1) 進入libtest/lib目錄,執行命令:
gcc hello.c-I../include -fPIC -shared -o libhello.so
這一步將在當前目錄生成動態庫文件libhello.so,參數-fPIC -shared固定格式,不用糾結他們什麼意思。
(2) 進入libtest/src目錄,執行命令:
gcc main.c-I../include -L../lib -lhello -o main
此時在當前目錄中已經生成了可執行文件main,執行./main時卻提示錯誤:
./main: error while loading shared libraries: libhello.so: cannotopen shared object file: No such file or directory
也就是找不到動態庫文件libhello.so,在網上找了答案說如果遇到這樣的問題需要設置環境變數LD_LIBRARY_PATH,如下:
export LD_LIBRARY_PATH=」../lib」
gcc main.c -I../include -L../lib -lhello -o main
然後再執行./main就沒有錯誤了。
【補充】
環境變數LD_LIBRARY_PATH指示動態連接器可以裝載動態庫的路徑,在鏈接動態庫文件前設置該變數為庫文件所在路徑,注意:用export LD_LIBRARY_PATH=」…」方式只是臨時生效的,如果要永久有效可以寫入~/.bashrc文件中,跟修改PATH類似,exportLD_LIBRARY_PATH=$LD_LIBRARY_PATH:」…」。
當然如果有root許可權的話,也可以修改/etc/ld.so.conf文件,將要添加的動態庫搜索路徑寫入該文件中,然後調用/sbin/ldconfig來達到同樣的目的。
9. Linux下gcc命令怎麼使用,詳細的參數說明
用法:gcc [選項] 文件...
選項:
-pass-exit-codes 在某一階段退出時返回最高的錯誤碼
--help 顯示此幫助說明
--target-help 顯示目標機器特定的命令行選項
(使用『-v --help』顯示子進程的命令行參數)
-mpspecs 顯示所有內建 spec 字元串
-mpversion 顯示編譯器的版本號
-mpmachine 顯示編譯器的目標處理器
-print-search-dirs 顯示編譯器的搜索路徑
-print-libgcc-file-name 顯示編譯器伴隨庫的名稱
-print-file-name=<庫> 顯示 <庫> 的完整路徑
-print-prog-name=<程序> 顯示編譯器組件 <程序> 的完整路徑
-print-multi-directory 顯示不同版本 libgcc 的根目錄
-print-multi-lib 顯示命令行選項和多個版本庫搜索路徑間的映射
-print-multi-os-directory 顯示操作系統庫的相對路徑
-Wa,<選項> 將逗號分隔的 <選項> 傳遞給匯編器
-Wp,<選項> 將逗號分隔的 <選項> 傳遞給預處理器
-Wl,<選項> 將逗號分隔的 <選項> 傳遞給鏈接器
-Xassembler <參數> 將 <參數> 傳遞給匯編器
-Xpreprocessor <參數> 將 <參數> 傳遞給預處理器
-Xlinker <參數> 將 <參數> 傳遞給鏈接器
-combine 將多個源文件一次性傳遞給匯編器
-save-temps 不刪除中間文件
-pipe 使用管道代替臨時文件
-time 為每個子進程計時
-specs=<文件> 用 <文件> 的內容覆蓋內建的 specs 文件
-std=<標准> 指定輸入源文件遵循的標准
--sysroot=<目錄> 將 <目錄> 作為頭文件和庫文件的根目錄
-B <目錄> 將 <目錄> 添加到編譯器的搜索路徑中
-b <機器> 為 gcc 指定目標機器(如果有安裝)
-V <版本> 運行指定版本的 gcc(如果有安裝)
-v 顯示編譯器調用的程序
-### 與 -v 類似,但選項被引號括住,並且不執行命令
-E 僅作預處理,不進行編譯、匯編和鏈接
-S 編譯到匯編語言,不進行匯編和鏈接
-c 編譯、匯編到目標代碼,不進行鏈接
-o <文件> 輸出到 <文件>
-x <語言> 指定其後輸入文件的語言
允許的語言包括:c c++ assembler none
『none』意味著恢復默認行為,即根據文件的擴展名猜測
源文件的語言
以 -g、-f、-m、-O、-W 或 --param 開頭的選項將由 gcc 自動傳遞給其調用的
不同子進程。若要向這些進程傳遞其他選項,必須使用 -W<字母> 選項。
10. GCC -L命令
用-l的方式指定庫名時, 實際上會自動添加lib前綴 及.a/.so後綴。
所以 你的庫名字應該改成
libstatic_lib.a
這樣就能找到了。
對於靜態庫,也可以直接
gcc 1.c static_lib.a -o xxx