无法为android编译适当的32位libzip库

时间:2017-09-06 13:34:04

标签: android cmake android-ndk

我从这里克隆了libgip的hg存储库: https://hg.nih.at/libzip/

我知道有一个用于android的libzip软件包,但首先我想尝试使用原始软件包,因为我希望我的未来项目在其他平台上使用相同版本的库源操作,直到我可以管理。

我对CMake构建系统不太熟悉, 所以我从构建测试NDK项目的Android Studio生成的cmake_build_command.txt中借用了必要的参数。

所以,我执行cmake的批处理文件是这样的:

rmdir /S /Q build
"C:\Android\sdk\cmake\3.6.4111459\bin\cmake.exe"^
 .^
 -H"D:\Project\External\libzip"^
 -B"D:\Project\External\libzip\build"^
 -G"Android Gradle - Ninja"^
 -D"ANDROID_ABI=x86"^
 -D"ANDROID_NDK=C:\Android\sdk\ndk-bundle"^
 -D"CMAKE_LIBRARY_OUTPUT_DIRECTORY=D:\Project\External\libzip\build"^
 -D"CMAKE_BUILD_TYPE=Debug"^
 -D"CMAKE_MAKE_PROGRAM=C:\Android\sdk\cmake\3.6.4111459\bin\ninja.exe"^
 -D"CMAKE_TOOLCHAIN_FILE=C:\Android\sdk\ndk-bundle\build\cmake\android.toolchain.cmake"^
 -D"ANDROID_PLATFORM=android-23"
cd build
C:\Android\sdk\cmake\3.6.4111459\bin\ninja.exe

这是输出:

D:\Project\External\libzip>"C:\Android\sdk\cmake\3.6.4111459\bin\cmake.exe" . -H"D:\Project\External\libzip" -B"D:\Project\External\libzip\build" -G"Android Gradle - Ninja" -D"ANDROID_ABI=x86" -D"ANDROID_NDK=C:\Android\sdk\ndk-bundle" -D"CMAKE_LIBRARY_OUTPUT_DIRECTORY=D:\Project\External\libzip\build" -D"CMAKE_BUILD_TYPE=Debug" -D"CMAKE_MAKE_PROGRAM=C:\Android\sdk\cmake\3.6.4111459\bin\ninja.exe" -D"CMAKE_TOOLCHAIN_FILE=C:\Android\sdk\ndk-bundle\build\cmake\android.toolchain.cmake" -D"ANDROID_PLATFORM=android-23"
-- Check for working C compiler: C:/Android/sdk/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64/bin/clang.exe
-- Check for working C compiler: C:/Android/sdk/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64/bin/clang.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Looking for _chmod
-- Looking for _chmod - not found
-- Looking for _close
-- Looking for _close - not found
-- Looking for _dup
-- Looking for _dup - not found
-- Looking for _fdopen
-- Looking for _fdopen - not found
-- Looking for _fileno
-- Looking for _fileno - not found
-- Looking for _open
-- Looking for _open - not found
-- Looking for _setmode
-- Looking for _setmode - not found
-- Looking for _snprintf
-- Looking for _snprintf - not found
-- Looking for _strdup
-- Looking for _strdup - not found
-- Looking for _stricmp
-- Looking for _stricmp - not found
-- Looking for _strtoi64
-- Looking for _strtoi64 - not found
-- Looking for _strtoui64
-- Looking for _strtoui64 - not found
-- Looking for _umask
-- Looking for _umask - not found
-- Looking for _unlink
-- Looking for _unlink - not found
-- Looking for explict_bzero
-- Looking for explict_bzero - not found
-- Looking for explicit_memset
-- Looking for explicit_memset - not found
-- Looking for fileno
-- Looking for fileno - found
-- Looking for fseeko
-- Looking for fseeko - found
-- Looking for ftello
-- Looking for ftello - found
-- Looking for getprogname
-- Looking for getprogname - found
-- Looking for open
-- Looking for open - found
-- Looking for mkstemp
-- Looking for mkstemp - found
-- Looking for setmode
-- Looking for setmode - not found
-- Looking for snprintf
-- Looking for snprintf - found
-- Looking for strcasecmp
-- Looking for strcasecmp - found
-- Looking for strdup
-- Looking for strdup - found
-- Looking for stricmp
-- Looking for stricmp - not found
-- Looking for strtoll
-- Looking for strtoll - found
-- Looking for strtoull
-- Looking for strtoull - found
-- Looking for include file fts.h
-- Looking for include file fts.h - found
-- Looking for include file stdbool.h
-- Looking for include file stdbool.h - found
-- Looking for include file strings.h
-- Looking for include file strings.h - found
-- Looking for include file unistd.h
-- Looking for include file unistd.h - found
-- Looking for include file inttypes.h
-- Looking for include file inttypes.h - found
-- Looking for include file stdint.h
-- Looking for include file stdint.h - found
-- Looking for include file sys/types.h
-- Looking for include file sys/types.h - found
-- Looking for sys/types.h
-- Looking for sys/types.h - found
-- Looking for stdint.h
-- Looking for stdint.h - found
-- Looking for stddef.h
-- Looking for stddef.h - found
-- Check size of __int8
-- Check size of __int8 - failed
-- Check size of int8_t
-- Check size of int8_t - done
-- Check size of uint8_t
-- Check size of uint8_t - done
-- Check size of __int16
-- Check size of __int16 - failed
-- Check size of int16_t
-- Check size of int16_t - done
-- Check size of uint16_t
-- Check size of uint16_t - done
-- Check size of __int32
-- Check size of __int32 - failed
-- Check size of int32_t
-- Check size of int32_t - done
-- Check size of uint32_t
-- Check size of uint32_t - done
-- Check size of __int64
-- Check size of __int64 - failed
-- Check size of int64_t
-- Check size of int64_t - done
-- Check size of uint64_t
-- Check size of uint64_t - done
-- Check size of short
-- Check size of short - done
-- Check size of int
-- Check size of int - done
-- Check size of long
-- Check size of long - done
-- Check size of long long
-- Check size of long long - done
-- Check size of off_t
-- Check size of off_t - done
-- Check size of size_t
-- Check size of size_t - done
-- Check size of ssize_t
-- Check size of ssize_t - done
-- Check if the system is big endian
-- Searching 16 bit integer
-- Check size of unsigned short
-- Check size of unsigned short - done
-- Using unsigned short
-- Check if the system is big endian - little endian
-- Found ZLIB: C:/Android/sdk/ndk-bundle/platforms/android-23/arch-x86/usr/lib/libz.so (found version "1.2.3")
-- Could NOT find BZip2 (missing:  BZIP2_LIBRARIES BZIP2_INCLUDE_DIR)
-- Looking for getopt
-- Looking for getopt - found
-- Configuring done
-- Generating done
-- Build files have been written to: D:/Project/External/libzip/build

D:\Project\External\libzip>cd build

D:\Project\External\libzip\build>C:\Android\sdk\cmake\3.6.4111459\bin\ninja.exe
[133/133] Linking C executable regress\tryopen

我将此与我的项目联系起来:

include_directories( ../../../External/libzip/lib
                     ../../../External/libzip/build
                     )

target_link_libraries( native-lib

                       ${z-lib}
                       D:/Project/External/libzip/build/lib/libzip.a
                       )

我用这个gradle设置构建了我的ndk项目:

externalNativeBuild {
            cmake {
                arguments "-DANDROID_TOOLCHAIN=clang", "-DANDROID_STL=c++_static"
                cppFlags "-std=c++14", "-frtti", "-fexceptions"
            }
        }
        ndk {
            abiFilters "x86"
        }

老实说,我没想到会轻易做到这一点。 但令人惊讶的是,它与我的测试NDK项目成功链接并顺利运行。 我可以用zip_open()打开我的apk文件,并且没有问题地读取各个文件的内容。

但在我意识到其他ABI并非如此之后不久。 在除了我的初始尝试之外的所有其他ABI中,即arm64-v8a,zip_open()返回NULL。 我可以用调试器检查的是zip_open()的参数变得一团糟,apk路径的字符串突然变成“1”,而其他所有的东西都在zip_open()里面也是垃圾。

后来我也发现x86_64与模拟器的工作方式就像arm64-v8a一样,但x86再次失败。 所以我怀疑这是某种32/64位问题,但我无法弄清楚究竟是什么导致了这个问题。

我还尝试了一些其他与gcc工具链和-D“CMAKE_C_FLAGS = -m32”的组合,但对我没什么用。

有帮助吗?

(并且要清楚,以上所有代码片段均来自x86设置,而不是成功的arm64或x86_64。)

修改

我找到了问题的根源,所以我想在这里分享。

首先,我不应该拥有受信任的Android原生调试器。 正如我上面提到的,zip_open()中的所有参数看起来都已损坏,但它只是调试器吐出错误信息。 从那里我浪费了相当多的时间来挖掘错误的地方,比如召集会议等。

问题的真正根源是libzip源中的一个表达式:

offset < ZIP_FSEEK_MIN

其中“ZIP_FSEEK_MIN”定义为-0x80000000L,“offset”在我的情况下为-65578。

当然它应该产生“假”,但它不是在32位ABI中。 (请注意,“offset”是zip_int64_t,在任何平台上都是64位整数。)

所以我进行了一些测试,结果是:

offset < ZIP_FSEEK_MIN     // yield "true"
offset < -0x80000000L      // yield "true"
offset < -0x80000000LL     // yield "false"
offset < -0x80000000LL-1LL // yield "false"
offset < -0x80000000L+1L   // yield "true"
offset < -0x7fffffffL-1L   // yield "false", sometimes cause crash in armeabi
offset < -2147483648       // yield "false"

似乎-0x80000000L是表示最小有符号32位整数的“坏形式”。 所有std c库都将其定义为“-0x7fffffffL-1L”或“-2147483647i32 - 1”。

还有一个可怕的角落案例,其中“-0x7fffffffL-1L”导致程序在armeabi中崩溃(v7a和x86很好),但我找不到确切的条件来触发它。 (我甚至不确定如何处理这个问题。)

就是这样。以下是我从中学到的东西:

  1. 尽量避免将某些内容与“-0x80000000L”进行比较。
  2. 相反,请使用“-0x7fffffffL-1L”或类似的内容。
  3. 不要太信任android原生调试器。
  4. 感谢上帝armeabi,只有设备不再常见。
  5. 谢谢。

0 个答案:

没有答案