gcc中(-I -l -L)參數的意義

關於編譯連接的常識helloworld背後發生了什麼?(CSAPP筆記2)

gcc -o hello hello.c   -I/home/hello/include  -L/home/hello/lib  -lworld
//有時候還需設置環境變量 LD_LIBRARY_PATH

前面的編譯選項,一般來說大家都熟悉,關鍵是後面幾個,我們逐一解釋:

-I/home/hello/include

我們知道,一般在寫代碼時候有時候會用到頭文件,比如你要用vector就得include< vector >,對於系統來說,它會優先去系統目錄下去找這個庫,如果使用include “ccc.h” 則會優先去當前目錄下找。

而-I選項則告訴編譯器優先去指定目錄下查找再去默認的目錄下查找,比如上述的例子:尋找的頭文件的順序:/home/hello/include –> /usr/include –> /usr/local/include

-L/home/hello/lib

表示將/home/hello/lib目錄作爲第一個尋找庫文件的目錄,查找庫文件的順序依次是:/home/hello/lib –> 系統目錄 –> 當前目錄

-lworld

表示尋找動態鏈接庫文件 libword.so(也就是文件名去掉前綴和後綴所代表的庫文件)

如果加上編譯選項-static,表示尋找靜態鏈接庫文件,也就是libword.a

注意:

對於第三方提供的動態鏈接庫(.so),一般將其拷貝到一個lib目錄下(/usr/local/lib),或者使用-L來指定其所在目錄, 然後使用-l來指定其名稱


動態庫和靜態庫

庫是寫好的現有的,成熟的,可以複用的代碼。現實中每個程序都要依賴很多基礎的底層庫,不可能每個人的代碼都從零開始,因此庫的存在意義非同尋常。

本質上來說庫是一種可執行代碼的二進制形式,可以被操作系統載入內存執行。庫有兩種:靜態庫(.a、.lib)和動態庫(.so、.dll)。

他們的區別:

靜態庫

在鏈接階段,會將彙編生成的目標文件.o與引用到的庫一起鏈接打包到可執行文件中。因此對應的鏈接方式稱爲靜態鏈接。

試想一下,靜態庫與彙編生成的目標文件一起鏈接爲可執行文件,那麼靜態庫必定跟.o文件格式相似。其實一個靜態庫可以簡單看成是一組目標文件(.o/.obj文件)的集合,即很多目標文件經過壓縮打包後形成的一個文件。靜態庫特點總結:

靜態庫對函數庫的鏈接是放在編譯時期完成的。

程序在運行時與函數庫再無瓜葛,移植方便。

浪費空間和資源,因爲所有相關的目標文件與牽涉到的函數庫被鏈接合成一個可執行文件。

Linux靜態庫命名規範,必須是”lib[your_library_name].a”:lib爲前綴,中間是靜態庫名,擴展名爲.a。


動態庫

空間浪費是靜態庫的一個問題。

另一個問題是靜態庫對程序的更新、部署和發佈頁會帶來麻煩。如果靜態庫liba.lib更新了,所以使用它的應用程序都需要重新編譯、發佈給用戶(對於玩家來說,可能是一個很小的改動,卻導致整個程序重新下載,全量更新)。

動態庫在程序編譯時並不會被連接到目標代碼中,而是在程序運行是才被載入。不同的應用程序如果調用相同的庫,那麼在內存裏只需要有一份該共享庫的實例,規避了空間浪費問題。動態庫在程序運行是才被載入,也解決了靜態庫對程序的更新、部署和發佈頁會帶來麻煩。用戶只需要更新動態庫即可,增量更新。

動態鏈接庫的名字形式爲 libxxx.so,前綴是lib,後綴名爲“.so”。

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章