c/c++ static library

 

概念

static library(静态库)是一种在编译时就被链接到最终可执行文件中的库

包含一组函数或代码实现, 当程序需要使用这些功能时, 链接器会将静态库中相关部分复制到可执行文件中, 扩展名表示为 .a(Unix/Linux);.lib(Windows)

静态库特点

  • 编译时链接

静态库在程序编译阶段就被链接到可执行文件中, 编译器和链接器会把所需的库代码嵌入到最终程序

  • 运行时依赖

静态库不依赖于运行时环境, 程序运行时无需再查找或加载库文件, 因为库代码已经被编译进可执行文件

  • 文件体积

由于库代码会被复制到每个依赖它的可执行文件中, 最终生成的程序体积通常比动态链接程序大

  • 版本控制

静态库没有版本控制机制, 库文件更新后, 已编译程序不会自动生效, 需要重新编译程序才能使用新版本库

特性 静态库 动态库
链接时间 编译时 在运行时由操作系统加载和链接
文件大小 可执行文件包含库代码, 较大 可执行文件较小, 库文件单独
性能 无需在运行时加载, 启动速度较快 启动时需要加载, 可能稍慢
更新 更新库文件需要重新编译所有依赖程序 更新库文件后, 无需重新编译, 程序直接使用新库
依赖管理 无需在运行时寻找库文件 程序需要在运行时找到正确库文件
内存使用 每个程序包含库副本 多个程序可以共享同一个动态库内存

开发流程

graph LR;
    A[/.c .cpp/]-->X(编译器)-->B[/.o目标文件/]-->Y(打包)-->C[/.a/]

生成

// static_api.h
#ifndef __STATIC_API_HPP__
#define __STATIC_API_HPP__

#include <iostream>

extern "C" {
    int add(int x, int y);
    void hello();
}

#endif
// static_api.cpp
#include "static_api.hpp"

int add(int x, int y) {
    return x + y;
}

void hello() {
    std::cout << "Hello World" << std::endl;
}

编译器

clang++ 源文件 -c -o 目标文件

ar rcv 库文件 目标文件
graph LR;
    X(参数)
    X-->A(ar)-->A1(创建、修改提取静态库)
    X-->B(rcv)
        B-->B1("r")-->B11(将目标文件插入库中, 若库已存在则追加)
        B-->B2("c") -->B21(创建新库, 若库已存在则覆盖)
        B -->B3("v") -->B31(详细输出添加到库中文件名)
  • 示例, 生成静态库
clang++ static_api.cpp -c -o static_api.o

ar rcv libstatic_api.a static_api.o

构建工具

通过cmake等工具生成静态库

# CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(static_api)

add_library(${PROJECT_NAME} STATIC "")
target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}/static_api.cpp)

使用

  • 示例, 使用静态库
// main.cpp
#include "static_api.hpp"

int main(void) {
    hello();
    std::cout << add(0xA, 0xB) << std::endl;

    return 0;
}
clang++ 源文件 库文件 -o 可执行文件