How to compile C code using NDK for Android Device (ARM)? - c

I need to perform the following steps:
write a simple counter that keeps resetting itself after overflow in C/C++
compile and push that code into the phone via ADB
run it as a regular executable in background via ADB shell
how to compile the above C code using NDK toolchain? I found a couple of similar links but none of them give simple and complete steps to do so.
If there is a link with complete steps please do refer me to the same.
Compile Environment: Ubuntu, compile should be done via console not any IDE

You're right, I made a mistake, I had not even tested it and gave me the
same error, is due to the entry point of the "main", as this has not
changed but I hope this works for you. Anyway check the symbol table "nm",
the real-time execution "strace", you can even use gdbserver.
#include <stdio.h>
int main (int argc, char *argv[])
{
printf ("hello world");
return 0;
}
export NDK_ROOT=your_ndk_path
export PATH=$NDK_ROOT/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86/bin:$PATH
export CC=arm-linux-androideabi-gcc
export LD=arm-linux-androideabi-ld
arm-linux-androideabi-gcc -I$NDK_ROOT/platforms/android-18/arch-arm/usr/include -Wl,-rpath-link=$NDK_ROOT/platforms/android-18/arch-arm/usr/lib -Wl,-L$NDK_ROOT/platforms/android-18/arch-arm/usr/lib -Wl,-lc -o test test.c
If ld return with erros like "... ld: error: cannot open... : No such file or directory"
try this for your losed files:
ln -s $NDK_ROOT/platforms/android-18/arch-arm/usr/lib/crtend_android.o
ln -s $NDK_ROOT/platforms/android-18/arch-arm/usr/lib/crtbegin_dynamic.o

I use gcc4.8 and android API-level18
usin this you can try:
First way using command line.
export NDK_ROOT=your_ndk_path
export PATH=$NDK_ROOT/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86/bin:$PATH
export CC=arm-linux-androideabi-gcc
export LD=arm-linux-androideabi-ld
export CPPFLAGS=-I$NDK_ROOT/platforms/android-18/arch-arm/usr/include
export CFLAGS="-nostdlib" LDFLAGS="-Wl,-rpath-link=$NDK_ROOT/platforms/android-18/arch-arm/usr/lib/ -L$NDK_ROOT/platforms/android-18/arch-arm/usr/lib"
export LIBS="-lc"
arm-linux-androideabi-gcc -nostdlib -o test test.c
If run "file test" you should see this:
test: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, not stripped
Second way using autotools.
export PATH=$NDK_ROOT/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86/bin:$PATH
./configure --host=arm-linux-androideabi CC=arm-linux-androideabi-gcc LD=arm-linux-androideabi-ld CPPFLAGS="-I$NDK_ROOT/platforms/android-18/arch-arm/usr/include" CFLAGS="-nostdlib" LDFLAGS="-Wl,-rpath-link=$NDK_ROOT/platforms/android-18/arch-arm/usr/lib/ -L$NDK_ROOT/platforms/android-18/arch-arm/usr/lib" LIBS="-lc"
make
http://embelinux.blogspot.com/2013/09/autotools1-hola-mundo-la-autotools.html
Third way using android developers ndk full feature.
Read Android.mk file syntax specification. This document describes the
syntax of Android.mk build file written to describe your C and C++ source
files to the Android NDK.
http://www.kandroid.org/ndk/docs/ANDROID-MK.html

gdbserver is to debug an application running on the Android device and can
control gdb from the PC using a TCP connection. gdb (The GNU Debugger)
need the debugging symbols.
When you compile an application the compiler puts all the symbols defined
in something called as symbol table, the problem was not link to rtbegin_dynamic.o,
crtend_android.o that if you specify -nostdlib option the program is created but no work (Table Simbol empty)
nm (list symbols from object files) eg: nm test
gcc is not a compiler, it is a driver that controls the execution
of other applications that are what make the job
for example try invoque the compiler using -### as unique option for see details
LDFLAGS: are the flags for the linker
CFLAGS: are the flags to the compiler (not links)
Anyway if you are new to the compilation, even in cross compiling strongly
recommend you use the Android.mk way
Sorry for my English ;)

#Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
#module name
LOCAL_MODULE := test
#src
LOCAL_SRC_FILES := test.c
#build executable
include $(BUILD_EXECUTABLE)
export PATH=path_to_ndk_root:$PATH
export NDK_PROJECT_PATH=.
ndk-build APP_BUILD_SCRIPT=Android.mk

Related

How to use the hidapi library from Signal11?

I installed the hidapi library from Signall11 on my windows10 pc (using minGW). But now I'm having some trouble actually getting it to work with gcc. I have some main.c file in which I include the hidapi.h file. My gcc command looks like
gcc main.c
I'm not sure where I'm going wrong because whenever I try to run this command I get an undefined reference error to some function that is defined in the hidapi.h file.
A full compile command for a project using hidapi is like this:
gcc -o your_app your_app.c -lhidapi-hidraw
It's not enough to include #include "hidapi.h" in the C-code, which does let gcc compile. You also need -lhidapi-hidraw to link with the library. I.e. compiling is in fact a 2 step process.

Issue cross-compiling apr-1.5.2 for ARM

I am trying to cross compile Apache Portable Run-time library APR-1.5.2 lib for ARM platform. I am following below steps.
./configure --host=aarch64-unknown-linux-gnu CC=aarch64-unknown-linux-gnu-gcc
make
I am not getting any error in configure and make but when i try to link it to my code i am getting linking error.
#include <iostream>
#include <stdio.h>
using namespace std;
#include "apr_general.h"
#include "apr_network_io.h"
#include "apr_strings.h"
int main(){
apr_initialize();
std::cout<<"Welcome Program compiling "<<std::endl;
return 0;
}
When i am compiling the code using cross compiler getting error.
aarch64-unknown-linux-gnu-g++ -o Test -I ../../../../Static_APR/apr-1.5.2/include DAS.cpp ../../../../Static_APR/apr-1.5.2/.libs/libapr-1.a -lpthread
**apr-1.5.2/.libs/libapr-1.a(start.o): Relocations in generic ELF (EM: 62)**
Code compiles fine with g++.
g++ -o Test -I ../../../../Static_APR/apr-1.5.2/include DAS.cpp ../../../../Static_APR/apr-1.5.2/.libs/libapr-1.a -lpthread
Why APR lib didn't built for arm (cross compiler) even though i have used CC=aarch64-unknown-linux-gnu-gcc
Can anyone help me with correct way to build APR for cross compilation?
I am following below steps.
./configure --host=aarch64-unknown-linux-gnu CC=aarch64-unknown-linux-gnu-gcc
make
Your ./configure should include a --build. --host is the machine you are compiling for. Also see How To Configure for Android? on the Autoconf mailing list. Maybe something like:
export CPP=aarch64-unknown-linux-gnu-cpp
export CC=aarch64-unknown-linux-gnu-gcc
export CXX=aarch64-unknown-linux-gnu-g++
export LD=aarch64-unknown-linux-gnu-ld
export AR=aarch64-unknown-linux-gnu-ar
export AS=aarch64-unknown-linux-gnu-as
export RANLIB=aarch64-unknown-linux-gnu-ranlib
export CFLAGS="..."
export CXXFLAGS="..."
./configure --build=`config.guess` --host=aarch64-unknown-linux-gnu
The snippet above should ensure all the tools are available. You may need to add CFLAGS and CXXFLAGS with the appropriate header location; and an LDFLAGS with the appropriate library location.
You should verify the program for RANLIB. Its may not be what you think. For example, on one version of Ubuntu for ARM it is:
export RANLIB=aarch64-unknown-linux-gcc-ranlib-4.7
You may need to find config.guess:
$ find /usr -name 'config.guess'
/usr/lib/rpm/redhat/config.guess
/usr/share/automake-1.15/config.guess
...
Finally, you might find these scripts useful. They help build another library by setting paths and setting tools: setenv-android.sh and setenv-embedded.sh.

eCos : Compile and Run sample application on Linux

I have installed eCos OS on a linux system (Ubuntu 13.02). After installation, the eCos files are located in opt/ecos.
As I read the eCos tutorial, I see hello.c is stored in opt/ecos/ecos-3.0/examples/hello.c (And I notice that maybe all main eCos system files store in the ecos-3.0 directory).
I have followed the eCos tutorial found on the official website, but I still cannot successfully compile hello.c.
More detail. When I try to run :
$ export INSTALL_DIR=BASE_DIR/ecos-work/arm_install
$ TARGET-gcc -g -IBASE_DIR/ecos-work/install/include hello.c \
-LBASE_DIR/ecos-work/install/lib -Ttarget.ld -nostdlib
I get the error : TARGET-gcc : command not found
I have tried some other tutorials, but I'm still having issues (too messy to list here).
I am looking for step-by-step instruction on compiling hello.c in eCos system. I see the eCos manual lacking in this area.
Thanks :)
It appears that you've missed a subtle convention in the eCos documentation. Items in italics are provided by you! They are variables.
The documentation mentions this here:
Note: Remember that when this manual shows TARGET-gcc you should use
the full name of the cross compiler, e.g. i386-elf-gcc, arm-elf-gcc,
or sh-elf-gcc. When compiling for the synthetic Linux target, use the
native gcc which must have the features required by eCos.
Replace TARGET with the appropriate value and BASE_DIR with (I think, in your case) /opt/ecos. You should verify the include directory before moving forward:
$ ls -l /opt/ecos/ecos-work/install/include
If that doesn't list directory contents, then you simply need to locate ecos-work
The Ecosconfig on Windows and Linux Quick Start section of the docs has you create the BASE_DIR directory (below is a snippet that I am quoting ... italics will not display).
$ mkdir BASE_DIR/ecos-work
$ cd BASE_DIR/ecos-work
So, this could be the correct invocation.
$ export INSTALL_DIR=/opt/ecos/ecos-work/arm_install
$ arm-elf-gcc -g -I/opt/ecos/ecos-work/install/include hello.c \
-L/opt/ecos/ecos-work/install/lib -Ttarget.ld -nostdlib
you need to do
# source /opt/ecos/ecosenv.sh
Then you can try to compile by changing TARGET=
$ TARGET-gcc -g -IBASE_DIR/ecos-work/install/include hello.c \
-LBASE_DIR/ecos-work/install/lib -Ttarget.ld -nostdlib

How to solve "error while loading shared libraries" when trying to run an arm binary with qemu-arm?

I'm running Linux Mint 14 with qemu, qemu-user, and the gnueabi toolchain installed. I compiled test.c with arm-linux-gnueabi-gcc test.c -o test.
When I try and run qemu-arm /usr/arm-linux-gnueabi/lib/ld-linux.so.3 test
I get an error saying: test: error while loading shared libraries: test: cannot open shared object file: No such file or directory. Running qemu-arm test, as I've previously tried, gives /lib/ld-linux.so.3: No such file or directory
However, the file does exist and is reachable.
$ stat /usr/arm-linux-gnueabi/lib/ld-linux.so.3
File: `/usr/arm-linux-gnueabi/lib/ld-linux.so.3' -> `ld-2.15.so'
Size: 10 Blocks: 0 IO Block: 4096 symbolic link
Device: 801h/2049d Inode: 4083308 Links: 1
Access: (0777/lrwxrwxrwx) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2013-04-22 16:19:48.090613901 -0700
Modify: 2012-09-21 08:31:29.000000000 -0700
Change: 2013-04-22 15:58:41.042542851 -0700
Birth: -
Does anyone know how I can make qemu run an arm program without having to emulate an entire arm Linux kernel?
test.c is
#include <stdio.h>
int main() {
printf("this had better work\n");
}
and file test is
test: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.31, BuildID[sha1]=0xf2e49db65394b77c77ee5b65b83c0cc9220cbfc0, not stripped
you can run the example by providing a path to the arm-linux-gnueabi shared libs using the -L flag.
qemu-arm -L /usr/arm-linux-gnueabi/
also make sure the LD_LIBRARY_PATH is not set.
unset LD_LIBRARY_PATH
$ export QEMU_LD_PREFIX=/usr/arm-linux-gnueabi
This works for me.
It's basically the same thing as:
$ qemu-arm -L /usr/arm-linux-gnueabi/
You can add it to the ~/.bashrc file so you don't have to type it everytime you open the terminal.
I also met this problem when running a C program with assembly code. My solution is to build the executable with the option "-static", for instance
arm-linux-gnueabi-gcc -static -g main.c square.s
Then
qemu-arm a.out
will not report the error saying "can not find the /lib/ld-linux.so.3".
The only drawback is that the executable could be with a large size. But it's helpful when you just want to test your code.
Of course, you can go with the method from Balau(see artless noise's answer). But if you don't want to feel frustrated by something like "UART serial ports" in this step, which is only to run a simple "test" function, go for a try of my fix.
I solved the problem by copying the following libraries into /lib but I believe there should be a way better solution rather than this nasty solution I invented!
sudo cp /usr/arm-linux-gnueabi/lib/ld-linux.so.3 /lib
sudo cp /usr/arm-linux-gnueabi/lib/libgcc_s.so.1 /lib
sudo cp /usr/arm-linux-gnueabi/lib/libc.so.6 /lib
Please let me know if there are other better solutions as I am interested to know.
If you want to run ARM without Linux, then you need a different compiler (at least). arm-linux-gnueabi-gcc is a compiler for Linux. The compiler and libc are intimately linked. You will need a newlib compiler with a portability layer for qemu.porting newlib
See: Balau and Google newlib+qemu. A newlib port is hosted at Github and seems to the same as the Balau blog.
Typically a non-Linux gcc is called arm-none-eabi-gcc. The prefix arm-none-eabi- is recognized by some configure scripts.
A variant, which worked for me, was to pass the loader library directly and to specify the required library paths using the loader parameter --library-path. For example:
$ TOOLCHAIN_ROOT=/usr/local/gcc-linaro-arm-linux-gnueabihf-4.7-2013.03-20130313_linux/arm-linux-gnueabihf
$ qemu-arm $TOOLCHAIN_ROOT/libc/lib/ld-linux-armhf.so.3 --library-path $TOOLCHAIN_ROOT/libc/lib/arm-linux-gnueabihf:/$TOOLCHAIN_ROOT/lib ./my_executable
Or equivalently export LD_LIBRARY_PATH instead of using --library-path.

compiling ImageMagick core in c

I am trying to compile simple imageMagick (MagickCore). I am using the C interface. The code I am trying to compile is the first example this site MagickCore API!
The configuration and installation of the library goes perfect. the "make check" command result all check to "PASS".
I also able to run operations on the command line, example:
convert logo: test.gif
Now, I want to use the C programming API. I just start with an example provided on MagickCore API!
I try to compile it using the following command: (which itself is provided on the same site as the source code):
cc -o test `pkg-config --cflags --libs MagickCore` test.c
but it results the following error (I try to look around and it is taking my time).
fatal error: MagickCore/MagickCore.h: No such file or directory
any suggestion please?
please note that I have also set the PKG_CONFIG_PATH environment variable, so ImageMagick is now in my default system path: export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
Try use the compiler argument -I path_to_headers, specifying the path of Magick headers (or something others).

Resources