静态库链接在编译时将.a文件中用到的代码复制进可执行文件,运行时不依赖外部库但体积大、更新难;动态库链接仅在运行时加载.so,需确保LD_LIBRARY_PATH或rpath正确。
静态库链接:编译时把
文件直接塞进可执行文件
静态库本质是一堆已编译的
目标文件打包成的归档(
),链接时会把用到的符号代码“复制”进最终的可执行文件。这意味着运行时不依赖外部库文件,但体积大、更新困难。
实操上,用
链接静态库要显式指定路径和库名:
注意几个关键点:
告诉链接器去哪找库,不是自动搜
或当前目录
会实际查找
(不是
),名字必须匹配前缀规则
和
是防止混链动态版系统库——否则即使你用了
,仍可能在运行时报
如果
本身又依赖其他静态库(比如用了
),得把依赖库也列在命令行里,且顺序不能错:被依赖的库要放在依赖它的库之后(
,不能反过来)
动态库链接:运行时加载
,构建时只记个符号引用
动态库(
)不参与编译,链接阶段只检查符号是否存在、签名是否匹配,真正加载发生在程序启动或调用
时。好处是共享内存、便于热更新;坏处是部署时得确保
正确,或库在系统默认路径下。
立即学习
“
C++免费学习笔记(深入)
”;
构建命令看着差不多,但行为完全不同:
C知道
CSDN推出的一款AI技术问答工具
下载
这里没加
,链接器默认优先找
。常见陷阱有:
明明放了
在
,却报
:大概率是该
编译时没导出对应符号(没加
或没写
)
程序编译通过,运行时报
:说明运行时找不到它。临时解决可用
,但生产环境应改用
:
(
指可执行文件所在目录)
动态库版本升级后崩溃?检查
是否变了(用
),
不一致会导致链接器拒绝加载
和
是查符号问题的第一工具
链接失败,别急着重装工具链——先确认符号到底存不存在、可见性对不对。静态库和动态库都适用:
看静态库里有没有某函数:
,输出带
(text)表示定义了,
表示未定义(即只是引用)
看动态库导出的符号(注意是否隐藏):
,
只显示动态符号表里的内容,没输出就说明没导出
进一步确认符号绑定属性:
,如果显示
就是未定义,
才算正常导出
这些命令不依赖构建系统,能快速定位是代码没编译进去、声明没导出,还是链接参数漏写了库。
CMake 中控制动静态链接容易混淆的三个配置点
CMake 默认倾向动态链接,但很多项目需要混合或强制静态。关键不在
,而在目标属性设置:
让某个 target 强制链接静态版系统库:
指定第三方库用静态方式链接(假设
同时提供
和
):
,避免
自动挑
全局禁用动态库搜索(慎用):
,这会让所有
优先找
,但可能破坏
模块逻辑
最常被忽略的是:CMake 的
目标(比如用
)必须手动设置
指向具体文件,否则
会静默失败,连错误都不报。
.a.olibxxx.ag++g++ main.cpp -L./libs -lmylib -static-libgcc -static-libstdc++-L./libs/usr/lib-lmyliblibmylib.amylib.a-static-libgcc-static-libstdc++libmylib.alibstdc++.so.6: version `GLIBCXX_3.4.29' not foundlibmylib.alibz.a-lmylib -lz.solibxxx.sodlopen()LD_LIBRARY_PATHg++ main.cpp -L./libs -lmylib-static.solibmylib.so./libsundefined reference to `xxx'.so-fvisibility=default__attribute__((visibility("default")))error while loading shared libraries: libmylib.so: cannot open shared object fileexport LD_LIBRARY_PATH=./libsrpathg++ main.cpp -L./libs -lmylib -Wl,-rpath,'$ORIGIN/../libs'$ORIGINSONAMEreadelf -d libmylib.so | grep SONAMEDT_SONAMEnmobjdumpnm -C libmylib.a | grep 'my_function'TUnm -C -D libmylib.so | grep 'my_function'-Dobjdump -t libmylib.so | grep my_function*UND*FUNC GLOBAL DEFAULTfind_package()set_target_properties(myapp PROPERTIES LINK_FLAGS "-static-libgcc -static-libstdc++")mylib.a.sofind_library(MYLIB_STATIC NAMES mylib PATHS ./libs NO_DEFAULT_PATH)target_link_libraries(myapp ${MYLIB_STATIC})find_package(mylib).soset(CMAKE_FIND_LIBRARY_SUFFIXES ".a${CMAKE_FIND_LIBRARY_SUFFIXES}")find_library.aFindXXX.cmakeIMPORTEDadd_library(mylib IMPORTED)IMPORTED_LOCATIONtarget_link_libraries