Maxima で綴る数学の旅

紙と鉛筆の代わりに、数式処理システムMaxima / Macsyma を使って、数学を楽しみましょう

-Android- クロスコンパイル成功!新しいECLで最新のMaximaをAndroid向けにクロスコンパイル

f:id:jurupapa:20200419131536j:plain


Android端末で実行可能なMaximaのarmバイナリを作ることができました。もう少し正確にいうと、ECL 20.4.24をarmバイナリにクロスコンパイルした結果を使って、Maxima 5.43.2をarmバイナリにクロスコンパイルすることに成功しました。

 

出来上がったバイナリを実機(自分のスマホ)にadbで突っ込んで、無事に起動を確認することができました。

 

今回のクロスコンパイルは割といい感じでできたので、その辺を簡単に書きます。詳細手順についてはGithubにGistをひとつ作ったのでそちらを参照してください。

How to cross-compile Maxima for Android using ECL20.4.24 (Embeddable Common Lisp) · GitHub

このGistはステップバイステップの手順書です。

 

ロスコンパイル、この場合は、Intel cpuのホストコンピュータ上でarmバイナリを生成することを指します。MaximaAndroidで動かす際の必須の技術です。C言語ならクロスコンパイラさえ入手できれば比較的簡単なクロスコンパイル、Lisp言語ではどうすれば良いのでしょうか。

 

ECLはいにしえのKCL (Kyoto Common Lisp)の流れを組み、Lisp → C → 機械語の手順でコンパイルが進みます。(compile-file "tako.lisp")などとすると、tako.lispの中身をtako.cとtako.hに変換してから、gcc tako.cを呼び出します。結果tako.oが出来て、それをlispリンク可能なtako.fasという形式に変換します。これでcompile-fileが終了です。後から(load "tako.fas")とやると無事にLisp環境にリンクされる訳です。

このgccの代わりに、Android NDKに入っているクロスコンパイラ、この場合で言うとarmv7a-linux-android-clangと言うコマンドなのですが、を使えとcompile-file関数に教えてあげれば、tako.oもtako.fasもarmバイナリになります。この置き換え指示をどのように行うのが正しいのか、ECLのマニュアルを見てもよく分かりません。今回、ここが最初の関門でした。

考えてみると、ECLでECLをクロスコンパイルする際にこの辺の置き換えが自動的に行われています。その過程を細かく分析した結果、cmpdefs.lspと言うファイルを読み込めばコンパイラコンパイラに渡すフラグも一切合切が適切に置き換わることが分かりました。開発環境でECLを起動して、cmpdefs.lspと言うファイルを読み込んでから、(compile-file "tako.lisp")とやり、生成されたtako.fasをadbで実機に入れて、実機上のECLを起動して(load "tako.fas")で読み込み、tako.lispの中の関数を実行することができました。

Maximaは巨大なソフトで、構成ファイル間には依存関係もあります。このためコンパイルを手順に従って行うための手続きもプログラム化されています。Makefileのようなものですが、Lisp言語専用で、defsystemと呼ばれています。以前とは異なり、今回はこのdefsystemを完全に利用して、以下のコマンドでコンパイルできました。

(mk::oos "maxima" :compile :load-source-instead-of-binary t)

通常、defsystemを利用したコンパイルでは諸般の事情で生成したファイル(上記の例ならtako.fas)がすぐに読み込まれますが、ここに第2の関門があります。この場合、armバイナリなので読み込みに失敗します。それを避けるおまじない(:load-source-instead-of-binary t)をつけることで、Maxima全体のコンパイルに成功しました。

ECLやMaximaソースコード には一切変更の必要はありませんでした。