简体   繁体   中英

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). On calling functions from my App I receive messages that libraries like libc.so.6 or libstdc++.so.6 cannot be found.

Within my /usr directory I have an aarch64-linux-gnu folder containing bin , include and lib folders.

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:

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?

EDIT1: Adding the aarch64-linux-gnu folder to my build directory and explicitly including

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 . Removing the malloc line also removes the error messages. Calling the testFunc also return the correct value to my App which I can display. src_file.cpp

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

header_file.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)

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

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).

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

There is no RPATH tag. The RUNPATH entry is the location of my .so.6 and .so files I copied from the /usr/aarch64-linux-gnu folder. I think my main problem is bundling the necessary libraries correctly within my application as David Grayson implicated.

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

EDIT4: Within my app/build.gradle I have the following lines

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!

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.

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.

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_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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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