Android Studio CMake - 共享库缺少 libc++_shared.so? CMake 可以捆绑这个吗?
Android Studio CMake - shared library missing libc++_shared.so? Can CMake bundle this?
现在 Android Studio 2.2 正式发布,我正在从旧的 ndk-build 过程迁移到尝试在 AS 中使用 CMake。由于我正在合并我公司内部的几个代码库(我无法编辑),这些代码库大量使用 C++11 代码(包括可怕的 std::to_string() 方法),我可以编译的唯一方法是有 select 几个配置选项 - 所有这些都是我在开始使用 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.so 和 libc++_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)
我写了一个应该打包 STL 文件的 CMake 配置:
https://github.com/jomof/ndk-stl/blob/master/ndk-stl-config.cmake
将此文件复制到 CMakeLists.txt
旁边并在 CMakeLists.txt
中执行
include(ndk-stl-config.cmake)
如有问题请告诉我
正如 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
替换为您的目标名称。
将此添加到您的 build.gradle (Module: app)
externalNativeBuild {
cmake {
cppFlags "-std=c++14 -fexceptions -frtti"
arguments "-DANDROID_ARM_NEON=TRUE",'-DANDROID_STL=c++_shared'
}
}
我只是将这个脚本添加到 moudle 的 build.gradle:
externalNativeBuild {
cmake {
cppFlags ""
arguments "-DANDROID_STL=c++_shared"
}
}
它将'libc++_shared.so'打包到apk文件
在Application.mk
中添加以下行
APP_STL := c++_shared
现在 Android Studio 2.2 正式发布,我正在从旧的 ndk-build 过程迁移到尝试在 AS 中使用 CMake。由于我正在合并我公司内部的几个代码库(我无法编辑),这些代码库大量使用 C++11 代码(包括可怕的 std::to_string() 方法),我可以编译的唯一方法是有 select 几个配置选项 - 所有这些都是我在开始使用 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.so 和 libc++_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)
我写了一个应该打包 STL 文件的 CMake 配置: https://github.com/jomof/ndk-stl/blob/master/ndk-stl-config.cmake
将此文件复制到 CMakeLists.txt
旁边并在 CMakeLists.txt
中执行
include(ndk-stl-config.cmake)
如有问题请告诉我
正如 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
替换为您的目标名称。
将此添加到您的 build.gradle (Module: app)
externalNativeBuild {
cmake {
cppFlags "-std=c++14 -fexceptions -frtti"
arguments "-DANDROID_ARM_NEON=TRUE",'-DANDROID_STL=c++_shared'
}
}
我只是将这个脚本添加到 moudle 的 build.gradle:
externalNativeBuild {
cmake {
cppFlags ""
arguments "-DANDROID_STL=c++_shared"
}
}
它将'libc++_shared.so'打包到apk文件
在Application.mk
中添加以下行APP_STL := c++_shared