Linux靜態庫

 
一、引言
通常情況下,對函數庫的鏈接是放在編譯時期(compile time)完成的。所有相關的對象文件(object file)與牽涉到的函數庫(library)被鏈接合成一個可執行文件(executable file)。程序在運行時,與函數庫再無瓜葛,因爲所有需要的函數已拷貝到自己門下。所以這些函數庫被成爲靜態庫(static libaray),通常文件名爲“libxxx.a”的形式。另外,我們也可以把對一些庫函數的鏈接載入推遲到程序運行,這種庫稱之爲動態庫,關於動態庫的詳細內容請參考《linux動態庫(轉)
二、編譯靜態庫
編譯靜態庫很簡單。
比如:gcc robin.c -c -L. -lRobinDynamic -o robin.o
注意這裏一定要加-c選項,不然如果的代碼中沒有Main函數的話,就編譯不過。
這裏-L. -lRobinDynamic表示在當前目錄下搜尋RobinDynamic庫,並載入它。該庫可以是靜態,也可以是動態的。編譯靜態庫或編譯動態庫時,對庫的搜尋和載入都一樣,因此關於此 部分的知識請參照《linux動態庫(轉)
注意:如果要使用多個庫的話,可以如下形式:gcc test.c -L. -lRobin -lRobinDynamic -o test.exe
三、打包靜態庫
編譯完成,我需要用ar命令對生成的目標文件進行打包,以便使用。
ar命令選項如下:
d -----從指定的靜態庫文件中刪除文件
m -----把文件移動到指定的靜態庫文件中
p -----把靜態庫文件中指定的文件輸出到標準輸出
q -----快速地把文件追加到靜態庫文件中
r -----把文件插入到靜態庫文件中
t -----顯示靜態庫文件中文件的列表
x -----從靜態庫文件中提取文件
還有多個修飾符修改以上基本選項,詳細請man ar 以下列出三個:
        a -----把新的目標文件(*.o)添加到靜態庫文件中現有文件membername之後,如果沒有membername項就表示所有現有文件之後
        b -----把新的目標文件(*.o)添加到靜態庫文件中現有文件membername之前,如果沒有membername項就表示所有現有文件之前
        c -----創建一個新的.a文件
        v -----使用詳細模式,該模式下,將顯示你添加的所有文件。
ar命令的命令行格式如下:
    ar [-]{dmpqrtx}[abcfilNoPsSuvV] [membername] [count] archive files...
參數archive定義庫的名稱, files是你向庫文件要添加的目標文件的清單, 用空格分隔每個文件.
比如目標文件添加到一個靜態庫文件的命令如下:
    ar r libapue.a error.o errorlog.o lockreg.o
如果此次該靜態文件庫還不存在的話,它會先創建它再添加目標文件。
如果我們想新建一個靜態庫(如果有,先刪除)的話,可以用如下的命令:
ar crv libRobin.a robin.o libRobinDynamic.so
這樣就了創建了librobin.a靜態庫文件, 你可以用 t 選項顯示包含在庫中的文件
創建庫文件之後,可以創建這個靜態庫文件的索引來幫助提高和庫連接的其他程序的編譯速度.
使用ranlib程序創建庫的索引,索引存放在庫文件內部.
ranlib libapue.a
用nm命令可以進行顯示目標文件或.so文件的符號,系統必須依靠這些符號找到其對應的代碼地址,然後執行這些代碼。
nm命令用於顯示.a存檔文件的時候,它將顯示.a中所有目標文件或.so文件的符號
顯示目標文件的符號,可用如下命令:
nm robin.o | more
0000000000000000 T sayHello
                 U sayHelloWorld
顯示.so文件的符號,可用如下命令
nm libRobinDynamic.so
0000000000200e50 a _DYNAMIC
0000000000200fe8 a _GLOBAL_OFFSET_TABLE_
                 w _Jv_RegisterClasses
0000000000200e30 d __CTOR_END__
0000000000200e28 d __CTOR_LIST__
0000000000200e40 d __DTOR_END__
0000000000200e38 d __DTOR_LIST__
0000000000000670 r __FRAME_END__
0000000000200e48 d __JCR_END__
0000000000200e48 d __JCR_LIST__
0000000000201018 A __bss_start
                 w __cxa_finalize@@GLIBC_2.2.5
00000000000005c0 t __do_global_ctors_aux
0000000000000500 t __do_global_dtors_aux
0000000000201010 d __dso_handle
                 w __gmon_start__
0000000000201018 A _edata
0000000000201028 A _end
00000000000005f8 T _fini
0000000000000498 T _init
00000000000004e0 t call_gmon_start
0000000000201018 b completed.7424
0000000000201020 b dtor_idx.7426
0000000000000580 t frame_dummy
                 U puts@@GLIBC_2.2.5
00000000000005ac T sayHelloWorld
如果用nm命令對.a存檔文件進行操作的時候,它將顯示.a中所有目標文件或.so文件的符號。
命令如下:
nm libapue.a | more
三、使用靜態庫
使用靜態庫,只有在編譯時才需要,運行時就不要需要了。
使用靜態庫,在進行編譯時,可以和使用動態庫一樣進行使用因此關於此部分的知識請參照《linux動態庫(轉)
另外,如果要使用多個庫的話,可以如下形式gcc test.c -L. -lRobin -lRobinDynamic -o test.exe
另外也可以以如下形式使用靜態庫:
gcc test.cpp –o test.exe libexample.a
使用靜態庫進行編譯時需要注意如下事項:
1)編譯時,靜態庫如果不放在-l項中,那麼一定要放在最後。
如:(在-o後面)
gcc test.cpp –o test.exe libexample.a
2)使用靜態庫時一定要連接所有用到的靜態庫,有多個靜態庫時,應該按照從新到舊(越底層越後面)的順序進行排列
如要使用libwinkeemq-cpp.a,由於libwinkeemq-cpp.a用到了libactivemq-cpp.a,
而libactivemq-cpp.a又用到了libpthread.a, libuuid.a等等庫。
其命令應如下
gcc test.cpp –o test.exe libwinkeemq-cpp.a lib libactivemq-cpp.a libpthrea.a libuuid.a…
3)靜態庫和動態庫結合使用。
這時動態庫應該放到靜態庫前面,動態庫按照從舊到新(越底層越前面)的順序排列。
比如:gcc test.cpp –L/usr/local/lib –lactivemq-cpp –lrobin –o test.exe libwinkeemq-cpp.a
這裏activemq-cpp就比robin更底層,即robin庫會使用activemq-cpp庫
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章