簡體   English   中英

aarch64 缺少標准庫交叉編譯 Android

[英]Missing Standard Library Crosscompiling for aarch64 Android

在我的主機系統(Ubuntu,64 位)上,我使用gcc/g++編譯器為我的 Android 應用程序 (arm64-v8a) 交叉編譯我的庫。 從我的應用程序調用函數時,我收到消息稱找不到libc.so.6libstdc++.so.6等庫。

在我的/usr目錄中,我有一個包含binincludelib文件夾的aarch64-linux-gnu文件夾。

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)

錯誤消息如下:

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

或者

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

我是否必須設置 Sysroot 或其他路徑以便在我的工具鏈文件中找到我的庫,以及我應該使用哪些路徑?

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

仍然導致提到的錯誤消息。

我使用下面的.cpp.hpp文件做了一個錯誤的最小示例,在這種情況下導致libc.so.6 not found 刪除 malloc 行也會刪除錯誤消息。 調用 testFunc 還會將正確的值返回到我可以顯示的應用程序。 源文件.cpp

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

頭文件.hpp

extern "C" int testFunc_();

我還將以下行添加到我的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:在運行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]

將以下行添加到我的CMakeLists.txt (從我的工具鏈文件中刪除與RPATH相關的內容或將它們也更改為./之后)應該允許我在構建文件夾(arm64-v8a)中的library.so旁邊添加庫).

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

沒有RPATH標簽。 RUNPATH條目是我從/usr/aarch64-linux-gnu文件夾復制的.so.6.so文件的位置。 我認為我的主要問題是在我的應用程序中正確地捆綁必要的庫,正如 David Grayson 所暗示的那樣。

EDIT3:運行file libc.so.6還顯示其 ELF 64 位 LSB 共享 object 與 ARM aarch64 架構動態鏈接 GNU/Linux 3.7.0,解釋器/lib/ld-linux-aarch64.so.1,剝離

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"
    }
  }
}

並且

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'
}

我可能使用了錯誤的編譯器/試試我的 ndk 文件夾中的獨立工具鏈!

您要么需要將這些庫靜態鏈接到您的可執行文件中( -static在鏈接時可能會起作用),要么您需要將它們與您的可執行文件一起發送並將它們放在可執行文件可以找到它們的地方,例如在同一目錄中。

我對 Android 不是很熟悉,但也可能有一種方法可以讓目標 Android 系統在運行時提供這些庫,因為它們非常常見且使用廣泛。

我解決了它在工具鏈文件中更改我的編譯器( 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)

使用 Android API 21 級。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM