Guile on the NGW100You are here: Andrew Ho > Software > NGW100 > Packages > Guile Guile is a GNU implementation of the Scheme programming language, which is designed to be easily embeddable and extensible in C. It also conveniently includes bindings for Unix functions like file and socket I/O, making it a good general purpose scripting language. Among Scheme interpreters, its footprint and speed are in the middle of the road. This page documents some hacks I have had to apply to build Guile for the NGW100. For information on setting up the buildroot based cross-compilation environment, see my page on buildroot for NGW100 on CentOS 5.3; and for other packages, see my page on building packages for the NGW100. For the examples on this page, I use $BUILDROOT to represent the buildroot top-level directory, which is the one with the top level makefile; $AVR32 to represent $BUILDROOT/build_avr32/staging_dir, which contains the actual cross-compilation tools; and $NGW100 to represent $BUILDROOT/project_build_avr32/atngw100/root, which contains the actual root filesystem for the NGW100 target. I built the most recent versions available at the time of build: Guile 1.8.7, Libtool 2.2, and GMP 4.3.1. PrerequisitesThe Guile build process requires GNU libtool and the GMP bignum library. It is sufficient to cross compile these and have the static libraries available during the Guile build time; you do not need to install them separately on the NGW100, and I did not figure out how to make these available as DLLs. Building libtoolTODO: add details. CC=$AVR32/bin/avr32-linux-gcc \ LDFLAGS='-L$AVR32/lib' \ CPPFLAGS='-I$AVR32/include' \ CPP=$AVR32/bin/avr32-linux-cpp \ CXX=$AVR32/bin/avr32-linux-g++ \ CXXCPP=$AVR32/bin/avr32-linux-cpp \ ./configure --host=avr --build=avr-unknown-none \ --enable-shared --enable-ltdl-install Install it in a temporary location: make install prefix=/var/tmp/guile-support Building libgmpTODO: add details. CC=$AVR32/bin/avr32-linux-gcc \ LDFLAGS='-L$AVR32/lib' \ CPPFLAGS='-I$AVR32/include' \ CPP=$AVR32/bin/avr32-linux-cpp \ CXX=$AVR32/bin/avr32-linux-g++ \ CXXCPP=$AVR32/bin/avr32-linux-cpp \ ./configure --host=avr --build=avr-unknown-none \ --enable-shared Install it in a temporary location: make install prefix=/var/tmp/guile-support Building GuileTODO: add detailed notes. I had to build libtool and libgmp (although these did not need to be installed onto the NGW100, and were only needed during building). Then, I had to perform some manual configure hacking, edit config.h after configure, create a fake library that exports an empty __cxa_atexit() function, and manually run one of the build steps. Modify configureDisable some configure tests which fail, apparently spuriously: @@ -12299,6 +12299,7 @@ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi +cat >> /dev/null << end_libltdl_check { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_ltdl_lt_dlinit" >&5 $as_echo "$ac_cv_lib_ltdl_lt_dlinit" >&6; } if test "x$ac_cv_lib_ltdl_lt_dlinit" = x""yes; then @@ -12313,6 +12314,7 @@ $as_echo "$as_me: error: libltdl not found. See README." >&2;} { (exit 1); exit 1; }; } fi +end_libltdl_check if test "${ac_cv_header_ltdl_h+set}" = set; then { $as_echo "$as_me:$LINENO: checking for ltdl.h" >&5 @@ -35053,6 +35055,7 @@ if test "$with_threads" = pthreads; then +cat >> /dev/null << end_pthread_attr_getstack_check_part1 { $as_echo "$as_me:$LINENO: checking whether pthread_attr_getstack works for the main thread" >&5 $as_echo_n "checking whether pthread_attr_getstack works for the main thread... " >&6; } old_CFLAGS="$CFLAGS" @@ -35121,12 +35124,14 @@ ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then +end_pthread_attr_getstack_check_part1 works=yes cat >>confdefs.h <<\_ACEOF #define PTHREAD_ATTR_GETSTACK_WORKS 1 _ACEOF +cat >> /dev/null << end_pthread_attr_getstack_check_part2 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 @@ -35138,6 +35143,7 @@ rm -rf conftest.dSYM rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi +end_pthread_attr_getstack_check_part2 CFLAGS="$old_CFLAGS" Modify config.hManually disable a couple library functions which had unresolved symbol errors when run on the NGW100 with only stock libraries: @@ -708,7 +708,7 @@ #define HAVE_TM_ZONE 1 /* Define to 1 if you have the `trunc' function. */ -#define HAVE_TRUNC 1 +#define HAVE_TRUNC 0 /* Define to 1 if you have the `truncate' function. */ #define HAVE_TRUNCATE 1 @@ -739,7 +739,7 @@ #define HAVE_UNSETENV 1 /* Define to 1 if csqrt is bug-free */ -#define HAVE_USABLE_CSQRT 1 +#define HAVE_USABLE_CSQRT 0 /* Define to 1 if you have the `usleep' function. */ #define HAVE_USLEEP 1 TODO: add details on error messages. guile: can't resolve symbol '__cxa_atexit' guile: can't resolve symbol 'trunc' Segmentation fault Disable __cxa_atexit()TODO: add background, explanation, and links. Even with a --disable-__cxa_atexit configure option, the generated guile binary still dies on the NGW100 with a "can't resolve symbol '__cxa_atexit'" error. The solution is to stub it out with a dummy function. Create a file disable__cxa_atexit.c in the libguile subdirectory, with the following line in it: void __cxa_atexit(void (*arg1)(void*), void* arg2, void* arg3) {} Create an object file using the cross compiler: $AVR32/bin/avr32-linux-gcc -c disable__cxa_atexit.c Build GuileRun the configure script: CC=$AVR32/bin/avr32-linux-gcc \ LDFLAGS='-L$AVR32/lib -L/var/tmp/guile-support/lib' \ CPPFLAGS='-I$AVR32/include -I/var/tmp/guile-support/include' \ CPP=$AVR32/bin/avr32-linux-cpp \ CXX=$AVR32/bin/avr32-linux-g++ \ CXXCPP=$AVR32/bin/avr32-linux-cpp \ ./configure --host=avr --build=avr-unknown-none \ --disable-discouraged --disable-deprecated --disable-elisp \ --disable-__cxa_atexit The make command dies on the link step when trying to create the guile binary. You have to change to the libguile subdirectory, and re-run the failing link step, adding the path to libltdl.a, the path to disable__cta_atexit.o, and an -lltdl library link flag. TODO: add details, including error messages and command lines. Install Standard LibraryGuile will not start up (even for guile -h) without at least some basic ice-9 libraries, which you can point it at with the GUILE_LOAD_PATH environment variable, if necessary: ERROR: In procedure primitive-load-path: ERROR: Unable to find file "ice-9/boot-9.scm" in load path To fix this, I simply installed Guile 1.8 on a regular Linux box, and just copied /usr/share/guile/1.8 to /usr/local/share/guile/1.8 on the NGW100, which happens to already be in the built-in %load-path list on the Guile built using the instructions on this page. Build VerificationFor a Guile "hello, world" equivalent, run guile to get to the interactive Guile read-eval-print loop: (+ 1 1) You should see the expected result of 2. Test that networking works by fetching a web page (this example is similar to one from the network socket examples from the Guile reference manual): (use-modules (ice-9 rdelim)) (define (last-in-vector vec) (vector-ref vec (- (vector-length vec) 1)) ) (define (hostname->ip hostname) (car (map inet-ntoa (last-in-vector (gethostbyname hostname)))) ) (let ((s (socket PF_INET SOCK_STREAM 0))) (connect s AF_INET (inet-aton (hostname->ip "www.google.com")) 80) (display "GET / HTTP/1.0\r\n\r\n" s) (do ((line (read-line s) (read-line s))) ((eof-object? line)) (display line) (newline) )) If successful, you should see an HTTP/1.1 response, including headers, with an entity body with the Google front page HTML. |