Перекомпиляция Android библиотек под х86. JavaCV и Alljoyn

от автора

Android смартфоны на базе процессоров Intel Atom уже перестали быть экзотикой, и тема оптимизации библиотек и приложений под х86 платформу перешла из теоретической плоскости в чисто практическую: софт, одинаково хорошо работающий и на ARM, и на х86 в конечном счете будет иметь преимущество перед тем, что оптимизирован только под одну архитектуру. В связи с этим мы посчитали полезным перевести две статьи инженера Intel Ксавьера Халада (Xavier Hallade), описывающие практические примеры перекомпиляции Android библиотек под х86.

Получение х86 версии JavaCV под Android

JavaCV представляет собой обертку (wrapper) для библиотек OpenCV и ffmpeg. В то время как эти библиотеки отлично совместимы с х86 версией Android, JavaCV не имеет соответствующих скриптов сборки и не интегрирован в бинарники х86.
Хотя компиляция подходящих х86 версий пакетов JavaCV и не займет много времени, для самых торопливых сразу же приведем ссылки:

Теперь давайте посмотрим, что нам потребовалось для сборки. Вам понадобятся традиционные средства сборки (gcc, make, …), а также maven.
Для начала необходимо перекомпилировать cppjars

Перекомпилирование cppjars (OpenCV и ffmpeg)

Этого легко достичь, используя скрипты сборки, прилагаемые к пакету cppjars:

wget https://javacv.googlecode.com/files/javacv-0.7-cppjars.zip unzip javacv-0.7-cppjars.zip cd javacv-cppjars 

Скрипты сборки для Android: build_opencv-android-arm.sh и build_ffmpeg-android-arm.sh. Нам нужно создать эквивалентные build_opencv-android-x86.sh и build_ffmpeg-android-x86.sh. Для этого в -х86 копиях заменим:

  • arm-linux-androideabi- на i686-linux-android- (префикс бинарника toolchain)
  • arm-linux-androideabi- на x86- (toolchain)
  • -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mfpu=neon… на -mtune=atom -mssse3 -mfpmath=sse (флаги компилятора)
  • arm-linux на i686-linux
  • прочие суффиксы -arm на -x86

Не делайте этого вслепую – все будет работать лучше, если вы понимаете, что делаете 🙂

Вот что в результате у меня получилось в файле build_ffmpeg-android-x86.sh:

ANDROID_BIN=$ANDROID_NDK/toolchains/x86-4.8/prebuilt/linux-x86_64/bin ANDROID_ROOT=$ANDROID_NDK/platforms/android-14/arch-x86 tar -xjvf ffmpeg-$FFMPEG_VERSION.tar.bz2 mv ffmpeg-$FFMPEG_VERSION ffmpeg-$FFMPEG_VERSION-android-x86 cd ffmpeg-$FFMPEG_VERSION-android-x86 tar -xjvf ../last_stable_x264.tar.bz2 X264=`echo x264-snapshot-*` cd $X264 ./configure --enable-static --enable-pic --disable-cli --disable-opencl --cross-prefix=$ANDROID_BIN/i686-linux-android- --sysroot=$ANDROID_ROOT --host=i686-linux --extra-cflags="-fpic -pipe -DANDROID -DNDEBUG -mtune=atom -mssse3 -ffast-math -mfpmath=sse -fomit-frame-pointer -fstrict-aliasing -funswitch-loops -finline-limit=300" --extra-ldflags="-lm -lz -Wl,--no-undefined -Wl,-z,noexecstack" make -j8 cd ../ patch -p1 < ../ffmpeg-$FFMPEG_VERSION-android-x86.patch ./configure --prefix=$ANDROID_NDK/../ --enable-shared --enable-gpl --enable-version3 --enable-libx264 \  --disable-static --disable-symver --disable-doc --disable-ffplay --disable-ffmpeg --disable-ffprobe --disable-ffserver --disable-encoders --disable-muxers --disable-devices --disable-demuxer=sbg --disable-demuxer=dts --disable-parser=dca --disable-decoder=dca --disable-decoder=svq3 --enable-network --enable-version3 --disable-amd3dnow --disable-amd3dnowext --disable-outdev=sdl\  --extra-cflags="-I$X264" --extra-ldflags="-L$X264" --enable-cross-compile --cc=$ANDROID_BIN/i686-linux-android-gcc --sysroot=$ANDROID_ROOT --target-os=linux --arch=x86 --cpu=i686 \ --enable-asm --enable-yasm --enable-pic --extra-cflags="-DANDROID -DNDEBUG -fPIC -pipe -mtune=atom -mssse3 -ffast-math -mfpmath=sse" \ --extra-ldflags="-lm -lz -Wl,--no-undefined -Wl,-z,noexecstack" --disable-stripping --disable-symver --disable-programs  make -j8 LIBS="libavcodec/libavcodec.so libavdevice/libavdevice.so libavfilter/libavfilter.so libavformat/libavformat.so libavutil/libavutil.so libpostproc/libpostproc.so libswresample/libswresample.so libswscale/libswscale.so" $ANDROID_NDK/toolchains/x86-4.8/prebuilt/linux-x86_64/bin/i686-linux-android-strip $LIBS mkdir -p com/googlecode/javacv/cpp/android-x86/ cp $LIBS com/googlecode/javacv/cpp/android-x86/ jar cvf ../ffmpeg-$FFMPEG_VERSION-android-x86.jar com/ rm -Rf com/ cd ../ 

Здесь ffmpeg-$FFMPEG_VERSION-android-x86.patch точно тот же самый, что и в arm версии, можете его просто скопировать.
А вот файл build_opencv-android-x86.sh:

tar -xzvf opencv-$OPENCV_VERSION.tar.gz mkdir opencv-$OPENCV_VERSION/build_android-x86 cd opencv-$OPENCV_VERSION cd build_android-x86 ANDROID_BIN=$ANDROID_NDK/toolchains/x86-4.6/prebuilt/linux-x86_64/bin/ \ ANDROID_CPP=$ANDROID_NDK/sources/cxx-stl/gnu-libstdc++/4.6/ \ ANDROID_ROOT=$ANDROID_NDK/platforms/android-9/arch-x86/ \ cmake -DCMAKE_TOOLCHAIN_FILE=platforms/android/android.toolchain.cmake -DANDROID_ABI=x86 -DOPENCV_EXTRA_C_FLAGS="-O3 -ffast-math -mtune=atom -mssse3 -mfpmath=sse" -DOPENCV_EXTRA_CXX_FLAGS="-O3 -ffast-math -mtune=atom -mssse3 -mfpmath=sse" -DCMAKE_INSTALL_PREFIX=$ANDROID_NDK/../ -DBUILD_SHARED_LIBS=ON -DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=OFF -DBUILD_ANDROID_EXAMPLES=OFF -DBUILD_JASPER=ON -DBUILD_JPEG=ON -DBUILD_OPENEXR=ON -DBUILD_PNG=ON -DBUILD_TBB=ON -DBUILD_TIFF=ON -DBUILD_ZLIB=ON -DBUILD_opencv_java=OFF -DBUILD_opencv_python=OFF -DENABLE_PRECOMPILED_HEADERS=OFF -DWITH_1394=OFF -DWITH_FFMPEG=OFF -DWITH_GSTREAMER=OFF -DWITH_TBB=ON -DWITH_CUDA=OFF -DWITH_OPENCL=OFF .. make -j8 LIBS="lib/x86/libopencv*.so lib/x86/libtbb.so" $ANDROID_NDK/toolchains/x86-4.6/prebuilt/linux-x86_64/bin/i686-linux-android-strip $LIBS mkdir -p com/googlecode/javacv/cpp/android-x86/ cp $LIBS com/googlecode/javacv/cpp/android-x86/ jar cvf ../../opencv-$OPENCV_VERSION-android-x86.jar com/ rm -Rf com/ cd ../../ 

Здесь я удалил вызов -arm патча, который генерировал другой android.mk файл и положился на platforms/android/android.toolchain.cmake, предоставляемый OpenCV, а также добавил некоторые специфичные флаги для большей оптимизации:

-DANDROID_ABI=x86 -DOPENCV_EXTRA_C_FLAGS="-O3 -ffast-math -mtune=atom -mssse3 -mfpmath=sse" -DOPENCV_EXTRA_CXX_FLAGS="-O3 -ffast-math -mtune=atom -mssse3 -mfpmath=sse" 

Теперь если вы выполните:

sh ./build_all.sh android-x86 cd .. 

То получите ffmpeg-2.1.1-android-x86.jar и opencv-2.4.8-android-x86.jar.
Теперь мы, наконец, можем собрать пакет JavaCV.

Сборка х86 версии JavaCV

Сначала скачайте и установите JavaCPP:

git clone https://code.google.com/p/javacpp/ cd javacpp/ git checkout 0.6 mvn install cd .. 

После скачайте исходники JavaCV:

git clone https://code.google.com/p/javacv/ cd javacv git checkout 0.7 

Теперь вы можете собрать android-x86 версию JavaCV, установив свойство android-x86 в JavaCPP:

mvn package -Pffmpeg -Djavacpp.options="-properties android-x86 -Dplatform.root=$ANDROID_NDK -Dcompiler.path=$ANDROID_NDK/toolchains/x86-4.6/prebuilt/linux-x86_64/bin/i686-linux-android-g++ -Dcompiler.includepath=$ANDROID_NDK/sources/cxx-stl/gnu-libstdc++/4.6/include\ :$ANDROID_NDK/sources/cxx-stl/gnu-libstdc++/4.6/libs/x86/include\ :../javacv-cppjars/opencv-2.4.8/build_android-x86/\ :../javacv-cppjars/opencv-2.4.8/modules/core/include\ :../javacv-cppjars/opencv-2.4.8/modules/androidcamera/include\ :../javacv-cppjars/opencv-2.4.8/modules/flann/include\ :../javacv-cppjars/opencv-2.4.8/modules/imgproc/include\ :../javacv-cppjars/opencv-2.4.8/modules/highgui/include\ :../javacv-cppjars/opencv-2.4.8/modules/features2d/include\ :../javacv-cppjars/opencv-2.4.8/modules/calib3d/include\ :../javacv-cppjars/opencv-2.4.8/modules/ml/include\ :../javacv-cppjars/opencv-2.4.8/modules/video/include\ :../javacv-cppjars/opencv-2.4.8/modules/legacy/include\ :../javacv-cppjars/opencv-2.4.8/modules/objdetect/include\ :../javacv-cppjars/opencv-2.4.8/modules/photo/include\ :../javacv-cppjars/opencv-2.4.8/modules/gpu/include\ :../javacv-cppjars/opencv-2.4.8/modules/nonfree/include\ :../javacv-cppjars/opencv-2.4.8/modules/contrib/include\ :../javacv-cppjars/opencv-2.4.8/modules/stitching/include\ :../javacv-cppjars/opencv-2.4.8/modules/ts/include\ :../javacv-cppjars/opencv-2.4.8/modules/videostab/include\ :../javacv-cppjars/ffmpeg-2.1.1-android-x86 \ -Dcompiler.linkpath=$ANDROID_NDK/sources/cxx-stl/gnu-libstdc++/4.6/libs/x86\ :../javacv-cppjars/opencv-2.4.8/build_android-x86/lib/x86\ :../javacv-cppjars/ffmpeg-2.1.1-android-x86/libswscale\ :../javacv-cppjars/ffmpeg-2.1.1-android-x86/libavcodec\ :../javacv-cppjars/ffmpeg-2.1.1-android-x86/libswresample\ :../javacv-cppjars/ffmpeg-2.1.1-android-x86/libpostproc\ :../javacv-cppjars/ffmpeg-2.1.1-android-x86/libavfilter\ :../javacv-cppjars/ffmpeg-2.1.1-android-x86/libavformat\ :../javacv-cppjars/ffmpeg-2.1.1-android-x86/libavutil\ :../javacv-cppjars/ffmpeg-2.1.1-android-x86/libavdevice" 

Вы найдете собранные пакеты в папке target/:

2.7M Jan 15 19:09 javacv-android-x86.jar 3.6M Jan 15 19:09 javacv-bin.zip 747K Jan 15 19:09 javacv-src.zip 734K Jan 15 19:09 javacv.jar 

Добавление х86 версии в ваше приложение

Из пакетов, скачанных по ссылкам в начале статьи или из тех, что вы только что собрали, вы можете скопировать сгенерированные файлы .so, находящиеся внутри javacv-android-x86.jar, ffmpeg-2.1.1-android-x86.jar и opencv-2.4.8-android-x86.jar в папку /lib/x86/ вашего Android пакета, точно так же, как и arm версии в папку /lib/armeabi-v7a/.

х86 версия Alljoyn для Android

Alljoyn – это кросс-платформенная библиотека для peer-to-peer связи между различными устройствами с использованием различных транспортов.
Библиотека имеет открытый исходный код (лицензия Apache), изначально она создана в Qualcomm Innovation Center. Проект присоединился к AllSeen Alliance и теперь хостится здесь.
Даже в том случае, если прекомпилированная х86 версия отсутствует на официальном вебсайте, компилирование из исходников прекрасно поддерживается.
Когда вы скачаете пакет под Android, то увидите следующее:

cpp/    core AllJoyn functionality, implemented in C++           - built from Git projects alljoyn_core and common           - required for all AllJoyn applications java/   optional Java language binding          (built from alljoyn_java)           - required for Android apps c/      optional ANSI C language binding        (built from alljoyn_c)           - required by Unity binding unity/  optional Unity language binding         (built from alljoyn_unity) about/  implements AllJoyn About Feature. (built from about.git/(cpp and java)) 

Если вы используете Java обвязку alljoyn.jar, то обнаружите liballjoyn_java.so в каталоге lib/armeabi/. Бинарники (файлы .so/.a) из этого пакета предназначены только для ARMv5, но отлично собираются из исходников под другие платформы.
По этой ссылке вы можете скачать х86 версию, которую я скомпилировал для вас. Она имеет ту же архитектуру, что и версия для ARMv5.
Если вы просто используете AllJoyn .jar под Android, вы можете взять liballjoyn_java.so и поместить его в каталог lib/x86 вашего Android приложения.
Если же вы желаете сами скомпилировать бинарник и узнать больше об этом процессе, вот описание того, что я сделал.

Компиляция Alljoyn для x86 платформы под Android

Первым делом скачайте исходники:

git clone https://git.allseenalliance.org/gerrit/core/alljoyn cd alljoyn 

Затем возьмите libcrypto.so и libssl.so с реального x86 устройства или x86 эмулятора и поместите их в папку build/android/x86/release/dist/cpp/lib/:

mkdir -p build/android/x86/release/dist/cpp/lib/ adb pull /system/lib/libcrypto.so build/android/x86/release/dist/cpp/lib/ adb pull /system/lib/libssl.so build/android/x86/release/dist/cpp/lib/ 

Теперь вы можете собрать библиотеку для х86, как описано в документации; самое скучное в этом процессе – необходимость иметь копию исходников AOSP:

export CLASSPATH=/usr/share/java/junit.jar scons OS=android CPU=x86 ANDROID_NDK=/opt/android-ndk ANDROID_SDK=/opt/android-sdk ANDROID_SRC=/home/ph0b/android-build VARIANT=release BINDINGS=cpp,c,java,unity 

Оригиналы статей:

ссылка на оригинал статьи http://habrahabr.ru/company/intel/blog/219581/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *