简体   繁体   English

aarch64 缺少标准库交叉编译 Android

[英]Missing Standard Library Crosscompiling for aarch64 Android

On my host system (Ubuntu, 64Bit) I use gcc/g++ compilers to crosscompile my library for my Android app (arm64-v8a).在我的主机系统(Ubuntu,64 位)上,我使用gcc/g++编译器为我的 Android 应用程序 (arm64-v8a) 交叉编译我的库。 On calling functions from my App I receive messages that libraries like libc.so.6 or libstdc++.so.6 cannot be found.从我的应用程序调用函数时,我收到消息称找不到libc.so.6libstdc++.so.6等库。

Within my /usr directory I have an aarch64-linux-gnu folder containing bin , include and lib folders.在我的/usr目录中,我有一个包含binincludelib文件夹的aarch64-linux-gnu文件夹。

CMakeLists.txt: CMakeLists.txt:

cmake_minimum_required(VERSION 3.6.0)

set(CMAKE_TOOLCHAIN_FILE android.toolchain.cmake)

project(testlibrary)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STYANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# find header & source
file(GLOB_RECURSE SOURCE_CPP "src/*.cpp")
file(GLOB_RECURSE HEADER "src/*.h")

add_library(${PROJECT_NAME}  SHARED
  ${SOURCE_CPP}
  ${HEADER}
)

source_group("Header include" FILES ${HEADER})
source_group("Source src"     FILES ${SOURCE_CPP})

android.toolchain.cmake: android.toolchain.cmake:

cmake_minimum_required(VERSION 3.6.0)

set(CMAKE_SYSTEM_NAME Android)
set(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(CMAKE_ANDROID_ARCH_ABI arm64-v8a)

set(CMAKE_C_COMPILER "aarch64-linux-gnu-gcc")
set(CMAKE_CXX_COMPILER "aarch64-linux-gnu-g++")
set(CMAKE_ANDROID_NDK /home/ubuntu/Android/Sdk/ndk/21.4.7075529)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

The error messages are the following:错误消息如下:

dlopen failed: library "libc.so.6" not found: needed by /my/lib/path/testlib.so in namespace classloader-namespace

or或者

dlopen failed: library "libstdc++.so.6" not found: needed by /my/lib/path/testlib.so in namespace classloader-namespace

Do I have to set a Sysroot or other paths so my libraries are found within my toolchain file and which path(s) do I use?我是否必须设置 Sysroot 或其他路径以便在我的工具链文件中找到我的库,以及我应该使用哪些路径?

EDIT1: Adding the aarch64-linux-gnu folder to my build directory and explicitly including EDIT1:aarch64-linux-gnu文件夹添加到我的构建目录并明确包括

target_link_libraries($PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}/aarch64-linux-gnu/lib/libstdc++.so.6)
# also any other lib, e.g. libstdc++.so, libc.so and libc.so.6 don't work

still results in the mentioned error message.仍然导致提到的错误消息。

I made a minimal example of the error using the .cpp and .hpp files below which results in this case in libc.so.6 not found .我使用下面的.cpp.hpp文件做了一个错误的最小示例,在这种情况下导致libc.so.6 not found Removing the malloc line also removes the error messages.删除 malloc 行也会删除错误消息。 Calling the testFunc also return the correct value to my App which I can display.调用 testFunc 还会将正确的值返回到我可以显示的应用程序。 src_file.cpp源文件.cpp

#include "header_file.hpp"
#include <stdlib.h> // for malloc
int testFunc_(){
  char* buffer;
  buffer = (char *) malloc (10);
  return 42;
}

header_file.hpp头文件.hpp

extern "C" int testFunc_();

I also added the following lines to my android.toolchain.cmake file (I copied the folder from /usr/aarch64/linux-gnu/ to my build dir)我还将以下行添加到我的android.toolchain.cmake文件中(我将文件夹从 /usr/aarch64/linux-gnu/ 复制到我的构建目录)

set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
set(CMAKE_INSTALL_RPATH "")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)

set(LDFLAGS="-Wl,-rpath,../aarch64-linux-gnu/lib")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LDFLAGS}" CACHE INTERNAL "" FORCE)
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} ${LDFLAGS}" CACHE INTERNAL "" FORCE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LDFLAGS}" CACHE INTERNAL "" FORCE)
set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} ${LDFLAGS}" CACHE INTERNAL "" FORCE)

EDIT2: On running readelf -d 'path/to/lib' I get the following (necessary I suppose) entries EDIT2:在运行readelf -d 'path/to/lib'时,我得到以下(我想是必要的)条目

Tag         Type            Name/Value
0x000...1   (NEEDED)        Shared library: [libc.so.6]
0x000..1d   (RUNPATH)       Library runpath: [/home/username/Desktop/projectfolder/aarch64-linux-gnu/lib]

Adding the following line to my CMakeLists.txt (after removing the RPATH related stuff from my toolchain file or changing them also to ./ ) should allow me to add the libraries right next to my library.so in the build folder (arm64-v8a).将以下行添加到我的CMakeLists.txt (从我的工具链文件中删除与RPATH相关的内容或将它们也更改为./之后)应该允许我在构建文件夹(arm64-v8a)中的library.so旁边添加库).

set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "-Wl,-rpath,./")

There is no RPATH tag.没有RPATH标签。 The RUNPATH entry is the location of my .so.6 and .so files I copied from the /usr/aarch64-linux-gnu folder. RUNPATH条目是我从/usr/aarch64-linux-gnu文件夹复制的.so.6.so文件的位置。 I think my main problem is bundling the necessary libraries correctly within my application as David Grayson implicated.我认为我的主要问题是在我的应用程序中正确地捆绑必要的库,正如 David Grayson 所暗示的那样。

EDIT3: Running file libc.so.6 also shows its an ELF 64-bit LSB shared object with ARM aarch64 architecture dynamically linked for GNU/Linux 3.7.0, interpreter /lib/ld-linux-aarch64.so.1, stripped EDIT3:运行file libc.so.6还显示其 ELF 64 位 LSB 共享 object 与 ARM aarch64 架构动态链接 GNU/Linux 3.7.0,解释器/lib/ld-linux-aarch64.so.1,剥离

EDIT4: Within my app/build.gradle I have the following lines EDIT4:在我的app/build.gradle中,我有以下几行

if(isNewArchitectureEnabled()) {
  externalNativeBuild {
    ndkBuild {
      arguments "APP_PLATFORM=android-12",
      "APP_STL=c_++shared",
      "NDK_TOOLCHAIN_VERSION=gcc", // was clang before
      "GENERATED_SRC_DIR=$buildDir/generated/source",
      "PROJECT_BUILD_DIR=$buildDir",
      "REACT_ANDROID_DIR=${reactNativeRoot}/ReactAndroid",
      "REACT_ANDROID_BUILD_DIR=${reactNativeRoot}/ReactAndroid/build",
      "NODE_MODULES_DIR=$rootDir/../node_modules"
      cflags "-Wall", "-Werror", "-fexceptions", "-frtti", "-DWITH_INSPECTOR=1"
      cppFlags "-std=c++17", //maybe 11 here(?) tried out both my App and .so to 11 but also no success

      targets "myapp_appmodules"
    }
  }
}

and also并且

packagingOptions {
   pickFirst 'lib/arm64-v8a/libc++_shared.so'
   pickFirst 'lib/arm64-v8a/libm.so'
   pickFirst 'lib/arm64-v8a/libm.so.6'
   pickFirst 'lib/arm64-v8a/libstdc++.so'
   pickFirst 'lib/arm64-v8a/libstdc++.so.6'
   pickFirst 'lib/arm64-v8a/libc.so'
   pickFirst 'lib/arm64-v8a/libc.so.6'
}

Am I probably using a wrong compiler/give the standalone toolchain within my ndk folder a try!我可能使用了错误的编译器/试试我的 ndk 文件夹中的独立工具链!

You either need to link those libraries statically into your executable ( -static at link time might work) or you need to ship them with your executable and put them somewhere the executable will find them, like in the same directory.您要么需要将这些库静态链接到您的可执行文件中( -static在链接时可能会起作用),要么您需要将它们与您的可执行文件一起发送并将它们放在可执行文件可以找到它们的地方,例如在同一目录中。

I'm not very familiar with Android but there might also be a way to have the target Android system provide those libraries at run time, since they are very common and used widely.我对 Android 不是很熟悉,但也可能有一种方法可以让目标 Android 系统在运行时提供这些库,因为它们非常常见且使用广泛。

I solved it changing my compilers ( CMAKE_C_COMPILER and CMAKE_CXX_COMPILER ) within the toolchain file and leaving my CMakeLists.txt as it was in the first place.我解决了它在工具链文件中更改我的编译器( CMAKE_C_COMPILERCMAKE_CXX_COMPILER )并将我的CMakeLists.txt保留在第一个位置。

cmake_minimum_required(VERSION 3.6.0)

set(CMAKE_SYSTEM_NAME Android)
set(CMAKE_SYSTEM_VERSION 21)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(CMAKE_ANDROID_ARCH_ABI arm64-v8a)

set(CMAKE_C_COMPILER /home/username/path/to/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang)
set(CMAKE_CXX_COMPILER /home/username/path/to/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang++)
set(CMAKE_ANDROID_NDK /home/username/path/to/ndk)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

using Android API level 21.使用 Android API 21 级。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM