- 靜態庫/動態庫概要
在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是個好東西!你值得擁有!