ところどころ手を加える必要があったので備忘録をかねて。(Cygwinと書きましたがほかの環境でも参考になると思います。)
Cygwin (またはGNU/LinuxなどのNDKを動かせるもの) の導入
今回は省きます。と、言ってもほとんど初期状態でも大丈夫な気がしますが。
ただ、Cygwin
やMSYS/MinGW
などのWindows上の環境でやるには管理者権限が必要です。
ビルドする際にシンボリックリンクを張りながら進むものがあってそれでとまります。NDKのツールが解釈できない模様。
echo "" >> ~/.zshrc
echo "export CYGWIN='dosfilewarning winsymlinks:native'" >> ~/.zshrc
などとしておくと好いでしょう。ただ、管理者権限で起動するとなぜかdosfilewarning
が効かないのつらい。改めてsource ~/.zshrc
とかexport CYGWIN=以下略
とかすると大丈夫なんだけどね…
Android NDKの導入
NDKの配置
自分の環境にあったNDKをダウンロードして、好きな場所に伸張します。
ここではandroid-ndk-r9d-windows-x86_64.zip
を~/Dev/Android/
で伸張します。
cd ~/Dev/Android/
unzip android-ndk-r9d-windows-x86_64
環境変数などの設定
NDKのパスは好きにしてもらってかまわないのですが(先程の例だとNDK_ROOT=$HOME/Dev/Android/andrioid-ndk-r9d
になります)、irbがRubyをビルドしたときのprefixを見に行くのでANDBOXはそのときに置くパスの一部にすると、後々楽に作業ができます。
(irbなどのshebangが決め打ちされます、わざわざ書き換えるのは面倒。それこそスクリプト書けばいいのだけれど)
たとえば、id:rattcvさんのrboxに組み込むなら、ANDBOX=/data/data/jackpal.androidterm/shared_prefs/rbox
などとすると好いでしょう。(Androidのバージョンによっては違うかもしれないので各自確認のこと)
ちなみにplatformsはこのページのAPI Levelに対応しています。
echo "" >> ~/.zshrc
echo "export ANDBOX=/path/to/your/directoory" >> ~/.zshrc
echo "export NDK_ROOT=/path/to/your/ndk" >> ~/.zshrc
echo "export SYSROOT=$NDK_ROOT/platforms/android-9" >> ~/.zshrc
source ~/.zshrc
スタンドアローンのビルドツールをインストール
動かすAndroidのアーキテクスチャはarmということで進めていきます。
$NDK_ROOT/build/tools/make-standalone-toolchain.sh \
--platform=android-9 \
--arch=arm \
--install-dir=/usr/local/android_ndk_standalone-r9d \
--ndk-dir=$NDK_ROOT
echo "export PATH=$PATH:/usr/local/android_ndk_standalone-r9d/bin" >> ~/.zshrc
事前に必要なもののビルド
と書きましたが、実際にはなくてもRubyのビルドはできます。ただ、一部機能が使えなくなるなど制約が生まれるので一緒にビルドしておくことをお勧めします。
対象 | 概要 |
---|---|
libffi | Fiddleを使うため。 |
ncurses | Ruby2.1.0からはgem(curses)になった。 |
openssl | gemとか使うのに必要なので。 |
readline | irbとかpryとかで直前の入力を再利用したい。 |
pryで問題が出るので私はlessもビルドしました。
(ビルドオプションは最大公約数的にするといいかも。あと-Iとか-Lを忘れずに。)
準備
ビルドするフォルダの作成
mkdir -p ~/tmp/android/
cd ~/tmp/android/
libffi
特になし
cd ~/tmp/android/
wget ftp://sourceware.org/pub/libffi/libffi-3.0.13.tar.gz
tar xfv libffi-3.0.13.tar.gz
cd libffi-3.0.13
export CC=arm-linux-androideabi-gcc
export CXX=arm-linux-androideabi-g++
export CFLAGS='-march=armv5te -msoft-float -Os -static-libgcc'
export LDFLAGS='-static-libgcc'
CC=$CC ./configure \
--host=arm-linux-androideabi \
--with-sysroot=$SYSROOT \
---shared \
--enable-static \
--prefix=$ANDBOX/usr/local/
make && make install
ncurses
特になし
cd ~/tmp/android/
wget http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.9.tar.gz
tar xfv ncurses-5.9.tar.gz
cd ncurses-5.9
export CC=arm-linux-androideabi-gcc
export CXX=arm-linux-androideabi-g++
export CFLAGS='-march=armv5te -msoft-float -Os -static-libgcc'
export LDFLAGS='-static-libgcc'
ac_cv_header_locale_h=no ./configure \
--host=arm-linux-androideabi \
--without-cxx-binding \
--enable-multibyte \
--enable-static \
---shared \
--prefix=$ANDBOX/usr/local/
make && make install
openssl
CygwinだとMakefileに手直しが必要。
no-sharedにすると後々問題が発生。
(最近のAndroid=>4.3だとopenssl-1.x.xのほうがいいのかもしれない。参考)
cd ~/tmp/android/
wget https://www.openssl.org/source/openssl-0.9.8y.tar.gz
tar xfv openssl-0.9.8y.tar.gz
cd openssl-0.9.8y
export CC=gcc
export CXX=g++
export CFLAGS='-march=armv5te -msoft-float -Os -static-libgcc'
export LDFLAGS='-static-libgcc'
CROSS_COMPILE=arm-linux-androideabi- ./Configure \
--prefix=$ANDBOX/usr/local/ threads zlib shared no-asm linux-generic32
# ここまででMakefileができるので少々手直し
# ドキュメント何ぞ不要
-install: all install_docs install_sw
+install: all install_sw
# CygwinでNDKを使っているとパスの解釈が…
-$(RANLIB) $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/$$i.new; \
+$(RANLIB) `cygpath -m $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/$$i.new`; \
make && make install
readline
これもCygwinだとMakefileに手直しが必要。
./support/config.sub
が古くAndroid用の設定がないので対策。
ちょっとパッチもあてる。
mkdir ~/tmp/android/readline
cd ~/tmp/android/readline
wget ftp://ftp.cwru.edu/pub/bash/readline-6.3.tar.gz
tar xfv readline-6.3.tar.gz
cd readline-6.3
wget -O support/config.guess 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD'
wget -O support/config.sub 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD'
パッチ:参考
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1784,7 +1784,7 @@
exit (w == 0); /* exit 0 if wcwidth broken */
}
],
-bash_cv_wcwidth_broken=yes, bash_cv_wcwdith_broken=no,bash_cv_wcwidth_broken=no)])
+bash_cv_wcwidth_broken=yes, bash_cv_wcwidth_broken=no,bash_cv_wcwidth_broken=no)])
if test "$bash_cv_wcwidth_broken" = yes; then
AC_DEFINE(WCWIDTH_BROKEN, 1, [wcwidth is usually not broken])
fi
autoconf
export CC=arm-linux-androideabi-gcc
export CXX=arm-linux-androideabi-g++
export CFLAGS="-march=armv7-a -msoft-float -Os -static-libgcc -I$ANDBOX/usr/local/include"
export LDFLAGS="-static-libgcc -L$ANDBOX/usr/local/lib -lncurses"
export SYSROOT=$NDK_ROOT/platforms/android-9
./configure \
--host=arm-linux-androideabi \
--with-curses \
--with-sysroot=$SYSROOT \
--enable-multibyte \
--enable-static \
--enable-shared \
--prefix=$ANDBOX/usr/local/stow/readline-6.3
# MakefileをCygwin(ry
- -test -n "$(RANLIB)" && $(RANLIB) `$@
+ -test -n "$(RANLIB)" && $(RANLIB) `cygpath -m $@`
- -test -n "$(RANLIB)" && $(RANLIB) `$@
+ -test -n "$(RANLIB)" && $(RANLIB) `cygpath -m $@`
- -test -n "$(RANLIB)" && $(RANLIB) $(DESTDIR)$(libdir)/libreadline.a
+ -test -n "$(RANLIB)" && $(RANLIB) `cygpath -m $(DESTDIR)$(libdir)/libreadline.a`
- -test -n "$(RANLIB)" && $(RANLIB) $(DESTDIR)$(libdir)/libhistory.a
+ -test -n "$(RANLIB)" && $(RANLIB) `cygpath -m $(DESTDIR)$(libdir)/libhistory.a`
make && make install
Ruby
ビルド
configureをちょっと書き換えれば(たぶん)大丈夫。
ただ、Cygwinだとパスの解釈がだめだったのでconfigure実行時の記述はCygwin用に調整したもの、注意。(見たら分かると思うけど)
具体的には--with-opt-dir=`cygpath -m $ANDBOX/local`
cd ~/tmp/android/
wget http://cache.ruby-lang.org/pub/ruby/2.1/ruby-2.1.0.tar.gz
tar xfv ruby-2.1.0.tar.gz
cd ruby-2.1.0
このページのconfigureに対するパッチを参考にすると。
--- ruby-2.1.0/configure 2013-12-26 00:25:39.000000000 +0900
+++ ruby-2.1.0_mod/configure 2014-02-17 15:13:16.758781200 +0900
@@ -18846,7 +18846,9 @@
$as_echo_n "(cached) " >&6
else
if test "$cross_compiling" = yes; then :
- as_fn_error $? "cannot check setpgrp when cross compiling" "$LINENO" 5
+ #as_fn_error $? "cannot check setpgrp when cross compiling" "$LINENO" 5
+ # hack for Android
+ ac_cv_func_setpgrp_void=yes
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -19928,7 +19930,11 @@
nacl) :
LDSHARED='$(CC) -shared' ;; #(
*) :
- : ${LDSHARED='$(LD)'} ;;
+# : ${LDSHARED='$(LD)'} ;;
+# : ${LDSHARED='ld'} ;;
+# hack for Android
+ : ${LDSHARED='$(CC) -shared'} ;;
+
esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $rb_cv_dlopen" >&5
$as_echo "$rb_cv_dlopen" >&6; }
こんな感じになった。参考ページでは他の箇所もいじっていたけど、とりあえずこれでビルドできる。
mkdir ~/tmp/android/ruby-build/
cd ~/tmp/android/ruby-build/
export CC=arm-linux-androideabi-gcc
export CXX=arm-linux-androideabi-g++
export CFLAGS='-march=armv5te -msoft-float -DYAML_DECLARE_STATIC'
export LDFLAGS='-static-libgcc'
export LDSHARED='arm-linux-androideabi-gcc -shared -static-libgcc'
../ruby-2.1.0/configure \
--host=arm-linux-androideabi \
--enable-shared \
---ipv6 \
---install-doc \
--with-sysroot=$SYSROOT \
--with-opt-dir=`cygpath -m $ANDBOX/usr/local` \
--prefix=$ANDBOX/usr/local
make && make install
そして実機へ…
cd $ANDBOX/usr/local/
tar czfv ruby-2.1.0_for_android.tar.gz bin/* lib/*
これであとはruby-2.1.0_for_android.tar.gz
をAndroidの好きな場所に展開してパスとか通すだけですね!
ちなみに最初のほうで言っていたrboxの場合は、SDカードのルートに圧縮ファイルを置いたとするとrboxで
pwd #=> /data/data/jackpal.androidterm/shared_prefs/rbox/home つまり $ANDBOX/home なんです
mkdir ../usr/local
cd ../usr/local
cp /sdcard/ruby-2.1.0_for_android.tar.gz ./
tar xfv -2.1.0_for_android.tar.gz
echo "" >> ~/.zshrc
echo "export RBOX=/data/data/jackpal.androidterm/shared_prefs" >> ~/.zshrc
echo "export PATH=$RBOX/usr/local/bin:$PATH" >> ~/.zshrc
echo "export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$RBOX/usr/local/lib" >> ~/.zshrc
touch ~/.gemrc
echo "gem: --no-rdoc --no-ri" >> ~/.gemrc
これでAndroid上のRubyで便利な有理数リテラルや、キーワード引数などの新機能。
irbやpryで履歴が参照できるすばらしさを味わうことができるでしょう。
P.S.:
記憶を辿りながら書いているので間違いや、あるいはtypoがあるかもしれません。
もし見つけたら教えていただけると幸いです。