불쌍한 내 LGT 갤탭에 생명력을 불어넣기 위해서 공부를 하기 시작한 안드로이드..^^
하도 테그라크 커널을 칭찬하는 글이 많아서 함 설치해 본다. 써보니 훌륭하다!! 짱~

bootloader쪽과 안드로이드를 잘 아시네..

따라해봐야지~


<설치>

아래 본문을 참조해서 따라해 봤다.
http://pspmaster.tistory.com/120

 

1. 갤럭시 탭 초기화

이미지를 잘못구워서 무한 로고 반복되는 현상을 보여서, 초기화를 해야 했다.

갤럭시 탭 초기화하는 방법
http://blog.naver.com/jolith25/100120050336

 

2. 최신 펌웨어 다운로드

삼성 Kies 어플 다운로드
http://www.samsung.com/sec/sppt/pcApplication.do

 

삼성 Kies 어플을 이용해서 갤럭시탭을 최신 펌웨어로 업그레이드한다.

image

갤택의 빌드번호를 확인한다. “환경설정>시스템 정보>빌드 번호”

 

http://pspmaster.tistory.com/120 에 있는 tar 파일을 다운받는다.  빌드번호와 동일한 것임을 확인한다.

image

 

3. 갤럭시탭 다운로드 모드 변경

홈키 + 볼륨 다운키 + 전원키 를 동시에 눌러 Downling 화면이 나오게 한다.

 

4. Odin 을 이용해서 테그라크 커널 다운로드한다.

삼성 Kies 어플을 종료하고, Odin 1.85 다운로드 받고 실행한다.
http://jnstory.net/1640

Serial Com 포트가 연결되어 있음을 확인해야 한다.(COM4)

image

 

다운받은 테그라크 커널을  pda Files에 넣고, start를 버튼을 눌러준다.

image

 

Message가 다음과 같이 출력된다. Setup Connection에서 멈추어져 있으면, 갤럭시탭과 Odin과의 통신이 된 것이 아니므로 Odin을 다시 실행하거나, 갤럭시탭의 downloading 상태로 다시 실행한다.

잘 되면, 다음과 같은 로그가 출력된다.


<ID:0/005> Added!!
<ID:0/005> Odin v.3 engine (ID:5)..
<ID:0/005> File analysis..
<ID:0/005> SetupConnection..
<ID:0/005> Initialzation..
<ID:0/005> Get PIT for mapping..
<ID:0/005> Firmware update start..
<ID:0/005> zImage
<ID:0/005> NAND Write Start!!
<ID:0/005> RQT_CLOSE !!
<ID:0/005> RES OK !!
<ID:0/005> Completed..
<OSM> All threads completed. (succeed 1 / failed 0)
<ID:0/005> Removed!!
<ID:0/004> Added!!

잘되면 zImage 파일이 다운되면서 PASS 라는 파일이 뜬다.

image

 

부팅하면서 Tegrak Kernel 정보가 뜬다.  build 30

 

5. Wifi 설정을 한다.

 

6. 테그라크 애플리케이션을 마켓에서 다운받는다.

테그라크 커널, 테그라크 오버클럭, 맛클 핵펀치

 

7. 테그라크 커널 애플리케이션을 실행한다.

관련정보를 모두 확인하고 테스트해본다.

 

<루팅>

테그라크 커널 애플리케이션에서 ‘Enable 루팅’, ‘Disable 루팅’을 선택한다.

 

<오버 클러킹>

‘Enable 루팅’한 상태에서 테그라크 오버클럭 어플리케이션을 실행한다.

오버클럭 모듈 로드를 먼저 실행한후, CPU 최대 클럭 변경을을 선택한다. 1.3Ghz로 선택했다. 엄청 빠르다..

 

<삼성 Kies 연동>

테그라크 커널 모듈을 설치해도 삼성 Kies와 연동이 잘 되는 것 같다.

 

<백업>

백업을 잘 해놓자. recovery mode로 가서 system과 data 디렉토리를 백업한다.

http://pspmaster.tistory.com/120

http://cafe.naver.com/tendog.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=70966&

http://cafe.naver.com/sejongs0.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=219&

Posted by '김용환'
,

 

아이패드 게임으로 나온 FIFA 12를 보면서 앞으로 어떤 게임이 나올지 사뭇 궁금해졌다.

 

아이패드를 모니터로 하고. 아이폰을 게임 패드로 해서 게임을 해보면서
앞으로 스마트폰이 정말 대세가 되겠다하는 생각이 들었다.

게임 입장할 때, 블루투쓰로 연결하려고 한다.

image

 

블루투쓰 연결이 되면 latency 가 보인다.

image

 

실제 게임을 하는 장면으로. 잘 돌아간다. 

나는 블루투쓰 통신은 1:1인줄 알았는데. 아이패드1-아이폰2 대의 연결을 보면서 가능성을 볼 수 있었다. 
이거 어떻게 짠거지?? 하는 호기심도 많이 발동한 것 같다.

IMG_1123

 

아이폰 화면은 이렇게 콘트롤러 패드 형태로 나오면서 게임을 즐길 수 있다.

IMG_1122

Posted by '김용환'
,
Posted by '김용환'
,


조금 어플 큰거 다운받으면 '기기에 공간이 부족하다는' 에러가 많이 받았다.

진저브레드이고, 갤택 최신 커널도 설치했고, 메모리도 많은데 무엇이 문제가 있가 했다.


“XXX” 다운로드 중에 오류가 발생했습니다.
기기에 공간이 부족합니다.

 
결론은..
설정-응용프로그램관리-(다운로드됨) 메뉴에서 –마켓 를 선택한 후 업데이트 제거 했더니 잘 받아진다. .

Posted by '김용환'
,

리눅스 커널 영역에서는 사용자 메모리 공간을 포인터를 이용해서 메모리를 바로 사용할 수 없다.
따라서 복사해야 한다.

유저영역의 메모리를 커널로 복사하는 함수는 copy_from_user 이다.

이런 불편함때문에 생긴게 mmap 이다.  어플이 메모리를 커널에 바로 메모리를 (zero copy) 잡는다.



안드로이드 ipc에는 이런 코드들이 있다. 
binder_wirte_read struct를 을 복사할 때는 copy_from_user, get_user 함수를 이용한다.

transport 하는 데이터는 mmap 으로 관리하도록 되어 있다.
binder_mmap 함수가 바로 그것..

그 안에 binder_update_page_range 함수를 호출하여 물리메모리와 커널의 가상메모리의 수신버퍼, 사용자 공간의 수신버퍼를 매핑한다.

Posted by '김용환'
,
Posted by '김용환'
,



안드로이드 소스





* intent 사용예제

// 1. 어떤 이름인지 모를 때. (클래스 이름을 모를때)
// 필터를 줄 수 있다. 서버의 manifest.xml의 service -> intent-filter -> action에 넣어야 한다. 
Intent i = new Intent("com.google.p.server.REMOTE_SERVICE");

// 2. 클래스 이름을 알고 있을 때.
//             Intent i = new Intent(IMyService.class.getName());



* bind


생명주기













  이미지 출처 
     http://shadowxx.egloos.com/10726222
    http://blog.naver.com/mirnae/100101468187




* aidl

http://developer.android.com/guide/developing/tools/aidl.html

aidl 매니저가  aidl 파일을 일고 stub 코드를 알아서 생성
client가 쓸 수 있는 proxy 코드와 server가 쓸 수 있는  stub 코드를 생성한다.


package com.google.p.server;

interface IMyService {
 int getStatus();
}




=> gen 디렉토리 밑에 자동으로 파일을 생성되어 있다.


/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: C:\\AndroidP\\eclipse\\workspaces\\RemoteServerClient\\src\\com\\google\\p\\server\\IMyService.aidl
 */
package com.google.p.server;
public interface IMyService extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.google.p.server.IMyService
{
private static final java.lang.String DESCRIPTOR = "com.google.p.server.IMyService";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
 * Cast an IBinder object into an com.google.p.server.IMyService interface,
 * generating a proxy if needed.
 */

public static com.google.p.server.IMyService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.google.p.server.IMyService))) {
return ((com.google.p.server.IMyService)iin);
}
return new com.google.p.server.IMyService.Stub.Proxy(obj);
}
public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getStatus:
{
data.enforceInterface(DESCRIPTOR);
int _result = this.getStatus();
reply.writeNoException();
reply.writeInt(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.google.p.server.IMyService
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
public int getStatus() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getStatus, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_getStatus = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public int getStatus() throws android.os.RemoteException;
}





* manifest.xml 

 service에 remote 설정하고 프로세스 단위의 통신이 된다.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.google.p.client"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="8" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".AIDLClient"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name="com.google.p.server.MyService" android:process=":remote" >
            <intent-filter>
                <action android:name="com.google.p.server.REMOTE_SERVICE"></action>
            </intent-filter>
        </service>

    </application>
</manifest>




어플을 올리고, bind 가 되게 한 후(start binding),
 DDMS로 확인하니. 아래와 같이 remote 프로세스가 뜨는지 확인


adb shell로 들어가서, proc 정보를 본다.



어느 파일들을 읽고 있나 본다.
app_process 프로세스와 binder , dalvk 관련 내용들이  보인다.



결국 이런 개념이 됨
 remoteservice.jpg


(이미지 출처 : http://liveeasily.dothome.co.kr/wiki/doku.php?id=android_service)



---------------------------------

인사이드 안드로이드 의 8장 안드로이드 서비스 프레임워크
(네이티브) 샘플 소스를 보드에 넣어보고 테스트해 보기


HelloWorld 시스템 소스



1. 복사를 먼저 한다. 
1)  include 파일은 소스디렉토리\frameworks\base\include 에 include에  복사
2) libs 파일은 소스디렉토리\\frameworks\base\libs 에 libs 에 복사
3) helloworld client 소스는 소스디렉토리\\frameworks\base\helloworld 에 복사

2. 다음은 전체 컴파일을 한다.  

소스디렉토리 # ./build_android.sh 

3. output이 정상적으로 나왔는지 확인
소스디렉토리\out\target\product\sv210\system\lib 밑에 보면,libhelloworld.so 파일이 들어가 있다.


서비스와 클라이언트 파일이 정상적으로 만들어졌는지 본다.

 

4. 이미지 복사
소스빌드디렉토리에서 (out\target\product\sv210)  root.img, system.img 파일을 복사하여 이미지를 다운받기 좋은 곳으로 보낸다.
기존에 있던 bootloader  zImage 파일도 복사해 둔다.


5. 이미지 다운로드
Hybus 보드에 그 이미지를 넣는다.  odin 같은거 없고, 벤더에서 준 ndw.exe 라는 파일을 이용한다.
드라이버 설치하고 나서, 내 컴의 ndw.exe 를 실행한다.

1) nand init
nand scrub
nand erase 80000 FF80000

2) kernel write
nand erase 600000 500000
dnw c0008000
[내 컴의 ndw.exe] Select USB Port -> Transmit -> Transmit -> Select zImage
nand write c0008000 600000 500000

3) root.img write
nand erase b00000 500000
dnw 40000000
[내 컴의 ndw.exe]  Select USB Port -> Transmit -> Transmit -> Select root.img
nand write.yaffs 40000000 b00000 <byte size of system.img>

4) system.img write
nand erase 1000000 5a00000
dnw 40000000
[내 컴의 ndw.exe]  Select USB Port -> Transmit -> Transmit -> Select system.img
nand write.yaffs 40000000 1000000  <byte size of system.img>

5) reset
(Hybus를 재시작한다.)


6. adb shell로 명령어를 통해 디바이스로 접근하고 실행해 본다.

# cd /system/bin
# ./helloworldservide &
# ./helloworldclient
hello, world




--------------------------------------------------

안드로이스 시스템 서비스 예제

vender 디렉토리에 넣고, 그 부분만 컴파일 하기

소스



zip을 풀고, 소스 디렉토리\external 아래로 복사하고 빌드한다.
hybus의 기계이름은 HyBus_sv210이다.

# .  build/envsetup.sh
# chooseproduct  HyBus_sv210
# mmm  external/ExService3

make 파일처럼 out\target\product\sv210\system\lib 디렉토리에 libSQRS03.so이 나왔다.

(vender depedent)
4. Hybus 에서는 yaffs로 system  이미지를 바꿔야 한다. system.img를 yaffs 파일시스템 형식으로 변환

소스디렉토리/vendor# ./mkyaffs2image  /work/android_froyo_sv210/out/target/product/sv210/system system.img
system 디렉토리를 yaffs 파일시스템형식으로 img 파일을 복사한다.

(원형    # vendor/mkyaffs2image  system  system.img )


4. 빌드 결과 이미지를 타깃 시스템에 올린다.

1) nand init
nand scrub
nand erase 80000 FF80000

2) kernel write
nand erase 600000 500000
dnw c0008000
[내 컴의 ndw.exe] Select USB Port -> Transmit -> Transmit -> Select zImage
nand write c0008000 600000 500000

3) root.img write
nand erase b00000 500000
dnw 40000000
[내 컴의 ndw.exe]  Select USB Port -> Transmit -> Transmit -> Select root.img
nand write.yaffs 40000000 b00000 <byte size of system.img>

4) system.img write
nand erase 1000000 5a00000
dnw 40000000
[내 컴의 ndw.exe]  Select USB Port -> Transmit -> Transmit -> Select system.img
nand write.yaffs 40000000 1000000  <byte size of system.img>

5) reset
(Hybus를 재시작한다.)


5. 결과 확인
#adb shell로 접근한다.

 


6. server 실행하기

  # logcat &

  # addserver03 &

7. client 실행하기

  # sqrtest3





Posted by '김용환'
,

안드로이드 플러그인이 설치된 이클립스에서 새로운 프로젝트를 생성한다.
Create proejcty from existing sample을 선택하면 Sample 컴보박스가 뜬다.





여기서 예제들을 선택하고 개념을 파악하면 쉽다.



Posted by '김용환'
,


1. 안드로이드 JNI 로그 남기기

이클립스의 LogCat 에서 jni가 출력되는 것을 보고 싶을 때 유용한다.
jni의 native단에서 printf로 출력되는 것은 adb shell로만 볼 수 있다.


Android.mk에 다음을 추가한다.
LOCAL_LDLIBS := -llog

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := test
LOCAL_SRC_FILES := test.c
LOCAL_LDLIBS := -llog

include $(BUILD_SHARED_LIBRARY)






C 코드에 다음을 추가한다.

#include <android/log.h>

__android_log_print(ANDROID_LOG_DEBUG, "Tag_Name", "Message...");

레벨은 많다.
ANDROID_LOG_UNKNOWN
ANDROID_LOG_DEFAULT
ANDROID_LOG_VERBOSE
ANDROID_LOG_DEBUG
ANDROID_LOG_INFO
ANDROID_LOG_WARN
ANDROID_LOG_ERROR
ANDROID_LOG_FATAL
ANDROID_LOG_SILENT




#include <jni.h>
#include <android/log.h>
#include <stdio.h>

#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT jint JNICALL Java_com_google_AddJniActivity_addJNI
  (JNIEnv *env, jobject thiz, jint num1, jint num2)
{
        __android_log_print(ANDROID_LOG_ERROR, "GOOGLE", "******Message...");
         return num1+num2;
}

#ifdef __cplusplus
}
#endif




logcat에 에러가 남는다.




2. 두 개의 모듈을 컴파일 해보기


java  ==  jni-c  이런 상황에서 jni-c 파일이 사용하는 라이브러리가 따로 있는 경우를 의미한다.
즉 jni에서 명시적으로 가지고 쓰는 경우를 의미한다.


first.h

#ifndef FIRST_H
#define FIRST_H

extern int first(int  x, int  y);

#endif /* FIRST_H */




first.c

#include <android/log.h>

int  first(int  x, int  y)
{
 __android_log_print(ANDROID_LOG_DEBUG, "google", "** first.c, first function ");
     return x + y;
}






jni 코드 : test.c

#include <jni.h>
#include <android/log.h>
#include "first.h"

#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_google_TwoLibs
 * Method:    add
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_google_TwoLibs_add
  (JNIEnv *env, jobject thiz, jint x, jint y) {
 __android_log_print(ANDROID_LOG_DEBUG, "google", "*******Message...");
   return first(x, y);
}

#ifdef __cplusplus
}
#endif





이런 경우의 android make 파일은 다음과 같이 지정한다.

Android.mk

LOCAL_PATH := $(call my-dir)

## 1st 다음은 libwolib-first 모듈를 만들자
include $(CLEAR_VARS)

LOCAL_MODULE    := libtwolib-first
LOCAL_SRC_FILES := first.c
LOCAL_LDLIBS := -llog

include $(BUILD_STATIC_LIBRARY)

## 2nd 다음은 libwolib-second 모듈을 만들자

include $(CLEAR_VARS)

LOCAL_MODULE    := libtwolib-second
LOCAL_SRC_FILES := second.c
LOCAL_LDLIBS := -llog

LOCAL_STATIC_LIBRARIES := libtwolib-first

include $(BUILD_SHARED_LIBRARY)



obj/local/armeabi 디렉토리 밑에 보면, first.a 파일과 secod.so 파일이 있는지 확인가능하다.
static lib는 linux archive를 의미한다.

$  ls -al
libtwolib-first.a
libtwolib-second.so
objs

libs/eabi 디렉토리는 static library를 포함하는 so 파일들이 만들어져 있다.
libs/eabi/libtwolib-second.so 파일을 이클립스 프로젝트에서 복사해서 사용한다.


3. module을 export 하기

여러 모듈(c, header) 파일이 있을 때, 여러개의 so파일과 함께 jni가 make 파일을 이용하여 프로그래밍을 할 수 있다.


foo.h

#ifndef FOO_H
#define FOO_H

extern int  foo(int x);

#endif /* FOO_H */




foo.c


#include "foo.h"
#include <android/log.h>

/* FOO should be defined to '2' when building foo.c */
#ifndef FOO
#error FOO is not defined here !
#endif

# android.mk 파일에서 설정값에 parameter값을 넣어서 동작되는 지를 확인하는 코드

#if FOO != 2
#error FOO is incorrectly defined here !
#endif

#define  LOG_TAG    "libfoo"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)

int  foo(int  x)
{
    LOGI("foo(%d) called !", x);
    return x+1;
}





bar.h


#ifndef BAR_H
#define BAR_H

/* FOO should be defined to '1' here with the magic of LOCAL_EXPORT_CFLAGS */
#ifndef FOO
#error FOO should be defined here !
#endif

#if FOO != 1
#error FOO is not correctly defined here !
#endif

extern int  bar(int  x);

#endif /* BAR_H */





bar.c

#include "bar.h"
#include <android/log.h>

#define LOG_TAG  "libbar"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

int bar(int x)
{
 LOGI("bar(%d) called!!", x);
 return foo(x)-1;
}




zoo.c


#include "bar.h"
#include <android/log.h>

int something(void)
{
 __android_log_print(ANDROID_LOG_INFO, "libzoo", "something() called!!");
 return bar(42);
}




test.c

#include <jni.h>

#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT jint JNICALL Java_com_google_ModuleExports_foo
  (JNIEnv *env, jobject thiz, jint val)
{
 return foo(val);
}

JNIEXPORT jint JNICALL Java_com_google_ModuleExports_bar
  (JNIEnv *env, jobject thiz, jint val)
{
 return bar(val);
}

JNIEXPORT jint JNICALL Java_com_google_ModuleExports_zoo
  (JNIEnv *env, jobject thiz, jint val)
{
 return something();
}

#ifdef __cplusplus
}
#endif




java파일

class ActivityTest .... {

    public native int  foo(int val);
    public native int  bar(int val);
    public native int  zoo(int val);
   
    static {
        System.loadLibrary("bar");
        System.loadLibrary("zoo");
    }

}


Android.mk

LOCAL_PATH := $(call my-dir)

# FOO 값을 2로 만들어서  foo.c을 컴파일하고, FOO값을 1로 셋팅한후 archive 파일을 만든다.
include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo/foo.c
LOCAL_CFLAGS := -DFOO=2
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/foo
LOCAL_EXPORT_CFLAGS := -DFOO=1
LOCAL_EXPORT_LDLIBS := -llog
include $(BUILD_STATIC_LIBRARY)

# bar.c 를 컴파일하고 static 파일이었던 foo.a 를 모아 bar.so 파일로 만든다.
include $(CLEAR_VARS)
LOCAL_MODULE := bar
LOCAL_SRC_FILES := bar/bar.c
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/bar
LOCAL_STATIC_LIBRARIES := foo
include $(BUILD_SHARED_LIBRARY)

# zoo 파일을 jni파일인 test.c 파일과 함께 컴파일하고, zoo.so 파일로 만든다.
include $(CLEAR_VARS)
LOCAL_MODULE := zoo
LOCAL_SRC_FILES := test.c zoo/zoo.c
LOCAL_SHARED_LIBRARIES := bar
include $(BUILD_SHARED_LIBRARY)



../../ndk-build 결과는 다음과 같은 so 파일이 생성된다.






 

Posted by '김용환'
,

가장 따뜻한 11월 에 나온 ndk 7이다.

Linux 32/64-bit (x86) android-ndk-r7-linux-x86.tar.bz2


android nkd 7을 다운받아서 ndk 해보는데. 잘 안된다.  구글 검색해도 안나와서.. 좀 열받는다.

ndk 빌드하면 이렇게 아래로 나오는데..

/work/android-ndk-r7/samples/san-angeles# ../../ndk-build
/work/android-ndk-r7/prebuilt/linux-x86/bin/awk: 1: ELF : not found
/work/android-ndk-r7/prebuilt/linux-x86/bin/awk: 4: Syntax error: word unexpected (expecting ")")
Android NDK: Host 'awk' tool is outdated. Please define HOST_AWK to point to Gawk or Nawk !   
/work/android-ndk-r7/build/core/init.mk:258: *** Android NDK: Aborting.    .  Stop.



추적을 해보니. 어라. awk 문법에 맞는 것이 동작이 안된다.

/work/android-ndk-r7/samples/san-angeles# ../../build/awk/check-awk.awk
../../build/awk/check-awk.awk: line 22: BEGIN: command not found
../../build/awk/check-awk.awk: line 26: syntax error near unexpected token `s1,"world"'
../../build/awk/check-awk.awk: line 26: `    if (! match(s1,"world")) {'


awk도 최신 버전인데..

# apt-get install awk
Reading package lists... Done
Building dependency tree      
Reading state information... Done
Package awk is a virtual package provided by:
  original-awk 2010-05-23-1
  mawk 1.3.3-15ubuntu2
  gawk 1:3.1.7.dfsg-5

 




mk 파일보면서 android -ndk에 awk가 이상이 있나 확인해보았다.

32비트 x86 버전에서 prebuild/linux-x86/bin/awk 파일은 64 비트용이었다... 아하~

/work/android-ndk-r7/prebuilt/linux-x86/bin# file awk
awk: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, stripped


awk 파일을 지우고 gawk를 링크를 걸어준다.

/work/android-ndk-r7/prebuilt/linux-x86/bin# mv awk awk.old
/work/android-ndk-r7/prebuilt/linux-x86/bin# ln -s /usr/bin/gawk awk

그리고, 샘플 디렉토리 가서 테스트해보니. 오예~ 빌드 완료.

/work/android-ndk-r7/samples/hello-jni# ../../ndk-build
Gdbserver      : [arm-linux-androideabi-4.4.3] libs/armeabi/gdbserver
Gdbsetup       : libs/armeabi/gdb.setup
Compile thumb  : hello-jni <= hello-jni.c
SharedLibrary  : libhello-jni.so
Install        : libhello-jni.so => libs/armeabi/libhello-jni.so
Posted by '김용환'
,