Android C native development using the NDK under Windows

http://www.pocketmagic.net/?p=1462

Android C native development using the NDK under Windows

By Radu Motisan Posted on November 18th, 2010

A lot has changed since my previous article, on Android C native development, back in 2009.
The Android NDK has been released and the JNI development is not only possible, but also easy. Have a look on this article on the Android NDK.
The new challenge is to use the NDK to compile Native ARM-EABI executables that would run on an Android phone. I don't want to setup the complete Google Android source code as I did in my first article.

This is possible, and I will provide the steps to do it:
Step 1. Install the NDK
Step 2. Install Cygwin
(as presented in the Android NDK Article)
While this guide is for Windows, you can easily adapt the following for a Linux box or a Mac.

Create a simple C code file, test.c

 
#include <stdio.h>
 
int main()
{
	printf("Hello Google Android world!/nwww.pocketmagic.net/n");
	return 1;
	exit(0);
}
 

Find the following locations:
NDK_ROOT (eg. D:/work_code/android/android-ndk-r4b/ )
NDK_ROOT/build/platforms/
NDK_ROOT/build/prebuilt/windows/arm-eabi-4.2.1/
You will need them.

When starting Cygwin using the Cygwin.bat BATCH File, make sure you define the PATH to the Android NDK:

 
set PATH=D:/work_code/android/android-sdk-windows/tools;D:/work_code/android/android-ndk-r4b;D:/work_code/android/android-ndk-r4b/build/prebuilt/windows/arm-eabi-4.2.1/bin/;$PATH;D:/work_code/android/android-ndk-r4b/build/platforms/android-5/arch-arm/usr/lib/;
 

Step 3. If you read my Android NDK article, you already know the NDK folder contains the ndk-build script, that is used to compile the JNI code.
We will build a similar script, to compile our test.c code file.

Let's call this file ndk-comp and place it where ndk-build is.

 
#!/bin/sh 
 
OS='windows'
ANDROIDSDK='android-3'
 
PROGDIR=`dirname $0`
PROGDIR=`cd $PROGDIR && pwd`
 
ARMEABIGCC=$PROGDIR/build/prebuilt/$OS/arm-eabi-4.2.1/bin/arm-eabi-gcc
ARMEABILIB=$PROGDIR/build/platforms/$ANDROIDSDK/arch-arm/usr/lib
ARMEABIINC=$PROGDIR/build/platforms/$ANDROIDSDK/arch-arm/usr/include
ARMEABICRT=$PROGDIR/build/platforms/$ANDROIDSDK/arch-arm/usr/lib/crtbegin_dynamic.o
 
LINKER=/system/bin/linker
 
echo "GCC:"$ARMEABIGCC "LIB:"$ARMEABILIB "LINKER":$LINKER "PARAMS:"$@
 
$ARMEABIGCC $@ -Wl,-rpath-link=$ARMEABILIB,-dynamic-linker=$LINKER -L$ARMEABILIB $ARMEABICRT -I$ARMEABIINC -nostdlib -lc
 

If you did everything correctly, you should be able to call this script from within Cygwin's shell. Using cd command, navigate in Cygwin shell to the test.c folder. Compile it using ndk-comp -o test test.c :
compile android native c file using ndk 1
As you can see, running it on the device using ADB works. Here is another picture showing the executable started using the Terminal app, directly on the Android smartphone:
compile android native c file using ndk 2
It works well.

There is another even better way of compiling native C apps for Android using the NDK, as presented by Mamadou on his blog.
You can create a Makefile in the same folder with test.c then navigate there with the Cygwin shell and run make.
The Makefile is as follows:

 
APP := test
ROOT:=/cygdrive/d/work_code/android
NDK_PLATFORM_VER := 3
INSTALL_DIR := /data/tmp
 
ANDROID_NDK_ROOT:=$(ROOT)/android-ndk-r4b
ANDROID_NDK_HOST:=windows
ANDROID_SDK_ROOT:=$(ROOT)/android-sdk-windows
PREBUILD:=$(ANDROID_NDK_ROOT)/build/prebuilt/$(ANDROID_NDK_HOST)/arm-eabi-4.4.0
BIN := $(PREBUILD)/bin
 
CPP := $(BIN)/arm-eabi-g++
CC := $(BIN)/arm-eabi-gcc
CFLAGS := -I$(ANDROID_NDK_ROOT)/build/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/include
LDFLAGS := -Wl,--entry=main,-rpath-link=$(ANDROID_NDK_ROOT)/build/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/lib,-dynamic-linker=/system/bin/linker -L$(ANDROID_NDK_ROOT)/build/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/lib
LDFLAGS += -nostdlib -lc -disable-multilib
 
all: $(APP)
 
OBJS += $(APP).o
 
$(APP): $(OBJS)
	$(CPP) $(LDFLAGS) -o $@ $^
 
%.o: %.c
	$(CC) -c $(INCLUDE) $(CFLAGS) $< -o $@
install: $(APP)
	$(ANDROID_SDK_ROOT)/tools/adb push $(APP) $(INSTALL_DIR)/$(APP)
	$(ANDROID_SDK_ROOT)/tools/adb shell chmod 777 $(INSTALL_DIR)/$(APP)
 
shell:
	$(ANDROID_SDK_ROOT)/tools/adb shell
 
run:
	$(ANDROID_SDK_ROOT)/tools/adb shell $(INSTALL_DIR)/$(APP)
 
r: $(APP)
	$(ANDROID_SDK_ROOT)/tools/adb push $(APP) $(INSTALL_DIR)/$(APP)
	$(ANDROID_SDK_ROOT)/tools/adb shell chmod 777 $(INSTALL_DIR)/$(APP)
	$(ANDROID_SDK_ROOT)/tools/adb shell $(INSTALL_DIR)/$(APP)
 
clean:
	@rm -f $(APP).o $(APP)
 

Makefile
If you copy paste this, make sure you replace the spaces before "$(CPP) $(LDFLAGS.." and the other paragraphs with one TAB. Not doing so will result in an error:

 
$ make
Makefile:24: *** missing separator.  Stop.
 
ITX@itxserv /cygdrive/d/work_code/android/TBTS/Native
 

If everything is in place, you can use the following defined commands:
make clean - will delete all object files and prepare for a new build
make - will compile your code
make r - copies the compiled binary to your Android device, it sets executable permissions and launches it.

Here's an image showing that:
compile android native c file using ndk 3

For some reason this binary produces a segmentation fault, just before it terminates. I didn;t have the time to look into this, but Mamadou also had the error. For the moment I'd suggest you stick to my first script.

By Radu Motisan

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值