Linux系統下cmake生成動態庫、靜態庫。

庫的概念

  寫程序肯定離不開庫的調用。在上一篇關於cmake的文章中,main函數調用了func1.c與func2.c兩個源文件的函數。顯然func1.c和func2.c是程序中的庫。不過,在操作系統中一般將目標文件的打包稱爲庫。也就是說把func1.c與func2.c與其頭文件打包成一個整體,就是庫了。
  庫分爲靜態庫和動態庫兩種,在Linux系統中靜態庫的後綴爲.a,動態庫的後綴爲.so。在Windows系統中靜態庫的後綴爲.lib,動態庫的後綴爲.dll。
  靜態庫動態庫本身的內容是一樣的(都是需要被調用的目標文件),他們的差異在於以何種方式加入到程序中

靜態庫

  靜態庫是在程序的編譯鏈接階段加入到源代碼的在程序運行階段不需要調用。形象地講,靜態庫在編譯鏈接階段與源代碼“合二爲一”形成了整體。當程序開始運行時,由於可執行文件中已經包含了庫,因此代碼的運行已經與原先的靜態庫毫無關聯(把原先的靜態庫刪掉了也沒事)。
  可執行程序與原先的靜態庫毫無關聯是件好事,但是爲達到這一目的,需要把整個庫的內容都要加到程序中,這樣無疑增加了計算機存儲與內存上的負擔。假設一個靜態庫大小爲2MB,一個操作系統上運行了100個包含該靜態庫的程序,顯然由於調用庫的關係,內存爲此足足耗費了200MB的空間。
  可見靜態庫的特點爲:
  1.靜態庫在編譯鏈接階段實現了與源代碼的鏈接。
  2.可執行程序本身與所需的庫沒有關聯,移植起來比較方便,不需要考慮移植平臺上是否擁有此種庫。
  3.相對浪費了內存和存儲資源。如果需要更新靜態庫,需要將源代碼重新編譯生成。如果應用程序採用靜態庫鏈接方式,則更新程序需要下載安裝完整的程序,比較麻煩。

動態庫

  動態庫是在程序的運行階段加入到源代碼的在程序的編譯鏈接階段只會生成一個小小的表,用來記錄調用動態庫的地址。形象地講,可執行代碼和動態庫各是各的,是分開的。只有在程序開始運行後,程序纔會去找動態庫,然後一起工作。
  由動態庫的工作原理可知,程序與動態庫的關聯性極強。當程序執行時必須有動態庫存在。如果運行環境中不包含動態庫,那麼程序將無法運行。同時這樣帶來了一個好處,動態庫實現了程序之間的資源共享(有時候動態庫也被稱爲共享庫)。假設一個動態庫大小爲2MB,一個操作系統上運行了100個包含該動態庫的程序,顯然由於動態庫共享的關係,內存只需要騰出個2MB來存放該動態庫的副本就可以了(與上面某種方式形成了鮮明對比)。
  可見動態庫的特點爲:
  1.動態庫在程序運行階段實現與源代碼的鏈接。
  2.可執行程序本身與所需的庫關聯性極強,移植起來較爲麻煩,需要考慮移植平臺上是否擁有此庫。
  3.相對節約了內存和存儲資源。如果需要更新動態庫,直接用新的動態庫把原先的替換掉就行了,不需要其他操作。應用程序的增量更新就是基於此原理。
  PS:在Windows平臺上破解軟件或者修改軟件是不是經常要用新的dll文件去代替原先的dll文件呢?其實這就是動態庫的更新,顯然不需要修改程序的其他地方。

cmake生成靜態庫動態庫

  新建一個文件夾,按下圖所示進行組織:
在這裏插入圖片描述

  build文件夾:存放編譯生成的中間文件。
  lib文件夾:存放生成的靜態庫,動態庫。
  lib_func文件夾:存放生成庫的原始庫代碼文件。這裏爲了方便,將上個cmake文章中的簡單代碼放了進去。
  func1.c代碼如下,提供了一個打印數字的函數:

#include "func1.h"
#include <stdio.h>

void DataShow(int data)
{
    printf("the input data is:%d \n",data);//打印一個數字
}


  func1.h代碼如下:

#ifndef  _FUNC1_H_
#define _FUNC1_H_
extern void DataShow(int data);
#endif 

  func2.c代碼如下,提供了一個數字相加的函數:

#include <stdio.h>
#include "func2.h"

void DataAdd(int a,int b)//打印兩個數字之和
{
    int c = a+b;
    printf("the number is:%d\n",c);
}

  func2.h代碼如下:

#ifndef _FUNC2_H_
#define _FUNC2_H_
extern void DataAdd(int a,int b);

#endif // !_FUNC2_H_


  工程中有兩個CMakeLists.txt。在工程根目錄的內容爲:


cmake_minimum_required (VERSION 2.8)#cmake最低版本爲2.8

project (demo)#工程名爲demo

add_subdirectory (lib_func)#將lib_func這個文件夾設爲子目錄


  內容的前兩句好懂。第三句add_subdirectory (lib_func)意爲將lib_func文件夾設定爲子目錄。設定爲子目錄會產生什麼效果呢?效果就是執行到第三句之後,cmake會自動去lib_func文件夾下尋找CMakeLists.txt,然後再執行那個CMakeLists.txt。
  也就是說,這個工程是先執行工程根目錄下的CMakeLists.txt,再執行子目錄(lib_func)下的CMakeLists.txt。兩個CMakeLists.txt的關係是順序執行。
  lib_func中的CMakeLists.txt內容如下:

aux_source_directory(. SRC_LIST)#將此目錄的源文件集合稱爲變量SRC_LIST
add_library(funcLib_shared SHARED ${SRC_LIST})#庫的名稱,庫的類型,庫的源文件(動態庫)
add_library(funcLib_static STATIC ${SRC_LIST})#庫的名稱,庫的類型,庫的源文件(靜態庫)

set_target_properties(funcLib_shared PROPERTIES OUTPUT_NAME "funcLib")#庫的名稱,庫的輸出名稱(動態庫)
set_target_properties(funcLib_static PROPERTIES OUTPUT_NAME "funcLib")#庫的名稱,庫的輸出名稱(靜態庫)

set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)#庫的輸出路徑爲工程根目錄下的lib文件夾。

  由註釋可得,最終會生成2個同名稱的靜態庫與動態庫。
  進入build文件夾,打開端口。老辦法,先輸入cmake ..,再輸入make
在這裏插入圖片描述
在這裏插入圖片描述
  最後到lib文件夾下查看,已經生成了一個動態庫和一個靜態庫。
在這裏插入圖片描述

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