Linux-(C/C++)生成並使用靜態庫/動態庫

  • 靜態庫/動態庫概要

在Windows下靜態庫的後綴爲:.lib、動態庫後綴爲:.dll;而在Linux下靜態庫的後綴爲:.a、動態庫的後綴爲:.so。

那麼什麼是靜態庫呢?

首先我們來看看程序編譯的大體流程:預處理——編譯——彙編——鏈接

在我們的項目開發中,有些代碼會被反覆使用,那麼這時我們便可將這些代碼編譯成庫的形式來調用,像靜態庫就是在可執行文件中包含庫代碼的一份完整拷貝,但這種方式有個很嚴重的缺點就是會造成多份冗餘拷貝。靜態庫會在程序的鏈接階段被複制到程序中,所以程序在運行後是不會調用靜態庫的。

那動態庫又是什麼呢?

動態庫不像靜態庫那樣,在鏈接階段並沒有被複制到程序中,反而是程序運行的時候由系統動態的加載到內存中供程序調用,所以這裏解決了靜態庫早晨多份冗餘拷貝的缺點,系統只需要載入一次動態庫,不同的程序可以得到內存中相同的動態庫副本,因此可以節省大量的內存。


  • 生成靜態庫/動態庫

下面進入主題看看在linux中如何生成靜態庫跟動態庫:

首先我們先創建三個文件,分別爲hello.cc、hello.h、main.cc,如下圖:



“hello.h":

#ifndef __HELLO_H__
#define __HELLO_H__

#include <stdio.h>

void Hello();

#endif

"hello.cc":

#include "hello.h"

void Hello()
{
    printf("Hello World!!!\n");
}

"main.cc":

#include "hello.h"

int main(void)
{
    Hello();

    return 0;
}

這時我們hello world代碼算是寫完了。接下來我們生成靜態庫

g++ -o main main.cc -static -lhello -L.

我們先簡單介紹下"gcc"跟"g++":gcc 最開始的時候是 GNU C Compiler, 如你所知,就是一個c編譯器。但是後來因爲這個項目裏邊集成了更多其他不同語言的編譯器,GCC就代表 the GNU Compiler Collection,所以表示一堆編譯器的合集。 g++則是GCC的c++編譯器。


此處我們使用g++,如果使用c語言可以將g++改爲gcc:

1、將hello.cc編譯成hello.o(靜態庫和動態庫都是由.o文件生成)

g++ -c hello.cc

2、爲了遵循linux中靜態庫的命名規範,靜態庫命名爲libhello.a

ar cr libhello.a hello.o

3、將main.cc與靜態庫連接,生成可執行文件:“main”

g++ -o main main.cc -static -lhello -L.

最後文件如下如:


4、運行可執行文件

./main

下面進行動態庫的生成

1、生成動態庫libhello.so

g++ -c -fPIC hello.cc -o hello.o
g++ -shared hello.o -o libhello.so

當然這裏我們可以直接通過cmake來生成動態庫,下面我們用cmake的方式生成動態庫並鏈接動態庫。

首先我們改造下目錄結構:

  

我們刪除上一步生成的靜態庫跟動態庫,只保留源代碼,在開始的code目錄下創建兩個文件夾分別是:build、lib;在code跟lib目錄下分別創建一個CMakeLists.txt文件(用於編寫cmake代碼),並在code同級目錄下創建code2目錄,在該目錄下創建build、src目錄,將之前的main.cc移到src下,在code2目錄跟src目錄下創建CMakeLists.txt文件,先來看看code目錄下的CMakeLists.txt文件,代碼如下:

PROJECT(HELLOLIB)
ADD_SUBDIRECTORY(lib)

lib目錄下的CMakeLists.txt文件代碼如下:

SET(LIBHELLO_SRC hello.cc)
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
INSTALL(TARGETS hello hello
LIBRARY DESTINATION lib)
INSTALL(FILES hello.h DESTINATION include/hello)

對上面代碼解析下,ADD_LIBRARY用於生成庫文件,hello是動態庫名(libxxx.x中xxx的名字),SHARED表示生成的庫爲動態庫。之後的INSTALL是安裝共享庫和頭文件,安裝到系統庫中(/usr/lib跟usr/include/hello目錄下,這裏的hello文件夾是我自己創建的)。

最後在build目錄下運行終端(在執行INSTALL時需要用到root權限,所以在執行make前先切換到root模式下),輸入命令行如下:

cmake -DCMAKE_INSTALL_PREFIX=/usr ..
make
make install

可以到指定目錄中查看庫跟頭文件已經成功安裝到了指定目錄下。

下面我們在main.cc中調用我們生成的動態庫。

首先我們先將main.cc中引入的頭文件#include "hello.h"改爲#include <hello.h>;

我們先看看code2目錄下的CMakeLists.txt下的腳本:

PROJECT(NEWHELLO)
ADD_SUBDIRECTORY(src)

src目錄下的CMakeLists.txt腳本如下:

ADD_EXECUTABLE(main main.cc)
INCLUDE_DIRECTORIES(/usr/include/hello)
TARGET_LINK_LIBRARIES(main libhello.so)

跟上面一樣我們在終端下來到build目錄,並輸入命令行如下:

cmake ..
make

得到的輸出爲:Hello World!!!

到這裏我們鏈接庫的實例就說完了。cmake是個好東西!你值得擁有!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章