当前位置:首页>Linux>从源码到库文件:3分钟学会Linux静态/动态库编译

从源码到库文件:3分钟学会Linux静态/动态库编译

  • 2026-09-13 08:58:23
从源码到库文件:3分钟学会Linux静态/动态库编译
当代码版本接口已经稳定,希望约束调用方式,或者不希望代码功能被随便修改,或者有知识产权/核心算法保护诉求,或者希望统一版本,避免“他们改了一版源码自己跑飞了”的时候,这个时候我们可以将代码编译成库文件封装好后进行交付。
目标:在Linux中将C/C++代码编译成.a或者.so的库文件,在demo中调用。
以一个简单的函数为例子,提供一个 add(a, b),返回 a + b,演示怎么封装成库。照着这个做完,后面换成自己写的代码是同一套逻辑。
一、Linux下库的编译
封装好函数内部的代码。最终想做到业务侧代码只需要这样写,然后链接库,就能跑:
#include<iostream>#include"mylib.h"intmain(){int c = add(3, 5);std::cout << "result = " << c << std::endl;return0;}
目录结构
先建一个最小工程,文件目录结构如下:
demo_sdk/├── include/│   └── mylib.h├── src/│   └── mylib.cpp├── demo/│   └── main.cpp└── CMakeLists.txt
接着逐个写文件内容。
1 写头文件
文件:include/mylib.h,内容:
#ifndef MYLIB_H#define MYLIB_H#ifdef __cplusplusextern"C" {#endifintadd(int a, int b);#ifdef __cplusplus}#endif#endif
这个头文件是对外接口。这样写的好处是?内部虽然是 C++,但这样导出的接口更稳,尤其后面如果:给 C 调用、给不同编译器环境调用、想减少名字修饰问题,会更省事。
2 写实现文件
文件:src/mylib.cpp,内容:
#include"mylib.h"intadd(int a, int b){return a + b;}
这是库内部实现,也就是我们要封装的代码内容。
3 写调用 demo
文件:demo/main.cpp,内容:
#include<iostream>#include"mylib.h"intmain(){int result = add(10, 20);std::cout << "10 + 20 = " << result << std::endl;return0;}
4 写 CMakeLists.txt
文件:CMakeLists.txt,内容:
cmake_minimum_required(VERSION 3.10)project(demo_sdk)set(CMAKE_CXX_STANDARD 11)set(CMAKE_CXX_STANDARD_REQUIRED ON)# 头文件目录include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)# 生成静态库 libmylib.aadd_library(mylib STATIC    src/mylib.cpp)# 生成静态库 libmylib.so# add_library(mylib SHARED#     src/mylib.cpp# )# 生成可执行文件add_executable(main_demo    demo/main.cpp)# 把库链接给 demotarget_link_libraries(main_demo    mylib)
5 编译
在工程根目录执行:
mkdir -p buildcd buildcmake ..make
执行完以上命令后会在build文件夹下生成库文件,有.a静态库文件,和.so动态库文件
在Bash里输入./main_demo命令,可以运行我们写的demo,运行成功后输出10+20=30,完整的Bash命令及输出如下:
问:这就算“封装成库”了吗?
算。
因为现在已经是这种关系了:
  • mylib.h:对外暴露接口
  • libmylib.a:实现被打包成库
  • main_demo:调用方只通过头文件和库使用功能
调用方不需要再直接编译 mylib.cpp,只需要:
  • include 头文件
  • link 这个库
这就是最基本的“封装成库”。
注意:给别人交付时最少要给什么
如果现在要把这个库交付,最少给这几个东西:
sdk_package/├── include/│   └── mylib.h├── lib/│   └── libmylib.a└── demo/    └── main.cpp
那么使用的时候,只需要做两个步骤:
  • include 你的 mylib.h
  • link 你的 libmylib.a
二、编译成.a静态库和.so动态库有什么区别?
核心区别:
  • 静态库:编译时把代码“拷贝进可执行文件”。
  • 动态库:运行时再“加载库文件”。
程序体积区别:
  • 静态库:每个程序都会复制一份库代码;
  • 动态库:只存一份,所以,动态库节省磁盘空间;
内存占用:
  • 静态库每个程序都有一份代码段,内存占用大
  • 动态库所有进程共享代码段,内存占用小。
部署复杂度:
  • 静态库部署非常简单。只需要一个可执行程序,例如:main_demo直接运行。
  • 动态库部署复杂
    • 必须保证:libxxx.so 在系统能找到的路径,否则:会报错 error while loading shared libraries
    • 因此需要需要配置:LD_LIBRARY_PATH 或者:/usr/lib, /usr/local/lib
升级方式(动态库最大的优势)
  • 静态库升级需要:重新编译程序,重新发布程序。
  • 动态库升级只需要替换:libxxx.so,程序不用重新编译。
在嵌入式上部署更推荐静态库!
嵌入式通常更喜欢:静态库。原因有两点:
① 部署简单。嵌入式设备可能:文件系统小,没有标准库路径。不方便设置 LD_LIBRARY_PATH。静态库就不会有这些问题。
② 依赖更少。动态库可能依赖:glibc;libstdc++;libpthread;嵌入式环境经常版本不一致。
③ 稳定性更高。动态库容易出现:ABI 不兼容,比如:gcc 版本不同
所以很多嵌入式项目:全部使用静态链接。

最新文章

随机文章