• 正文
    • 一、前言
    • 二、 基礎(chǔ)知識
    • 三、 制作靜態(tài)庫
    • 四、 制作動態(tài)庫
    • 五、重新建立工程
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

《電話號碼管理系統(tǒng)》制作成靜態(tài)庫和動態(tài)庫

02/01 15:17
432
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

一、前言

上次寫了一篇關(guān)于Makefile的文章。有很多粉絲留言,有的粉絲想進一步了解cmake的使用方法,還有的粉絲想知道如何將一些函數(shù)編譯成動態(tài)庫或者靜態(tài)庫,然后再將該庫編譯到內(nèi)存中。

一口君必須安排,本篇先講如何將一些函數(shù)編譯成動態(tài)庫或者靜態(tài)庫。

這就涉及到一個庫的概念,關(guān)于制作的庫的基礎(chǔ)知識,一口君已經(jīng)在下面這篇文章中詳細的講述了相關(guān)概念,建議大家先看下面這篇文章。

《Linux庫概念,動態(tài)庫和靜態(tài)庫概念》

本文,一口君將繼續(xù)以之前的 電話號碼管理系統(tǒng)的項目為基礎(chǔ),給大家詳細講解如何將該項目中的函數(shù)制作成動態(tài)庫和靜態(tài)庫。

《從0寫一個《電話號碼管理系統(tǒng)》的C入門項目》

二、 基礎(chǔ)知識

1) 靜態(tài)庫

所謂靜態(tài)庫,就是在靜態(tài)編譯時由編譯器到指定目錄尋找并且進行鏈接,一旦鏈接完成,最終的可執(zhí)行程序中就包含了該庫文件中的所有有用信息,包括代碼段、數(shù)據(jù)段等。

2)動態(tài)庫

所謂動態(tài)庫,就是在應(yīng)用程序運行時,由操作系統(tǒng)根據(jù)應(yīng)用程序的請求,動態(tài)到指定目錄下尋找并裝載入內(nèi)存中,同時需要進行地址重定向。

3)庫文件命名

靜態(tài)庫的名字一般為libxxxx.a,其中xxxx是該lib的名稱;動態(tài)庫的名字一般為libxxxx.so.x.y.z,含義如下圖所示:

4)制作庫文件常用參數(shù)

首先需要了解gcc編譯庫要用到一些參數(shù),很重要。

參數(shù) 含義
-shared 指定生成動態(tài)鏈接庫。
-static 指定生成靜態(tài)鏈接庫。
-fPIC 表示編譯為位置獨立的代碼,用于編譯共享庫。目標文件需要創(chuàng)建成位置無關(guān)碼,概念上就是在可執(zhí)行程序裝載它們的時候,它們可以放在可執(zhí)行程序的內(nèi)存里的任何地方。
-L 表示要連接的庫在當前目錄中。
-l 指定鏈接時需要的動態(tài)庫。編譯器查找動態(tài)連接庫時有隱含的命名規(guī)則,即在給出的名字前面加上lib,后面加上.so來確定庫的名稱。
-Wall 生成所有警告信息。
-ggdb 此選項將盡可能的生成gdb的可以使用的調(diào)試信息。
-g 編譯器在編譯的時候產(chǎn)生調(diào)試信息。
-c 只激活預(yù)處理、編譯和匯編,也就是把程序做成目標文件(.o文件)。
-Wl,options 把參數(shù)(options)傳遞給鏈接器ld。如果options中間有逗號,就將options分成多個選項,然后傳遞給鏈接程序。

三、 制作靜態(tài)庫

原始文件目錄如下:

peng@ubuntu:/mnt/hgfs/code/phone3$?tree?.
.
├──?main.c
├──?phone.c
└──?phone.h

0?directories,?3?files

其中
phone.c包含了對鏈表的所有的操作函數(shù)
phone.h 是phone.c中所有函數(shù)的原型說明
main.c是主程序

下面我們將phone.c制作成靜態(tài)庫。

1. 把 listd.c 編譯成.o文件

?peng@ubuntu:/mnt/hgfs/code/phone3$?gcc?-c?phone.c

2. 使用 ar 命令生成靜態(tài)庫libadd.a

靜態(tài)庫名字遵循靜態(tài)庫命名的規(guī)則 lib + 名字 + .a

peng@ubuntu:/mnt/hgfs/code/phone3$?ar?-rc?libphone.a?phone.o?

3. 將庫和頭文件拷貝到其他目錄下

將庫文件移動到lib目錄下

peng@ubuntu:/mnt/hgfs/code/phone3$?mkdir?lib
peng@ubuntu:/mnt/hgfs/code/phone3$?mv?libphone.a?lib

移動頭文件到include目錄下

peng@ubuntu:/mnt/hgfs/code/phone3$?mkdir?include
peng@ubuntu:/mnt/hgfs/code/phone3$?mv?phone.h?include/

刪除phone.c

peng@ubuntu:/mnt/hgfs/code/phone3$?rm?phone.c

此處可不刪除,下面的的編譯已經(jīng)用不到該文件
刪除僅僅是為了排除干擾,有些同學(xué)會以為這個文件還會被編譯進去

最終文件結(jié)構(gòu)如下:

peng@ubuntu:/mnt/hgfs/code/phone3$?tree?./
./
├──?include
│???└──?phone.h
├──?lib
│???└──?libphone.a
├──?main.c
└──?run

2?directories,?6?files

lib include 目錄也可以是其他目錄,實際項目中庫文件和頭文件都會放到一些指定目錄下

4.編譯

值編譯main.c,會有以下錯誤提示,主要是因為phone.h

peng@ubuntu:/mnt/hgfs/code/phone3$?gcc?main.c?
main.c:3:19:?致命錯誤:phone.h:沒有那個文件或目錄
編譯中斷。

制定頭文件位置,編譯結(jié)果如下,可以看到錯誤提示,“沒有定義create”,這是因為在鏈接的時候找打不到這些函數(shù)的定義的地方

peng@ubuntu:/mnt/hgfs/code/phone3$?gcc?main.c?-I?./include
/tmp/cctUUKm9.o:?In?function?`management':
main.c:(.text+0x109):?undefined?reference?to?`create'
main.c:(.text+0x120):?undefined?reference?to?`delete'
main.c:(.text+0x137):?undefined?reference?to?`search'
main.c:(.text+0x14e):?undefined?reference?to?`display'
main.c:(.text+0x167):?undefined?reference?to?`allfree'
/tmp/cctUUKm9.o:?In?function?`main':
main.c:(.text+0x2e3):?undefined?reference?to?`init'
collect2:?ld?返回?1

最終我們執(zhí)行

peng@ubuntu:/mnt/hgfs/code/phone3$?gcc?main.c?-I?./include?./lib/libphone.a?

指定了頭文件和庫文件位置,執(zhí)行結(jié)果如下:

與之前運行現(xiàn)象是一樣的。

可見,使用庫的時候我們必須制定頭文件目錄以及庫目錄。

四、 制作動態(tài)庫

原始文件

peng@ubuntu:/mnt/hgfs/code/phone3$?tree?.
.
├──?main.c
├──?phone.c
└──?phone.h

0?directories,?3?files

1. 把phone.c編譯成動態(tài)鏈接庫libphone.so

gcc?-fPIC?-o?libphone.o?-c?phone.c
gcc?-shared?-o?libphone.so?libphone.o

也可以直接使用一條命令

gcc?-fPIC?-shared?-o?libphone.so?phone.c

2. 動態(tài)庫的安裝

通常動態(tài)庫拷貝到/lib下:

peng@ubuntu:/mnt/hgfs/code/phone4$?sudo?mv?libphone.so?/lib/
[sudo]?password?for?peng:?

刪除phone.c

peng@ubuntu:/mnt/hgfs/code/phone3$?rm?phone.c

3. 編譯執(zhí)行

編譯動態(tài)庫:

peng@ubuntu:/mnt/hgfs/code/phone4$?gcc?main.c?-lphone?-o?run

此時使用我們制作的動態(tài)庫,只需要加上 -lphone即可

注意觀察編譯時動態(tài)庫的名字與庫文件對應(yīng)關(guān)系

libphone.so<--------->-lphone?

執(zhí)行結(jié)果如下:

五、重新建立工程

下面我們將文件重新放置

當前文件目錄如下:

./include
└──?phone.h
./Makefile?
./obj
└──?Makefile
./src
├──?main.c
└──?Makefile

0?directories,?5?files

并添加3個Makefile

編譯步驟如下:

 

    1. 聲明環(huán)境變量
CC???????編譯名稱
LIBS?????用到的動態(tài)庫
SUBDIRS??子目錄
OBJS?????src下所有的目標文件
BIN??????最終生成的可執(zhí)行程序名字
OBJS_DIR?目標文件存放目錄
BIN_DIR??可執(zhí)行程序存儲目錄

 

      1. 執(zhí)行make的默認目標all,依賴CHECK_DIR $(SUBDIRS)
      1. 執(zhí)行目標CHECK_DIR ,創(chuàng)建目錄bin
      1. 執(zhí)行目標@ ,進入子目錄src、obj執(zhí)行子目錄的Makefile,
      1. 打印語句

echo begin compile phone!

 

      1. 進入子目錄src執(zhí)行Makfile,
    1. 執(zhí)行命令
@$(CC)?-c?main.c?-I../include?-o?../$(OBJS_DIR)/main.o??
@?:打印該條命令
-I../include?頭文件在上一級目錄下的include中
-o?../$(OBJS_DIR)/main.o?生成的目標文件存放在../obj/main.o

 

      1. 進入子目錄obj執(zhí)行Makfile,
      1. 目標為../bin/phone:main.o

 

    1. 執(zhí)行命令
@$(CC)?-o?$@?$^??$(LIBS)
@$(CC)?同上
$@?表示生成的目標文件,即../bin/phone
$^?表示所有的依賴文件,即上面:后面目標文件main.o

編譯完成后就會在bin目錄下創(chuàng)建可執(zhí)行程序文件phone,

運行結(jié)果如下:

所有源碼:公眾號【一口Linux】后臺回復(fù):電話號碼管理

相關(guān)推薦

登錄即可解鎖
  • 海量技術(shù)文章
  • 設(shè)計資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄

公眾號『一口Linux』號主彭老師,擁有15年嵌入式開發(fā)經(jīng)驗和培訓(xùn)經(jīng)驗。曾任職ZTE,某研究所,華清遠見教學(xué)總監(jiān)。擁有多篇網(wǎng)絡(luò)協(xié)議相關(guān)專利和軟件著作。精通計算機網(wǎng)絡(luò)、Linux系統(tǒng)編程、ARM、Linux驅(qū)動、龍芯、物聯(lián)網(wǎng)。原創(chuàng)內(nèi)容基本從實際項目出發(fā),保持原理+實踐風格,適合Linux驅(qū)動新手入門和技術(shù)進階。