问题
在你的开发环境中,编译、链接、运行测试都没问题,迁移到其他机器上运行程序时,程序运行不起来或运行异常。
场景一
开发环境的机器CPU为ARM架构,而测试环境的机器CPU为x86架构。
场景二
测试环境中缺乏程序依赖的库。体现在没有把开发环境中编译时所依赖的相关库迁移到测试环境中。
场景三
测试环境中程序运行时,所依赖库的版本不一致。一种场景是,程序在开发环境中编译、链接依赖 libstdc++.so.6.0.28 的符号版本为 GLIBCXX_3.4.22,而测试环境中的为 libstdc++.so.6.0.21,其最高支持的版本符号为 GLIBCXX_3.4.20,导致在程序运行时,出现类似于 /usr/lib64/libstdc++.so.6: version
GLIBCXX_3.4.22’ not found` 的报错。
解决方案
- 首先确定开发环境和测试环境的CPU架构是一致的,或者是程序已经做好了跨平台处理。
- 确保开发环境和测试环境的一致性,这样能最低程度的减少因为环境不一致而带来的种种问题。使用docker能够很好的解决该问题,应该成为共识。
- 针对上面描述的 场景二 和 场景三,确保程序所依赖的库在开发环境和测试环境中保持一致,保持编译器(gcc、clang)的版本一致。一种方案是,将你在开发环境中编译好的测试程序及其所依赖的所有库打包移植到测试环境中,且修改测试程序运行时查找依赖库的路径,保证程序从拷贝过来的依赖库中进行查找、链接。
工程实践
动态加载共享库的工作原理
**Shared Libraries: Understanding Dynamic Loading** 这篇文章详细的介绍了linux中动态加载共享库的内部工作原理,推荐阅读。
移植性强的程序编译、链接、运行方法
-
首先,推荐使用docker进行开发和测试,这是保证开发、测试、部署环境一致性的最有效方式。
-
若不使用docker,尽量保持开发和测试时,编译器的版本一致,避免因标准库符号版本不一致而导致的编译问题。
-
可执行程序在不同环境中迁移时,所依赖的库需要同步迁移。
使用
ldd
命令查看所依赖库的本地路径,将其复制到指定目录下,例如~/yourProject/libs
,然后设置LD_LIBRARY_PATH
变量的值。#!/bin/bash # 设置程序运行时所依赖共享库的查找路径,注意,需要放在第一个位置; # 因为当查找到所依赖的库时,即使后面的路径中也存在相同(版本不同)共享库时, # 不会往后继续查找 export LD_LIBRARY_PATH=~/yourProject/libs:$LD_LIBRARY_PATH ./yourProgram
参考链接
- https://amir.rachum.com/shared-libraries/