アクトインディ開発者ブログ

子供とお出かけ情報「いこーよ」を運営する、アクトインディ株式会社の開発者ブログです

KLICのビルド


2016/9/13追記

version 3.01が出ていました。この記事は不要になりました。 http://www.ueda.info.waseda.ac.jp/software-j.html


こんにちは、akiyama です。

アクトインディ Advent Calendar 2015 の10日目の記事です。

弊社のchibaからGHCの本を借りたので、実際に動かしてみたいと思いKLICをビルドしました。
ビルド環境はMacOSX 10.10.5 Apple LLVM version 7.0.0 (clang-700.1.76)です。

(余談ですがKLICをなぜかKL1Cだと読み待ちがえたまま覚えていて、 口頭でKLICと聞いたときに同じものだと認識できていませんでした)

まず、 http://www.ueda.info.waseda.ac.jp/~kaneki/klic/klic_top.html より klic-3.005-extio-shared.tar.gzをダウンロードします。
展開してディレクトリに移動するとConfigureという実行可能ファイルがあるので、これを実行してみます。

# This is version of KLIC contains its sequential core,
# a distributed parallel implementation and a shared memory parallel
# implementation that works either on Sparc-based system with Solaris
# 2.X or Alpha-based system with DEC OSF/1 with gcc

などと歴史を感じるメッセージが表示され感慨深いものがあります。

そのまま質問に答えていくと、次のメッセージとともにアボートします。

!!! Couldn't locate libc.a in directories  /usr/lib /usr/local/lib !!!
Aborting KLIC configuration script

Configureを読んでみるとこのエラーはlibcを見つけられなかったりnmで抽出したシンボルの検出に失敗して出ているようなのでConfigureを修正します。

diff --git a/Configure b/Configure
index 7fc15e5..e43babd 100755
--- a/Configure
+++ b/Configure
@@ -799,7 +799,7 @@ esac
 KLICLDFLAGS="$KLICLDFLAGS $XLDFLAGS"

 LIBPATH=""
-for dir in /lib /usr/lib /usr/local/lib; do
+for dir in /lib /usr/lib /usr/local/lib /usr/lib/system; do
     if test -d $dir; then
  LIBPATH="$LIBPATH $dir"
     fi
@@ -829,7 +829,7 @@ echo ' '

 LIBNAMES=""
 locate_file libc_s.a f $LIBPATH && LIBNAMES="$LIBNAMES libc_s"
-( locate_file libm.a f $LIBPATH || locate_file libm.so f $LIBPATH ) \
+( locate_file libm.a f $LIBPATH || locate_file libm.so f $LIBPATH || locate_file libm.dylib f $LIBPATH) \
  && LIBNAMES="$LIBNAMES libm"
 ( locate_file libelf.a f $LIBPATH || locate_file libelf.so f $LIBPATH ) \
  && LIBNAMES="$LIBNAMES libelf"
@@ -846,6 +846,7 @@ echo ' '
 locate_file libc.a f $LIBPATH ||
 locate_file libc_s.a f $LIBPATH ||
 locate_file libc.so f $LIBPATH ||
+locate_file libsystem_c.dylib f $LIBPATH ||
 give_up_config "Couldn't locate libc.a in directories $LIBPATH"
 LIBFILES="$where"
 echo $n "# Using library file(s):"$c
@@ -857,6 +858,9 @@ for lib in $LIBNAMES; do
 # for SGI IRIS IRIX 5.2
     LIBFILES="$LIBFILES $where"
     echo $n " $where"$c
+  elif locate_file $lib.dylib f $LIBPATH; then
+    LIBFILES="$LIBFILES $where"
+    echo $n " $where"$c
   else
     give_up_config "Couldn't find $lib.a in $LIBPATH"
   fi
@@ -945,7 +949,7 @@ try_sed()
     return
 }

-try_sed 's/^.* [ATDSIW]  *[_.]*//p' 's/^.* [ATDSIW] //p' ||
+try_sed 's/^.* [ATDSIW]  *[_.]*//p' 's/^.* [ATDSIW] //p' 's/ (.*)$//p' ||
 try_sed 's/^__*//' 's/^\([a-zA-Z_0-9$]*\).*xtern.*/\1/p' ||
 try_sed '/|UNDEF/d' '/FUNC..GL/s/^.*|__*//p' ||
 try_sed 's/^.* D __*//p' 's/^.* D //p' ||

自前でlibフィイルからシンボル検索して使えるか判断してるあたり時代を感じます。

Configureが実行できるようになったので設定します。

ここで重要なのは DEF_BUILD_DLL=’no’ です。ついこれをYESにしてだいぶはまりました。 後でわかったことですが、KLICはkl1ファイルをCに変換してコンパイルします。
そのさいに、module_mainという関数が定義されruntimeから呼ばれます。
runtime自体にはmodule_mainが含まれていないため、 dllにしてしまうとruntimeのリンク時にundefined symbolになってしまいビルドができません。
なのでstatic linkでビルドし、kl1ファイルコンパイル時に埋め込む形になります。
(dllで動く方法ありましたら教えてください)

その他の設定はこんなかんじです。とりあえずはまりそうなパラレルなどは無効にしています。

DEF_PARALLEL='no'
DEF_CC='gcc'
DEF_OPTLEVEL='2'
DEF_DEBUGFLAGS='-g'
DEF_UOPTFLAGS='-fomit-frame-pointer'
DEF_KLICCFLAGS='none'
DEF_FORT='none'
DEF_USECC_AS_LD='yes'
DEF_TYPE='linux'
DEF_BUILD_DLL='no'
DEF_LN='ln -s'
DEF_ASYNCIO='yes'
DEF_DIRPREFIX='/usr/local'
DEF_USE_DEFAULT_SETTING='yes'
DEF_LIBPATH=' /usr/lib /usr/local/lib /usr/lib/system'
DEF_INCLUDEDIR='/usr/include'
DEF_LIBNAMES=' libm'
DEF_KLICINCLUDE='/usr/local/include'
DEF_SPKLICINCLUDE='yes'
DEF_INSTPARALLEL='0'

Configureが終わればMakefileが出力されるので一気にビルドしたいところですが、 K&R Cということもありclangではコンパイルエラーが起こりました。
大体がインクルード時に大域変数の重複宣言なってしまっていたり、未定義シンボルだったりするので一つずつ潰していきます。
DLL YESしてしまってmodule_main(とそれを保持するpredicate_main_xmain_0)の参照エラーさえなければ簡単だと思います。
ちょっと長くなりますが、最終的な差分は次の通りになります。

diff --git a/Configure b/Configure
index 7fc15e5..e43babd 100755
--- a/Configure
+++ b/Configure
@@ -799,7 +799,7 @@ esac
 KLICLDFLAGS="$KLICLDFLAGS $XLDFLAGS"

 LIBPATH=""
-for dir in /lib /usr/lib /usr/local/lib; do
+for dir in /lib /usr/lib /usr/local/lib /usr/lib/system; do
     if test -d $dir; then
  LIBPATH="$LIBPATH $dir"
     fi
@@ -829,7 +829,7 @@ echo ' '

 LIBNAMES=""
 locate_file libc_s.a f $LIBPATH && LIBNAMES="$LIBNAMES libc_s"
-( locate_file libm.a f $LIBPATH || locate_file libm.so f $LIBPATH ) \
+( locate_file libm.a f $LIBPATH || locate_file libm.so f $LIBPATH || locate_file libm.dylib f $LIBPATH) \
  && LIBNAMES="$LIBNAMES libm"
 ( locate_file libelf.a f $LIBPATH || locate_file libelf.so f $LIBPATH ) \
  && LIBNAMES="$LIBNAMES libelf"
@@ -846,6 +846,7 @@ echo ' '
 locate_file libc.a f $LIBPATH ||
 locate_file libc_s.a f $LIBPATH ||
 locate_file libc.so f $LIBPATH ||
+locate_file libsystem_c.dylib f $LIBPATH ||
 give_up_config "Couldn't locate libc.a in directories $LIBPATH"
 LIBFILES="$where"
 echo $n "# Using library file(s):"$c
@@ -857,6 +858,9 @@ for lib in $LIBNAMES; do
 # for SGI IRIS IRIX 5.2
     LIBFILES="$LIBFILES $where"
     echo $n " $where"$c
+  elif locate_file $lib.dylib f $LIBPATH; then
+    LIBFILES="$LIBFILES $where"
+    echo $n " $where"$c
   else
     give_up_config "Couldn't find $lib.a in $LIBPATH"
   fi
@@ -945,7 +949,7 @@ try_sed()
     return
 }

-try_sed 's/^.* [ATDSIW]  *[_.]*//p' 's/^.* [ATDSIW] //p' ||
+try_sed 's/^.* [ATDSIW]  *[_.]*//p' 's/^.* [ATDSIW] //p' 's/ (.*)$//p' ||
 try_sed 's/^__*//' 's/^\([a-zA-Z_0-9$]*\).*xtern.*/\1/p' ||
 try_sed '/|UNDEF/d' '/FUNC..GL/s/^.*|__*//p' ||
 try_sed 's/^.* D __*//p' 's/^.* D //p' ||
diff --git a/include/klic/basic.h b/include/klic/basic.h
index ac92038..c12cbd5 100644
--- a/include/klic/basic.h
+++ b/include/klic/basic.h
@@ -35,10 +35,12 @@

 typedef void voidfn ();

+#ifndef IN_DEBUG_C
 extern NoReturn voidfn fatal;
 extern NoReturn voidfn fatalf;
 extern NoReturn voidfn fatalp;
 extern void debug_printf();
+#endif

 /*
   PARALLEL flag is DIST || SHM.
diff --git a/include/klic/g_basic.h b/include/klic/g_basic.h
index 223a156..56dcbb0 100644
--- a/include/klic/g_basic.h
+++ b/include/klic/g_basic.h
@@ -133,9 +133,10 @@ extern q** make_larger_stack();
   external functions
 */

+#ifndef DEFINE_GLOBAL
 #ifdef __GNUC__
 extern Volatile voidfn G_error;
 #else
 extern voidfn G_error;
 #endif
-
+#endif
diff --git a/include/klic/options.h b/include/klic/options.h
index 9a27441..3b87e9b 100644
--- a/include/klic/options.h
+++ b/include/klic/options.h
@@ -20,8 +20,6 @@ enum argtype {
     ARG_NOT_USED
 };

-extern Const struct opttable opttable[];
-
 char *parse_opts();

 /* not copied when spawned */
diff --git a/include/klic/timing.h b/include/klic/timing.h
index 6553f31..d722334 100644
--- a/include/klic/timing.h
+++ b/include/klic/timing.h
@@ -24,6 +24,10 @@
 #include <sys/times.h>
 #include <sys/param.h>

+#ifndef HZ
+#define HZ 60
+#endif
+
 #define  tick2msec(n)   ((n)*1000.0/HZ)

 #define     timerstruct    struct tms
diff --git a/runtime/bb.c b/runtime/bb.c
index d3e1187..c041219 100644
--- a/runtime/bb.c
+++ b/runtime/bb.c
@@ -260,7 +260,7 @@ q bblt_fix_2(x)

  type_error:
   builtin_2_type_error(x,
-    predicate_floating__arithmetics_xfloating__point__to__integer_2,
+    &amp;predicate_floating__arithmetics_xfloating__point__to__integer_2,
           "fix/2");
  suspend_x:
   return suspend_builtin_2(x,
diff --git a/runtime/debug.c b/runtime/debug.c
index fa8fa8f..1978bf3 100644
--- a/runtime/debug.c
+++ b/runtime/debug.c
@@ -8,6 +8,7 @@
 #include <setjmp.h>
 #include <ctype.h>
 #include <errno.h>
+#define IN_DEBUG_C
 #include <klic/basic.h>
 #include <klic/struct.h>
 #include <klic/primitives.h>
diff --git a/runtime/generic.c b/runtime/generic.c
index 93418f2..c55194a 100644
--- a/runtime/generic.c
+++ b/runtime/generic.c
@@ -5,6 +5,7 @@
 %       (Read COPYRIGHT-JIPDEC for detailed information.)
 ----------------------------------------------------------- */

+#define DEFINE_GLOBAL
 #include <klic/gdobject.h>
 #include <klic/functorstuffs.h>
 #include <klic/atomstuffs.h>
diff --git a/runtime/print.c b/runtime/print.c
index 91ab677..a8a9533 100644
--- a/runtime/print.c
+++ b/runtime/print.c
@@ -15,18 +15,11 @@
 #include <klic/gobj.h>
 #include <klic/susp.h>

-print_partially(x, depth, length)
-     q x;
-     unsigned long depth, length;
-{
-  fprint_partially(stdout, x, depth, length);
-}
-
 #ifdef DEBUGLIB
 int verbose_print;
 #endif

-fprint_partially(stream, x, depth, length)
+void fprint_partially(stream, x, depth, length)
      FILE *stream;
      q x;
      unsigned long depth, length;
@@ -156,6 +149,13 @@ fprint_partially(stream, x, depth, length)
   return;
 }

+print_partially(x, depth, length)
+     q x;
+     unsigned long depth, length;
+{
+  fprint_partially(stdout, x, depth, length);
+}
+
 fprint(stream, x)
      FILE *stream;
      q x;
diff --git a/runtime/unify.c b/runtime/unify.c
index 06b008d..8008033 100644
--- a/runtime/unify.c
+++ b/runtime/unify.c
@@ -41,7 +41,7 @@ extern struct predicate predicate_unify__term__dcode_xunify__goal_2;

 /* Resume a goal with the same priority as current */

-Inline void resume_same_prio(gp)
+void resume_same_prio(gp)
      struct goalrec *gp;
 {
   declare_globals;
@@ -60,7 +60,7 @@ Inline void resume_same_prio(gp)
   by the unification with `y'
 */

-Inline q *resume_goals(allocp, x, y)
+q *resume_goals(allocp, x, y)
      q * allocp;
      q x;
      q y;

ビルドが通ったらテストを実行します。

make tests
...
...
...
echo 'Seq. impl.: OK' >tests.log

無事テストも完走しました。これでKLICを実行できるようになりました。
actindiの公用プログラミング言語 にKL1を追加できるよう使ってみたいと思います。