溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Linux 環境下 gcc 鏈接庫 編譯、鏈接(概覽) 以及 自動化工具Makefile的編寫

發布時間:2020-07-03 05:41:15 來源:網絡 閱讀:4402 作者:堅韌的石頭 欄目:編程語言

個人博客首頁(點擊查看詳情) -- https://blog.51cto.com/11495268
 
1、簡介
    程序編譯一般需要經預處理、編譯、匯編和鏈接,在實際應用中,有些公共代碼需要反復使用,就把這些代碼編譯成為 "庫" 文件,本文 主要 描述 Linux 平臺下 庫文件的 創建 和 鏈接 相關操作(既然都看 這么底層的內容了,相信 也有一定的基礎,所以本文 對相關命令 也不會進行詳細解釋)
Linux 環境下 gcc 鏈接庫 編譯、鏈接(概覽) 以及 自動化工具Makefile的編寫
    
備注:
    linux平臺下,靜態鏈接庫是以 .a 的后綴文件,動態鏈接庫是以 .so 的后綴文件
    widows平臺下,靜態鏈接庫是以 .lib 的后綴文件,動態庫文件是以 .dll 的后綴文件
    

2、庫文件
    庫是寫好的 現有的、成熟的 一種可執行、可以復用代碼的二進制形式(注,其本身不可執行),可以被操作系統載入內存執行;分為 靜態鏈接庫 和 動態鏈接庫
    

2.1 靜態庫
2.1.1 簡介
    靜態鏈接庫可以簡單看成一組目標文件.o 的集合,即很多目標文件經過壓縮打包后形成的一個文件
    

2.1.2 原理
    鏈接器將從 靜態(鏈接)庫 取得所需的代碼,復制到生成的可執行文件
Linux 環境下 gcc 鏈接庫 編譯、鏈接(概覽) 以及 自動化工具Makefile的編寫
    

2.1.3 特點
    靜態庫對函數庫的鏈接是放在程序編譯時期完成
    程序在運行時對函數庫再無瓜葛(因為所有相關的目標文件和牽涉到的函數庫被鏈接合成一個可執行文件)
    浪費空間和資源(因為所有相關的目標文件和牽涉到的函數庫被鏈接合成一個可執行文件)
    

2.1.4 創建流程
Linux 環境下 gcc 鏈接庫 編譯、鏈接(概覽) 以及 自動化工具Makefile的編寫
    

備注:
    linux下使用ar工具(windows下用lib.exe)將目標文件壓縮到一起,并且對其進行編號和索引,以便于查找和索引
    

2.1.5 命令規則
    靜態鏈接庫的名稱 和 庫文件名稱不同但有聯系;例如,庫名稱為"static_library",那么起庫文件名為"libstatic_library.a"
    

2.2 動態庫
2.2.1 簡介
    程序在開始運行后調用 動態(鏈接)庫(Dynamic Link Library)中的函數 才被載入
    

2.2.2 原理
    程序編譯是并不會被連接到目標代碼中,而是在程序運行時才被載入
Linux 環境下 gcc 鏈接庫 編譯、鏈接(概覽) 以及 自動化工具Makefile的編寫
    

2.2.3 特點
    動態庫把對一些庫函數的鏈接載入推遲到程序運行時期
    進程之間的相同動態庫實現共享
    

2.2.4 創建
    創建動態庫與創建靜態庫不同,不需要打包工具,直接使用編譯器創建動態庫

# gcc -fPIC -shared -o libxxx.so xx1.c xx2.c xx3.c

    

2.2.5 命名規則
    動態鏈接庫的名稱 和 庫文件名稱不同但有聯系;例如,庫名稱為"dynamic_library",那么起庫文件名為"libdynamic_library.a"
    

3、庫文件 編譯、鏈接(實戰操作)
3.1 靜態庫 編譯、鏈接
3.1.1 靜態庫 源碼

# cat gcc_lib_header.h
#ifndef __GCC_LIB_HEADER_H_ 
#define __GCC_LIB_HEADER_H_

#include <stdio.h>

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 靜態庫 編譯

# 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 靜態庫 鏈接

## -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 動態庫 編譯、鏈接
3.1.1 動態庫 源碼
    為了便于測試比較,使用 與 靜態庫編譯相同的源碼
    

3.1.2 動態庫 編譯

# gcc -fPIC -shared -o libdynamic_gcc.so  gcc_lib_first.c gcc_lib_sec.c gcc_lib_third.c

    

3.1.3 動態庫 鏈接

# gcc -o gcc_lib_main_dynamic gcc_lib_main.c -L ./ -l dynamic_gcc

    

3.1.4 共享路徑設置(不詳細解釋)

## 共享路徑設置 :
##     1@:LD_LIBRARY_PATH 修改 這個全局變量
##     2@:修改 /etc/ld.so.conf 配置
## 本文 就 詳細描述了,直接把 生成的共享庫 cp 至 系統默認路徑下
# cp libdynamic_gxx.so /usr/local/lib/

## 重新讀取 庫文件信息(需root用戶執行)
# ldconfig

    

備注:
    如果 不設置 共享路徑 或者 共享路徑下 找不到 指定的 庫文件,系統 就會 提示相關的錯誤信息:"./g++_lib_main_static: error while loading shared libraries: libstatic_gcc.so: cannot open shared object file: Error 40"
    

3.1.5 執行

## 查看 依賴庫,沒有問題 就執行
# 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 執行

## 創建 靜態庫 鏈接的 可執行文件
# 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

## 創建 動態庫 鏈接的 可執行文件
# 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

    

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女