個(gè)人博客首頁(yè)(點(diǎn)擊查看詳情) -- https://blog.51cto.com/11495268
1、簡(jiǎn)介
程序編譯一般需要經(jīng)預(yù)處理、編譯、匯編和鏈接,在實(shí)際應(yīng)用中,有些公共代碼需要反復(fù)使用,就把這些代碼編譯成為 "庫(kù)" 文件,本文 主要 描述 Linux 平臺(tái)下 庫(kù)文件的 創(chuàng)建 和 鏈接 相關(guān)操作(既然都看 這么底層的內(nèi)容了,相信 也有一定的基礎(chǔ),所以本文 對(duì)相關(guān)命令 也不會(huì)進(jìn)行詳細(xì)解釋)
備注:
linux平臺(tái)下,靜態(tài)鏈接庫(kù)是以 .a 的后綴文件,動(dòng)態(tài)鏈接庫(kù)是以 .so 的后綴文件
widows平臺(tái)下,靜態(tài)鏈接庫(kù)是以 .lib 的后綴文件,動(dòng)態(tài)庫(kù)文件是以 .dll 的后綴文件
成都創(chuàng)新互聯(lián)公司專注于定結(jié)網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠(chéng)為您提供定結(jié)營(yíng)銷型網(wǎng)站建設(shè),定結(jié)網(wǎng)站制作、定結(jié)網(wǎng)頁(yè)設(shè)計(jì)、定結(jié)網(wǎng)站官網(wǎng)定制、微信小程序開發(fā)服務(wù),打造定結(jié)網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供定結(jié)網(wǎng)站排名全網(wǎng)營(yíng)銷落地服務(wù)。
2、庫(kù)文件
庫(kù)是寫好的 現(xiàn)有的、成熟的 一種可執(zhí)行、可以復(fù)用代碼的二進(jìn)制形式(注,其本身不可執(zhí)行),可以被操作系統(tǒng)載入內(nèi)存執(zhí)行;分為 靜態(tài)鏈接庫(kù) 和 動(dòng)態(tài)鏈接庫(kù)
2.1 靜態(tài)庫(kù)
2.1.1 簡(jiǎn)介
靜態(tài)鏈接庫(kù)可以簡(jiǎn)單看成一組目標(biāo)文件.o 的集合,即很多目標(biāo)文件經(jīng)過壓縮打包后形成的一個(gè)文件
2.1.2 原理
鏈接器將從 靜態(tài)(鏈接)庫(kù) 取得所需的代碼,復(fù)制到生成的可執(zhí)行文件
2.1.3 特點(diǎn)
靜態(tài)庫(kù)對(duì)函數(shù)庫(kù)的鏈接是放在程序編譯時(shí)期完成
程序在運(yùn)行時(shí)對(duì)函數(shù)庫(kù)再無(wú)瓜葛(因?yàn)樗邢嚓P(guān)的目標(biāo)文件和牽涉到的函數(shù)庫(kù)被鏈接合成一個(gè)可執(zhí)行文件)
浪費(fèi)空間和資源(因?yàn)樗邢嚓P(guān)的目標(biāo)文件和牽涉到的函數(shù)庫(kù)被鏈接合成一個(gè)可執(zhí)行文件)
2.1.4 創(chuàng)建流程
備注:
linux下使用ar工具(windows下用lib.exe)將目標(biāo)文件壓縮到一起,并且對(duì)其進(jìn)行編號(hào)和索引,以便于查找和索引
2.1.5 命令規(guī)則
靜態(tài)鏈接庫(kù)的名稱 和 庫(kù)文件名稱不同但有聯(lián)系;例如,庫(kù)名稱為"static_library",那么起庫(kù)文件名為"libstatic_library.a"
2.2 動(dòng)態(tài)庫(kù)
2.2.1 簡(jiǎn)介
程序在開始運(yùn)行后調(diào)用 動(dòng)態(tài)(鏈接)庫(kù)(Dynamic Link Library)中的函數(shù) 才被載入
2.2.2 原理
程序編譯是并不會(huì)被連接到目標(biāo)代碼中,而是在程序運(yùn)行時(shí)才被載入
2.2.3 特點(diǎn)
動(dòng)態(tài)庫(kù)把對(duì)一些庫(kù)函數(shù)的鏈接載入推遲到程序運(yùn)行時(shí)期
進(jìn)程之間的相同動(dòng)態(tài)庫(kù)實(shí)現(xiàn)共享
2.2.4 創(chuàng)建
創(chuàng)建動(dòng)態(tài)庫(kù)與創(chuàng)建靜態(tài)庫(kù)不同,不需要打包工具,直接使用編譯器創(chuàng)建動(dòng)態(tài)庫(kù)
# gcc -fPIC -shared -o libxxx.so xx1.c xx2.c xx3.c
2.2.5 命名規(guī)則
動(dòng)態(tài)鏈接庫(kù)的名稱 和 庫(kù)文件名稱不同但有聯(lián)系;例如,庫(kù)名稱為"dynamic_library",那么起庫(kù)文件名為"libdynamic_library.a"
3、庫(kù)文件 編譯、鏈接(實(shí)戰(zhàn)操作)
3.1 靜態(tài)庫(kù) 編譯、鏈接
3.1.1 靜態(tài)庫(kù) 源碼
# cat gcc_lib_header.h
#ifndef __GCC_LIB_HEADER_H_
#define __GCC_LIB_HEADER_H_
#include
void gcc_lib_one();
void gcc_lib_two();
void gcc_lib_three();
#endif
# cat gcc_lib_first.c
/*
filename : gcc_lib_first.c
*/
#include "gcc_lib_header.h"
void gcc_lib_one(){
printf("call gcc_lib_one() function\n");
}
# cat gcc_lib_sec.c
/*
filename : gcc_lib_sec.c
*/
#include "gcc_lib_header.h"
void gcc_lib_two(){
printf("call gcc_lib_two() function\n");
}
# cat gcc_lib_third.c
/*
filename : gcc_lib_third.c
*/
#include "gcc_lib_header.h"
void gcc_lib_three(){
printf("call gcc_lib_three() function\n");
}
# cat gcc_lib_main.c
/*
filename : gcc_lib_main.c
*/
#include "gcc_lib_header.h"
int main(int argc, char *argv[])
{
gcc_lib_one();
gcc_lib_two();
gcc_lib_three();
return 0;
}
3.1.2 靜態(tài)庫(kù) 編譯
# gcc -c gcc_lib_first.c
# gcc -c gcc_lib_sec.c
# gcc -c gcc_lib_third.c
# ar cqs libstatic_gcc.a gcc_lib_first.o gcc_lib_sec.o gcc_lib_third.o
3.1.3 靜態(tài)庫(kù) 鏈接
## -L ./ 等同于 -L.
# gcc -o gcc_lib_main_static gcc_lib_main.c -L. -static -l static_gcc
# ./gcc_lib_main_static
call gcc_lib_one() function
call gcc_lib_two() function
call gcc_lib_three() function
3.2 動(dòng)態(tài)庫(kù) 編譯、鏈接
3.1.1 動(dòng)態(tài)庫(kù) 源碼
為了便于測(cè)試比較,使用 與 靜態(tài)庫(kù)編譯相同的源碼
3.1.2 動(dòng)態(tài)庫(kù) 編譯
# gcc -fPIC -shared -o libdynamic_gcc.so gcc_lib_first.c gcc_lib_sec.c gcc_lib_third.c
3.1.3 動(dòng)態(tài)庫(kù) 鏈接
# gcc -o gcc_lib_main_dynamic gcc_lib_main.c -L ./ -l dynamic_gcc
3.1.4 共享路徑設(shè)置(不詳細(xì)解釋)
## 共享路徑設(shè)置 :
## 1@:LD_LIBRARY_PATH 修改 這個(gè)全局變量
## 2@:修改 /etc/ld.so.conf 配置
## 本文 就 詳細(xì)描述了,直接把 生成的共享庫(kù) cp 至 系統(tǒng)默認(rèn)路徑下
# cp libdynamic_gxx.so /usr/local/lib/
## 重新讀取 庫(kù)文件信息(需root用戶執(zhí)行)
# ldconfig
備注:
如果 不設(shè)置 共享路徑 或者 共享路徑下 找不到 指定的 庫(kù)文件,系統(tǒng) 就會(huì) 提示相關(guān)的錯(cuò)誤信息:"./g++_lib_main_static: error while loading shared libraries: libstatic_gcc.so: cannot open shared object file: Error 40"
3.1.5 執(zhí)行
## 查看 依賴庫(kù),沒有問題 就執(zhí)行
# ldd gcc_lib_main_dynamic
linux-vdso.so.1 => (0x00007fff241e9000)
libdynamic_gcc.so => /usr/local/lib/libdynamic_gcc.so (0x00007fe587990000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe5875c6000)
/lib64/ld-linux-x86-64.so.2 (0x000055b1d62ea000)
# ./gcc_lib_main_dynamic
call gcc_lib_one() function
call gcc_lib_two() function
call gcc_lib_three() function
4、自定義工具(Makefile)
4.1 安裝 make
# apt-get install make
4.2 編寫 Makefile
# cat Makef
default_target : help
help :
@echo "usage : make [opt]"
@echo "\topt arguement is one of \"static_gcc、dynamic_gcc\""
gcc_lib_first.o : gcc_lib_first.c gcc_lib_header.h
gcc -c gcc_lib_first.c
gcc_lib_sec.o : gcc_lib_sec.c gcc_lib_header.h
gcc -c gcc_lib_sec.c
gcc_lib_third.o : gcc_lib_third.c gcc_lib_header.h
gcc -c gcc_lib_third.c
static_gcc : gcc_lib_first.o gcc_lib_sec.o gcc_lib_third.o
ar cqs /tmp/libstatic_gcc.a gcc_lib_first.o gcc_lib_sec.o gcc_lib_third.o
gcc -o gcc_lib_main_static gcc_lib_main.c -L /tmp -static -l static_gcc
dynamic_gcc :
gcc -fPIC -shared -o /tmp/libdynamic_gcc.so gcc_lib_first.c gcc_lib_sec.c gcc_lib_third.c
gcc -o gcc_lib_main_dynamic gcc_lib_main.c -L /tmp -l dynamic_gcc
cp /tmp/libdynamic_gcc.so /usr/local/lib/
ldconfig
4.3 執(zhí)行
## 創(chuàng)建 靜態(tài)庫(kù) 鏈接的 可執(zhí)行文件
# make static_gcc
ar cqs /tmp/libstatic_gcc.a gcc_lib_first.o gcc_lib_sec.o gcc_lib_third.o
gcc -o gcc_lib_main_static gcc_lib_main.c -L /tmp -static -l static_gcc
## 創(chuàng)建 動(dòng)態(tài)庫(kù) 鏈接的 可執(zhí)行文件
# make dynamic_gcc
gcc -fPIC -shared -o /tmp/libdynamic_gcc.so gcc_lib_first.c gcc_lib_sec.c gcc_lib_third.c
gcc -o gcc_lib_main_dynamic gcc_lib_main.c -L /tmp -l dynamic_gcc
cp /tmp/libdynamic_gcc.so /usr/local/lib/
ldconfig