Android, AOSP tree, external project (ffmpeg) is built for AMD64 - android

I'm trying to build ffmpeg4android on current AOSP tree (from /external), which is lunch-configured to aosp_arm-eng and set to PLATFORM_VERSION=4.2.
Resulting files are generated for AMD64 (host native) architecture, even though the major rest of tree is built (as expected) ARM:
readelf -a android/aosp_arm-eng/ffplay|egrep "Class:|Machine:"
Class: ELF64 Machine:
Advanced Micro Devices X86-64
versus
readelf -a
aosp/out/target/product/generic/symbols/system/lib/libril.so | egrep "Class:|Machine:"
Class: ELF32
Machine: ARM
I will probably switch to other ways of getting ffmpeg-arm (presumably the one described here); the reason of asking this question is to understand, at which build stage does cross-compilation environment breaks.

Related

Using 32 Bit Android SDK as User

I would like to compile Android Apps with SDK 23.0.3 as a user on CentOS. Unfortunately, everytime build-tools/23.0.3/aapt is run, it returns
bash: build-tools/23.0.3/aapt: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory
The problem seems to be that 32 bit libraries need to be installed. If I have sudo rights (on Ubuntu), I can run sudo apt install libc6-i386 lib32stdc++6 lib32gcc1 (like described in CentOS 64 bit bad ELF interpreter), but unfortunately, I do not have sudo on the machine where I would like to compile.
I assumed that I could get the used libraries (like described in https://www.cs.virginia.edu/~dww4s/articles/ld_linux.html) and then replace the used libraries by setting LD_LIBRARY_PATH (like described in http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html). I extracted the libraries by
ldd ../androidsdk/build-tools/23.0.3/aapt | \
grep "i386" | awk '{print $3}' | \
while read file
do cp $file .
done
and copied them to /home/test. Then I ran export LD_LIBRARY_PATH=/home/test, but then aapt returns the same error.
Another thing I tried was getting and extracting the libraries (on Ubuntu):
apt-get download libc6-i386 lib32stdc++6 lib32gcc1
for file in *.deb
do dpkg -x $file .
done
And aftwards setting the LD_LIBARY_PATH to /home/test/lib:/home/test/lib32, which also did not work.
This could be reproduced by a docker container: running docker run -it ubuntu bash and then
apt update && apt install git unzip wget openjdk-8-jdk
cd home/
wget https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip
unzip sdk-tools-linux-4333796.zip
cd tools/
yes | bin/sdkmanager --install "build-tools;23.0.3"
cd ..
For setup. Then, build-tools/23.0.3/aaptreturns
bash: build-tools/23.0.3/aapt: No such file or directory
which is the same problem as in the CentOS (Can not run android/sdk/build-tools/23.0.2/aapt): A 32 bit library is missing.
Can someone tell me what would be the correct way to add the libraries?
EDIT
Since the interpreter, normally /lib/ld-linux.so.2 starts interpreting files, it needs to be replaced. If I manually extract all .so-files like described above, put them in lib/ and run
LD_LIBRARY_PATH=$(pwd)/libs libs/ld-linux.so.2 build-tools/23.0.3/aapt
the aapt-command is executed correctly. Unfortunately, this is not enough for building:
LD_LIBRARY_PATH=/nfs/user/do820mize/workspaces/dissworkspace/androidsdk/libs /nfs/user/do820mize/workspaces/dissworkspace/androidsdk/libs/ld-linux.so.2 ./gradlew --init-script ../init.gradle assemble
returns the ELF-error again, since the gradle-wrapper (and Java and so on) are 64 bit binaries.
glibc.i686 is available from the base repository:
$ yum whatprovides ld-linux.so.2
glibc-2.17-260.el7.i686 : The GNU libc libraries
Repo : base
Matched from:
Provides : ld-linux.so.2
in case it should not be possible to have basic dependencies provided, that cluster is useless. of course it would need to be installed on all nodes; the chances that it would break something are rather slim, while having the same version number for the x86_64 version of the glibc library.
The problem is, that the header of the elf file (e.g. aapt) contains a link to the interpreter (e.g. /lib/ld-linux.2.so). This link needs to be replaced for execution, but only for the 32 bit elf-binaries. Gradle and Java still need to be executed with their regular 64 bit Interpreter. Since the processes that are called (e.g. aapt) are sub processes, calling another interpreter directly is not possible.
One possible solution is using patchelf (https://nixos.org/patchelf.html). First, it needs to be compiled (even if they say, that there is a binary, I did not find it):
wget https://nixos.org/releases/patchelf/patchelf-0.9/patchelf-0.9.tar.bz2
tar -xvf patchelf-0.9.tar.bz2
cd patchelf-0.9/
./configure && make
Afterwards, you'll find an patchelf executable in src/ (which was a rather surprising location for me).
Just add this to the path by PATH=$(pwd)/src:$PATH, get the ld-linux.so.2 from your system, save it to $MY_PLACE/libs/ld-linux.so.2, cd to your Android SDK and execute
patchelf --set-interpreter $MY_PLACE/libs/ld-linux.so.2 build-tools/23.0.1/aapt
patchelf --set-interpreter $MY_PLACE/libs/ld-linux.so.2 build-tools/23.0.1/aidl
patchelf --set-interpreter $MY_PLACE/libs/ld-linux.so.2 build-tools/23.0.1/zipalign
Then, you'll need to set the library path, e.g. by export LD_LIBRARY_PATH=$MY_PLACE/libs/. Afterwards ./gradlew assemble is running fine (for exactly this build tools version).
While this solution works, you'll need to edit every binary (which may be needed later) manually. I assume that there is some magic in multiarch systems which determines which interpreter to use, the 32 or 64 bit one (ldd will return different pathes for the interpreter depending on the file). It would be a better solution to make use of this magic in order to run 32 bit executables without root. Therefore, I'll accept a solution which make it possible to run builds by just changing environment variables and without tampering with the executables.

"dlopen failed: is 32-bit instead of 64-bit" in tests only

I'm having a set or Gradle modules that uses the core module based on c++ code:
Core (C++ with JNI glue, aar with libxyz-jni.so)
Tests (Android instrumentation tests)
App (regular Android app)
Core module includes native 32 bit libxyz-jni.so compiled for armeabi-v7a and x86 and is compiled to aar. It does not have arm64 libraries.
App module depends on Core and is working on arm64 hardware device without any issues (is able to load libxyz-jni.so)
Tests depends on Core and fails to load libxyz-jni.so (with System.loadLibrary(..)) with following error:
java.lang.UnsatisfiedLinkError: dlopen failed: "/data/app/package.tests.test-2/lib/arm/libxyz-jni.so" is 32-bit instead of 64-bit.
I've checked tests apk not to contain any arch except armeabi-v7a and x86. The tests can run in android emulator but can't on 64 bit hardware device with Android Nougat. The App can run on arm64 device.
That's the difference between tests and app in terms of loading library?
You should check to see what libraries your app is using at runtime. You can do this with these commands:
# get your running pid
adb shell ps | grep <your package name> | tr -s ' ' | cut -d ' ' -f 2
32333
adb shell lsof | grep 32333 | grep so
.xxx 32333 u0_a222 mem REG 259,30 133152 2629 /system/lib64/libcompiler_rt.so
.xxx 32333 u0_a222 mem REG 259,30 30824 2759 /system/lib64/libmemalloc.so
As you can see in this case Android has loaded lib64 libraries. If you want it to default to loading 32-bit libraries, you need to have lib/armeabi-v7a/lib.so in your APK.
If you have your libraries somewhere else in the APK, and you extract, and load dynamically, Android won't know they are 32bit.

How can mercurial be run on android?

This page documents running an old version (1.8.4) of mercurial but says
"(later versions need an unavaliable python module named grp)"
This is the way I did it (but am still interested to hear of alternative ways) using an Ubuntu 16.04 machine and a intel 64bit android emulator running on Windows 7, using mercurial 3.7.3
Using an Ubuntu system, follow these instructions for creating 2.7 version of python capable of running hg.
Copy python onto android device into an app files directory (so it can be executed)
on windows host
adb push python279.x86_64 /sdcard
adb -e shell
on android device
cd /data/user/0/$SOMEAPPDIR/files
cp -Rav /scard/python279.x86_64 .
make python excutable
chmod +x python279.x86_64/bin/python2.7
set some env vars need to make python run on android
export LD_LIBRARY_PATH=/data/user/0/$SOMEAPPDIR/files/python279.x86_64/lib
export LD_PRELOAD=libffi.so:libbz2.so
export PATH=$PATH:/data/user/0/$SOMEAPPDIR/files/python279.x86_64/bin
Python should now be able to be run with python2.7
Build mercurial on Ubuntu host.
download mercurial 3.7.3
uz mercurial-3.7.3.tar.gz
cd mercurial-3.7.3 && make all
HOME=$PWD/dist make install
Make minor modifications
cd dist/mercurial-3.7.3/dist/lib/python/mercurial
rm *.so
cp pure/*.py .
Edit posix.py and delete the "import grp" line.
copy mercurial onto android device
on windows host
adb push dist /sdcard
adb -e shell
on android device
cd /data/user/0/$SOMEAPPDIR/files
cp /sdcard/dist .
alias hg to make it easy to use
alias hg='python2.7 /data/user/0/$SOMEAPPDIR/files/dist/bin/hg'
Hg should now be possible to use on android device.
It's even possible to clone remote repos but I also had to pass the --insecure flag to bypass ssl errors.
The answer made on "Feb 15 '17" works fine however there is one fairly big drawback.
This answer address this drawback and is intended to be used in conjunction with the previous answer.
The problem
This procedure:
rm *.so
cp pure/*.py .
removes the native libraries and uses the python 'pure' implementation of these libraries instead. This causes major performance problem when working with large repositories, especially on slower android devices.
The solution
Cross compiling mercurial with android ndk, produces native libraries that can be used on android.
I've added some helper scripts to a mercurial 4.8.2 fork to make cross compiling easier.
Linux instructions:
Clone the repo
hg clone https://bitbucket.org/hindlemail/hg-stable-android/
update to 331892efe015
hg update -r 331892efe015
Set these for environment variables with appropriate values:
provide location of android NDK
ANDROID_NDK="$HOME/Android/android-ndk-r13b"
specify build arch - (armeabi, x86, x86_64, arm64)
ARCH="armeabi"
specify target android sdk verison
PLATFORM="android-22"
specify output of cross compiled python.
(see answer from Feb 15 '17" for more info )
PYTHONDIR="/usr/local/android/install/python279.arm22"
Run crosscompile.sh

Google's shipping 64-bit SDK stuff by default now?

I'm just starting to use Android Studio on Linux, spent almost a year getting it working, yesterday I did some tutorials then did some downloads with sdk manager. Now my ADB doesn't work anymore. Big surprise, my ADB executable is now dated today, and fastboot, etc. So I checked with the "file" utility and:
file adb
adb: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically
linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.24,
BuildID[sha1]=90addc5e3980f6efab749c9032cc8d7ad60dfb94, not stripped
file fastboot
fastboot: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV),
dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux
2.6.24, BuildID[sha1]=f0fd57bfe0c22d4ba1e0b3e211441162066433b4, not stripped
file dmtracedump
dmtracedump: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV),
dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux
2.6.24, BuildID[sha1]=86871b6d114d9f8f9f0263d061cd9db8eb8886b7, not stripped
file sqlite3
sqlite3: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically
linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.24,
BuildID[sha1]=68c2ef312f09631815b20ecbc5dce2669e350807, not stripped
You mean to tell me Google can't afford to keep a 32-bit build machine? I can't run 64 bit on my computers. Maybe it was an accident. This was apparently Platform-tools 23.1. I had it working for 1 day, grrr.
Copied in a tarball of platform_tools 22.x from another machine, seems to be working so far. I couldn't even bring up the emulator, that also uses ADB to communicate with it.
Under System Requirements (http://developer.android.com/sdk/index.html#Requirements) you can find:
Tested on UbuntuĀ® 14.04, Trusty Tahr (64-bit distribution capable of
running 32-bit applications).
If you want to keep compatibility to whatever your architecture and platform is perhaps you should use https://packages.debian.org/sid/android-tools-adb which may have older versions but perhaps enough to what you are trying to acieve.

Running the Android SDK on ARM-netbook (Ubuntu)

I'm trying to install an Android developement environment (JDK+SDK+Eclipse+Plugins) on my Toshiba AC100 (ARM architecture), but
http://developer.android.com/sdk/index.html
says the SDK is only available for x86 architecture. Does anyone have an idea how to get it running on my device? I'm using Ubuntu 11.10.
based on TerminalIDE chrooted arm env for compilling APK on android devices,
there is maybe a way to isolate compiller binaries to run under linux-arm
I'll try, if I'm able, I will let you known ....
But you will have notepad/eclipse // cmd line compillation (you could make an ant env or some not ugly .sh)
ok, a bit more ....
(based on terminal ide env & w32 env)
You'll need jdk (arm) then
aapt (is a binary so needs to find its sources ;( but it's just required to create R.java (resource id manager) -- if you project to make a cli program : it is not mandatory...) | ;( |
dx is a JVM script : that calls a pure java jar (w32 uses dx.jar from sdk) | ;) |
apkbuilder is a JVM script : that calls a pure java jar (w32 uses sdklib.jar from sdk) | ;) |
javac is the classical javac but add android.jar to its classpath (I recommend the API-8 froyo version to be most compatible) | ;) |

Categories

Resources