Javacpp-presets: Build FFmpeg for Android without GCC

Created on 19 May 2018  路  11Comments  路  Source: bytedeco/javacpp-presets

I edited https://github.com/bytedeco/javacpp-presets/blob/master/ffmpeg/cppbuild.sh script a little bit to build FFmpeg without x264/265 and other extra libs:

#!/bin/bash
# This file is meant to be included by the parent cppbuild.sh script
if [[ -z "$PLATFORM" ]]; then
    pushd ..
    bash cppbuild.sh "$@" ffmpeg
    popd
    exit
fi

DISABLE="--disable-static --disable-iconv --disable-opencl --disable-sdl2 --disable-bzlib --disable-lzma --disable-linux-perf"
ENABLE="--enable-shared --enable-version3 --enable-runtime-cpudetect"

FFMPEG_VERSION=4.0

download http://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.bz2 ffmpeg-$FFMPEG_VERSION.tar.bz2

mkdir -p $PLATFORM
cd $PLATFORM
INSTALL_PATH=`pwd`
echo "Decompressing archives..."
tar --totals -xjf ../ffmpeg-$FFMPEG_VERSION.tar.bz2

patch -Np1 -d ffmpeg-$FFMPEG_VERSION < ../../ffmpeg.patch

cd ffmpeg-$FFMPEG_VERSION

case $PLATFORM in
    android-arm)
        export AR="$ANDROID_BIN-ar"
        export CPP="$ANDROID_BIN-cpp"
        export CC="$ANDROID_BIN-gcc"
        export CXX="$ANDROID_BIN-g++"
        export RANLIB="$ANDROID_BIN-ranlib"
        export STRIP="$ANDROID_BIN-strip"
        export CPPFLAGS="$ANDROID_FLAGS -D_FILE_OFFSET_BITS=32"
        export CFLAGS="$ANDROID_FLAGS -D_FILE_OFFSET_BITS=32"
        export CXXFLAGS="$ANDROID_FLAGS -D_FILE_OFFSET_BITS=32"
        export LDFLAGS="-Wl,--no-undefined -Wl,--fix-cortex-a8 -z text"
        export LIBS="-lgcc -ldl -lz -lm -lc"
        patch -Np1 < ../../../ffmpeg-android.patch
        sed -i="" 's/_FILE_OFFSET_BITS=64/_FILE_OFFSET_BITS=32/g' configure
        ./configure --prefix=.. $DISABLE $ENABLE --enable-pthreads --enable-cross-compile --cross-prefix="$ANDROID_BIN-" --ranlib="$ANDROID_BIN-ranlib" --sysroot="$ANDROID_ROOT" --target-os=linux --arch=arm --extra-cflags="-I../include/ $CFLAGS" --extra-ldflags="-L../lib/ -L$ANDROID_CPP/libs/armeabi/ $LDFLAGS" --extra-libs="-lgnustl_static $LIBS" --disable-symver --disable-programs
        make -j $MAKEJ
        make install
        ;;

    android-arm64)
        export AR="$ANDROID_BIN-ar"
        export CPP="$ANDROID_BIN-cpp"
        export CC="$ANDROID_BIN-gcc"
        export CXX="$ANDROID_BIN-g++"
        export RANLIB="$ANDROID_BIN-ranlib"
        export STRIP="$ANDROID_BIN-strip"
        export CPPFLAGS="$ANDROID_FLAGS"
        export CFLAGS="$ANDROID_FLAGS"
        export CXXFLAGS="$ANDROID_FLAGS"
        export LDFLAGS="-Wl,--no-undefined -z text"
        export LIBS="-lgcc -ldl -lz -lm -lc"
        patch -Np1 < ../../../ffmpeg-android.patch
        ./configure --prefix=.. $DISABLE $ENABLE --enable-pthreads --enable-cross-compile --cross-prefix="$ANDROID_BIN-" --ranlib="$ANDROID_BIN-ranlib" --sysroot="$ANDROID_ROOT" --target-os=linux --arch=aarch64 --extra-cflags="-I../include/ $CFLAGS" --extra-ldflags="-L../lib/ -L$ANDROID_CPP/libs/arm64-v8a/ $LDFLAGS" --extra-libs="-lgnustl_static $LIBS" --disable-symver --disable-programs
        make -j $MAKEJ
        make install
        ;;
    *)
        echo "Error: Platform \"$PLATFORM\" is not supported"
        ;;
esac

cd ../..

build works fine for arm64

but for just arm (armv7a) I get an error:

user@user-PC:~/Android/JavaCPP/javacpp-presets$ ANDROID_NDK=$NDK bash cppbuild.sh -platform android-arm install ffmpeg
Detected platform "linux-x86_64"
Building for platform "android-arm"
Installing "ffmpeg"
~/Android/JavaCPP/javacpp-presets/ffmpeg/cppbuild ~/Android/JavaCPP/javacpp-presets
Decompressing archives...
Total bytes read: 68341760 (66MiB, 32MiB/s)
patching file configure
patching file ffbuild/library.mak
/home/user/Android/Sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc is unable to create an executable file.
C compiler test failed.

If you think configure made a mistake, make sure you are using the latest
version from Git.  If the latest version fails, report the problem to the
[email protected] mailing list or IRC #ffmpeg on irc.freenode.net.
Include the log file "ffbuild/config.log" produced by configure as this will help
solve the problem.

enhancement

Most helpful comment

It's done! Now all presets for Android get built with Clang from NDK r18b: http://bytedeco.org/builds/

All 11 comments

x86 and x86_64 also work fine

 android-x86)
#        ANDROID_ROOT=${ANDROID_ROOT//14/21}
#        ANDROID_FLAGS=${ANDROID_FLAGS//14/21}
        export AR="$ANDROID_BIN-ar"
        export CPP="$ANDROID_BIN-cpp"
        export CC="$ANDROID_BIN-gcc"
        export CXX="$ANDROID_BIN-g++"
        export RANLIB="$ANDROID_BIN-ranlib"
        export STRIP="$ANDROID_BIN-strip"
        export CPPFLAGS="$ANDROID_FLAGS -D_FILE_OFFSET_BITS=32"
        export CFLAGS="$ANDROID_FLAGS -D_FILE_OFFSET_BITS=32"
        export CXXFLAGS="$ANDROID_FLAGS -D_FILE_OFFSET_BITS=32"
        export LDFLAGS="-Wl,--no-undefined -z text"
        export LIBS="-lgcc -ldl -lz -lm -lc"
        patch -Np1 < ../../../ffmpeg-android.patch
        sed -i="" 's/_FILE_OFFSET_BITS=64/_FILE_OFFSET_BITS=32/g' configure
        ./configure --prefix=.. $DISABLE $ENABLE --enable-pthreads --enable-cross-compile --cross-prefix="$ANDROID_BIN-" --ranlib="$ANDROID_BIN-ranlib" --sysroot="$ANDROID_ROOT" --target-os=linux --arch=atom --extra-cflags="-I../include/ $CFLAGS" --extra-ldflags="-L../lib/ -L$ANDROID_CPP/libs/x86/ $LDFLAGS" --extra-libs="-lgnustl_static $LIBS" --disable-symver --disable-programs
        make -j $MAKEJ
        make install
        ;;

     android-x86_64)
        export AR="$ANDROID_BIN-ar"
        export CPP="$ANDROID_BIN-cpp"
        export CC="$ANDROID_BIN-gcc"
        export CXX="$ANDROID_BIN-g++"
        export RANLIB="$ANDROID_BIN-ranlib"
        export STRIP="$ANDROID_BIN-strip"
        export CPPFLAGS="$ANDROID_FLAGS"
        export CFLAGS="$ANDROID_FLAGS"
        export CXXFLAGS="$ANDROID_FLAGS"
        export LDFLAGS="-Wl,--no-undefined -z text"
        export LIBS="-lgcc -ldl -lz -lm -lc"
        patch -Np1 < ../../../ffmpeg-android.patch
        ./configure --prefix=.. $DISABLE $ENABLE --enable-pthreads --enable-cross-compile --cross-prefix="$ANDROID_BIN-" --ranlib="$ANDROID_BIN-ranlib" --sysroot="$ANDROID_ROOT" --target-os=linux --arch=atom --extra-cflags="-I../include/ $CFLAGS" --extra-ldflags="-L../lib/ -L$ANDROID_CPP/libs/x86_64/ $LDFLAGS" --extra-libs="-lgnustl_static $LIBS" --disable-symver --disable-programs
        make -j $MAKEJ
        make install
        ;;
    *)

only arm fails

p.s. last lines from config.log:

/home/user/Android/Sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc -Wl,--no-undefined -Wl,--fix-cortex-a8 -z text -L../lib/ -L/home/user/Android/Sdk/ndk-bundle/sources/cxx-stl/gnu-libstdc++/4.9//libs/armeabi/ -Wl,--no-undefined -Wl,--fix-cortex-a8 -z text --sysroot=/home/user/Android/Sdk/ndk-bundle/platforms/android-19/arch-arm/ -march=armv7-a -o /tmp/ffconf.pWXlyIs5/test /tmp/ffconf.pWXlyIs5/test.o -lgnustl_static -lgcc -ldl -lz -lm -lc
/home/user/Android/Sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld: error: cannot find -lgnustl_static
collect2: error: ld returned 1 exit status
C compiler test failed.

it says error: cannot find -lgnustl_static

My OS: Linux 64 (Ubuntu 18.0), NDK: v17

solved I have to use NDK r15c instead of r17 to build for arm, though r17 works ok for other archs

Well, let's keep that opened since Google will apparently be removing GCC from in NDK r18:

  • GCC is no longer supported. It will be removed in NDK r18.

https://github.com/android-ndk/ndk/wiki/Changelog-r17

So we'll need to figure out something for that eventually.
Hopefully someone somewhere will keep GCC alive for Android...

Is there a solution for this on NDK r17? I'm getting the same issue with a javacpp project im working on.

the 64bit armv8 builds fine, but the armv-7a fails with this error

@zkrige these building scripts are supposed to work with NDK 15, no one at that time tested/optimized them for newer version of NDK, there is no need to downvote my comments, have some respect

It's done! Now all presets for Android get built with Clang from NDK r18b: http://bytedeco.org/builds/

There is no Gradle build for Android, if that's what you mean. It wouldn't be portable to any other platform, so I'm not going to spend time on this personally, but as usual contributions are welcome! Please send a pull request.

@saudet I see you have changed minimum API version from 14 to 21 in the script (for 32 cpu architectures) https://github.com/bytedeco/javacpp-presets/commit/9f279b604a6994d22cabefe9747011af31d1cfe8#diff-1e00f893b0beb998acb8357f4f0163a1R35
why so? or it doesn't matter and is it still going to work on 19 API for example? (19 - KitKat is still quite popular)

It might work, yes, could you give it a try? We need to cut somewhere at some point, so unless there is a good reason to not do it now, might as well be now. It only creates more maintenance for me to adjust the builds all the time, but again, if you have time to spend on this, any and all contributions are welcome!

Tested with script from https://github.com/IljaKosynkin/FFmpeg-Development-Kit to Build FFmpeg 4.0.3

I can't get it work on my KitKat device (19 API, armeabi-v7a) - failed: dlopen failed: cannot locate symbol "mmap64" referenced by "libavutil.so"... when I try to use it in my Android app

on Marshmallow (23 API, 'arm64-v8a') device it works ok

The tiny script to build FFmpeg 4.0.3 with Clang:

DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PARENT="$(dirname "${DIR}")"
NDK="$(dirname "${PARENT}")"
SYSROOT="$NDK/sysroot"
HOST="linux-x86_64"
LLVM_TOOLCHAIN="$NDK/toolchains/llvm/prebuilt/$HOST/bin"

CFLAGS="-O3 -fPIC"
LDFLAGS="-lc"

build () {
    ARCH=$1
    LEVEL=$2
    CONFIGURATION="--enable-cross-compile --disable-static --disable-programs --disable-doc --disable-htmlpages --disable-manpages --disable-podpages --disable-txtpages --enable-shared --disable-protocols --enable-protocol=file --enable-pic --disable-hwaccels --disable-parsers --disable-bsfs --disable-indevs --disable-outdevs --disable-devices --disable-filters --disable-network $3"
    LIB_FOLDER="lib"

    case $ARCH in
        "armeabi-v7a")
            TARGET="arm-linux-androideabi"
            CC_FLAGS="-target thumbv7-none-linux-androideabi -mfpu=vfpv3-d16 -mfloat-abi=soft"
            LDFLAGS="--fix-cortex-a8 $LDFLAGS"
            PLATFORM_ARCH="arm"
            TOOLCHAIN_FOLDER=$TARGET
        ;;
        "arm64-v8a")
            TARGET="aarch64-linux-android"
            CC_FLAGS="-target aarch64-none-linux-android -mfpu=neon -mfloat-abi=soft"
            PLATFORM_ARCH="arm64"
            TOOLCHAIN_FOLDER=$TARGET
        ;;
        "x86")
            TARGET="i686-linux-android"
            CC_FLAGS="-target i686-none-linux-androideabi -mtune=intel -mssse3 -mfpmath=sse -m32"
            PLATFORM_ARCH="x86"
            TOOLCHAIN_FOLDER=$PLATFORM_ARCH
        ;;
        "x86_64")
            TARGET="x86_64-linux-android"
            CC_FLAGS="-target x86_64-none-linux-androideabi -msse4.2 -mpopcnt -m64 -mtune=intel"
            PLATFORM_ARCH="x86_64"
            LIB_FOLDER="lib64"
            TOOLCHAIN_FOLDER=$PLATFORM_ARCH
        ;;
    esac

    TOOLCHAIN=$NDK/toolchains/$TOOLCHAIN_FOLDER-4.9/prebuilt/$HOST/bin

    CC=$LLVM_TOOLCHAIN/clang
    CXX=$LLVM_TOOLCHAIN/clang++
    AS=$CC

    AR=$TOOLCHAIN/$TARGET-ar
    LD=$TOOLCHAIN/$TARGET-ld
    STRIP=$TOOLCHAIN/$TARGET-strip

    PREFIX="android/$ARCH"

    ./configure --prefix=$PREFIX  \
                $CONFIGURATION \
                --ar=$AR --strip=$STRIP --ld=$LD --cc=$CC --cxx=$CXX --as=$AS \
                --target-os=android \
                --extra-cflags="$CC_FLAGS -I$SYSROOT/usr/include/$TARGET $CFLAGS" \
                --extra-ldflags="-L$NDK/toolchains/$TOOLCHAIN_FOLDER-4.9/prebuilt/$HOST/lib/gcc/$TARGET/4.9.x -L$NDK/platforms/android-$LEVEL/arch-$PLATFORM_ARCH/usr/$LIB_FOLDER $LDFLAGS" \
                --sysroot=$SYSROOT --extra-libs=-lgcc

    $NDK/prebuilt/$HOST/bin/make clean
    $NDK/prebuilt/$HOST/bin/make -j4
    $NDK/prebuilt/$HOST/bin/make install
}

build "armeabi-v7a" "19" "--disable-asm"
build "arm64-v8a" "21" "--disable-asm --disable-pthreads"
build "x86" "19"
build "x86_64" "21" "--disable-asm"

Well, version 1.4.4 has been released and it requires Android 5.0. I'm assuming use of KitKat has dropped dramatically over the holidays, so I'm not concerned about that :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Maurice-Betzel picture Maurice-Betzel  路  32Comments

mmanco picture mmanco  路  20Comments

blueberry picture blueberry  路  32Comments

blueberry picture blueberry  路  34Comments

kusaanko picture kusaanko  路  43Comments