Kinx Tips - 実行形式ファイルを作る
はじめに
「見た目は JavaScript、頭脳(中身)は Ruby、(安定感は AC/DC)」 でお届けしているスクリプト言語 Kinx。今回は Tips です。
- 参考
- 最初の動機 ... スクリプト言語 KINX(ご紹介)
- 個別記事へのリンクは全てここに集約してあります。
- リポジトリ ... https://github.com/Kray-G/kinx
- Pull Request 等お待ちしております。
- 最初の動機 ... スクリプト言語 KINX(ご紹介)
皆さん、実行ファイルを作る時どうしてますか? ...そう、普通は C や C++ で書いてコンパイルしますね。もっと簡単に作れるといいですね。
Kinx は独立した exe を作ることはサポートしていませんが、Kinx のワールドの中であれば exe にして単体実行コマンドのように見せかけて実行できるモジュールを作れるようにしています。
その辺を少々。
コマンド kxrepl.exe
、kxtest.exe
実は v0.13.1 リリースより kxrepl.exe
と kxtest.exe
というコマンドが同梱されています。Linux 版では .exe
はついて無くて kxrepl
と kxtest
です。
kxrepl
を実行してみましょう。
$ kxrepl
kinx[ 0]> .quit
REPL が動作しましたね。
次は kxtest
です。
$ kxtest -v -T declaration.md
Test Cout = 11
Entry: doc/spec/statement/declaration.md
Suite: Declaration statement
Case[ 0]: Normal case ................................... successful ( 0.10s)
Case[ 1]: With initializer .............................. successful ( 0.09s)
Case[ 2]: With initializer of expression ................ successful ( 0.09s)
Case[ 3]: Multiple variable declaration ................. successful ( 0.10s)
Case[ 4]: Constant value (1) ............................ successful ( 0.07s)
Case[ 5]: Constant value (2) ............................ successful ( 0.10s)
Case[ 6]: Constant value (3) ............................ successful ( 0.07s)
Case[ 7]: Constant value (4) ............................ successful ( 0.07s)
Case[ 8]: Constant value (5) ............................ successful ( 0.09s)
Case[ 9]: Destructuring assignment (1) .................. successful ( 0.09s)
Case[10]: Destructuring assignment (2) .................. successful ( 0.07s)
<Test Result>
Total Test Cases: 11
Successful : 11
Failed : 0
Warning : 0
SpecTest が動作しましたね。
もう一つ、試しにやってみましょう。
$ diff -s kxrepl kxtest
Files kxrepl and kxtest are identical
「ファイルは同一です」 というメッセージがでました。というか、そうなんです。この 2 つは バイナリとして全く同じ です。
--exec
オプションの話
この話の前に、一つ Kinx のオプションに関する情報を書いておきます。--exec
というオプションです。README にも書いてある通り、このオプションによって以下の 2 つのオプションがサポートされています。
-
--exec:repl
... REPL を実行する。 -
--exec:specttest
... SpecTest を実行する。
このメカニズムは、以下の通りになっています。
-
--exec:xxx
を認識したら、Kinx の実行ファイルのあるフォルダから見てlib/exec/xxx.kx
、またはlib/exec/3rdparty/xxx.kx
を探す。 - そのファイルがあったら、そのファイルがスクリプトファイルとして指定されたとみなして実行する。
なので、REPL と SpecTest はそれぞれ lib/exec/repl.kx
と lib/exec/spectest.kx
ファイルを探してそれを実行する、という動作をしているのです。この仕組みによって、REPL と SpecTest の修正はバイナリを修正せずに実施できるようにもなっています。
kxrepl
さて、kxrepl のバイナリ(= kxtest のバイナリ)ですが、どういう作りになっているのでしょう(概ね見当は付くと思いますが)。答えはこうです。
- 自分自身の実行ファイル名(
name
としましょう)を取得(argv[0]
から取得できます)。 - コマンドライン引数の先頭に
--exec:name
を割り込ませて引数リストを更新。 - Kinx のメインロジックに制御を渡す。
するとどうでしょう。自動的に lib/exec/name.kx
(または lib/exec/3rdparty/name.kx
)を参照して実行してくれるのです!
ということで、kxrepl
は lib/exec/kxrepl.kx
を、kxtest
は lib/exec/kxtest.kx
を自動的に実行してくれるという寸法です。
ん?、そんなファイルあったっけ?はい、追加したんです(=あります)。中身を見てみましょう。
using exec.repl;
using exec.spectest;
これだけです。中で using
するだけのファイルを用意して実現しました。using
の検索パスに従って repl.kx
と spectest.kx
を見つけてくれるので、これで正しく動作します。というわけで、kxrepl.exe
を repl.exe
に書き換えても同様に動きます。
ということで、もうお分かりですね。
オリジナル exe
を作ろう
オリジナル exe
ファイルの作り方は以下の通りです。動作には Kinx の dll と各種ライブラリが必要なので、kinx.exe
と同じ場所に、作成した exe
を置かなくてはなりませんが、やりたいことをコマンド一発でできるようにはなります。
具体的な例で。
kxcat.exe
cat
コマンドみたいなものとして、kxcat
コマンドを作ってみましょう。指定されたファイルを指定された順に出力します。cat
コマンドと名前が重ならないように kxcat
にしておきましょう。一先ずオプションは無しで、ファイルだけ複数受け付けるようにします。
$$.each {
// Ignoring the script file name.
if (_2 > 0) {
System.print(File.load(_1));
}
};
さて、そうしたら kxtest.exe
をコピーして名前を変えましょう。Windows でも Linux でもコマンドは違いますが、やりたいことは同じです。
$ copy /y kxtest.exe kxcat.exe
$ cp -f kxtest kxcat
コピーしたらそのまま kxcat
コマンドを実行!
$ ./kxcat README.md ChangeLog.md
<p align="right">
<img src="https://github.com/Kray-G/kinx/workflows/Unit%20Test/badge.svg?branch=master"/>
<img src="http://img.shields.io/badge/license-MIT-blue.svg?style=flat"/>
</p>
...(省略)
## V0.1.0 (1st Preview Release)
* Initial Release.
できましたね。
インストールされたもので実行したい場合、Linux では以下の場所に kinx
コマンドのバイナリがあるので、例えば上記の場合、kxcat
コマンドは同じ位置に配置してください。kxrepl
、kxtest
も同じ場所に配置してあります。
$ which kinx kxrepl kxtest
/usr/bin/kinx
/usr/bin/kxrepl
/usr/bin/kxtest
おわりに
C でがっつり書いてコンパイルして実行ファイルを作る、でもいいんですけど、スクリプトでササっと書いたのを実行形式ファイルにしたいですよね。かといって、必要なライブラリとか dll とかを全部含めると結構なサイズになったりするので、ここは割り切って Kinx 自体が存在する前提でコマンド化できるようにしてみました。
これはこれで便利かなー、と思います。
あと、やればすぐできるんですけど、例えば kinx.dll の位置を環境変数で指定したり、オプションで渡したりできると、.exe
ファイル自体はどこにおいても良くなるのでそのくらいの対応は今後するかも入れません(要望があれば)。xxx.exe
と同じ場所にある xxx.kx
を実行するとかね。そのほうが便利かなー。dll
の場所は何かしらの方法で指定しておく必要はありますが。
ではでは、また次回。