日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

gcc/g++ 链接库的编译与链接

發(fā)布時間:2023/12/2 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 gcc/g++ 链接库的编译与链接 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

? ? ? 程序編譯一般需要經(jīng)預(yù)處理、編譯、匯編和鏈接幾個步驟。在實(shí)際應(yīng)用中,有些公共代碼需要反復(fù)使用,就把這些代碼編譯成為“庫”文件。在鏈接步驟中,連接器將從庫文件取得所需的代碼,復(fù)制到生成的可執(zhí)行文件中,這種庫稱為靜態(tài)(鏈接)庫,其特點(diǎn)是可執(zhí)行文件中包含了庫代碼的一份完整拷貝,缺點(diǎn)是被多次使用就會多份冗余拷貝。還有一種庫,就是程序在開始運(yùn)行后調(diào)用庫函數(shù)時才被載入,這種庫獨(dú)立于現(xiàn)有的程序,其本身不可執(zhí)行,但包含著程序需要調(diào)用的一些函數(shù),這種庫稱為動態(tài)(鏈接)庫(Dynamic Link Library)。

? ? ? ?在widows平臺下,靜態(tài)鏈接庫是.lib文件,動態(tài)庫文件是.dll文件。在linux平臺下,靜態(tài)鏈接庫是.a文件,動態(tài)鏈接庫是.so文件。這里主要講在linux平臺下的動態(tài)庫和靜態(tài)庫的生成以及鏈接。本文主要參考【1】【2】【3】【4】


一、庫的基本知識

? ? ?首先說明要對庫有一個比較直觀的理解。庫是寫好的現(xiàn)有的,成熟的,可以復(fù)用的代碼?,F(xiàn)實(shí)中每個程序都依賴很多基礎(chǔ)的底層庫,不可能每個人的代碼都從零開始,因此庫的存在意義非同尋常。本質(zhì)上說來庫是一種可執(zhí)行代碼的二進(jìn)制形式(注,其本身不可執(zhí)行),可以被操作系統(tǒng)載入內(nèi)存執(zhí)行。

? ? ? ?靜態(tài)鏈接庫,之所以稱為“靜態(tài)庫”,是因?yàn)樵阪溄与A段,會將匯編生成的目標(biāo)文件.o與引用到的庫一起鏈接打包到可執(zhí)行文件中,因此對應(yīng)的鏈接方式為靜態(tài)鏈接。其實(shí)一個靜態(tài)鏈接庫可以簡單看成一組目標(biāo)文件(.o/.obj文件)的集合,即很多目標(biāo)文件經(jīng)過壓縮打包后形成的一個文件。靜態(tài)庫特點(diǎn)總結(jié):

? ? ? ? ? ? ? 1. 靜態(tài)庫對函數(shù)庫的鏈接是放在編譯時期完成

? ? ? ? ? ? ? 2. 程序在運(yùn)行時對函數(shù)庫再唔瓜葛,一直方便。

? ? ? ? ? ? ? 3. 浪費(fèi)空間和資源,因?yàn)樗邢嚓P(guān)的目標(biāo)文件和牽涉到的函數(shù)庫被鏈接合成一個可執(zhí)行文件。

? ? ? ?linux下使用ar工具(windows下用lib.exe)(具體的用法參考【5】),可以將目標(biāo)文件壓縮到一起,并且對其進(jìn)行編號和索引,一便于查找和索引。一般創(chuàng)建靜態(tài)鏈接庫的步驟如下:


?? ? ? ?靜態(tài)鏈接庫的命名規(guī)則,庫的名稱和庫文件名稱不同,有聯(lián)系,假定庫名稱為"my_library_name",那么起庫文件名為"lib[my_library_name].a"(方括號是為了區(qū)分,實(shí)際上沒有)

? ? ? ??動態(tài)鏈接庫,在程序編譯是并不會被連接到目標(biāo)代碼中,而是在程序運(yùn)行時才被載入。不同的應(yīng)用程序如果調(diào)用相同的庫,那么在內(nèi)存里只需要有一份該共享庫的實(shí)例,規(guī)避了空間浪費(fèi)問題。動態(tài)庫的一些總結(jié):

? ? ? ? ? ?1. 動態(tài)庫把對一些庫函數(shù)的鏈接載入推遲到程序運(yùn)行時期

? ? ? ? ? ?2. 可以實(shí)現(xiàn)進(jìn)程之間的資源共享,(動態(tài)庫也成為共享庫)

? ? ? ? ? ?3. 將一些程序升級變得簡單

? ? ? ? ? ?4. 設(shè)置可以真正做到鏈接載入完全由程序員在程序代碼中控制(顯式調(diào)用)

? ? ? ? Linux下gcc編譯的執(zhí)行文件默認(rèn)是ELF格式,不需要初始化入口,亦不需要函數(shù)做特別的聲明,編寫比較方便。與windows系統(tǒng)下的格式不同。與創(chuàng)建靜態(tài)庫不同的是,不需要打包工具,直接使用編譯器即可創(chuàng)建動態(tài)庫。

?? ? ? ?動態(tài)鏈接庫的命名規(guī)則,與靜態(tài)鏈接庫的方式相同,不過其后綴名為.so,命名形式為"lib[my_library_name].so"? ?。但是在實(shí)際使用過程中l(wèi)ibxxx.so 大多數(shù)情況只是一個鏈接,它鏈接到一個包含版本信息的庫文件 libxxxx.so.xx,如下圖。當(dāng)然自己可以使用 ln 命令,制作鏈接?ln -s libxxxx.so.xx libxxxx.so。



二、庫的編譯和鏈接

? ? ? ? 下面使用一個例子來說明鏈接庫是如何生成與鏈接的。這個例子的源代碼參考【4】。這里有五個文件,頭文件“SoDemoTest.h”,三個cpp文件“one.cpp”、"two.cpp"、"three.cpp",main函數(shù)實(shí)現(xiàn)文件“main.cpp”。

[cpp] view plaincopy
  • #ifndef?_SO_DEMO_TEST_HEADER_??
  • #define?_SO_DEMO_TEST_HEADER_??
  • #include?<iostream>??
  • using?namespace?std;??
  • void?one();??
  • void?two();??
  • void?three();??
  • #endif??
  • [cpp] view plaincopy
  • /*?one.cpp?*/??
  • #include?"SoDemoTest.h"??
  • void?one(){??
  • ????cout?<<?"call?one()?function"?<<?endl;??
  • }??
  • [plain] view plaincopy
  • /*?two.cpp?*/??
  • #include?"SoDemoTest.h"??
  • void?two(){??
  • ????cout?<<?"call?two()?function"?<<?endl;??
  • }??
  • [cpp] view plaincopy
  • /*?three.cpp?*/??
  • #include?"SoDemoTest.h"??
  • void?three(){??
  • ????cout?<<?"call?three()?function"?<<?endl;??
  • }??
  • [cpp] view plaincopy
  • /*?main.cpp?*/??
  • #include?"SoDemoTest.h"??
  • int?main(){??
  • ????one();??
  • ????two();??
  • ????three();??
  • ????return?0;??
  • }??


  • ? ? ??gcc/g++的編譯參數(shù),這里只介紹 -L 、-l、-include、-I、-shared、-fPIC

    ? ? ? -L :表示要鏈接的庫所在的目錄。-L. ?表示要鏈接的庫在當(dāng)前目錄, -L/usr/lib 表示要連接的庫在/usr/lib下。目錄在/usr/lib時,系統(tǒng)會自動搜索這個目錄,可以不用指明。

    ? ? ?-l (L的小寫):表示需要鏈接庫的名稱,注意不是庫文件名稱,比如庫文件為 libtest.so,那么庫名稱為test

    ? ? ?-include :包含頭文件,這個很少用,因?yàn)橐话闱闆r下在源碼中,都有指定頭文件。

    ? ? ? -I (i 的大寫):指定頭文件的所在的目錄,可以使用相對路徑。

    ? ? ?-shared :指定生成動態(tài)鏈接庫

    ? ? ?-fPIC: ?表示編譯為位置獨(dú)立的代碼,不用此選項(xiàng)的話編譯后的代碼是位置相關(guān)的所以動態(tài)載入時事通過代碼拷貝的方式來滿足不同進(jìn)程的需要,而不能達(dá)到真正代碼共享的目的。


    ? ? ??生成鏈接庫

    ? ? ? 第1步,生成目標(biāo)文件:g++ -c xxx.cpp

    ?? ? ? 第2步,創(chuàng)建靜態(tài)鏈接庫: ?ar ?cqs ?libxxxx.a ?xx1.o xx2.o xx3.o (參數(shù)選項(xiàng)請看【5】)

    ? ? ? ? 第3步,程序中使用靜態(tài)鏈接庫

    ? ? ? ? 第4步,創(chuàng)建動態(tài)鏈接庫 g++ -fPIC -shared -o libxxx.so xx1.cpp xx2.cpp xx3.cpp

    ? ? ? ? 第5步,動態(tài)鏈接庫使用



    ? ? ???庫的鏈接,上面簡單演示了一遍庫的生成過程,但是還有很多細(xì)節(jié)沒有講清楚。以下問題需要注意:

    ? ? ? ?1. 鏈接過程中可能出現(xiàn)多種鏈接方式,需要使用一些參數(shù)來指定,下面只是一個演示,在測試時,自己填寫具體的名稱

    [plain] view plaincopy
  • g++?testmain.o?-o?testmain?-WI,-Bstatic?-lstaticlib?-WI,-Bdynamic?-ldynamiclib??

  • ? ? ? ?2. 鏈接過程中同一個庫(名稱相同)的靜態(tài)和動態(tài)兩種鏈接庫,在鏈接過程中,系統(tǒng)優(yōu)先選擇動態(tài)鏈接庫

    ?? ? 3. 動態(tài)鏈接庫路徑,系統(tǒng)默認(rèn)在/usr/lib 和/usr/local/lib兩個庫目錄搜索,自己定義的庫需要格外指定路徑(設(shè)定變量LD_LIABRARY_PATH)或者將其拷貝到這兩個目錄下,在上面的例子的測試過程,已經(jīng)有說明。當(dāng)然也可以將當(dāng)前路徑添加到/etc/ld.so.conf文件中或者/etc/ld.so.conf.d目錄下的一個文件中。
    ? ? ? 4. 查看動態(tài)鏈接庫。有時候可能需要查看一個庫中到底有哪些函數(shù),nm命令可以打印出庫中的涉及到的所有符號。庫既可以是靜態(tài)的也可以是動態(tài)的。nm列出的符號有很多,常見的有三種: ? ? ? ? 一種是在庫中被調(diào)用,但并沒有在庫中定義(表明需要其他庫支持),用U表示; ? ? ? ? 一種是在庫中定義的函數(shù),用T表示,這是最常見的; ? ? ? ? 另一種所謂的“弱態(tài)”符號,它們雖然在庫中定義,但可能被其他庫中的同名符號覆蓋,用W表示。

    ? ? ? ? ?使用ldd命令可以查看程序的庫依賴:



    ? ? ? ? ?注:更多詳細(xì)的信息請閱讀下面的鏈接中的內(nèi)容~

    ? ? ? ?


    【1】博客園:C++靜態(tài)庫與動態(tài)庫

    【2】CSDN:Linux 靜態(tài)庫&動態(tài)庫調(diào)用

    【3】博客園:gcc/g++ 動態(tài)編譯和鏈接問題

    【4】Linux公社:用g++編譯生成動態(tài)連接庫*.so的方法及連接

    【5】CSDN:linux ar命令

    總結(jié)

    以上是生活随笔為你收集整理的gcc/g++ 链接库的编译与链接的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。