태그 보관물: tip

Android NDK build architecture 변경하기

아무 설정 없이 ndk를 build 하면 다음과 같이 arm용 library가 만들어진다.

$ <NDK_PATH>/ndk-build 
Gdbserver      : [arm-linux-androideabi-4.6] 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
$ file obj/local/armeabi/libhello-jni.so 
obj/local/armeabi/libhello-jni.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked, not stripped

NDK에서 build되는 binary의 architecture를 변경하려면 APP_ABI를 선언해 주어야 하는데, Android.mk에 추가해서는 제대로 동작하지 않는다. JNI directory 아래에 Application.mk file을 만들고  APP_ABI값에 build할 architecture를 설정해 준다. 다음은 x86 바이너리를 생성하는 예제이다.

$ cat jni/Application.mk 
APP_ABI := x86
$ <NDK_PATH>/ndk-build 
Gdbserver      : [x86-4.6] libs/x86/gdbserver
Gdbsetup       : libs/x86/gdb.setup
Compile x86    : hello-jni <= hello-jni.c
SharedLibrary  : libhello-jni.so
Install        : libhello-jni.so => libs/x86/libhello-jni.so
$ file obj/local/x86/libhello-jni.so 
obj/local/x86/libhello-jni.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, not stripped

* Build에 사용되는 toolchain은 <NDK_PATH>/toolchains/<architecture>-<version>의 형태로 위치한다.

 

cannot open shared object file: No such file or directory

64bit ubuntu에서 locate 등의 명령어로 찾아보면 library가 있으나 실제로는 수행할 때 찾을 수 없다는 오류를 내면서 죽는 경우가 있다. 아래는 android build 중에 수행되는 어떤 실행 파일이 libQtGui.so.4를 찾지 못해 종료한 빌드 로그이다.

...
./bin/EXE_FILE: error while loading shared libraries: libQtGui.so.4: cannot open shared object file: No such file or directory
...

하지만 찾아보면 libQtGui.so.4는 정상적으로 있다.

HOME$ locate libQtGui.so.4
/usr/lib/x86_64-linux-gnu/libQtGui.so.4
/usr/lib/x86_64-linux-gnu/libQtGui.so.4.8
/usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.1

문제는 이것들이 64bit용이고 실행파일은 32bit executable이라는 것인데 이는 file command로 알 수 있다.

EXE_FILE_PATH$ file EXE_FILE
EXE_FILE_PATH/EXE_FILE: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, BuildID[sha1]=0x39b2e75a8c8a0993f3774fa13ba55b893fa41a66, not stripped

EXE_FILE은 32bit 80386실행 파일이지만 ldd command로 검사해 보면 누락된 library들이 ‘not found’로 표시된다.

HOME$ ldd EXE_FILE_PATH/EXE_FILE
linux-gate.so.1 => (0xf7734000)
libQtGui.so.4 => not found
libQtCore.so.4 => not found
libpthread.so.0 => /lib/i386-linux-gnu/libpthread.so.0 (0xf7701000)
libstdc++.so.6 => /usr/lib/i386-linux-gnu/libstdc++.so.6 (0xf761c000)
libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xf75f0000)
libgcc_s.so.1 => /lib/i386-linux-gnu/libgcc_s.so.1 (0xf75d2000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7428000)
libz.so.1 => /lib/i386-linux-gnu/libz.so.1 (0xf7411000)
/lib/ld-linux.so.2 (0xf7735000)

32bit (i386)용 library를 다음과 같이 package명 뒤에 “:i386″을 붙이면 설치 할 수 있다.

$ sudo apt-get install libqtgui4:i386

의존성 있는 library들이 함께 설치되고 다시 ldd command를 실행해 보면 모든 library들이 정상적으로 찾아 지는 것을 볼 수 있다.

$ ldd EXE_FILE_PATH/EXE_FILE
	linux-gate.so.1 =>  (0xf776b000)
	libQtGui.so.4 => /usr/lib/i386-linux-gnu/libQtGui.so.4 (0xf6c80000)
	libQtCore.so.4 => /usr/lib/i386-linux-gnu/libQtCore.so.4 (0xf69a3000)
	libpthread.so.0 => /lib/i386-linux-gnu/libpthread.so.0 (0xf6987000)
	libstdc++.so.6 => /usr/lib/i386-linux-gnu/libstdc++.so.6 (0xf68a2000)
	libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xf6876000)
	libgcc_s.so.1 => /lib/i386-linux-gnu/libgcc_s.so.1 (0xf6858000)
	libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf66ae000)
	libz.so.1 => /lib/i386-linux-gnu/libz.so.1 (0xf6697000)
	libfontconfig.so.1 => /usr/lib/i386-linux-gnu/libfontconfig.so.1 (0xf6663000)
	libaudio.so.2 => /usr/lib/i386-linux-gnu/libaudio.so.2 (0xf664a000)
	libglib-2.0.so.0 => /lib/i386-linux-gnu/libglib-2.0.so.0 (0xf6551000)
	libpng12.so.0 => /lib/i386-linux-gnu/libpng12.so.0 (0xf6527000)
	libfreetype.so.6 => /usr/lib/i386-linux-gnu/libfreetype.so.6 (0xf648c000)
	libgobject-2.0.so.0 => /usr/lib/i386-linux-gnu/libgobject-2.0.so.0 (0xf643d000)
	libSM.so.6 => /usr/lib/i386-linux-gnu/libSM.so.6 (0xf6434000)
	libICE.so.6 => /usr/lib/i386-linux-gnu/libICE.so.6 (0xf641a000)
	libXi.so.6 => /usr/lib/i386-linux-gnu/libXi.so.6 (0xf640a000)
	libXrender.so.1 => /usr/lib/i386-linux-gnu/libXrender.so.1 (0xf63ff000)
	libXext.so.6 => /usr/lib/i386-linux-gnu/libXext.so.6 (0xf63ed000)
	libX11.so.6 => /usr/lib/i386-linux-gnu/libX11.so.6 (0xf62b9000)
	libdl.so.2 => /lib/i386-linux-gnu/libdl.so.2 (0xf62b4000)
	librt.so.1 => /lib/i386-linux-gnu/librt.so.1 (0xf62ab000)
	/lib/ld-linux.so.2 (0xf776c000)
	libexpat.so.1 => /lib/i386-linux-gnu/libexpat.so.1 (0xf6280000)
	libXt.so.6 => /usr/lib/i386-linux-gnu/libXt.so.6 (0xf6224000)
	libXau.so.6 => /usr/lib/i386-linux-gnu/libXau.so.6 (0xf6220000)
	libpcre.so.3 => /lib/i386-linux-gnu/libpcre.so.3 (0xf61e4000)
	libffi.so.6 => /usr/lib/i386-linux-gnu/libffi.so.6 (0xf61dd000)
	libuuid.so.1 => /lib/i386-linux-gnu/libuuid.so.1 (0xf61d6000)
	libxcb.so.1 => /usr/lib/i386-linux-gnu/libxcb.so.1 (0xf61b5000)
	libXdmcp.so.6 => /usr/lib/i386-linux-gnu/libXdmcp.so.6 (0xf61ae000)

 

WARNING: terminal is not fully functional

mac에서 git관련 command나 man 명령어와 같이 more/less를 사용하는 실행을 할 때 다음과 같은 경고가 출력되는 경우가 있다.

WARNING: terminal is not fully functional
- (press RETURN)

max os x의 경우 $TERM값이 기본적으로 xterm-256color로 설정되는데, Xcode를 설치 할 때 terminal관련 정보가 삭제되서 이 문제가 발생한다고 한다. 간단하게는 터미널 -> 환경설정 -> 고급에서 ‘터미널을 다음과 같이 선언’ 항목을 xterm-256 color가 아닌 다른 값으로 변경해 주면 쉽게 해결 할 수 있다. (터미널 종료 후 재실행)

또는 solaris나 linux와 같은 다른 시스템에 있는 xterm-256color를 mac os x로 복사해서도 사용할 수 있다. 가령 linux의 경우 term-256color file이 /usr/share/terminfo/x/xterm-256color에 위치 하므로 ssh 접속을 할 수 있다면 다음 command로 mac os x 의 /usr/share/terminfo/78/ 아래로 복사해 올 수 있다.

$>sudo scp 계정@리눅스:/usr/share/terminfo/x/xterm-256color /usr/share/terminfo/78/

 

[Tip] Hex string을 bash에서 보기

Unix command인 echo를 -e option과 함께쓰면 ‘\x’로 escape된 hex값을 문자로 보여 준다.

$ echo -e "\x5B\xEB\xAC\xBC\xEB\x86\x80\xEC\x9D\xB4\x20\xEA\xB7\xB8\xEB\xA6\xBC\xED\x8C\x90\x5D"
[물놀이 그림판]

Web browser등에서는 ‘\x’가 아닌 ‘%’를 escape character로 사용하기도 하는데 이런경우는 bash의 string 치환을 사용해서 ‘\x’로 변환해서 사용할 수 있다.

$ str='\x5B\xEB\xAC\xBC\xEB\x86\x80\xEC\x9D\xB4\x20\xEA\xB7\xB8\xEB\xA6\xBC\xED\x8C\x90\x5D'

$ echo -e ${str//%/\\x}
[물놀이 그림판]

* Bash에서 string을 다루는 방법에 대해서는 KLDP의 이 문서를 참고.