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文件夹下查看,已经生成了一个动态库和一个静态库。
在这里插入图片描述

发布了54 篇原创文章 · 获赞 18 · 访问量 9554

猜你喜欢

转载自blog.csdn.net/m0_37872216/article/details/103959546