2010年9月12日 星期日

[Linux 教學] Makefile 教學 (一)


轉載自 這裡
這個部份並不是很困難, 所以就以自己所知的用非常"白話"的方式來說, 如有不全地方, 請見諒~

一般在Linux下用gcc編譯C語言程式, 預設的情況編譯器只會搜尋標準的吸久久(C99)函式庫, 諸如stdio.h, math.h等等, 而標準的Linux系統函式通常存放在/lib 和 /usr/lib, 所以必需要告訴編譯器(linker)搜尋哪個函式庫, 而在Linux下函式庫名稱都是以lib為開頭, 隨後的名稱就根據該函式庫來定(m就代表數學函式庫), 而副檔名.a 就是指靜態函式庫, .so就是共享函式庫

比如我們寫了個小程式, 名稱 test.c
  1. #define PI 3.14159265  
  2. int main ()  
  3. {  
  4.   double param, result;  
  5.   param = 88.0;  
  6.   result = cos (param*PI/180);  
  7.   printf ("The cosine of %lf degrees is %lf.\n", param, result );  
  8.   return 0;  
  9. }  

使用gcc編譯:
gcc -o test test.c -lm

math.h 是吸久久標準函式庫, 這裡只是舉例, 如果程式加上#include的話, 這個-lm是可以不用寫的, 但是如果我們今天程式是有關處理系統執行緒的話, 就要加上 -lpthread 來編譯, 因為thread不在吸久久標準函式庫內。

而靜態函式庫是可以獨立存在, 但是不能共用的,常應用於嵌入式系統, 而動態函式庫是不可以獨立存在, 但是可以共用的, 而且一定要放在/lib底下才能實現共用 (或使用 export PATH=...), 所以常運用於PC軟體系統。 一般時後靜態函式比較省記憶體空間, 但是動態函式在需要大量的共用檔案時就比靜態函式庫還要省空間。

靜態函式庫:
比如我們現在在一個名為mytest的目錄中有 a.c, b.c, lib.h, main.c 四個檔案
其內容分別是
/*a.c*/
  1. #include   
  2. void a(char * arg)  
  3. {  
  4.     printf("a: you passed %s\n", arg);  
  5. }  

/*b.c*/
  1. #include   
  2. void b(int arg)  
  3. {  
  4.     printf("b: you passed %d\n", arg);  
  5. }  

/*lib.h*/
  1. void a (char*);  
  2. void b (int);  

/*main.c*/
  1. #include "lib.h"  
  2. int main()  
  3. {  
  4.     a("Hello World");  
  5.     exit(0);     
  6. }  

好了, 開始編譯:
john:~/test1/mkfile # gcc -c a.c b.c
john:~/test1/mkfile # ls *.o
a.o b.o

您就會見到 a.o 及 b.o 兩個目的檔, 再來
john:~/test1/mkfile # gcc -c main.c <產生main.o的目的檔>

現在我們來產生靜態函式庫:
john:~/test1/mkfile # ar crv libtest.a a.o b.o <產生libtest.a的靜態函式庫>
a - a.o
a - b.o

最後來使用這個函式庫來編譯出可執行檔:
john:~/test1/mkfile # gcc -o main main.o libtest.a <這樣就產生出一個名為 main 的執行檔>

我們也可以這樣寫來編出可執行檔
john:~/test1/mkfile # gcc -o main main.o -L. -ltest
-L. 指目前所在目錄, 如果libtest.a是放在其他目錄下, 請在-L後面加上所在位置, -ltest 就是指 libtest.a

一樣用ldd指令可以查詢執行檔所參考的lib檔喔
john:~/test1/mkfile # ldd main
linux-gate.so.1 => (0xffffe000)
libc.so.6 => /lib/libc.so.6 (0xb7dd6000)
/lib/ld-linux.so.2 (0xb7f06000)

如果對windows下面做比較的話:
Linux Windows
目的檔 : func.o | FUNC.OBJ
靜態函式庫 : lib.a | LIB.LIB
執行檔 : main | main.exe



動態函式庫: (我們採用上面的程式資料)
開始來做動態函式庫
john:~/test1/mkfile # gcc a.c b.c -shared -o libtest.so <編譯a.c及b.c成一個libtest.so動態函式>
john:~/test1/mkfile # gcc -c main.c <產生 main.o目的檔>
john:~/test1/mkfile # gcc -o main main.o libtest.so <利用libtest.so動態函式來產生main可執行檔>
john:~/test1/mkfile # ./main <當你執行main執行檔的時後就出現了錯誤~而錯誤訊息應該是這樣的:>
./main: error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory
因為要共用喔(前面有說過)所以:
john:~/test1/mkfile # cp libtest.so /lib <將libtest.so拷備到/lib目錄下>
john:~/test1/mkfile # ./main <再執行一次, 成功了吧~>
a: you passwd Hello World

一樣用ldd指令可以查詢它的lib檔喔
john:~/test1/mkfile # ldd main
linux-gate.so.1 => (0xffffe000)
libtest.so => /lib/libtest.so (0xb7fc5000)
libc.so.6 => /lib/libc.so.6 (0xb7ea5000)
/lib/ld-linux.so.2 (0xb7fd7000) 
This message was edited 1 time. Last update was at 11/02/2010 09:04:49

沒有留言:

張貼留言

[Git 常見問題] error: The following untracked working tree files would be overwritten by merge

  Source From  Here 方案1: // x -----删除忽略文件已经对 git 来说不识别的文件 // d -----删除未被添加到 git 的路径中的文件 // f -----强制运行 #   git clean -d -fx 方案2: 今天在服务器上  gi...