http://blog.csdn.net/hongfuhaocomon/article/details/51523394linux
http://blog.csdn.net/lanmanck/article/details/8462088程序員
一.庫shell
什麼是庫,簡單的能夠說是可執行代碼的二進制形式,可以被操做系統載入內存執行。操做系統的不一樣,兩者的庫也是不兼容的,如windows與linux.windows
庫又分爲靜態庫和動態庫,動態庫又稱爲共享庫。linux下靜態庫(.a)文件,動態庫(.so)文件。主要存放函數庫的路徑有:/lib , /usr/lib.app
二.靜態庫與動態庫函數
1.靜態庫工具
這類庫的名字通常是libname.a.利用靜態庫編寫的文件比較大,緣由是整個函數庫中的數據都被整合進目標代碼文件中去。它的優勢是,編譯後的執行程序不須要外部的函數庫支持,由於全部使用的函數都已經被編譯進可執行文件了。一樣它的不足,若是靜態函數庫改變了,那麼你的程序必須從新編譯,並且體積也較大。操作系統
2.動態庫.net
名字通常是libname.so.相對於靜態函數庫,動態函數庫在編譯的時候並無被編譯進目標代碼中,你的程序執行到相關函數是菜調用函數庫裏的函數,所以動態函數庫所產生的可執行文件比較小。因爲函數庫沒有被整合進你的程序,而是程序運行時動態申請並調用,因此程序的運行環境中必須提供相應的庫。動態函數庫的改變並不影響你的程序,因此動態函數庫的升級比較方便。並且若是多個應用程序都要使用同一函數庫,動態庫就很是適合,能夠減小應用程序的體積。unix
三.庫的建立
靜態庫的建立
gcc -c filen.c
ar -cr libname.a file1.o file2.o 。。
動態庫的建立
gcc -shard -fpic -o libname.so test1.c test2.c ....
-fpic:產生代碼位置無關代碼
-shared 生成一個共享庫
四.實際操做
1.編寫三個簡單函數ADD.c SUB.c MUL.c以下
ADD.c
#include <stdio.h>
int ADD(int a, int b)
{
return a+b;
}
SUB.c
#include <stdio.h>
int SUB(int a ,int b)
{
return a-b;
}
MUL.c
#include <stdio.h>
int MUL(int a , int b)
{
return a*b;
}
和一個頭文件 fun.h
#ifdef __FUN_H_
#define __FUN_H_
extern ADD(int a , int b);
extern SUB(int a , int b);
extern MUL(int a , int b);
#endif
以及一個main函數main.c
main.c
#include <stdio.h>
#include <fun.h>
int main (void)
{
int a=5;
int b=10;
printf("a=5,b=10\n");
printf("a+b=%d\n",ADD(a,b));
printf("a-b=%d\n",SUB(a,b));
printf("a*b=%d\n",MUL(a,b));
return 0;
}
其中main.c 放在~/app下 fun.h ADD.c SUB.c MUL.c放在~/src下
2.生成靜態庫
[hongfuhao@localhost src]$ ls
ADD.c fun.h makefile MUL.c SUB.c
[hongfuhao@localhost src]$ gcc -c *.c
[hongfuhao@localhost src]$ ls
ADD.c ADD.o fun.h makefile MUL.c MUL.o SUB.c SUB.o
[hongfuhao@localhost src]$ ar -cr libfun.a *.o
[hongfuhao@localhost src]$ ls
ADD.c ADD.o fun.h libfun.a makefile MUL.c MUL.o SUB.c SUB.o
上中libfun.a便是一個靜態庫
生成動態庫
[hongfuhao@localhost src]$ ls
ADD.c ADD.o fun.h libfun.a makefile MUL.c MUL.o SUB.c SUB.o
[hongfuhao@localhost src]$ gcc -shared -fpic -o libfun.so *.c
[hongfuhao@localhost src]$ ls
ADD.c ADD.o fun.h libfun.a libfun.so makefile MUL.c MUL.o SUB.c SUB.o
上中libfun.so 就是一個動態庫
3.靜態庫與動態庫的使用
對main.c進行編譯
[hongfuhao@localhost app]$ ls
main.c makefile
[hongfuhao@localhost app]$ gcc main.c
main.c:14:17: 錯誤:fun.h:沒有那個文件或目錄
編譯器報錯 找不到頭文件 須要指定頭文件的位置
-I選項 指定頭文件的路徑
[hongfuhao@localhost app]$ gcc -I../src main.c
/tmp/ccZw9v3Q.o: In function `main':
main.c:(.text+0x30): undefined reference to `ADD'
main.c:(.text+0x5a): undefined reference to `SUB'
main.c:(.text+0x84): undefined reference to `MUL'
collect2: ld 返回 1
連接器再一次報錯 未能找庫
-L選項來指定庫的路徑
-l選項來指定庫的名字 (去掉lib和.a .so)剩下的部分 即-lfun
[hongfuhao@localhost app]$ gcc -I../src main.c -L../src -lfun -o app
[hongfuhao@localhost app]$ ls
app main.c makefile
生成一個可執行文件 app
[hongfuhao@localhost app]$ ./app
./app: error while loading shared libraries: libfun.so: cannot open shared object file: No such file or directory
執行時出錯 找不到動態庫
[hongfuhao@localhost app]$ file app
app: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
這時咱們能夠發現 系統編譯時默認使用的是動態連接 執行時咱們須要指定動態庫的位置
兩種方法:
1:將函數庫移動到/lib 或者/usr/lib下 (須要root權限)
2:修改一個環境變量 LD_LIBRARY_PATH
在這裏我採用第二種方法
[hongfuhao@localhost app]$ ./app
./app: error while loading shared libraries: libfun.so: cannot open shared object file: No such file or directory
[hongfuhao@localhost app]$ file app
app: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
[hongfuhao@localhost app]$ cd ../src
[hongfuhao@localhost src]$ ls
ADD.c ADD.o fun.h libfun.a libfun.so makefile MUL.c MUL.o SUB.c SUB.o
[hongfuhao@localhost src]$ pwd
/home/hongfuhao/src
[hongfuhao@localhost src]$ cd ../app
[hongfuhao@localhost app]$ ls
app main.c makefile
[hongfuhao@localhost app]$ export LD_LIBRARY_PATH='/home/hongfuhao/src'
[hongfuhao@localhost app]$ ./app
a=5,b=10
a+b=15
a-b=-5
a*b=50
能夠看到程序成功執行
若是想採用靜態連接方式 須要-static關鍵字
[hongfuhao@localhost app]$ ls
main.c makefile
[hongfuhao@localhost app]$ gcc -static -I../src main.c -o bpp -L../src -lfun
[hongfuhao@localhost app]$ ls
bpp main.c makefile
[hongfuhao@localhost app]$ ./bpp
a=5,b=10
a+b=15
a-b=-5
a*b=50
這時再看bpp文件
[hongfuhao@localhost app]$ file bpp
bpp: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.18, not stripped
採用的靜態連接執行時不須要指定庫的路徑
兩個文件app與bpp的大小 使用du命令
[hongfuhao@localhost app]$ du app
8 app
[hongfuhao@localhost app]$ du bpp
744 bpp
看一個文件執行依賴的動態庫
[hongfuhao@localhost app]$ ldd app
linux-vdso.so.1 => (0x00007ffe7a3bf000)
libfun.so => /home/hongfuhao/src/libfun.so (0x00007f775018f000)
libc.so.6 => /lib64/libc.so.6 (0x00000030cee00000)
/lib64/ld-linux-x86-64.so.2 (0x00000030ce600000)
以上爲app依賴的動態庫文件
[hongfuhao@localhost app]$ ldd bpp
不是動態可執行文件
bpp不是動態連接因此不顯示
上述就完成一個靜態庫和動態庫的建立和使用
五.makefile
1.概述
Linux 環境下的程序員若是不會使用GNU make來構建和管理本身的工程,應該不能算是一個合格的專業程序員,至少不能稱得上是 Unix程序員。在 Linux(unix )環境下使用GNU 的make工具可以比較容易的構建一個屬於你本身的工程,整個工程的編譯只須要一個命令就能夠完成編譯、鏈接以致於最後的執行。不過這須要投入一些時間去完成一個或者多個稱之爲Makefile 文件的編寫。
所要完成的Makefile 文件描述了整個工程的編譯、鏈接等規則。其中包括:工程中的哪些源文件須要編譯以及如何編譯、須要建立那些庫文件以及如何建立這些庫文件、如何最後產生想要得可執行文件。儘管看起來多是很複雜的事情,可是爲工程編寫Makefile 的好處是可以使用一行命令來完成「自動化編譯」,一旦提供一個(一般對於一個工程來講會是多個)正確的 Makefile。編譯整個工程你所要作的惟一的一件事就是在shell 提示符下輸入make命令。整個工程徹底自動編譯,極大提升了效率。
make是一個命令工具,它解釋Makefile 中的指令(應該說是規則)。在Makefile文件中描述了整個工程全部文件的編譯順序、編譯規則。Makefile 有本身的書寫格式、關鍵字、函數。像C 語言有本身的格式、關鍵字和函數同樣。並且在Makefile 中可使用系統shell所提供的任何命令來完成想要的工做。Makefile(在其它的系統上多是另外的文件名)在絕大多數的IDE 開發環境中都在使用,已經成爲一種工程的編譯方法。
2.makefile 小結即規範
Make 執行總目標
Make clean 執行makefile 中的clean目標
Make -C directory 到directory中執行make
Make clean -C directory 同上兩命令
Make -f common_makefile 經過-f 指定一個makefile文件
Make var=value 給makefie傳一個參數其值爲value
# 註釋
VAR=XXX 定義變量VAR,強制賦值
VAR+=XXX 追加
VAR?=XXX 以前定義這用以前 沒有定義 則定義
Target: depend1 depend2 . . #依賴能夠是文件(目錄)或其餘目標
(tab) action1 action2 #動做那一行必須以TAB鍵打頭
Depend1:
@(tab)Action1 action2 #@j鍵表示不打印該行動做信息
2.實際操做
編寫本身的makefile
使用以前靜態庫與動態庫的案例
建立一個makefile
1 LIB_NAME?=fun
2
3 all:static_library shared_library
4
5 static_library:
6 gcc -c *.c;
7 ar -cr lib${LIB_NAME}.a *.o;
8
9 shared_library:
10 gcc -shared -fpic -o lib${LIB_NAME}.so *.c;
11
12 clean:
13 rm -rf *.o
14 rm -rf *.a *.so
[hongfuhao@localhost src]$ ls
ADD.c fun.h makefile MUL.c SUB.c
makefile已經建立完成
make命令能夠完成以前的操做
[hongfuhao@localhost src]$ ls
ADD.c fun.h makefile MUL.c SUB.c
[hongfuhao@localhost src]$ make
gcc -c *.c;
ar -cr libfun.a *.o;
gcc -shared -fpic -o libfun.so *.c;
[hongfuhao@localhost src]$ ls
ADD.c ADD.o fun.h libfun.a libfun.so makefile MUL.c MUL.o SUB.c SUB.o
完成了靜態庫和動態庫的建立 只須要make一下
對main.c進行makefile的編寫
makefile
1 APP_NAME?=APP
2
3 all:lib_make
4 gcc -static -I../src main.c -L../src -lfun -o ${APP_NAME};
5
6 lib_make:
7 make -C ../src;
8
9 clean:
10 rm -rf ${APP_NAME}
[hongfuhao@localhost app]$ ls
main.c makefile
[hongfuhao@localhost app]$ ls
main.c makefile
只須要make一下 就能夠完成main.c編譯
[hongfuhao@localhost app]$ make
make -C ../src;
make[1]: Entering directory `/home/hongfuhao/src'
gcc -c *.c;
ar -cr libfun.a *.o;
gcc -shared -fpic -o libfun.so *.c;
make[1]: Leaving directory `/home/hongfuhao/src'
gcc -static -I../src main.c -L../src -lfun -o APP;
[hongfuhao@localhost app]$ ls
APP main.c makefile
生成一個APP的可執行文件makefile中執行的是靜態連接
能夠直接執行APP
[hongfuhao@localhost app]$ ./APP
a=5,b=10
a+b=15
a-b=-5
a*b=50
程序成功執行
即完成了一個簡單的makefile的編寫