首页 > 解决方案 > 交叉编译的二进制文件显然需要比本地编译的更多的共享库

问题描述

我正在研究交叉编译设置,主机是 x86_64(Ubuntu 16.04),目标是 NVidia 的 Jetson Nano(aarch64,Ubuntu 18.04)。目标具有本机编译能力。我观察到交叉编译的二进制文件在运行时需要链接到更多的共享库,而不是 Jetson Nano 上的本机编译的二进制文件。当然,源代码完全一样,我使用基于 CMake 的构建配置。要检查执行生成的二进制文件所需的共享库,我运行以下命令: readelf -d <binary> | grep 'NEEDED'

要进行交叉编译,我使用以下工具链文件:

SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_SYSTEM_VERSION 4.9.140)
SET(CMAKE_SYSTEM_PROCESSOR aarch64)
SET(CMAKE_CROSSCOMPILING 1)
SET(CUDA_TOOLKIT_INCLUDE "/usr/local/cuda/include") # for Could NOT find CUDA (missing: CUDA_INCLUDE_DIRS) with cmake v 3.8 or higher (tested with 3.10)
SET(CUDA_TOOLKIT_ROOT_DIR "/usr/local/cuda")
SET(CUDA_VERSION "10.0") # This is like tricking the build system, otherwise FindCUDA.cmake on host tries to run an aarch64 binary
SET(CUDA_USE_STATIC_CUDA_RUNTIME OFF CACHE INTERNAL "")

SET(ROOTFS "$ENV{CROSS_ROOT}" CACHE INTERNAL "Copied from environment variable")
SET(TXROOT "${ROOTFS}")
SET(CC_PACKAGE_DIR "$ENV{BASE_DIR}" CACHE INTERNAL "Copied from environment variable")
SET(TOOLROOT "${CC_PACKAGE_DIR}/Toolchain/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu")


include_directories(${TXROOT}/usr/local/cuda/include)
include_directories(${TXROOT}/usr/local/cuda/samples/common/inc)


SET(CMAKE_C_COMPILER ${TOOLROOT}/bin/aarch64-linux-gnu-gcc)
SET(CMAKE_CXX_COMPILER ${TOOLROOT}/bin/aarch64-linux-gnu-g++)

SET(CMAKE_LINKER "${TOOLROOT}/bin/aarch64-linux-gnu-ld" CACHE FILEPATH "" FORCE)
SET(CMAKE_AR "${TOOLROOT}/bin/aarch64-linux-gnu-ar" CACHE FILEPATH "" FORCE)

SET(FLAGS "-Wl,-rpath-link,${TXROOT}/usr/lib/aarch64-linux-gnu -Wl,-rpath-link,${TXROOT}/lib/aarch64-linux-gnu")
SET(CMAKE_EXE_LINKER_FLAGS ${FLAGS} CACHE STRING "" FORCE)

SET(CUDA_CUDART_LIBRARY "${TXROOT}/usr/local/cuda/lib64/libcudart.so") # Only neeeded from Cmake v 3.8 and higher

SET(CMAKE_CXX_FLAGS "-L${TXROOT}/usr/local/cuda/lib64")
SET(CMAKE_SYSROOT "${TXROOT}")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --sysroot=${TXROOT}" CACHE INTERNAL "" FORCE)
SET(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} --sysroot=${TXROOT}" CACHE INTERNAL "" FORCE)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --sysroot=${TXROOT}" CACHE INTERNAL "" FORCE)
SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} --sysroot=${TXROOT}" CACHE INTERNAL "" FORCE)

SET(CMAKE_FIND_ROOT_PATH "${TXROOT}")
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

在运行交叉编译之前,我使用以下脚本设置环境:

#!/bin/bash

whereami() {
currdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" > /dev/null && pwd -L)"
echo "$currdir"
}

BASE_DIR=$(whereami)

extract_rootfs() {
if [ ! -d "$BASE_DIR/rootfs" ]; then
    echo "Extracting rootfs for cross compilation, you need to have sudo rights for this"
    sudo tar -xvjSf $BASE_DIR/rootfs.tar.bz2 -C $BASE_DIR/
fi
}


extract_rootfs
export LC_ALL=C
export BASE_DIR=$BASE_DIR
export CROSS_ROOT=$BASE_DIR/rootfs
export LD_LIBRARY_PATH=$CROSS_ROOT/usr/lib/aarch64-linux-gnu:$CROSS_ROOT/lib/aarch64-linux-gnu:$CROSS_ROOT/usr/lib:$CROSS_ROOT/lib:$LD_LIBRARY_PATH
export OpenCV_DIR=$BASE_DIR/rootfs/home/ubuntu/opencv-install-static
export HOME=/home/ubuntu

环境 $HOME 已更改,因为 CMake 文件使用它来确定在 Nano 上运行二进制文件时相关的一些路径(但我认为这就是这里所需要的全部)。

CMake 3.10.0 是我发现用于交叉编译的唯一一个(或者可能是少数几个之一,我无法探索很多),因为较低版本无法找到我正在使用的 Boost 库(1.65)并且更高版本尝试通过尝试运行失败的测试程序来测试(交叉)编译器。Nano 原生使用 CMake 3.10.2,但我不确定这是否是问题所在。在这两种情况下,gcc 版本都是 7.5.0。

对于交叉编译的情况,由于我直接使用在目标上编译的一些共享库,而这些共享库又依赖于特定路径(/usr/lib/aarch64-linux-gnu)上的一些库,所以我不得不手动保留这些/usr/lib/aarch64-linux-gnu 上的主机 (x86_64) 上的 libraires (aarch64)(不是一个好方法,但这是由于限制,因为我无法轻松获取这些依赖项的源代码来编译+再次安装它们)。我还必须/lib/ld-linux-aarch64.so.1 -> /usr/lib/aarch64-linux-gnu/ld-2.27.so在主机上创建此链接:否则make会提示找不到 /lib/ld-linux-aarch64.so.1。

现在的问题:交叉编译的二进制文件无法在 Jetson Nano 上运行,因为它找不到一些共享库(如开头提到的两种情况下所需库的差异)。现在我可以在 Nano 上安装缺少的共享库(试过了,它可以工作),但这些可能有一些我担心的许可证限制,我不想走这条路。当然,本机编译的二进制文件在 Nano 上运行。

问题:关于如何调试的任何指针?我基本上需要使交叉编译的二进制文件需要与本地编译的完全相同的共享库才能运行。

标签: c++linuxcmakecross-platform

解决方案


推荐阅读