首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >与CMake的交叉编译:链接器错误

问与CMake的交叉编译:链接器错误
EN

Stack Overflow用户
提问于 2020-07-22 06:25:34
回答 2查看 439关注 0票数 1

我正试图在我的ubuntu机器上为我的树莓派(32位armv8)交叉编译一个项目。我使用crosstool NG设置了一个工具链,并进行了编译,但链接失败。我的CMake工具链文件如下:

代码语言:javascript
复制
SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_SYSTEM_VERSION 1)

set(CMAKE_SYSROOT /home/stone/development/raspberry_pi/armv8-rpi3-linux-gnueabihf/armv8-rpi3-linux-gnueabihf/sysroot)

SET(CMAKE_C_COMPILER /home/stone/development/raspberry_pi/armv8-rpi3-linux-gnueabihf/bin/armv8-rpi3-linux-gnueabihf-gcc)
SET(CMAKE_CXX_COMPILER /home/stone/development/raspberry_pi/armv8-rpi3-linux-gnueabihf/bin/armv8-rpi3-linux-gnueabihf-g++)

SET(CMAKE_FIND_ROOT_PATH /home/stone/development/raspberry_pi/armv8-rpi3-linux-gnueabihf)

SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# for libraries and headers in the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

我有一些链接器找不到的库。问题出在我的sysroot上。我将pi中的/usr和/lib复制到由crosstool NG创建的sysroot文件夹中。被链接的库驻留在sysroot/usr/lib/arm-linux-gnueabihf中。

但是,链接器不会检查该目录,它会检查sysroot/usr/lib和其他一些目录,但由于某些原因,它不会检查arm-linux-gnueabihf目录。

在pi上,我可以运行ld -lasound --verbose并获得以下输出:

代码语言:javascript
复制
attempt to open //usr/local/lib/arm-linux-gnueabihf/libasound.so failed
attempt to open //usr/local/lib/arm-linux-gnueabihf/libasound.a failed
attempt to open //lib/arm-linux-gnueabihf/libasound.so failed
attempt to open //lib/arm-linux-gnueabihf/libasound.a failed
attempt to open //usr/lib/arm-linux-gnueabihf/libasound.so succeeded

所以它在圆周率上找到它是正确的。

当我使用crosstool NG生成的ld执行相同的操作时:

代码语言:javascript
复制
attempt to open /home/stone/development/raspberry_pi/armv8-rpi3-linux-gnueabihf/armv8-rpi3-linux-gnueabihf/bin/../sysroot/home/stone/x-tools/armv8-rpi3-linux-gnueabihf/armv8-rpi3-linux-gnueabihf/lib/libasound.so failed
attempt to open /home/stone/development/raspberry_pi/armv8-rpi3-linux-gnueabihf/armv8-rpi3-linux-gnueabihf/bin/../sysroot/home/stone/x-tools/armv8-rpi3-linux-gnueabihf/armv8-rpi3-linux-gnueabihf/lib/libasound.a failed
attempt to open /home/stone/development/raspberry_pi/armv8-rpi3-linux-gnueabihf/armv8-rpi3-linux-gnueabihf/bin/../sysroot/usr/local/lib/libasound.so failed
attempt to open /home/stone/development/raspberry_pi/armv8-rpi3-linux-gnueabihf/armv8-rpi3-linux-gnueabihf/bin/../sysroot/usr/local/lib/libasound.a failed
attempt to open /home/stone/development/raspberry_pi/armv8-rpi3-linux-gnueabihf/armv8-rpi3-linux-gnueabihf/bin/../sysroot/lib/libasound.so failed
attempt to open /home/stone/development/raspberry_pi/armv8-rpi3-linux-gnueabihf/armv8-rpi3-linux-gnueabihf/bin/../sysroot/lib/libasound.a failed
attempt to open /home/stone/development/raspberry_pi/armv8-rpi3-linux-gnueabihf/armv8-rpi3-linux-gnueabihf/bin/../sysroot/usr/lib/libasound.so failed

它无法找到它,因为它没有在arm-linux-gnueabihf目录中查找。我将库.so文件从sysroot/usr/lib/arm-linux-gnueabihf复制到sysroot/usr/lib,它可以成功编译和链接,但我希望这样就不必这样做了。如何让链接器检查arm-linux-gnueabihf目录?

编辑:我还将/etc/ld.so.conf和/etc/ld.so.conf.d从pi复制到我的sysroot中,但这似乎不会影响链接器。

编辑:经过进一步的研究,这看起来可能是由于gcc-多拱门的原因。我不确定那是什么,但希望我能弄清楚。

编辑:我验证了链接器确实没有搜索arm-linux-gnueabihf路径:

代码语言:javascript
复制
 ./armv8-rpi3-linux-gnueabihf-ld --verbose | grep -i "search"

输出:

代码语言:javascript
复制
SEARCH_DIR("=/home/stone/x-tools/armv8-rpi3-linux-gnueabihf/armv8-rpi3-linux-gnueabihf/lib"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib");
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-07-23 09:27:12

好了,我都搞清楚了。我在here中学到了让它工作的诀窍。我很感谢这个repo,如果没有它,我就不会让它工作。

问题出在链接器上。由comes ng拉入的普通旧binutils附带的链接器不会搜索arm-linux-gnueabihf子目录。这些目录的存在是因为Debian的多拱门,为了获得一个在这样的目录中查找的链接器,binutils需要打补丁。下面的说明假设您已经基于rpi3示例生成了ct-ng配置。

在raspberry pi上,我安装了binutils-source包:

代码语言:javascript
复制
$ sudo apt install binutils-source

这将允许访问位于/usr/src/binutils/patches中的修补程序文件。

在主机上,您需要在构建工具链的目录( ct-ng配置文件所在的目录)中添加一个补丁目录。它必须具有反映交叉库中packages结构的特定结构(即,在patches/内部,您必须有一个包含包名称的目录,在该目录中,您必须具有版本号,在该目录中,您可以放置修补程序。):

代码语言:javascript
复制
$ cd your_toolchain_directory
$ mkdir -p patches/binutils/2.31.1/

现在,我们可以将补丁文件从pi复制到主机。我们需要的特定补丁是129_multiarch_libpath.patch:

代码语言:javascript
复制
$ cd patches/binutils/2.31.1/
$ scp pi@raspberrypi:/usr/src/binutils/129_multiarch_libpath.patch

现在我们有了补丁,我们需要更新配置文件,告诉ct-ng包含本地补丁,并为gcc启用多拱门标志。您可以使用ct-ng menuconfig执行此操作,因此请切换回包含配置文件的目录并运行:

代码语言:javascript
复制
$ ct-ng menuconfig

在paths和misc选项中,您需要将补丁来源更改为bundled,然后添加${CT_TOP_DIR}/patches作为本地补丁目录。这将在.config文件的解压缩部分下生成以下行:

代码语言:javascript
复制
CT_PATCH_BUNDLED_LOCAL=y
CT_PATCH_ORDER="bundled,local"
CT_PATCH_USE_LOCAL=y
CT_LOCAL_PATCH_DIR="${CT_TOP_DIR}/patches"

接下来,您需要在gcc选项中添加--enable-multiarch标志。再次使用menuconfig,转到C编译器设置。将--enable-multiarch添加到gcc的额外配置设置中。配置文件在gcc设置中应包含以下内容:

代码语言:javascript
复制
CT_CC_GCC_EXTRA_CONFIG_ARRAY="--enable-multiarch"

保存配置。我们需要做的最后一件事是导出一个变量。

代码语言:javascript
复制
$ export DEB_TARGET_MULTIARCH=arm-linux-gnueabihf

现在我们可以构建工具链了:

代码语言:javascript
复制
$ ct-ng build

完成后,您可以切换到生成的工具链的bin目录并运行:

代码语言:javascript
复制
$ ./ld --verbose | grep -i "search"

您应该看到arm-linux-gnueabihf目录现在位于搜索路径中。这真是个过程。

票数 1
EN

Stack Overflow用户

发布于 2020-07-22 07:36:14

您需要改用静态库。则可执行文件将包含库的二进制文件。但请记住,可执行文件会更大(显然取决于哪个库...)。当您使用交叉编译时,您应该检查您使用的库是否存在于您执行程序的其他环境中。解决方案是根据CmakeList.txt文件添加静态单词

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63024006

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档