linux静态库合并实践

本文介绍了如何在C++项目中将两个静态库liba.a和libb.a合并为一个新库libmerge.a,通过CMakeLists.txt配置,以及通过编写示例程序验证合并后的库功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在实际的项目开发过程中,可能会用到很多的静态库,有时会想把几个静态库打包成一个静态库,链接起来更方便。本文将要学习如果将静态库合并。

前期准备

准备一个静态库liba.a,后续将这个静态库与其他静态库合并。
头文件a.h

#pragma once
class a
{
public:
    a() {}
    ~a() {}
    void test_a();
};

cpp文件a.cpp

#include "a.h"
#include <iostream>
void a::test_a()
{
    std::cout << "this is test_a" << std::endl;
}

CMakeLists.txt

CMAKE_MINIMUM_REQUIRED(VERSION 3.10)
PROJECT(a)
SET(CMAKE_CXX_FLAGS "-fPIC -g ")
# 指定源代码目录
AUX_SOURCE_DIRECTORY(${PROJECT_SOURCE_DIR} LIBSRC)
# 指定静态库生成的目录
SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
# 生成静态库
ADD_LIBRARY(a STATIC ${LIBSRC})

使用以上代码,能够make出来一个静态库,名为liba.a。

合并静态库

接下来,我们将生成另一个静态库libb.a,这个库使用了liba.a的函数,然后把liba.a和libb.a合并成一个新的静态库libmerge.a。
头文件b.h

#pragma once
class b
{
public:
    b() {}
    ~b() {}
    void test_b();
};

cpp文件b.cpp

#include <iostream>
#include "b.h"
#include "../liba/a.h"

void b::test_b()
{
    std::cout << "this is test_b" << std::endl;
    a tmp_a{};           // 使用了liba.a的类
    tmp_a.test_a();
}

CMakeLists.txt

CMAKE_MINIMUM_REQUIRED(VERSION 3.10)
PROJECT(b)

SET(CMAKE_CXX_FLAGS "-fPIC -g ")

SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)

ADD_LIBRARY(a STATIC IMPORTED)
SET_TARGET_PROPERTIES(a PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/../liba/lib/liba.a)

# 指定源代码目录
AUX_SOURCE_DIRECTORY(${PROJECT_SOURCE_DIR} LIBSRC)
# 生成静态库
ADD_LIBRARY(b_static STATIC ${LIBSRC})
# 对b_static的重名为b
SET_TARGET_PROPERTIES(b_static PROPERTIES  OUTPUT_NAME "b")
# cmake 在构建一个新的target时,清理掉其他使用这个名字的库
SET_TARGET_PROPERTIES(b_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)

# 将liba.a和libb.a合并成一个新的静态库libmerge.a
ADD_CUSTOM_COMMAND(OUTPUT libmerge.a
    COMMAND ar rcsT ../lib/libmerge.a $<TARGET_FILE:b_static> $<TARGET_FILE:a>
    DEPENDS a b_static
)
# 创建target,用于生成libmerge.a,不创建则不会生成libmerge.a
ADD_CUSTOM_TARGET(_merge ALL DEPENDS libmerge.a)

在CMakeLists.txt中的ADD_CUSTOM_COMMAND是执行一个命令,命令的功能是使用ar将libb.a和liba.a打包合并成libmerge.a
使用命令nm libmerge.a查看符号,能够看到两个库的符号都包含在内。

[root@VM-8-2-centos lib]# nm libmerge.a

b.cpp.o:
                 U __cxa_atexit
                 U __dso_handle
0000000000000000 V DW.ref.__gxx_personality_v0
                 U _GLOBAL_OFFSET_TABLE_
00000000000000c8 t _GLOBAL__sub_I_b.cpp
                 U __gxx_personality_v0
                 U _Unwind_Resume
000000000000007f t _Z41__static_initialization_and_destruction_0ii
                 U _ZN1a6test_aEv
0000000000000000 W _ZN1aC1Ev
0000000000000000 W _ZN1aC2Ev
0000000000000000 n _ZN1aC5Ev
0000000000000000 W _ZN1aD1Ev
0000000000000000 W _ZN1aD2Ev
0000000000000000 n _ZN1aD5Ev
0000000000000000 T _ZN1b6test_bEv
                 U _ZNSolsEPFRSoS_E
                 U _ZNSt8ios_base4InitC1Ev
                 U _ZNSt8ios_base4InitD1Ev
                 U _ZSt4cout
                 U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
0000000000000000 r _ZStL19piecewise_construct
0000000000000000 b _ZStL8__ioinit
                 U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc

a.cpp.o:
                 U __cxa_atexit
                 U __dso_handle
                 U _GLOBAL_OFFSET_TABLE_
0000000000000083 t _GLOBAL__sub_I_a.cpp
000000000000003a t _Z41__static_initialization_and_destruction_0ii
0000000000000000 T _ZN1a6test_aEv
                 U _ZNSolsEPFRSoS_E
                 U _ZNSt8ios_base4InitC1Ev
                 U _ZNSt8ios_base4InitD1Ev
                 U _ZSt4cout
                 U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
0000000000000000 r _ZStL19piecewise_construct
0000000000000000 b _ZStL8__ioinit
                 U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc

实验验证

写一个小程序,引用libmerge.a并调用class b的成员函数test_b。

#include <iostream>
#include "b.h"

int main()
{
    b tmp_b{};
    tmp_b.test_b();
    return 0;
}

CMakeLists.txt

CMAKE_MINIMUM_REQUIRED(VERSION 3.10)
PROJECT(test)

# 指定源代码目录
AUX_SOURCE_DIRECTORY(${PROJECT_SOURCE_DIR} LIBSRC)

INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/../libb)

LINK_DIRECTORIES(${PROJECT_SOURCE_DIR}/../libb/lib)

ADD_EXECUTABLE(test ${LIBSRC})

TARGET_LINK_LIBRARIES(test merge)

编译代码

[root@VM-8-2-centos build]# cmake ../
-- The C compiler identification is GNU 8.5.0
-- The CXX compiler identification is GNU 8.5.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
m-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (0.4s)
-- Generating done (0.0s)
-- Build files have been written to: /root/work_dir/test_programs/lib_merge/test/build
[root@VM-8-2-centos build]# make
[ 50%] Building CXX object CMakeFiles/test.dir/test.cpp.o
[100%] Linking CXX executable test
[100%] Built target test

运行代码

[root@VM-8-2-centos build]# ./test
this is test_b
this is test_a

运行成功!

结束语

本文学习了如果将多个静态库合并成一个,链接起来更方便,对于库的使用者更加友好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hankin-Liu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值