Manually compile C code with command line to run on Android - android

I want to compile some C code manually in order to run it on Android. The C code can be as simple as this hello world program:
#include<stdio.h>
int main() {
printf("Hello World\n");
return 0;
}
The result should be an executable binary file, which I can run with adb like this:
adb push exename /data/local/tmp
adb shell chmod 777 /data/local/tmp
adb shell /data/local/tmp
I am able to create such an executable with Android Studio and the NDK. To better understand the compiling process I want to know how I can manually compile the code with the command line. I know that there are different ABIs that are compiled with different tools, but the process should still be the same.
I am pretty sure it is possible as the NDK includes multiple executables like aarch64-linux-android-as, which allows me to compile Assembly to an executable. Unfortunately, I could not find any documentation of all tools included in the NDK in order to find out which is the correct tool myself.
The question now is if someone knows which tools of the NDK I have to use in order to create an executable from my provided C code. If the process for compiling multiple .c files into one binary is different from gcc I would also appreciate the process of compiling multiple files.
Thank you very much in advance!

~/Library/Android/sdk/ndk/24.0.8215888/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang --target=aarch64-linux-android21 helloworld.c -o helloworld

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.

Compile in Fedora and run on Android

Is it possible to compile a c code in Fedora and to run it on Android with gcc? I tried to compile using gcc file.c -o f1 and it didn't work. Any seggustions? I was unable to execute it with ADB tool.
If your c code is run in terminal, you can simple cross compile it and push the executable file to your phone by using ADB tools.
get a cross compiler
download a cross compiler, for example:
http://www.mentor.com/embedded-software/sourcery-tools/sourcery- codebench/editions/lite-edition/
you can build android develop environment from:
http://source.android.com/source/building.html
use arm-eabi-gcc for compiling your c code , generate executable file ie. a.out
adb push a.out /sdcard, chmod 777, then you can run it from adb shell

running the NDK native-activity sample from a command-line IDE

similar questions have been asked:
How to run NDK samples?
Making Android NDK apps with NativeActivity?
I've got the command-line documentation down to the point where I can create an empty Android project, I do not know how to build-install-run the NDK examples, particularly the NativeActivity one, in a non-Eclipse build environment (Ubuntu 10.0.04).
So my questions are
does the NativeActivity example "just work" or do you have to do something besides just $adb -d shell "am start -a android.intent.action.MAIN -n com.example.nativeActivity"?
How do you build, install, run the NativeActivity example?
I can't answer about this specific example. But here's the general process for building and installing an Android application which uses the NDK.
cd to the root of its source code.
Run ndk-build. This builds the native code, and should result in some .so files being put into the libs directory.
android update project --path . --name something
ant debug (or similar). This will build the Java code and create an .apk. Crucially, the build process will pick up the .so files left within the libs directory and include them into the .apk.
adb install bin/name-of-project.apk
Then launch as normal using the Android GUI or using an am start command such as you give.

Android link .so for command line executable?

I am developing a cross-platform library, and am trying to test on Android. I have compiled my library with ndk-build, and am trying to compile and run a command-line test fixture we have for the library.
I use adb push to put the test fixture and .so in /data/local/tmp and chmod both to 777.
Then I use adb shell to run the test, but get the following error
shell#android:/data/local/tmp $ ./mytest
./mytest
link_image[1936]: 7289 could not load needed library 'libtconfig.so' for './mytest' (load_library[1091]: Library 'libtconfig.so' not found)CANNOT LINK EXECUTABLE
Both mytest executable and libtconfig.so are in the same directory. I would have assumed it looks in "." directory first?
I found I can add the path /data/local/tmp to LD_LIBRARY_PATH and it will work, however when using adb shell commands in a script, each "adb shell" is a new instance, so LD_LIBRARY_PATH is reset

NDK build error with cygwin

i am tying to build a tesseract project to use as a library for my project. I am getting this error with cygwin when trying to build on windows 7 with User Account Controls turned off.
$ /cygdrive/c/android-ndk-r8/ndk-build
SharedLibrary : liblept.so
C:/android-ndk-r8/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld.exe: ./obj/local/armeabi/libgnustl_static.a: No such file: Permission denied
collect2: ld returned 1 exit status
/cygdrive/c/android-ndk-r8/build/core/build-binary.mk:369: recipe for target `obj/local/armeabi/liblept.so' failed
make: *** [obj/local/armeabi/liblept.so] Error 1
please let me know what i should do to build the project.
Sorry It's my first time answering a question.
I was having a same issue as yours.
Then I solve it using cygwin bash with command: $ chmod -R 777 /cygdrive/c/android/workspace
C:/Android/workspace is my Eclipse work space.
Some one here gave me the insight
A lot of people have struggled with compiling tesseract under Windows, and Cygwin is normally suggested, however its often not necessary.
Have you tried looking at the tess-two project on github? Its tesseract wrapped with some handy android classes, compiling a running is simply a case of :
git clone git://github.com/rmtheis/tess-two tess
cd tess
cd tess-two
ndk-build
android update project --path .
ant release
I've been able to compile the above on 3 windows7 machines, a mac, and ubuntu without any issues.
if you're developing under windows, go to the file, and change it's premissions to full control.
it will be in /obj dir

Categories

Resources