【问题标题】:Android Studio CMake - shared library missing libc++_shared.so? Can CMake bundle this?Android Studio CMake - 共享库缺少 libc++_shared.so? CMake 可以捆绑这个吗?
【发布时间】:2017-01-29 22:49:37
【问题描述】:

现在 Android Studio 2.2 已正式发布,我正在从旧的 ndk-build 流程迁移到尝试在 AS 中使用 CMake。由于我正在合并我公司内部的几个代码库(我无法编辑),这些代码库大量使用 C++11 代码(包括可怕的 std::to_string() 方法),我可以编译的唯一方法是一些选择的配置选项——所有这些都是我之前开始使用 ndk-build 时发现的。 (见下文)

所以一切都会再次编译并构建到 APK 中 - 我 100% 验证我的输出共享库存在于 APK 中,但我无法成功使用 System.loadLibrary('mylibrary') - 事实证明这是因为依赖项 libc++_shared.so 丢失。

我收到以下错误:

java.lang.UnsatisfiedLinkError: dlopen failed: library "libc++_shared.so" not found

在我的旧 ndk-build 过程中,我总是在输出文件夹中使用 2 个库(mylibrary.solibc++_shared.so),从而将其捆绑到应用程序中。似乎 CMake 工具链根本没有捆绑 libc++_shared.so(实际上,它在 APK 中找不到)。

我已经为此努力了 6 个小时。我能以某种方式让 CMake 工具链捆绑这个缺失的库吗?有什么线索吗?

.

.

我的设置:

在 gradle.build 中:

externalNativeBuild {
        cmake {
            arguments '-DANDROID_STL=c++_shared', '-DANDROID_TOOLCHAIN=gcc', '-DANDROID_PLATFORM=android-16'
        }
    }

还有我的 CMakeLists.txt(为简洁起见删掉了文件名):

cmake_minimum_required(VERSION 3.4.1)

set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -std=gnu++11")

include_directories(.)
include_directories(./other)

set(my_SRCS jniInterface.cpp
    etc.cpp)


add_library(mylibrary SHARED ${my_SRCS})

target_link_libraries(mylibrary atomic log)

【问题讨论】:

标签: android c++11 android-ndk cmake std


【解决方案1】:

我只是将这个脚本添加到 moudle 的 build.gradle 中:

externalNativeBuild {
        cmake {
            cppFlags ""
            arguments "-DANDROID_STL=c++_shared"
        }
    }

它将'libc++_shared.so'打包到apk文件中

【讨论】:

  • 由于某种原因你还必须使用-DANDROID_ARM_NEON=1,否则库不会被捆绑,也许它取决于霓虹灯之类的。
  • 这应该去android{ defaultConfig{部分
【解决方案2】:

我编写了一个应该打包 STL 文件的 CMake 配置: https://github.com/jomof/ndk-stl/blob/master/ndk-stl-config.cmake

将此文件复制到您的CMakeLists.txt 旁边和CMakeLists.txt 里面做

include(ndk-stl-config.cmake)

如果有问题请告诉我

【讨论】:

  • 谢谢,我喜欢它的外观,但一直遇到错误“找不到“ndk-stl”提供的包配置文件” - 我尝试更改路径“。”到 PATHS ${CMAKE_CURRENT_LIST_DIR} 但仍然没有运气。在此期间将继续尝试......
  • 请注意,虽然我找到了解决该问题的另一种解决方法,但我认为如果可行,您的解决方法看起来更容易且更便携,所以如果我们能找出路径问题,我会给您答案
  • 该消息意味着 CMake 找不到包文件 ndk-stl-config.cmake。您是否将文件命名为 ndk-stl-config.cmake 并将其放在 CMakeLists.txt 旁边?如果是这样,嗯,有两个想法:(1)在 github 上与我分享一个 repro 项目,(2)粘贴你得到的完整消息(在命令行上使用 ./gradlew assemble 构建)
  • 编辑:我接受了 Gerry 的建议,使用 include(...) 而不是 find_package(...)。他证实这在他身边有效。
  • 这很好用,改变了样本来使用这个:它的实现要干净得多!谢谢
【解决方案3】:

将此添加到您的build.gradle (Module: app)

externalNativeBuild {
            cmake {
                cppFlags "-std=c++14 -fexceptions -frtti"
                arguments "-DANDROID_ARM_NEON=TRUE",'-DANDROID_STL=c++_shared'
            }
        }

【讨论】:

【解决方案4】:

正如 Gerry 所指出的,音频回声示例项目 (https://github.com/googlesamples/android-ndk/pull/298) 的最新更改包括对我有用的更改。我将此添加到我的 CMakeLists.txt 文件的底部。

# Android Studio CMake does not pack stl shared libraries, so app needs to pack
# the right shared lib into APK. The following code find right stl type and copy
# the needed shared lib into app's app/src/main/jniLibs, android studio assembles
# it into the final APK
# Helper function to retrieve shared stl path and name in NDK
# stl_path: the path to the NDK's shared lib path; empty if not using shared stl
function(get_stl_info stl_path stl_name)
   # assume app not uses shared stl lib
   set(${stl_path} "" PARENT_SCOPE)
   if(NOT ${ANDROID_STL} MATCHES "_shared")
       return()
   endif()

   # using shared lib, config lib name and path
   if("${ANDROID_STL}" MATCHES "c\\\+\\\+_")
       # app uses c++_shared for stl type
       set(stlPath "llvm-libc++/libs/${ANDROID_ABI}")
       set(stlName "libc++_shared.so")
   elseif(${ANDROID_STL} MATCHES "gnustl_")
       set(stlPath "gnu-libstdc++/4.9/libs/${ANDROID_ABI}")
       set(stlName "libgnustl_shared.so")
   else()
       # this sample not supporting other stl types
       message(FATAL_ERROR "Not Suppored STL type: ${ANDROID_STL}")
       return()
   endif()

   set(${stl_path} ${ANDROID_NDK}/sources/cxx-stl/${stlPath} PARENT_SCOPE)
   set(${stl_name} ${stlName} PARENT_SCOPE)
endfunction()

# force copying needed shared stl lib into ${project}/app/src/main/jniLibs
# so it will be packed into APK
get_stl_info(ndk_stl_path  ndk_stl_name)
if(NOT ${ndk_stl_path} STREQUAL "")
    set(jniLibs_dir "${CMAKE_CURRENT_SOURCE_DIR}/../jniLibs")
    add_custom_command(TARGET mylibrary PRE_BUILD
                   COMMAND "${CMAKE_COMMAND}" -E
                   copy ${ndk_stl_path}/${ndk_stl_name}
                   "${jniLibs_dir}/${ANDROID_ABI}/${ndk_stl_name}"
                   COMMENT "Copying Shared library to the packing directory")
endif()

我想这是一种解决方法,我们无需有一天就能解决...请注意,您必须更改add_custom_command(TARGET mylibrary PRE_BUILD 行并将mylibrary 替换为您的目标名称。

【讨论】:

    【解决方案5】:

    在 Application.mk 中添加以下行

    APP_STL := c++_shared
    

    【讨论】:

      猜你喜欢
      • 2020-12-06
      • 2016-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-22
      相关资源
      最近更新 更多