【问题标题】:Clang linking .so library libc++_shared.soClang 链接 .so 库 libc++_shared.so
【发布时间】:2019-03-15 13:53:19
【问题描述】:

我在 Android NDK 应用程序中的本机 C++ 代码出错

我的 main.cpp

#include <stdio.h>

int main() 
{
  printf("Hello, world\n");
  return 0;
}

main.c 完全一样。 如果我运行

/home/rip/Music/android-ndk-r19b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android26-clang -pie main.c

然后

adb push a.out /data/local/tmp

adb shell /data/local/tmp/a.out

一切正常。但是如果我运行

/home/rip/Music/android-ndk-r19b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android26-clang++ -pie main.cpp

然后

adb push a.out /data/local/tmp

 adb shell /data/local/tmp/a.out

错误信息是:

CANNOT LINK EXECUTABLE "/data/local/tmp/a.out": library "libc++_shared.so" not found

然后我尝试运行

/home/rip/Music/android-ndk-r19b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android26-clang++ -pie hello1.cpp  /home/rip/Music/android-ndk-r19b/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++_shared.so

链接库,但它无论如何都不起作用。

【问题讨论】:

  • 也许用LD_LIBRARY_PATH

标签: android c++ android-ndk clang


【解决方案1】:

错误信息是:

CANNOT LINK EXECUTABLE "/data/local/tmp/a.out": library "libc++_shared.so" not found

这是预期的行为。与标准 C 库(使用简单的 *-clang 构建程序时链接到的)不同,C++ 不是系统库。您必须像任何其他第三方库一样在设备上提供它。

引用自official documentation

注意: libc++ 不是系统库。如果您使用 libc++_shared.so,它必须包含在您的 APK 中。如果您使用 Gradle 构建应用程序,则会自动处理。

还有:

如果您在自己的构建系统中直接使用 clang,则默认情况下,clang++ 将使用 c++_shared。要使用静态变体,请将 -static-libstdc++ 添加到链接器标志中。

所以要么通过将-static-libstdc++ 传递给编译器来静态链接C++。或复制libc++_shared.so(在您的情况下来自&lt;NDK&gt;/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/)并运行如下:

adb push a.out libc++_shared.so /data/local/tmp/
adb shell
cd /data/local/tmp/
LD_LIBRARY_PATH=. ./a.out

除了上面讨论的 LLVM 的标准 C++ 库之外,还有一个有限的系统 C++ 运行时 (/system/lib(64)/libstdc++.so),“提供对基本 C++ 运行时 ABI 的支持”。但是“系统 STL 将在未来的 NDK 版本中删除。”

【讨论】:

    【解决方案2】:

    我在 .c 和 .cpp 文件中编译了相同的“hello world”代码,当我将应用程序推送到我的设备时没有遇到同样的问题。我假设您遇到与本主题相同的问题: Application can't find libc++_shared.so 当您手动调用 clang 时,问题可能来自您的工具链或工具链参数。

    我创建了一个可以运行和测试的简单项目: android-ndk-example

    add_executable( # Sets the name of the library.
        ndk_example_c
    
        # Provides a relative path to your source file(s).
        main.c
        )
    
    
    add_executable( # Sets the name of the library.
            ndk_example_cpp
    
            # Provides a relative path to your source file(s).
            main2.cpp
            )
    

    在生成的 cmake 脚本中,我可以看到以下 cpp 编译器的定义:

     rule CXX_COMPILER__ndk_example_cpp
      depfile = $DEP_FILE
      deps = gcc
      command = D:\Users\$USER\AppData\Local\Android\Sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe  --target=armv7-none-linux-androideabi19 --gcc-toolchain=D:/Users/$USER/AppData/Local/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64 --sysroot=D:/Users/$USER/AppData/Local/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64/sysroot  $DEFINES $INCLUDES $FLAGS -MD -MT $out -MF $DEP_FILE -o $out -c $IN_ABS
      description = Building CXX object $out
    

    【讨论】:

    • 我以前没有使用过 gradle。我该如何编译这个项目?
    • 你可以在android studio中打开项目,安装sdk和ndk,然后运行Build > Rebuild Project。二进制文件将在 app/.externalNativeBuild/cmake/debug/armeabi-v7a 中生成
    • 谢谢它的工作。我也可以使用 qml 代替 java gui 吗?
    • 是的,我几年前就这样做了。我当时正在使用 Android.mk。只需尝试检查如何使用 gradle 和 cmake 配置您的 qt android 项目。
    • 好的,我会在我回家后将其添加到我的答案中:-) 谢谢!
    【解决方案3】:

    我为解决方案编写了一个新答案,因为我无法编辑我的问题。 解决方案是带有armv7的android设备的以下命令:

    /home/tony/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ --target=armv7-none-linux-androideabi19 --gcc-toolchain=/home/tony/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64 --sysroot=/home/tony/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/sysroot main.cpp
    

    对于 aarch64 armv8,命令是:

    /home/tony/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ --target=aarch64-none-linux-android21 --gcc-toolchain=/home/tony/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64 --sysroot=/home/tony/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/sysroot main.cpp
    

    CMakeLists.txt 文件应如下所示:

    cmake_minimum_required(VERSION 3.1)
    set(CMAKE_CXX_COMPILER /home/tony/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++)
    
    project(Test CXX)
    
    set(CMAKE_CXX_FLAGS "--target=aarch64-none-linux-android21 --gcc-toolchain=/home/tony/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64 --sysroot=/home/tony/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/sysroot")
    
    set(SOURCES
            main.cpp
            )
    
    add_executable(Test ${SOURCES})
    

    那么应用就可以构建了

    cmake
    
    make
    
    adb push Test /data/local/tmp
    
    adb shell /data/local/tmp/Test
    

    【讨论】:

    • 您永远不需要手动配置这些东西。如果您使用的是 NDK 的 CMake 工具链文件,所有这些都已经为您处理好了。如果你需要这样做,那么你就是在错误地调用 CMake。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-29
    • 2018-02-10
    • 2020-12-06
    • 2012-10-22
    • 2012-01-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多