交叉编译静态库的链接顺序

解决交叉编译符号未定义问题

交叉编译时遇到:undefined reference to `XXX'.

解决办法:

一,用nm看看库里边是不是有对应的符号:

nm *.a/*.lib/*.so |grep "XXX"


二,看看是不是被strip过了:

$ file libusb-1.0.a libusb-1.0.so.0.1.0
libusb-1.0.a:        current ar archive
libusb-1.0.so.0.1.0: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked, not stripped


三,添加-v参数看看有没有别的线索

四,查看链接的库是不是添加了软连接到别的库了,而那个库版本不对应!

五,将XXX.o这种一般写在最前面,而后面的sdk提供的lib和a(被依赖者),使劲儿往后写。

参考相关资料:

-Wl选项告诉编译器将后面的参数传递给链接器。

《c专家编程》第五章。

《Linkers and Loaders》。

在链接静态库时,如果多个静态库之间存在依赖关系,则有依赖关系的静态库之间存在链接顺序问题。这在使用静态库时需要注意,否则会报符号找不到的链接错误。 
例如:
lib2.a 依赖于 lib1.a,而最终可执行文件 test 依赖于 lib2.a,则链接选项应为:-llib2.a -llib1.a,而不能反过来,否则会报 lib1.a 中的某些符号未定义。 

当程序员们使用多个库的时候,如果库之间存在循环依赖的时候经常需要将库列出多次。就是说,如果一个库A中的例程依赖一个库B中的例程,但是另一个库B中的例程又依赖了库A中的另一个例程,那么从A扫描到B或从B扫描到A都无法找到所有需要的例程。当这种循环依赖发生在三个或更多的库之间时情况会更加糟糕。告诉链接器去搜索A B A或者B A B,甚至有时为A B C D A B C D,这种方法看上去很丑陋,但是确实可以解决这个问题。将多个.o文件链接成可执行文件的时候。如果链接的顺序不对,会产生错误。

《An introduction of gcc》里面有下面一段话:
On Unix-like systems, the traditional behavior of compilers and linkers
is to search for external functions from left to right in the object files
specified on the command line. This means that the object file which
contains the definition of a function should appear after any files which
call that function.
但是也说了:
Most current compilers and linkers will search all object files, regardless
of order, but since not all compilers do this it is best to follow the
convention of ordering object files from left to right.
链接库的时候,也存在这个问题。
今天写程序做了一下试验,发现gcc和我现在用的一个板子的编译器都可以不用严格按照顺序。
但是同时发现了另一个问题,就是我们自己的操作系统提供的库文件有两个:libgcc.a和libcs.a。
链接的时候要加上 -lcs -lgcc ,如果这两个顺序搞乱了,就会报错。

《An introduction of gcc》我会上传到csdn里,含中英文两版本方便E文不好的童孩~。

为什么编译器在搜索目标文件的时候可以不看顺序,搜索库文件的时候却会报错呢?

下面是hh的解答:
不依命令行的顺序的话就得重复扫描目标文件,我猜可能是重复扫描库文件的开销比较大所以必须在命令行指定正确的顺序!!!


http://www.cnblogs.com/bourneli/archive/2012/04/27/2474103.html

http://gcc.gnu.org/ml/gcc-help/2005-12/msg00017.html

http://gfdice.iteye.com/blog/1117491

http://bbs.chinaunix.net/thread-1182198-1-1.html

http://www.iecc.com/linker/

http://linker.iecc.com/

http://hi.baidu.com/vv1133/item/b4872d961df7dcdb1b49dfad

http://bbs.chinaunix.net/thread-3731844-1-1.html

http://bbs.chinaunix.net/thread-3731778-1-1.html




要在 **交叉编译环境下使用 `websocketpp` 并链接静态的 OpenSSL 库**,你需要完成以下几个关键步骤: --- ## 🧰 交叉编译环境准备 假设你的目标平台是 **ARM Linux(如 arm-linux-gnueabi)**,开发主机是 **x86_64 Ubuntu Linux**,你需要准备: - 交叉编译工具链(如 `arm-linux-gnueabi-g++`) - OpenSSL 源码(用于交叉编译) - Boost 源码(可选,如果使用 Boost.Asio) - `websocketpp`(纯头文件库) --- ## 🔨 第一步:交叉编译 OpenSSL 静态库 ### 1. 下载 OpenSSL 源码 ```bash wget https://www.openssl.org/source/openssl-1.1.1w.tar.gz tar -xzvf openssl-1.1.1w.tar.gz cd openssl-1.1.1w ``` ### 2. 配置交叉编译目标平台 ```bash CC=arm-linux-gnueabi-gcc AR=arm-linux-gnueabi-ar RANLIB=arm-linux-gnueabi-ranlib CROSS_COMPILE=arm-linux-gnueabi- ``` ```bash ./Configure linux-armv4 no-shared --prefix=/usr/local/openssl-arm ``` > ✅ `linux-armv4` 是常见 ARM 架构配置,如使用其他架构,请查阅 OpenSSL 文档。 ### 3. 编译并安装 ```bash make -j$(nproc) sudo make install ``` > ✅ 编译完成后,你将在 `/usr/local/openssl-arm/lib` 下看到 `libssl.a` 和 `libcrypto.a` 静态库。 --- ## 🧱 第二步:交叉编译 Boost(可选) 如果你使用的是 `Boost.Asio`,你也需要交叉编译 Boost: ### 1. 下载 Boost ```bash wget https://boostorg.jfrog.io/artifactory/main/release/1.78.0/source/boost_1_78_0.tar.gz tar -xzvf boost_1_78_0.tar.gz cd boost_1_78_0 ``` ### 2. 设置交叉编译工具链 创建 `user-config.jam` 文件: ```bash echo "using gcc : arm : arm-linux-gnueabi-g++ ;" > user-config.jam ``` ### 3. 构建 Boost 静态库 ```bash ./bootstrap.sh --prefix=/usr/local/boost-arm ./b2 toolset=gcc-arm link=static runtime-link=static variant=release \ --with-system --with-thread --with-filesystem --with-chrono \ --prefix=/usr/local/boost-arm install ``` > ✅ 生成的静态库位于 `/usr/local/boost-arm/lib/` --- ## 📄 第三步:编写使用 `websocketpp` 的 WSS 客户端代码 ### 示例代码:`wss_client.cpp` ```cpp #include <websocketpp/config/asio_client.hpp> #include <websocketpp/client.hpp> #include <iostream> typedef websocketpp::client<websocketpp::config::asio_tls_client> client; using websocketpp::lib::placeholders::_1; using websocketpp::lib::placeholders::_2; using websocketpp::lib::bind; void on_message(client* c, websocketpp::connection_hdl hdl, client::message_ptr msg) { std::cout << "Received: " << msg->get_payload() << std::endl; } int main() { client c; c.set_access_channels(websocketpp::log::alevel::all); c.clear_access_channels(websocketpp::log::alevel::frame_payload); c.init_asio(); c.set_message_handler(bind(&on_message, c, ::_1, ::_2)); websocketpp::lib::error_code ec; client::connection_ptr con = c.get_connection("wss://echo.websocket.org", ec); if (ec) { std::cerr << "连接失败: " << ec.message() << std::endl; return -1; } // 设置 TLS 初始化 con->set_tls_init_handler([](websocketpp::connection_hdl) { return websocketpp::lib::make_shared<websocketpp::lib::asio::ssl::context>( websocketpp::lib::asio::ssl::context::sslv23); }); // 设置证书验证(可选) con->set_verify_mode(websocketpp::lib::asio::ssl::verify_peer); c.connect(con); c.run(); return 0; } ``` --- ## 🔗 第四步:交叉编译客户端程序并静态链接 OpenSSL ### 使用 `arm-linux-gnueabi-g++` 编译并链接静态库 ```bash arm-linux-gnueabi-g++ -std=c++11 \ -I./websocketpp \ -I/usr/local/openssl-arm/include \ -I/usr/local/boost-arm/include \ -L/usr/local/openssl-arm/lib \ -L/usr/local/boost-arm/lib \ -static-libgcc -static-libstdc++ \ wss_client.cpp \ -o wss_client_arm \ -Wl,-Bstatic \ -lboost_system -lboost_thread -lboost_filesystem -lboost_chrono -lboost_atomic \ -lssl -lcrypto \ -Wl,-Bdynamic -lpthread -ldl ``` > ✅ `-Wl,-Bstatic`:强制静态链接后面的库 > ✅ `-Wl,-Bdynamic`:恢复动态链接 > ✅ `-static-libgcc` 和 `-static-libstdc++`:静态链接 C++ 标准库 --- ## 🧪 第五步:验证交叉编译结果 使用 `file` 检查可执行文件架构: ```bash file wss_client_arm ``` 输出应类似: ``` ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, ... ``` 使用 `readelf` 查看是否静态链接: ```bash readelf -d wss_client_arm ``` 应无动态链接依赖(或极少)。 --- ## 🧠 常见问题与解决方案 | 问题 | 原因 | 解决方案 | |------|------|-----------| | 编译时报找不到 OpenSSL 头文件 | 头文件路径不正确 | 检查 `-I` 参数是否指向 OpenSSL 安装路径 | | 链接时报 `undefined reference to SSL_XXX` | OpenSSL 未正确静态编译 | 确保 `libssl.a` 和 `libcrypto.a` 已生成 | | Boost 库链接失败 | Boost 构建未包含所需组件 | 添加 `--with-chrono --with-atomic` 等 | | 可执行文件仍动态链接 | 链接顺序或参数错误 | 检查 `-Wl,-Bstatic/-Bdynamic` 顺序 | --- ## ✅ 总结 你现在已经完成了: - ✅ 交叉编译 OpenSSL 静态库(ARM) - ✅ 交叉编译 Boost.Asio 静态库(ARM) - ✅ 使用 `websocketpp` 实现 WSS 客户端 - ✅ 使用 `arm-linux-gnueabi-g++` 编译并静态链接 OpenSSL 和 Boost ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值