Кросс-скомпилированный двоичный файл, очевидно, нуждается в большем количестве общих библиотек, чем нативно скомпилированный - PullRequest
0 голосов
/ 17 марта 2020

Я работаю над настройкой кросс-компиляции с хостом x86_64 (Ubuntu 16.04) и целью - Jetson Nano от NVidia (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, но я не уверен, что это проблема. И версия g cc - 7.5.0 в обоих случаях.

Для случая кросс-компиляции, поскольку я напрямую использую некоторые совместно используемые библиотеки, скомпилированные в целевом объекте, которые, в свою очередь, зависят от некоторых библиотек по указанному пути c (/ usr / lib / aarch64- linux -gnu), мне пришлось вручную хранить эти библиотеки (aarch64) на хосте (x86_64) в / usr / lib / aarch64- linux -gnu (не очень хороший подход, но это связано с ограничением, так как я не могу легко получить исходный код этих зависимостей для компиляции + установить их снова). Мне также пришлось создать эту ссылку: /lib/ld-linux-aarch64.so.1 -> /usr/lib/aarch64-linux-gnu/ld-2.27.so на хосте, в противном случае make скомпоновал, что /lib/ld-linux-aarch64.so.1 не был найден.

Теперь проблема: Кросс-скомпилированный двоичный файл не может работать на Jetson Nano, потому что он не может найти некоторые общие библиотеки (как упоминалось в начале о разнице в required библиотеки в обоих случаях). Теперь я могу установить недостающие разделяемые библиотеки на Nano (пробовал, это работает), но у них могут быть некоторые лицензионные ограничения, которых я боюсь, и я бы не хотел go идти по этому пути. Естественно, скомпилированный двоичный файл работает, конечно, на Nano.

Вопрос: Есть ли какие-нибудь указатели относительно того, как это отладить? Мне нужно сделать так, чтобы кросс-скомпилированный двоичный файл нуждался в тех же общих библиотеках, что и нативно скомпилированный.

...