【问题标题】:Building+linking libpng in Android Studio with CMake on Windows在 Windows 上使用 CMake 在 Android Studio 中构建+链接 libpng
【发布时间】:2020-02-23 02:07:17
【问题描述】:

我正在尝试在 Windows 10 上使用 Android Studio 和 CMake 启动一个本机应用程序项目,但我坚持包含 libpng。

对于初学者来说,这是我第一次看到 CMakeLists.txt 文件。我花了一天时间才弄清楚target_link_libraries(native-activity ... png) 不可能是target_link_libraries(png native-activity ...),因为所有错误消息都是关于未创建文件和由于缺少工具链要求而导致命令失败(为什么列表末尾的基本错误?不酷!)。

在最终设法在项目中包含 libpng 之后,我现在遇到了构建错误:

Error:Execution failed for task ':app:externalNativeBuildDebug'.
...
error: unknown target CPU 'armv5te'
CMake Error at scripts/genout.cmake:78 (message):
    Failed to generate
    C:/APP_PATH/app/libpng-1.6.28/build/scripts/symbols.out.tf1
ninja: build stopped: subcommand failed.

我已经递归地 grep 了我的项目、.android、.AndroidStudio2.2 目录以及文件名,除了 genout.cmake 之外,在 armv5te 中什么也找不到。我的 abiFilters 行是abiFilters 'x86'

如何构建 libpng 以链接到我的本机应用程序?此外,在 Android Studio 中,它显示该项目现在包含 libpng 源文件(专用于它的项目不少于 9 个!)。有什么办法可以去掉吗?

这是我的 CMakeLists.txt:

cmake_minimum_required(VERSION 3.4.1)

# build native_app_glue as a static lib
add_library(app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c)

set(png_src_dir ../../../../libpng-1.6.28)
set(PNG_STATIC ON)
add_subdirectory(${png_src_dir} ${png_src_dir}/build)

# now build app's shared lib
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++14")

add_library(native-activity SHARED
            main.cpp logger.cpp logger.h game.cpp game.h
            shaders.cpp shaders.h assets.cpp assets.h)

target_include_directories(native-activity PRIVATE ${ANDROID_NDK}/sources/android/native_app_glue
                           C:/devlibs/include
                           ${png_src_dir})

# add lib dependencies
target_link_libraries(native-activity app-glue android log EGL GLESv2 png)

【问题讨论】:

    标签: android android-studio cmake


    【解决方案1】:

    我已经管理 libpng 以将 android NDK 应用程序(CMake 构建系统而不是 Android.mk)作为静态库。我用libpng-android repackaging。以下是我做过的事情:

    1. git clone https://github.com/julienr/libpng-android.git 转换为${YOUR_LIBS_FOLDER}(我使用了${ANDROID_NDK_ROOT_DIRECTORY}/sources/android)。
    2. ${ANDROID_NDK_ROOT_DIRECTORY}(对我来说是home/username/Android/sdk/ndk-bundle)添加到构建脚本所需的全局$PATH变量中。
    3. 使用ndk-build 构建lib(在带有lib 的目录中有./build.sh)。将为不同的ABI 目标(arm64-v8aarmeabix86_64 等)构建库。
    4. 此时,您在${YOUR_LIBS_FOLDER}/libpng-android/jnilibpng.a 处拥有库头文件${YOUR_LIBS_FOLDER}/libpng-android/obj/local/${ANDROID_ABI}/,其中${ANDROID_ABI} 是目标平台。
    5. 最后你可以在CMakeLists.txt 包含lib。 libpng 需要 zlib compression library,所以你也需要链接它(zlib 由 android studio 提供,所以只需添加 -lz 标志)。

    这是我CMakeLists.txt的相关文章:

    add_library(libpng STATIC IMPORTED)
    set_target_properties(libpng PROPERTIES IMPORTED_LOCATION
        ${YOUR_LIBS_FOLDER}/libpng-android/obj/local/${ANDROID_ABI}/libpng.a)
    
    add_library(appManager SHARED src/main/cpp/appManager.cpp)
    
    target_include_directories(appManager PRIVATE ${YOUR_LIBS_FOLDER}/libpng-android/jni/)
    
    target_link_libraries(appManager
                           android
                           libpng
                           z)
    

    有几点需要注意:

    • ${ANDROID_ABI} 是 Android Studio 构建系统设置的变量。
    • 再说一次:您需要链接到zlib,这就是为什么我们在target_link_libraries 中使用libpng z 而不是libpng

    【讨论】:

    • 我在 Windows 上,我不能使用 build.sh,而且这个重新打包很不稳定(即错误 #130,他们只是禁用了 arm 而不是实际修复它)我不妨包括我的项目中有十几个文件,并完全避免链接。
    • @Olivetree 在build.sh 中有一个命令:ndk-build NDK_PROJECT_PATH=./ $@,可以在没有.sh 的情况下手动执行。考虑到“bug 130”——同意,看起来很奇怪。
    • 是的,但最后一点仍然存在:我不妨手动将文件添加到我的项目中,并完全避免管理此构建及其工具链设置的负担。但我不太相信这种方法:你看过官方的 libpng 构建过程吗?期望在没有问题的情况下做到这一点有点太复杂了。
    【解决方案2】:

    使用 Android Studio 3.6,将 libpng 包含到您的项目中相当容易。

    • sourceforge 下载最新的源代码并解压缩 zip 文件。
    • 在 Android Studio 中,确保您已安装 NDKCMake(在 SDK 管理器 中)李>
    • 创建一个新的 Android 库 模块,将其命名为 pngAndroid(我会推荐 将Package Name设置为org.libpng.libpng,与MacOS相同)。保持 Java,并选择适合您的应用的最小 SDK。
    • 对于这个模块,选择File/Link C++ Project with Gradle。找到您在第 1 步中下载的 libpng 中的 CMakleLists.txt
    • pngAndroidbuild.gradle,添加

      android.defaultConfig.externalNativeBuild.cmake.targets "png_static"
      
    • Project Structure 对话框中,指定 Module 和 pngAndroid 之间的模块依赖关系。

    当你构建 pngAndroid 模块时,你会在 build/intermediates/cmake/debug/obj 目录下看到文件 libpng16d.a pngAndroid

    在您的模块中,您还有 CMakleLists.txt。在这个脚本中,你有一个目标,例如

    add_library(native-library SHARED …
    

    您应该添加 libpng 作为 native-library 的依赖项:

    target_link_libraries(native-library libpng)
    

    在这个 CMakleLists.txt 的其他地方,您应该定义导入的 libpng

    add_library(libpng STATIC IMPORTED)
    set_target_properties(libpng PROPERTIES IMPORTED_LOCATION
        ../pngAndroid/build/intermediates/cmake/debug/obj/${ANDROID_ABI}/libpng16d.a)
    set_target_properties(libpng PROPERTIES INTERFACE_INCLUDE_DIRECTORIES
        ../../lpng1637)
    set_target_properties(libpng PROPERTIES IMPORTED_LINK_INTERFACE_LIBRARIES
        z)
    

    请注意,这里我使用了相对路径 a) 到您添加到 Android Studio 项目中的 pngAndroid 模块,以及 b) 到您下载的 libpng 源。在您的设置中,相对路径可能不同。


    为了完整起见,这里有一个清理过的 build.gradle 脚本,用于 pngAndroid 构建共享库 libpng16d.so

    apply plugin: 'com.android.library'
    
    android {
        compileSdkVersion 29
        defaultConfig {
            minSdkVersion 16
            targetSdkVersion 29
            versionCode 1
            versionName "1.0"
            externalNativeBuild {
                cmake {
                    arguments "-DSKIP_INSTALL_ALL=YES"
                    targets "png"
                }
            }
        }
    
        externalNativeBuild {
            cmake {
                path file('../../lpng1637/CMakeLists.txt')
            }
        }
    }
    

    构建模块时,您会在 build/outputs 中获得一个 aar 文件,该文件包含 jni 目录和 @987654331 @ 和所有其他 ABI 变体。


    最后,值得一提的是 Google is working on an easier native package manager。不幸的是,它仍然没有发布。

    【讨论】:

    • 能否请您为我澄清一些时刻,这样您就可以提供我们创建一个模块并(例如)将libpng 包含到此模块中。结果是 - 我们有 libpng 的模块,但我仍然不明白如何将此模块包含到我的 cpp 项目中?我的意思是当我尝试在我的 cpp 文件中添加标题 #include <png.h> 时,我收到错误 png.h file not found... 我做错了什么?我想我需要在项目`CMakeList.txt`中添加一些配置,对吧?
    • 上面的代码为 Android 构建了 libpng。如果您想将其用作 C++ 依赖项之一,则使用 STATIC 版本要容易得多。我已经扩展了我的答案来解释如何定义这种依赖关系。
    • 你在这里是什么意思 - In Project Structure dialog, specify module dependency between your Module and pngAndroid?我打开了 Project Stucture 对话框,但我不明白我需要如何指定 myModule(我认为您的意思是应用程序模块)和 pngAndroid(它实际上也是模块)之间的依赖关系...?
    • 我想问一下lib的静态版本。据我了解,这意味着例如我已经编译源文件并将它们添加为静态库,所以如果我需要更新我的库(有人推送新提交)我需要再次重新编译源文件并添加替换库新一个,对吧?我的意思是使用静态版本的 lib 如果您需要更新您的 lib 会有点困难......不是吗?
    • @AlekseyTimoshchenko 静态和共享之间的区别很小。无论如何,Play 商店要求所有二进制文件都打包在 APK(或 AAB)中。因此,在这两种情况下,您都必须部署新版本。在这两种情况下,您都必须编译库(例如 libpng)。对于静态,这也会导致 CMake 再次链接依赖于 libpng 的二进制文件(例如 libnative-activity.so)。请注意,如果您使用共享 libpng,还必须确保将其打包到 APK 中。
    猜你喜欢
    • 2020-09-21
    • 2023-04-03
    • 2023-01-14
    • 1970-01-01
    • 1970-01-01
    • 2021-08-05
    • 2011-01-10
    • 2020-11-08
    相关资源
    最近更新 更多