[gambit-list] Example of compiling scheme file into dynamically loadable module that itself loads external dynamic library (was Re: Illegal character)

Bradley Lucier lucier at math.purdue.edu
Tue Jul 1 16:15:16 EDT 2008


On Jul 1, 2008, at 1:48 PM, Joel J. Adamson wrote:

>
> Bradley Lucier <lucier at math.purdue.edu> writes:
>
>> On Jun 30, 2008, at 4:08 PM, Joel J. Adamson wrote:
>>
>>> Did you notice anything else amiss with my compilation commands?
>>
>> If you just want to make a dynamically loadable library, it seems
>> somewhat perverse to ignore the built-in support for building
>> dynamically loadable libraries in gsc and not to define a file
>> "all.scm" that contains simply
>>
>> (include "file1.scm")
>> (include "file2.scm")
>> ...
>>
>> and then
>>
>> % gsc
>>> (compile-file "all")
>>> (load "all")
>>
>> unless you have a special reason (i.e., you need to link an external
>> library).
>
> I'm using the GNU Scientific Library: there's actually quite a bit of
> foreign code in these modules.
>
> Your approach makes a lot of sense, but the files I'm compiling are
> "headers" that include the conceptually linked parts of the  
> program: all
> the gsl-interfacing code is (include)d in "gsl_genx.scm," all the  
> srfis
> are in "srfi.scm" and so on.

 From the gambit documentation:

> The `-ld-options-prelude' and `-ld-options' options are only  
> meaningful when a dynamically loadable object file is being  
> generated (neither the `-c' or `-link' options are used). The `-ld- 
> options-prelude' and `-ld-options' options add the specified  
> options to the command that invokes the C linker (the options in ld- 
> options-prelude are passed to the C linker before the input file  
> and the options in ld-options are passed after). The main use of  
> this option is to specify additional object files or libraries that  
> need to be linked, or any C linker option that is different from  
> the default (such as the library search path and flags to select  
> between static and dynamic linking). For example:
>  	
>
> $ gsc -ld-options "-L/usr/X11R6/lib -lX11 -dynamic" bench.scm


Well, in fact, these options do nothing of the sort, but they give  
the right idea.  (Marc, the gsc-cc-o.bat command on my linux box is

> gcc  -Wall -W -Wno-unused -O1 -fno-math-errno -fschedule-insns2 - 
> fno-trapping-math -fno-strict-aliasing -fwrapv -fomit-frame-pointer  
> -fPIC -fno-common -mieee-fp -rdynamic -shared -I"$ 
> {GSC_CC_O_GAMBCDIR}include" -D___DYNAMIC -D___SINGLE_HOST -o "$ 
> {GSC_CC_O_OBJ_FILENAME}" ${GSC_CC_O_CC_OPTIONS} $ 
> {GSC_CC_O_LD_OPTIONS_PRELUDE} "${GSC_CC_O_C_FILENAME_BASE}" $ 
> {GSC_CC_O_LD_OPTIONS}


The GSC_CC_O_LD_OPTIONS_PRELUDE and GSC_CC_O_LD_OPTIONS are just  
passed to gcc, if gcc doesn't pass them along to ld, then they're not  
passed along to ld.  In particular, you just concatenate $ 
{GSC_CC_O_CC_OPTIONS} and ${GSC_CC_O_LD_OPTIONS_PRELUDE}. The  
documentation is way misleading.)

Here's an example of how to build a dynamically-loadable scheme  
module that itself loads a dynamic library.

For this example I built fftw-2.1.5 (because I had a program around  
that used the version 2 API, not the version 3 API), after  
configuring with

>    171  15:12   ./configure --enable-shared --prefix=/export/users/ 
> lucier//local/fftw-2.1.5


You need to have a shared library, hence the --enable-shared.  I also  
just put it in my home directory, hence the --prefix=/export/users/ 
lucier//local/fftw-2.1.5

Here's fftbasic.scm:


> ;;; start fftbasic.scm
>
> (c-declare
> "
> #include \"fftw.h\"
>
> fftwnd_plan p;
>
> ")
>
> (define fftw2d_create_plan_backward
>   (c-lambda ()
>             void
>             "p = fftw2d_create_plan(64,
>                                     64,
>                                     FFTW_BACKWARD,
>                                     FFTW_ESTIMATE | FFTW_IN_PLACE);
>             "))
>
> (define fftw2d_create_plan_forward
>   (c-lambda ()
>             void
>             "p = fftw2d_create_plan(64,
>                                     64,
>                                     FFTW_FORWARD,
>                                     FFTW_ESTIMATE | FFTW_IN_PLACE);
>             "))
>
> ;;; Both forward and backward ffts, depends on which way the plan  
> was created.
>
> (define fftwc
>   (c-lambda (scheme-object)
>             void
>             "
> int j; double *fp = (double *)((___WORD)___BODY_AS 
> (___arg1,___tSUBTYPED));
>   fftwnd_one(p,
>              (fftw_complex *)(fp),
>              NULL);
>   for (j = 0; j < 64 * 64 * 2; j++)
>     fp[j] *= .015625;
> "))
>
> ;;; end fftbasic.scm


and here's the command to compile fftbasic.scm to fftbasic.o1; when  
fftbasic.o1 is loaded into gsc, it will dynamically load libfftw.so.2:

> euler-315% gsc -cc-options "-I/export/users/lucier/local/fftw-2.1.5/ 
> include" -ld-options "-L/export/users/lucier/local/fftw-2.1.5/lib/ - 
> Wl,-rpath,/export/users/lucier/local/fftw-2.1.5/lib/ -lfftw"  
> fftbasic.scm
> euler-316% gsc
> Gambit v4.2.8
>
> > (load "fftbasic")
> "/export/users/lucier/programs/gambc-v4_2_8/test-load-options/ 
> fftbasic.o1"
> > fftwc
> #<procedure #2 fftwc>
> >
> *** EOF again to exit
> euler-317% ldd fftbasic.o1
>         libfftw.so.2 => /export/users/lucier/local/fftw-2.1.5/lib/ 
> libfftw.so.2 (0x0000002a9565a000)
>         libc.so.6 => /lib64/tls/libc.so.6 (0x0000002a957aa000)
>         libm.so.6 => /lib64/tls/libm.so.6 (0x0000002a959df000)
>         /lib64/ld-linux-x86-64.so.2 (0x000000552aaaa000)


The -Lpath command tells where ld is to find the libfftw at link  
time, the -rpath command (which uses "-Wl," to *really* pass it to  
the linker) tells the loader where to find libfftw at load time, the - 
I command says where to find fftw.h at compile time.

Brad



More information about the Gambit-list mailing list