コンパイルの詳細

nptのドキュメントです。
参照元:ANSI Common Lisp npt
前へ:インストール方法
次へ:nptコマンドの引数

2.1 手動でコンパイル

コンパイルをするには、srcディレクトリにある 全てのcファイルをコンパイルすることで実現できます。
簡単な例をあげます。

$ cc src/*.c -lm
$ ./a.out --version
npt Version 1.0.2
...
Lisp mode            ANSI-C
...

ただし、この方法でコンパイルすると、ANSI-Cモードという 機能を削減したモードでコンパイルされてしまいます。
機能が削減されていますので、Common Lispの機能を全て使うことができません。

全ての機能を使用したい場合は、 コンパイルするときに環境の種類を指定しなければなりません。
利用できる環境は下記のとおりです。

環境 #define ANSI Common Lispの機能
FreeBSD LISP_FREEBSD 全て使用可能
Linux LISP_LINUX 全て使用可能
Windows LISP_WINDOWS 全て使用可能
ANSI-C LISP_ANSIC (あるいは省略) 制限あり

例えば、FreeBSDを指定してコンパイルするときは次のように実行します。

$ cc -DLISP_FREEBSD src/*.c -lm
$ ./a.out --version
npt Version 1.0.2
...
Lisp mode            FreeBSD
...

2.2 デバッグ・リリース

通常のコンパイルでは、nptはリリースモードで行われます。
もしLISP_DEBUGを指定した場合、デバッグモードとしてコンパイルを行います。

例をあげます。

$ cc -DLISP_DEBUG -DLISP_FREEBSD src/*.c -lm
$ ./a.out --version
npt Version 1.0.2
...
Release mode         debug
...

デバッグモードとリリースモードの違いはチェックの数です。
デバッグモードではあらゆる場所にチェックのコードを配置しており、 もしチェックに違反していた場合は、プログラムが強制停止するようになっています。

一方、リリースモードではそのチェック自体が存在しないため、 デバッグモードに比べると実行が速くなります。

Lispとして使う分にはデバッグモードは必要ありませんが、 もしnptをC言語に組み込んで使用するのであれば、 少なくとも開発段階ではLISP_DEBUGを指定した方が良いかと思います。

2.3 プロンプト

プロンプトとは、入力を受け取るときに使用するモジュールです。
下記のモジュールを選択できます。

モジュール #define リンク
terme LISP_TERME
editline LISP_EDITLINE -ledit
readline LISP_READLINE -lreadline
stdin LISP_STDIN

termeは、nptのプロンプトの機能です。
FreeBSDとLinuxでは標準で使用されます。

editlineとreadlineは外部モジュールであり、 使用するには別途インストール作業が必要です。

stdinは、単純に標準入力から読み込みを行います。
履歴やカーソルの移動が使えません。

コンパイルの例を示します。

$ cc -DLISP_FREEBSD -DLISP_EDITLINE src/*.c -lm -ledit
$ ./a.out --version
npt Version 1.0.2
...
Prompt mode          editline
...

2.4 localメモリの方式変更

localメモリとは、heap領域とは別のメモリ領域であるstackのことです。
nptは起動時にheap領域のメモリをmallocにて一括で確保しますが、 localメモリをどのように確保するかを指定することができます。

通常はheapと同様、localメモリもmallocにて一括確保を行います。
もしコンパイル時にLISP_MEMORY_MALLOCを指定した場合は、 localメモリの確保を要求するたびにmallocにて確保します。

一括確保の方が速度が速く、LISP_MEMORY_MALLOCは若干遅いようです。
defineが指定された場合は nptコマンドの--versionDebug Memory trueが出現します。

2.5 ガベージコレクタ強制実行モード

ガベージコレクタとは、heap領域のメモリを掃除するための機能です。

nptでは、heap領域の使用量を監視しており、 もしメモリが圧迫されていると判断した場合は、 何らかのタイミングでガベージコレクタが実行されます。

もしコンパイル時にLISP_DEBUG_FORCE_GCが与えられた場合は、 ガベージコレクタ強制実行モードとなり、 実行できるタイミング全てでガベージコレクタが実行されるようになります。

本モードは動作が非常に遅くなります。
このモードの存在意義は、C言語にて開発しているときに メモリ破壊が生じないかを確認するためのものとなります。

2.6 Windows ANSI-Cモード

Windows環境でANSI-Cモードを使用すると、 ANSI C言語の機能だけではUnicodeのファイル名を扱えないという問題が生じます。

そこで、LISP_ANSICの代わりになる、LISP_ANSIC_WINDOWSモードを用意しました。
このモードは、ファイルのオープンにfopenではなく_wfopenを使用するので、 Unicodeのファイル名を問題なく扱うことができるようになります。

2.7 Windowsのメイン関数

Windows環境でC言語を扱うときには、 スタートアップ関数をC言語標準のmainにするのか、 あるいはWindows標準のWinMainにするのか選択できます。

nptでは、通常はmain関数を使いますが、 defineによって変更することができます。

関数 #define
main LISP_CONSOLE (または省略)
WinMain LISP_WINMAIN

ただスタートアップ関数を切り替えるだけであり、機能としての違いありません。

2.8 C++でコンパイル

nptはC++でコンパイルできることを確認しています。
コンパイルは次のようにして行います。

$ c++ -Wno-deprecated src/*.c

引数の-Wno-deprecatedは、 C++コンパイラで*.cファイルをコンパイルする際に出る 警告を抑止するためのものです。

確認は*features*で行うことができます。

$ ./a.out
*features*
(:LONG-FLOAT-80 :CPLUSPLUS :MATH-INACCURACY :NPT-64-BIT :NPT :64-BIT
 :ARCH-64-BIT :NPT-ANSI-C :ANSI-C :COMMON-LISP :ANSI-CL)

*features*の中に、:CPLUSPLUSが含まれているのがわかります。

CコンパイラとC++コンパイラで出力されるコードにほぼ違いはありませんが、 setjmpを使用しているコードがtry / catchに変更される部分があります。

2.9 デグレードモード

デグレードモードとは、C言語でテストを行うモードです。 コンパイル時にLISP_DEGRADEを付与することで実施できますが、 ソースファイルがsrcだけではなくtestにも含まれるようになるため、 単純にコンパイルすることができません。

通常このモードが必要になることはほぼないと思いますが、 実施したいのであればfreebsd_debug.shなどdebug指定のものを 使用することを考えてください。

2.10 関数番号の最大値

関数番号とは、C言語の関数ポインタを登録するときの番号です。
登録できる関数ポインタの数はデフォルトで32個ですが、 LISP_POINTER_EXTENDを指定することで変更することができます。

関数番号の個数を128個に変更する例を示します。

$ cc -DLISP_POINTER_EXTEND=128 src/*.c -lm

この例の場合、関数番号の範囲は0~127になります。

関数番号の使い方については 関数の登録をご確認ください。