使用 Cmake 为 Android 编译 libgcrypt 和 libgpgerror

Compiling libgcrypt and libgpgerror for Android with Cmake

对于一些必须用 C(++) 实现的代码,我需要像 AES 和 3DES 这样的加密函数 en-/decryption。由于 openssl 不再适用于 Playstore,因此我不得不选择其他库。我的选择是 libgcrypt。 现在我努力为 android 编译 libgpgerr。 (iOS 工作正常)

环境:

我的 libgcrypt 的(子)cmake:

cmake_minimum_required(VERSION 3.6)
include(ExternalProject)

set(CMAKE_CXX_STANDARD 11)

set(LIB_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)

set(LIBGPG_ERROR_DIR ${LIB_DIR}/libgpg-error)
set(LIBGCRYPT_DIR ${LIB_DIR}/libgcrypt)


set(THIS_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/)



message(STATUS "> ****************************** ${CMAKE_SYSTEM_PROCESSOR} >")
get_cmake_property(_variableNames VARIABLES)
foreach (_variableName ${_variableNames})
    message(STATUS "${_variableName}=${${_variableName}}")
endforeach()
execute_process(COMMAND "${CMAKE_COMMAND}" "-E" "environment")
message(STATUS "< ****************************** ${CMAKE_SYSTEM_PROCESSOR} <")

if (IS_ANDROID)

    # CMAKE_C_IMPLICIT_LINK_DIRECTORIES
    set(EXTRA_DIRS "-L/home/user/Android/Sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a -L/home/user/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/lib64/clang/5.0.300080/lib/linux/arm -L/home/user/Android/Sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/armv7-a/thumb -L/home/user/Android/Sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/arm-linux-androideabi/lib/armv7-a/thumb -L/home/user/Android/Sdk/ndk-bundle/platforms/android-19/arch-arm/usr/lib -I ${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES}")


    set(MAKE_ENV    
                   export "CFLAGS=${CMAKE_C_FLAGS} ${EXTRA_DIRS} -target ${ANDROID_LLVM_TRIPLE} -v -no-integrated-as -B${ANDROID_TOOLCHAIN_PREFIX}"
                   && export "CXXFLAGS=${CMAKE_CXX_FLAGS}"
                   && export "LDFLAGS=${ANDROID_LINKER_FLAGS} ${EXTRA_DIRS}"

                    #CFLAGS= "--sysroot=${}"
                    #LDFLAGS=
                    && export "LD=${CMAKE_LINKER} -v  -B${ANDROID_TOOLCHAIN_PREFIX}"
                    && export "AS=${ANDROID_ASM_COMPILER}"
                    && export "CC=${CMAKE_C_COMPILER} -v ${EXTRA_DIRS} -stdlib=${ANDROID_STL}"
                    && export "CXX=${CMAKE_CXX_COMPILER}"
                    && export "AR=${CMAKE_AR}"
                    && export "RANLIB=${CMAKE_RANLIB}"

                    && export "PATH=${ANDROID_LLVM_TOOLCHAIN_PREFIX}:${ANDROID_TOOLCHAIN_ROOT}/bin:${ANDROID_TOOLCHAIN_PREFIX}:$ENV{PATH}"

                    #GCC_TOOLCHAIN=${ANDROID_TOOLCHAIN_PREFIX}

                    )

    set(HOST ${ANDROID_HEADER_TRIPLE} )
    #set(HOST ${ANDROID_LLVM_TRIPLE} )

    ExternalProject_Add(
            libgpg-error
            SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/
            CONFIGURE_COMMAND  ${MAKE_ENV} && ${LIBGPG_ERROR_DIR}/configure --host=${HOST} --prefix=${THIS_PREFIX} --enable-static --disable-shared --disable-doc --disable-languages #--disable-asm
            #PREFIX ${THIS_PREFIX}
            BUILD_COMMAND  ${MAKE_ENV} && make
            INSTALL_COMMAND ${MAKE_ENV} && make install
    )
    # CMAKE_C_COMPILER_TARGET

    ExternalProject_Add(
            libgcrypt
            SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/
            CONFIGURE_COMMAND  ${MAKE_ENV} && ${LIBGCRYPT_DIR}/configure --host=${HOST} --prefix=${THIS_PREFIX} --enable-static --disable-shared --with-gpg-error-prefix=${THIS_PREFIX}  --disable-doc --disable-languages #--disable-asm
            #PREFIX ${THIS_PREFIX}
            BUILD_COMMAND  ${MAKE_ENV} && make
            INSTALL_COMMAND ${MAKE_ENV} && make install
            DEPENDS libgpg-error
    )


endif()

日志文件的最后一部分:

clang: warning: argument unused during compilation: '-L/home/user/Android/Sdk/ndk-bundle/platforms/android-19/arch-arm/usr/lib' [-Wunused-command-line-argument]
       "/home/user/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin/clang" -cc1 -triple thumbv7-none-linux-android -S -disable-free -disable-llvm-verifier -discard-value-names -main-file-name estream.c -mrelocation-model pic -pic-level 1 -mthread-model posix -mdisable-fp-elim -fmath-errno -masm-verbose -no-integrated-as -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu cortex-a8 -target-feature +soft-float-abi -target-feature -fp-only-sp -target-feature -d16 -target-feature +vfp3 -target-feature -fp16 -target-feature -vfp4 -target-feature -fp-armv8 -target-feature +neon -target-feature -crypto -target-abi aapcs-linux -mfloat-abi soft -target-linker-version 2.24 -v -v -dwarf-column-info -debug-info-kind=limited -dwarf-version=4 -debugger-tuning=gdb -ffunction-sections -coverage-notes-file /home/user/workspace/company/project-android/project/app/.externalNativeBuild/cmake/debug/armeabi-v7a/libgcrypt/libgpg-error-prefix/src/libgpg-error-build/src/estream.gcno -resource-dir /home/user/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/lib64/clang/5.0.300080 -dependency-file .deps/libgpg_error_la-estream.Tpo -sys-header-deps -MP -MT libgpg_error_la-estream.lo -isystem /home/user/Android/Sdk/ndk-bundle/sysroot/usr/include/arm-linux-androideabi -I /usr/include -D HAVE_CONFIG_H -I . -I /home/user/workspace/company/project-android/project/project-encrypt-lib/shared/lib/cmakeFiles/libgcrypt/../../libgpg-error/src -I .. -D "LOCALEDIR=\"/home/user/workspace/company/project-android/project/app/.externalNativeBuild/cmake/debug/armeabi-v7a/libgcrypt/share/locale\"" -D __ANDROID_API__=19 -D ANDROID -I /usr/include -internal-isystem /usr/local/include -internal-isystem /home/user/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/lib64/clang/5.0.300080/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wformat -Werror=format-security -Wall -Wpointer-arith -fno-dwarf-directory-asm -fdebug-compilation-dir /home/user/workspace/company/project-android/project/app/.externalNativeBuild/cmake/debug/armeabi-v7a/libgcrypt/libgpg-error-prefix/src/libgpg-error-build/src -ferror-limit 19 -fmessage-length 0 -femulated-tls -stack-protector 2 -fallow-half-arguments-and-returns -fno-signed-char -fobjc-runtime=gcc -fdiagnostics-show-option -o /tmp/estream-2a422f.s -x c /home/user/workspace/company/project-android/project/project-encrypt-lib/shared/lib/cmakeFiles/libgcrypt/../../libgpg-error/src/estream.c
      clang -cc1 version 5.0.300080 based upon LLVM 5.0.300080 default target x86_64-unknown-linux
      ignoring nonexistent directory "/include"
      ignoring duplicate directory "/usr/include"
      ignoring duplicate directory "/usr/include"
        as it is a non-system directory that duplicates a system directory
      #include "..." search starts here:
      #include <...> search starts here:
       .
       /home/user/workspace/company/project-android/project/project-encrypt-lib/shared/lib/cmakeFiles/libgcrypt/../../libgpg-error/src
       ..
       /home/user/Android/Sdk/ndk-bundle/sysroot/usr/include/arm-linux-androideabi
       /usr/local/include
       /home/user/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/lib64/clang/5.0.300080/include
       /usr/include
      End of search list.
      /home/user/workspace/company/project-android/project/project-encrypt-lib/shared/lib/cmakeFiles/libgcrypt/../../libgpg-error/src/estream.c:4869:15: error: invalid output constraint '=c' in asm
                    FD_ZERO (&readfds);
                    ^
      /usr/include/sys/select.h:93:26: note: expanded from macro 'FD_ZERO'
      #define FD_ZERO(fdsetp)         __FD_ZERO (fdsetp)
                                      ^
      /usr/include/bits/select.h:37:8: note: expanded from macro '__FD_ZERO'
                                : "=c" (__d0), "=D" (__d1)                          \
                                  ^
      /home/user/workspace/company/project-android/project/project-encrypt-lib/shared/lib/cmakeFiles/libgcrypt/../../libgpg-error/src/estream.c:4880:15: error: invalid output constraint '=c' in asm
                    FD_ZERO (&writefds);
                    ^
      /usr/include/sys/select.h:93:26: note: expanded from macro 'FD_ZERO'
      #define FD_ZERO(fdsetp)         __FD_ZERO (fdsetp)
                                      ^
      /usr/include/bits/select.h:37:8: note: expanded from macro '__FD_ZERO'
                                : "=c" (__d0), "=D" (__d1)                          \
                                  ^
      /home/user/workspace/company/project-android/project/project-encrypt-lib/shared/lib/cmakeFiles/libgcrypt/../../libgpg-error/src/estream.c:4891:15: error: invalid output constraint '=c' in asm
                    FD_ZERO (&exceptfds);
                    ^
      /usr/include/sys/select.h:93:26: note: expanded from macro 'FD_ZERO'
      #define FD_ZERO(fdsetp)         __FD_ZERO (fdsetp)
                                      ^
      /usr/include/bits/select.h:37:8: note: expanded from macro '__FD_ZERO'
                                : "=c" (__d0), "=D" (__d1)                          \
                                  ^
      3 errors generated.
      Makefile:876: die Regel für Ziel „libgpg_error_la-estream.lo“ scheiterte
      make[3]: *** [libgpg_error_la-estream.lo] Fehler 1
      make[3]: Verzeichnis „/home/user/workspace/company/project-android/project/app/.externalNativeBuild/cmake/debug/armeabi-v7a/libgcrypt/libgpg-error-prefix/src/libgpg-error-build/src“ wird verlassen
      Makefile:578: die Regel für Ziel „all“ scheiterte
      make[2]: *** [all] Fehler 2
      make[2]: Verzeichnis „/home/user/workspace/company/project-android/project/app/.externalNativeBuild/cmake/debug/armeabi-v7a/libgcrypt/libgpg-error-prefix/src/libgpg-error-build/src“ wird verlassen
      Makefile:474: die Regel für Ziel „all-recursive“ scheiterte
      make[1]: *** [all-recursive] Fehler 1
      make[1]: Verzeichnis „/home/user/workspace/company/project-android/project/app/.externalNativeBuild/cmake/debug/armeabi-v7a/libgcrypt/libgpg-error-prefix/src/libgpg-error-build“ wird verlassen
      Makefile:405: die Regel für Ziel „all“ scheiterte
      make: *** [all] Fehler 2
      ninja: build stopped: subcommand failed.

这是一个使用独立工具链的工作示例。

请注意,这个过程不是最优的; CMake 在 "configure" 阶段构建这些库。 不过改起来应该是比较容易的。

CMake 文件(片段):

cmake_minimum_required(VERSION 3.6)
include(ExternalProject)

set(CMAKE_CXX_STANDARD 11)

set(LIB_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)

set(LIBGPG_ERROR_DIR ${LIB_DIR}/libgpg-error)
set(LIBGCRYPT_DIR ${LIB_DIR}/libgcrypt)

set(THIS_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/)


if (IS_ANDROID)
    set(ENV{LIB_DIR}            ${CMAKE_CURRENT_LIST_DIR}/../..)
    set(ENV{LIBGPG_ERROR_DIR}   ${LIB_DIR}/libgpg-error)
    set(ENV{LIBGCRYPT_DIR}      ${LIB_DIR}/libgcrypt)

    message(STATUS "CURRENT=${ANDROID_SYSROOT_ABI}-${ANDROID_PLATFORM_LEVEL}-libc")
    execute_process(
        COMMAND bash -c "$ENV{LIBGPG_ERROR_DIR}/buildGpgError.sh ${ANDROID_SYSROOT_ABI}-${ANDROID_PLATFORM_LEVEL}-libc"
        OUTPUT_VARIABLE outVar
    )


    execute_process(
        COMMAND bash -c "$ENV{LIBGCRYPT_DIR}/buildGcrypt.sh ${ANDROID_SYSROOT_ABI}-${ANDROID_PLATFORM_LEVEL}-libc"
        OUTPUT_VARIABLE outVar
    )

    set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
    set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)
    set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)

    find_library(libgpg-error NAMES gpg-error HINTS $ENV{LIBGPG_ERROR_DIR}/${ANDROID_SYSROOT_ABI}-${ANDROID_PLATFORM_LEVEL}-libc)
    find_library(libgcrypt NAMES gcrypt HINTS $ENV{LIBGCRYPT_DIR}/${ANDROID_SYSROOT_ABI}-${ANDROID_PLATFORM_LEVEL}-libc)

endif()

buildGpgError.sh:

#!/bin/bash

TARGET=
SCRIPTPATH="$( cd "$(dirname "[=11=]")" ; pwd -P )"
TOOLCHAIN=$(basename $TARGET)
STLCHAIN=c++_shared

$SCRIPTPATH/../createToolchain.sh $TARGET

TOOLCHAIN_LOCATION=$HOME/toolchains/$TARGET

LIBDIR=$(pwd)
CLANG=$(basename $(find $TOOLCHAIN_LOCATION -name "*-clang" | grep $TOOLCHAIN))
CLANG_CPP=$(basename $(find $TOOLCHAIN_LOCATION -name "*-clang++" | grep $TOOLCHAIN))
CLANG_RANLIB=$(basename $(find $TOOLCHAIN_LOCATION -name "*-ranlib" | grep $TOOLCHAIN | grep -v gcc | grep -v llvm))
CLANG_LD=$(basename $(find $TOOLCHAIN_LOCATION -name "*-ld" | grep $TOOLCHAIN | grep -v gcc | grep -v llvm))
CLANG_AR=$(basename $(find $TOOLCHAIN_LOCATION -name "*-ar" | grep $TOOLCHAIN | grep -v gcc | grep -v llvm))
ABI=$(echo $CLANG | cut -d"-" -f1-3)

echo "clang     = $CLANG"
echo "clang++   = $CLANG_CPP"
echo "ranlib    = $CLANG_RANLIB"
echo "ld        = $CLANG_LD"
echo "ar        = $CLANG_AR"
echo "CROSS     = $ABI"
echo "toolchain = $TOOLCHAIN"
echo "basedir   = $TOOLCHAIN_LOCATION"

export PATH="$PATH:$TOOLCHAIN_LOCATION/bin"
export CC=$CLANG
export CXX=$CLANG_CPP
export RANLIB=$CLANG_RANLIB
export LD=$CLANG_LD
export AR=$CLANG_AR
export CROSS_COMPILE=$ABI
export APP_STL=$STLCHAIN
export ANDROID_STL=$STLCHAIN
export NDK_TOOLCHAIN_VERSION=clang

cd $SCRIPTPATH
find . -name "Makefile" -delete
rm -rf $SCRIPTPATH/src/.libs

# --------------------------------------------------
# Build libgpg-error
# --------------------------------------------------
export CFLAGS="-fPIE -fPIC -I$SCRIPTPATH/../libgpg-error/src"
export LDFLAGS="-pie -L$SCRIPTPATH/../libgpg-error/src"
./configure --host="$CROSS_COMPILE" --with-sysroot="$TOOLCHAIN_LOCATION/$TOOLCHAIN" 2>&1 > $SCRIPTPATH/build_$TARGET.log
make clean 2>&1 >> $SCRIPTPATH/build_$TARGET.log
make 2>&1 >> $SCRIPTPATH/build_$TARGET.log

mkdir -p $SCRIPTPATH/$TARGET
cp $SCRIPTPATH/src/mkerrcodes.h $SCRIPTPATH/$TARGET
cp $SCRIPTPATH/src/gpgrt.h $SCRIPTPATH/$TARGET
cp $SCRIPTPATH/src/gpg-error.h $SCRIPTPATH/$TARGET
cp $SCRIPTPATH/src/gpg-error.def $SCRIPTPATH/$TARGET
cp $SCRIPTPATH/src/err-sources-sym.h $SCRIPTPATH/$TARGET
cp $SCRIPTPATH/src/err-sources.h $SCRIPTPATH/$TARGET
cp $SCRIPTPATH/src/errnos-sym.h $SCRIPTPATH/$TARGET
cp $SCRIPTPATH/src/err-codes-sym.h $SCRIPTPATH/$TARGET
cp $SCRIPTPATH/src/err-codes.h $SCRIPTPATH/$TARGET
cp $SCRIPTPATH/src/code-to-errno.h $SCRIPTPATH/$TARGET
cp $SCRIPTPATH/src/code-from-errno.h $SCRIPTPATH/$TARGET
cp $SCRIPTPATH/src/.libs/libgpg-error.so $SCRIPTPATH/$TARGET

buildGcrypt.sh:

#!/bin/bash

TARGET=
SCRIPTPATH="$( cd "$(dirname "[=12=]")" ; pwd -P )"
TOOLCHAIN=$(basename $TARGET)
STLCHAIN=c++_shared

$SCRIPTPATH/../createToolchain.sh $TARGET

TOOLCHAIN_LOCATION=$HOME/toolchains/$TARGET

LIBDIR=$(pwd)
CLANG=$(basename $(find $TOOLCHAIN_LOCATION -name "*-clang" | grep $TOOLCHAIN))
CLANG_CPP=$(basename $(find $TOOLCHAIN_LOCATION -name "*-clang++" | grep $TOOLCHAIN))
CLANG_RANLIB=$(basename $(find $TOOLCHAIN_LOCATION -name "*-ranlib" | grep $TOOLCHAIN | grep -v gcc | grep -v llvm))
CLANG_LD=$(basename $(find $TOOLCHAIN_LOCATION -name "*-ld" | grep $TOOLCHAIN | grep -v gcc | grep -v llvm))
CLANG_AR=$(basename $(find $TOOLCHAIN_LOCATION -name "*-ar" | grep $TOOLCHAIN | grep -v gcc | grep -v llvm))
ABI=$(echo $CLANG | cut -d"-" -f1-3)

echo "clang     = $CLANG"
echo "clang++   = $CLANG_CPP"
echo "ranlib    = $CLANG_RANLIB"
echo "ld        = $CLANG_LD"
echo "ar        = $CLANG_AR"
echo "CROSS     = $ABI"
echo "toolchain = $TOOLCHAIN"
echo "basedir   = $TOOLCHAIN_LOCATION"

export PATH="$PATH:$TOOLCHAIN_LOCATION/bin:$SCRIPTPATH/../libgpg-error/src"
export CC=$CLANG
export CXX=$CLANG_CPP
export RANLIB=$CLANG_RANLIB
export LD=$CLANG_LD
export AR=$CLANG_AR
export CROSS_COMPILE=$ABI
export APP_STL=$STLCHAIN
export ANDROID_STL=$STLCHAIN
export NDK_TOOLCHAIN_VERSION=clang

cd $SCRIPTPATH
find . -name "Makefile" -delete
rm -rf $SCRIPTPATH/src/.libs

# --------------------------------------------------
# Build libgcrypt
# --------------------------------------------------
export CFLAGS="-Wunused-command-line-argument -fPIE -fPIC -I$SCRIPTPATH/../libgpg-error/$TARGET"
export LDFLAGS="-pie -L$SCRIPTPATH/../libgpg-error/$TARGET"
./configure --host="$CROSS_COMPILE" --with-sysroot="$TOOLCHAIN_LOCATION/$TOOLCHAIN" 2>&1 > $SCRIPTPATH/build_$TARGET.log
make clean 2>&1 > $SCRIPTPATH/build_$TARGET.log
make 2>&1 > $SCRIPTPATH/build_$TARGET.log

mkdir -p $SCRIPTPATH/$TARGET
mv $SCRIPTPATH/src/.libs/libgcrypt.so $SCRIPTPATH/$TARGET

createToolchain.sh:

#!/bin/bash

TARGET=

if [ -e "$HOME/toolchains/$TARGET" ]; then
    exit 0
fi

ARCH=$(echo $TARGET | cut -d"-" -f1)
API=$(echo $TARGET | cut -d"-" -f2)
STL=$(echo $TARGET | cut -d"-" -f3)

if [ "$STL" == "libc" ]; then
    STL="libc++"
fi

NDK_DIR=$(cat ../../../local.properties | grep '^ndk\.dir=' | sed 's/^ndk\.dir=//')

MAKETOOLCHAINPATH=$NDK_DIR/build/tools/make_standalone_toolchain.py

$MAKETOOLCHAINPATH --arch $ARCH --api $API --stl $STL --install-dir $HOME/toolchains/$TARGET