- 2008-03-02 19:53
- android
前回のエントリ「Mac OSXのAndroid m5-rc14でNativeファイルがSegmentation faultになる」では、MacでCプログラムをARM用にクロスコンパイルしたネイティブファイルをAndroidで実行して失敗しました。
そのコメントで色々アドバイスを頂き、成功しました。
本エントリではその内容を整理して説明します。
#MichaeLさん、安藤恐竜さん、ありがとうございました。
クロスコンパイル環境を構築します。
以下の環境で成功しました。
- OS: CentOS4.3
- CPU: Pen4
- Mem: 2GB
もしくは、
- 仮想マシン: VMWare Fusion 1.1.1
- Host: Mac OSX 10.5.2
- Guest: CentOS5.1 or Ubuntu7
- CPU: 2GHz Intel Core Duo (iMac)
- Mem: 2GB
今回使用したクロスコンパイラが32ビット向けなので、いずれのOSも32ビット版(i386)を準備しました。
クロスコンパイラはDownload the ARM 2007q3 Releaseから、
- Target Platform: ARM GNU/Linux
- Host Platform: IA32 GNU/Linux
として、ダウンロードしてきました。
Androidでうまく実行出来なかったクロスコンパイラもご紹介しておきます。
GNU ARM: Mac用のバイナリなども配布してくれています。しかし、Mac版のバイナリではクロスコンパイルできるのですが、Androidで実行できませんでした。(ref. Mac OSXのAndroid m5-rc14でNativeファイルがSegmentation faultになる)
ARM GCC toolchain for Linux and Mac OS X: ここでもMac(Intel)用のバイナリを配布してくれています。上と同じく、クロスコンパイルしたファイルはAndroidで実行できないバイナリでした。
失敗したバイナリファイルはこうなっています。
hello: ELF 32-bit LSB executable, ARM, version 1 (ARM), statically linked, not stripped
前回と同じくHello, world!プログラムをクロスコンパイルしてAndroid上で実行を試みます。
hello.c
#include <stdio.h> int main(int argc, char** argv) { printf("Hello, world!\n"); return 0; }
さっそく準備したクロスコンパイラでソースコードをコンパイルします。
arm-none-linux-gnueabi-gcc (CodeSourcery Sourcery G++ Lite 2007q3-51) 4.2.1
$ ./arm-none-linux-gnueabi-gcc -o hello-static hello.c -static
staticオプションでライブラリをバイナリに取り込んでいます。
これで、ライブラリに依存しない実行ファイルにできます。
コンパイルしたhello-staticファイルはこうなっています。
hello-static: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.14, statically linked, not stripped
ちゃんとstatically linkedされています。
バイナリファイルをAndroidに移して実行します。
$ adb shell
# cd /tmp
# chmod 755 hello-static
# ./hello-static
Hello, world!
うまく行きました!
上ではstaticオプションによりライブラリをバイナリファイルに取り込んでいました。
そのため、ファイルサイズは大きくなってしまいます。
564K hello-static
Hello, world!だけで564KBは大きいですね。
次に、Android上で動作する動的リンクなバイナリを生成します。
Hello, world!は同じです。
hello.c
#include <stdio.h> int main(int argc, char** argv) { printf("Hello, world!\n"); return 0; }
hello.c以外にもう1つファイルを準備します。
start.c
#include <stdlib.h> extern int main(int argc, char** argv); void _start(int argc, char** argv) { exit( main(argc, argv) ); }
エントリーポイントとなる_start関数を自前で準備しています。
さっそく、上のソースコードをクロスコンパイルします。
今回はstaticオプションを付けず、動的リンクするバイナリを生成します。
$ ./arm-none-linux-gnueabi-gcc -c start.c
$./arm-none-linux-gnueabi-ld –entry=_start –dynamic-linker /system/bin/linker -rpath /system/lib -lc -o hello-dynamic hello.o start.o
上の2行はオブジェクトファイルを生成しているだけです。
キモは3行目のコマンドです。下記の3つのオプションを指定します。
- entry: エントリポイントとなる関数名を指定します。
- dynamic-linker: ダイナミックリンカの場所を指定します。ここはAndroidのリンカの場所を指定。
- rpath: ローダがライブラリを検索するパスを指定します。ここはAndroidのライブラリの場所を指定。
ファイル情報を見てみます。
hello-dynamic: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), not stripped
ちゃんとdynamically linkedとなっています。
これで動的リンクするバイナリを生成することができました。
さっそく、動的リンクなバイナリをAndroidに移動して、実行してみます。
$ adb shell
# adb cd /tmp
# chmod 755 hello-dynamic
# ./hello-dynamic
Hello, world!
ちゃんと実行出来ました!
ちなみに静的リンクなバイナリファイル(hello-static)と動的リンクなバイナリファイル(hello-static)のサイズを比較してみます。
8.0K hello-dynamic
564K hello-static
ファイルサイズの差は一目瞭然ですね。
アドバイスを頂いた、MichaeLさん、安藤恐竜さん、ありがとうございました。とても勉強になりました。
motz diary: AndroidのNative Appに関して一番詳しいそうです。
AndroidでC言語で書いたネイティブアプリを動かしてみる: ScratchBoxというのを利用してクロスコンパイルしているみたいです。こんど試してみよう。
Comments:5
- 安藤恐竜 08-03-02 (日) 21:45
-
このエントリはかなりスゴイ。かっこいいです。クラッシュコースをハイウェイに変えるのは難しいんですよ。勉強になりました。
- adamrocker 08-03-02 (日) 23:53
-
ありがとうございます。
失敗例も重要な情報ですよね。同じ失敗を他の人が繰り返さないためにも。
失敗例を晒す事で、沢山のアドバイスも頂けましたし感謝です。 - 吉田 博 08-04-03 (木) 16:20
-
ここの資料、大変勉強になりました。
ただ、私はWindows上でコンパイルしているのですが
最後のhello-dynamicで以下のエラーが出てしまいます。# ./hello-dynamic
./hello-dynamic
ERROR: 592 could not load ‘libc.so.6′
ERROR: failed to link ./hello-dynamic
ERROR: CANNOT LINK EXECUTABLE ‘./hello-dynamic’何か情報を得られたらと思うのですが、いかがでしょうか?
(ちなみにstaticのほうは実行できましたし、
dynamicのビルドも問題はありませんでした。) - adamrocker 08-04-03 (木) 21:13
-
>吉田 博さん
コメントありがとうございます。
お役に立てたようで嬉しいです^^
エラー文からするにlibc.so.6が見つかっていないようなので、
libc.so.6というシンボリックリンクを作るとどうでしょう?
こんな感じでしょうか。$ adb shell
# cd /system/lib
# ln -s libc.so libc.so.6私もこの作業をやった気もするのですが、try and errorを繰り返していましたので曖昧な記憶です(汗)
- 吉田 博 08-04-04 (金) 9:15
-
シンボリックリンクを作成したところ、
hello-dynamicが動きました。
ありがとうございました。
Trackbacks:1
- Trackback URL for this entry
- http://www.adamrocker.com/blog/191/c_native_executable_file_on_android.html/trackback/
- Listed below are links to weblogs that reference
- AndroidでNative実行入門 from throw Life
- trackback from Okiraku Programming 08-06-24 (火) 5:17
-
[Linux] Android SDKで遊んでみた…
とりあえずダウンロード&起動 Mac OS X 10.5な環境で試してみます。Googleからダウンロードするといきなり動かせます。この簡単さは偉いなあ。 1. ht (more…)
