更新

Native Client in Ada

NACLでNativeなコード書くならAdaだろうということで試してみた。

NACLのバイナリは特殊なのでコードのコンパイルは用意されている特殊なGCCを使う(SDKですね)。これはいやな予感。ものは試しに叩いてみる。

yudai@mac% ./nacl-gcc ~/temp/example.adb
nacl-gcc: /Users/yudai/temp/example.adb: Ada compiler not installed on this system

はいはい、--enable-languages、--enable-languages。

しょうがないので、ソースをとってきてSDK自体をコンパイルする。Makefileを見る限り、GCC4.2.2になにやらパッチを当てているらしい。configureしてるところの--enable-languagesにadaを足して、ついでにgcc-ada-4.2.2.tar.bz2を拾ってきてnacl/googleclient/third_party/gccに入れておく。Makefileにtar xfする行も足しておこう。GCCのコンパイルは時間がかかるので、Linuxサーバ上で作業する。

とりあえず、Makeしてみるとエラーが出た。

cio.c: In function ‘put_int’:
cio.c:83: error: ‘stdout’ undeclared (first use in this function)
cio.c:83: error: (Each undeclared identifier is reported only once
cio.c:83: error: for each function it appears in.)
cio.c: In function ‘put_int_stderr’:
cio.c:89: error: ‘stderr’ undeclared (first use in this function)
cio.c: In function ‘put_char_stderr’:
cio.c:101: error: ‘stderr’ undeclared (first use in this function)
make[6]: *** [cio.o] Error 101make[6]: Leaving directory `/home/yudai/temp/nacl/googleclient/native_client/tools/BUILD/build-gcc-nacl/gcc/ada/rts'
make[5]: *** [gnatlib] Error 2make[5]: Leaving directory `/home/yudai/temp/nacl/googleclient/native_client/tools/BUILD/build-gcc-nacl/gcc/ada'
make[4]: *** [gnatlib-plain] Error 2makemake[4]: Leaving directory `/home/yudai/temp/nacl/googleclient/native_client/tools/BUILD/build-gcc-nacl/nacl/libada'
make[3]: *** [all-target-libada] Error 2makemakemake[3]: Leaving directory `/home/yudai/temp/nacl/googleclient/native_client/tools/BUILD/build-gcc-nacl'
make[2]: *** [all] Error 2make[2]: Leaving directory `/home/yudai/temp/nacl/googleclient/native_client/tools/BUILD/build-gcc-nacl'
make[1]: *** [gcc] Error 2make[1]: Leaving directory `/home/yudai/temp/nacl/googleclient/native_client/tools'
make: *** [build] Error 2

cio.cを見てみると、

/* Don't use macros on GNU/Linux since they cause incompatible changes between
   glibc 2.0 and 2.1#ifdef Linux#undef putchar */
#undef getchar
#undef fputc
#undef stderr
#undef stdout
#endif

あ、あんでふしてる……。とりあえず、コメントアウトしてる。

再度Makeするとまた似たようなたエラーが。直してみる。しかしエラー。何度か適当に直してみるとこんな感じのパッチのパッチが出来た。

ゴミが入っていたので修正。

*** gcc-4.2.2.patch.orig	2008-12-08 12:53:23.000000000 +0900
--- gcc-4.2.2.patch	2008-12-11 17:28:06.000000000 +0900
***************
*** 1890,1892 ****
--- 1890,2144 ----
  +++ gcc-4.2.2/stage_last	2008-11-29 16:18:47.320180000 -0800
  @@ -0,0 +1 @@
  +stage1
+ diff -Naru ../PRISTINE/gcc-4.2.2/gcc/ada/cio.c gcc-4.2.2/gcc/ada/cio.c
+ --- ../PRISTINE/gcc-4.2.2/gcc/ada/cio.c	2005-11-15 23:06:45.000000000 +0900
+ +++ gcc-4.2.2/gcc/ada/cio.c	2008-12-11 15:26:54.000000000 +0900
+ @@ -42,7 +42,7 @@
+  #include "adaint.h"
+  
+  /* Don't use macros on GNU/Linux since they cause incompatible changes between
+ -   glibc 2.0 and 2.1 */
+ +   glibc 2.0 and 2.1
+  #ifdef linux
+  #undef putchar
+  #undef getchar
+ @@ -50,6 +50,7 @@
+  #undef stderr
+  #undef stdout
+  #endif
+ +*/
+  
+  #ifdef VTHREADS
+  #undef putchar
+ !@@@@@@@@@@@@@@@@@
+ diff -Naru ../PRISTINE/gcc/ada/adaint.c gcc-4.2.2/gcc/ada/adaint.c
+ --- ../PRISTINE/gcc/ada/adaint.c	2006-02-15 18:30:39.000000000 +0900
+ +++ gcc-4.2.2/gcc/ada/adaint.c	2008-12-11 16:15:26.000000000 +0900
+ @@ -794,7 +794,7 @@
+  
+    strcpy (path, "GNAT-XXXXXX");
+  
+ -#if (defined (__FreeBSD__) || defined (linux)) && !defined (__vxworks)
+ +#if (defined (__FreeBSD__) || defined (linux) || defined (nacl)) && !defined (__vxworks)
+    return mkstemp (path);
+  #elif defined (__Lynx__)
+    mktemp (path);
+ @@ -884,7 +884,7 @@
+      free (pname);
+    }
+  
+ -#elif defined (linux) || defined (__FreeBSD__)
+ +#elif defined (linux) || defined (__FreeBSD__) || defined (nacl)
+  #define MAX_SAFE_PATH 1000
+    char *tmpdir = getenv ("TMPDIR");
+  
+ @@ -2574,8 +2574,8 @@
+  #if defined (CROSS_COMPILE)  \
+    || (! ((defined (sparc) || defined (i386)) && defined (sun) \
+        && defined (__SVR4)) \
+ -      && ! (defined (linux) && (defined (i386) || defined (__x86_64__))) \
+ -      && ! (defined (linux) && defined (__ia64__)) \
+ +      && ! ((defined (linux) || defined (nacl)) && (defined (i386) || defined (__x86_64__))) \
+ +      && ! ((defined (linux) || defined (nacl)) && defined (__ia64__))   \
+        && ! defined (__FreeBSD__) \
+        && ! defined (__hpux__) \
+        && ! defined (__APPLE__) \
+ diff -Naru ../PRISTINE/gcc-4.2.2/gcc/ada/cstreams.c gcc-4.2.2/gcc/ada/cstreams.c
+ --- ../PRISTINE/gcc-4.2.2/gcc/ada/cstreams.c	2005-07-01 10:29:17.000000000 +0900
+ +++ gcc-4.2.2/gcc/ada/cstreams.c	2008-12-11 16:43:13.000000000 +0900
+ @@ -53,7 +53,7 @@
+  
+  #ifdef linux
+  /* Don't use macros on GNU/Linux since they cause incompatible changes between
+ -   glibc 2.0 and 2.1 */
+ +   glibc 2.0 and 2.1
+  
+  #ifdef stderr
+  #  undef stderr
+ @@ -64,8 +64,8 @@
+  #ifdef stdout
+  #  undef stdout
+  #endif
+ -
+ +*/
+  #endif
+  
+  /* The _IONBF value in MINGW32 stdio.h is wrong.  */
+  diff -Naru ../PRISTINE/gcc/ada/init.c gcc-4.2.2/gcc/ada/init.c
+ --- ../PRISTINE/gcc/ada/init.c	2006-05-29 03:03:28.000000000 +0900
+ +++ gcc-4.2.2/gcc/ada/init.c	2008-12-11 16:17:34.000000000 +0900
+ @@ -632,7 +632,7 @@
+  /* GNU/Linux Section */
+  /*********************/
+  
+ -#elif defined (linux) && (defined (i386) || defined (__x86_64__) \
+ +#elif (defined (linux) || defined (nacl)) && (defined (i386) || defined (__x86_64__) \
+                            || defined (__ia64__))
+  
+  #include <signal.h>
+ diff -Naru ../PRISTINE/gcc/ada/link.c gcc-4.2.2/gcc/ada/link.c
+ --- ../PRISTINE/gcc/ada/link.c	2005-07-01 10:29:17.000000000 +0900
+ +++ gcc-4.2.2/gcc/ada/link.c	2008-12-11 16:18:04.000000000 +0900
+ @@ -162,7 +162,7 @@
+  unsigned char __gnat_using_gnu_linker = 1;
+  char *__gnat_object_library_extension = ".a";
+  
+ -#elif defined (linux)
+ +#elif (defined (linux) || defined (nacl))
+  const char *__gnat_object_file_option = "";
+  const char *__gnat_run_path_option = "-Wl,-rpath,";
+  char __gnat_shared_libgnat_default = STATIC;
+ diff -Naru ../PRISTINE/gcc/ada/sysdep.c gcc-4.2.2/gcc/ada/sysdep.c
+ --- ../PRISTINE/gcc/ada/sysdep.c	2006-05-29 03:03:28.000000000 +0900
+ +++ gcc-4.2.2/gcc/ada/sysdep.c	2008-12-11 16:18:57.000000000 +0900
+ @@ -314,7 +314,7 @@
+  }
+  #endif
+  
+ -#if defined (linux) || defined (sun) || defined (sgi) || defined (__EMX__) \
+ +#if (defined (linux) || defined (nacl)) || defined (sun) || defined (sgi) || defined (__EMX__) \
+    || (defined (__osf__) && ! defined (__alpha_vxworks)) || defined (WINNT) \
+    || defined (__MACHTEN__) || defined (__hpux__) || defined (_AIX) \
+    || (defined (__svr4__) && defined (i386)) || defined (__Lynx__) \
+ @@ -371,7 +371,7 @@
+                         int *avail,
+                         int waiting)
+  {
+ -#if defined (linux) || defined (sun) || defined (sgi) || defined (__EMX__) \
+ +#if (defined (linux) || defined (nacl)) || defined (sun) || defined (sgi) || defined (__EMX__) \
+      || (defined (__osf__) && ! defined (__alpha_vxworks)) \
+      || defined (__CYGWIN32__) || defined (__MACHTEN__) || defined (__hpux__) \
+      || defined (_AIX) || (defined (__svr4__) && defined (i386)) \
+ @@ -391,7 +391,7 @@
+        /* Set RAW mode, with no echo */
+        termios_rec.c_lflag = termios_rec.c_lflag & ~ICANON & ~ECHO;
+  
+ -#if defined(linux) || defined (sun) || defined (sgi) || defined (__EMX__) \
+ +#if (defined(linux) || defined (nacl)) || defined (sun) || defined (sgi) || defined (__EMX__) \
+      || defined (__osf__) || defined (__MACHTEN__) || defined (__hpux__) \
+      || defined (_AIX) || (defined (__svr4__) && defined (i386)) \
+      || defined (__Lynx__) || defined (__FreeBSD__)
+ diff -Naru ../PRISTINE/gcc/ada/tracebak.c gcc-4.2.2/gcc/ada/tracebak.c
+ --- ../PRISTINE/gcc/ada/tracebak.c	2006-05-29 03:03:28.000000000 +0900
+ +++ gcc-4.2.2/gcc/ada/tracebak.c	2008-12-11 16:19:21.000000000 +0900
+ @@ -354,7 +354,7 @@
+  
+  /*----------------------------- ia64 ---------------------------------*/
+  
+ -#elif defined (__ia64__) && (defined (linux) || defined (__hpux__))
+ +#elif defined (__ia64__) && ((defined (linux) || defined (nacl)) || defined (__hpux__))
+  
+  #define USE_GCC_UNWINDER
+  /* Use _Unwind_Backtrace driven exceptions on ia64 HP-UX and ia64
+ diff -Naru ../PRISTINE/gcc-4.2.2/gcc/ada/ctrl_c.c gcc-4.2.2/gcc/ada/ctrl_c.c
+ --- ../PRISTINE/gcc-4.2.2/gcc/ada/ctrl_c.c	2005-07-01 10:29:17.000000000 +0900
+ +++ gcc-4.2.2/gcc/ada/ctrl_c.c	2008-12-11 17:16:15.000000000 +0900
+ @@ -48,101 +48,9 @@
+  /* __gnat_uninstall_int_handler will reinstall the original handler */
+  void __gnat_uninstall_int_handler (void);
+  
+ -/* POSIX implementation */
+ -
+ -#if (defined (_AIX) || defined (unix)) && !defined (__vxworks)
+ -
+ -#include <signal.h>
+ -
+ -void (*sigint_intercepted) (void) = 0;
+ -
+ -struct sigaction original_act;
+ -
+ -static void
+ -__gnat_int_handler (int sig __attribute__ ((unused)))
+ -{
+ -  if (sigint_intercepted != 0)
+ -    sigint_intercepted ();
+ -}
+ -
+ -/* Install handler and save original handler. */
+ -
+ -void
+ -__gnat_install_int_handler (void (*proc) (void))
+ -{
+ -  struct sigaction act;
+ -
+ -  if (sigint_intercepted == 0)
+ -    {
+ -      act.sa_handler = __gnat_int_handler;
+ -      act.sa_flags = SA_RESTART;
+ -      sigemptyset (&act.sa_mask);
+ -      sigaction (SIGINT, &act, &original_act);
+ -    }
+ -
+ -  sigint_intercepted = proc;
+ -}
+ -
+ -/* Restore original handler */
+ -
+ -void
+ -__gnat_uninstall_int_handler (void)
+ -{
+ - if (sigint_intercepted != 0)
+ -   {
+ -     sigaction (SIGINT, &original_act, 0);
+ -     sigint_intercepted = 0;
+ -   }
+ -}
+ -
+ -/* Windows implementation */
+ -
+ -#elif defined (__MINGW32__)
+ -
+ -#include "mingw32.h"
+ -#include <windows.h>
+ -
+ -void (*sigint_intercepted) (void) = NULL;
+ -
+ -static BOOL WINAPI
+ -__gnat_int_handler  (DWORD dwCtrlType)
+ -{
+ -  switch (dwCtrlType)
+ -    {
+ -    case CTRL_C_EVENT:
+ -    case CTRL_BREAK_EVENT:
+ -      if (sigint_intercepted != 0)
+ -        sigint_intercepted ();
+ -      break;
+ -
+ -    case CTRL_CLOSE_EVENT:
+ -    case CTRL_LOGOFF_EVENT:
+ -    case CTRL_SHUTDOWN_EVENT:
+ -      break;
+ -    }
+ -}
+ -
+ -void
+ -__gnat_install_int_handler (void (*proc) (void))
+ -{
+ -  if (sigint_intercepted == NULL)
+ -    SetConsoleCtrlHandler (__gnat_int_handler, TRUE);
+ -
+ -  sigint_intercepted = proc;
+ -}
+ -
+ -void
+ -__gnat_uninstall_int_handler (void)
+ -{
+ -  if (sigint_intercepted != NULL)
+ -    SetConsoleCtrlHandler (__gnat_int_handler, FALSE);
+ -
+ -  sigint_intercepted = NULL;
+ -}
+ -
+  /* Default implementation: do nothing */
+  
+ -#else
+ +
+  
+  void
+  __gnat_install_int_handler (void (*proc) (void) __attribute__ ((unused)))
+ @@ -153,4 +61,4 @@
+  __gnat_uninstall_int_handler (void)
+  {
+  }
+ -#endif
+ +

なんかすごく適当です。ctrl_c.cとかひどい。

でもこれでも動かないんだなー。まだエラーがでる。

とりあえず今回はここまで。GCCに詳しい人に何とかしてもらいたいなぁ(チラッ。