【问题标题】:Cross compiling with CMake: linker errors使用 CMake 进行交叉编译:链接器错误
【发布时间】:2020-11-11 09:27:18
【问题描述】:

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

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 上。我将 /usr/lib 从 pi 复制到我的 sysroot 文件夹,该文件夹由 crosstool-NG 创建。被链接的库位于sysroot/usr/lib/arm-linux-gnueabihf

但是,链接器并没有检查那个目录,它检查 sysroot/usr/lib 和其他一些目录,但是由于某种原因它没有检查 arm-linux-gnueabihf 目录。

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

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

所以它可以在 pi 上正确找到它。

当我使用 crosstool-NG 生成的 ld 做同样的事情时:

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-multiarch 造成的。我不确定那是什么,但希望我能解决这个问题

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

 ./armv8-rpi3-linux-gnueabihf-ld --verbose | grep -i "search"

输出:

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");

【问题讨论】:

  • 那么/home/stone/development/raspberry_pi/armv8-rpi3-linux-gnueabihf/armv8-rpi3-linux-gnueabihf/bin/../sysroot/usr/lib/libasound.so 存在吗?
  • 它没有。我不得不将它从 sysroot/usr/lib/arm-linux-gnueabihf/ 复制到 sysroot/usr/lib 以消除链接器错误。但我不想对每个图书馆都这样做。我想知道如何强制链接器检查 sysroot/usr/lib/arm-linux-gnueabihf/ 目录。
  • 什么?那么具体是哪个目录呢?如果要搜索一些sysroot/usr... 路径,为什么将CMAKE_SYSROOT 设置为/home/stone/development/....How can I make the linker check that arm-linux-gnueabihf directory?“那个arm-linux-gnueabihf目录”到底是哪个目录?
  • 当我最初从 pi 复制它时,库文件位于 sysroot//usr/lib/arm-linux-gnueabihf/ 中。链接器似乎在那里找不到它。我可以通过手动将库文件从 sysroot/usr/lib/arm-linux-gnueabihf/ 复制到 sysroot/usr/lib 来修复它。链接器在将其放置在那里时会找到它。但不是放在 arm-linux-gnueabihf 目录中时。
  • 但是sysroot//usr/lib/arm-linux-gnueabihf/ 不是绝对路径,它不是以/ 开头的。什么是绝对路径? Ooooch,您写的是“sysroot”,而您的意思是根目录?所以没有/some/path/sysroot/usr/lib/arm-linux-gnueabihf/ 目录,sysroot 是指系统上的根目录?

标签: c++ cmake linker cross-compiling linker-errors


【解决方案1】:

好吧,我明白了。可以在here 找到我学习使其工作的技巧的存储库。我很感激这个 repo,没有它我就不会让它工作。

问题在于链接器。由 crosstool-ng 引入的普通旧 binutils 附带的链接器不会搜索 arm-linux-gnueabihf 子目录。这些目录的存在是因为 Debian multiarch,为了获得在这样的目录中查找的链接器,需要对 binutils 进行修补。以下说明假设您已经基于 rpi3 示例生成了 ct-ng 配置。

在树莓派上,我安装了 binutils-source 包:

$ sudo apt install binutils-source

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

在主机上,您需要在构建工具链的目录(ct-ng 配置文件所在的目录)中添加补丁目录。它必须具有反映 crosstool-ng 存储库中 packages 结构的特定结构(即,在 patch/ 中,您必须有一个带有包名称的目录,在其中您必须有版本号,并且在其中你放置补丁。):

$ cd your_toolchain_directory
$ mkdir -p patches/binutils/2.31.1/

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

$ cd patches/binutils/2.31.1/
$ scp pi@raspberrypi:/usr/src/binutils/129_multiarch_libpath.patch

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

$ ct-ng menuconfig

在路径和杂项选项中,您需要将补丁源更改为捆绑然后本地,然后添加 ${CT_TOP_DIR}/patches 作为本地补丁目录。这应该在 .config 文件的提取部分下产生以下行:

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 设置中包含以下内容:

CT_CC_GCC_EXTRA_CONFIG_ARRAY="--enable-multiarch"

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

$ export DEB_TARGET_MULTIARCH=arm-linux-gnueabihf

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

$ ct-ng build

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

$ ./ld --verbose | grep -i "search"

您应该会看到 arm-linux-gnueabihf 目录现在位于搜索路径中。什么过程。

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 库确实存在。我从 pi 复制了它们。他们在那里,链接器只是没有搜索 sysroot/usr/lib/arm-linux-gnueabihf/。我认为我不应该静态链接它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-07
    • 2016-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-25
    相关资源
    最近更新 更多