[Ecls-list] Re: ecls build under cygwin and shared libraries

Gregory Lampshire gregory_lampshire at hotmail.com
Sat Jan 5 13:25:02 UTC 2002

After fiddling some more with ecl, I was able to get shared libraries and
the compiler to work under cygwin.  However, it is not a clean, robust build
approach.  It would be helpful to know if this approach works for others as
well as where certain steps can be better integrated into the general build


For ECLS 0.5.

Approach to building ecl using a shared library and for enabling the
compiler and loader to work with shared libraries.

1) Build ecls as normal.  I used:

./configure --with-tcp

2) Install ecls as normal.

Boehm GC may have problems with the install.  You may need to cd
build/gc then make install.  Then modify the Makefile in ./build/c to
include the -I/whateverdir/src/gc/include dir during compilation.  I
also needed to do:

$ cd build/gc
$ make install

3) Modified src/h/machines.h to add shared library linker flags in the
   cygwin section (bottom of the file).  Replace /usr/local/lib/ecl
   with the destination library location.  Note the LDFLAGS,
   SHARED_LDFLAGS, and USE_DLOPEN settings may not really matter here
   as we will modify the lisp files or other headers directly in the
   next few steps.

#include <dlfcn.h>
#define USE_DLOPEN
#define LDFLAGS -L/usr/local/lib/ecl -lecl
#define SHARED_LDFLAGS --shared -L/usr/local/lib/ecl -lecl

4) Modified build/h/config.h to add #define ENABLE_DLOPEN instead of
   #undef ENABLE_DLOPEN.

5) Intentionally left blank.

6) Intentionally left blank.

7) Modify build/cmp/cmpcfg.lsp so that flags are set correctly.
   Append the following lines to the file or change the actual lines
   in the file.  It's not clear that these flags make any difference
   either give the changes made elsewhere.

(setq compiler::*ld-flags* "-L/usr/local/lib/ecl -lecl")
(setq compiler::*ld-shared-flags* "--shared -L/usr/local/lib/ecl -lecl")

For *ld-shared-flags*, the formatting string was changed so the -L and
-l parts may be redundent.

8) Modify ./src/cmp/cmpmain.lsp so all the static libraries are not

    (when (eq target :program)
      (setq ld-flags (append ld-flags '("-lecl"))))

Previous, it included a whole bunch of static libs that Cgywin should
    not try to access.

Modify the following line by appending the -lecl.  I was unable to
figure out how to add a library to the end of the shared library build
list so I just modified the format line itself and it was, of course,
important that the ecl library appear after the .o mention in the gcc
line.  Since Windows cannot have unresolved externals, we must
reference the big DLL library after the object file.

    (defvar *ld-shared-format* "~A ~A -o ~A -L~A ~{~A ~} ~A -lecl")

I think this oblivates the need to change *ld-shared-flags* above.

9) Remove files so they are rebuilt with the right configuration.

$ cd build
$ rm -f ./build/c/*.o ./build/c/*.c ./build/c/*.h ./build/c/*.data

10) Regenerate the basic ecl library with the right configuration.

cd build
rm libecl.a
make libecl.a

11) Load special compile-cygwin.lsp to compile LSP and CLOS libraries.
    Note that the statically linked ecl_min is used here.  The file
    compile-cygwin.lsp is at the bottom of this document.

$ ./ecl_min.exe < compile-cygwin.lsp

12) Combine all ecls "lisp" and dependent libraries into a single DLL.

$ gcc --Wl,--export-all-symbols --shared -o libecl.dll -Wl,--whole-archive
libgmp.a libgc.a libcmp.a libecl.a libclos.a
iblsp.a  -Wl,--no-whole-archive -Xlinker
"--out-implib=libecl.dll.a" -Xlinker "--output-def=libecl.def"

13) Create new ecl image using the dynamic library and the dlopen
     aware modules.  Use cygwin_main.c to generate the final ecl
     dynamically-linked file.  Using the source below helps ignore a
     (c::build-program ...) issue that sticks the :lisp-file libraries
     on the command line when building the excutable.

$ gcc -Wall -O -o ecl-dll ecl_cygwin.c -I/usr/local/lib/ecl/h -L./ -lecl
$ cat ecl_cygwin.c
#include <ecl.h>

#ifdef __cplusplus
#define ECL_CPP_TAG "C"
#define ECL_CPP_TAG

main(int argc, char **argv)
 extern ECL_CPP_TAG void init_CMP(cl_object);
 cl_boot(argc, argv);
 read_VV(OBJNULL, init_CMP);
 return 0;

14) Copy the old statically linked ecl.exe to a new name.

$ cp /usr/local/bin/ecl.exe /usr/local/bin/ecl-static.exe

15) Copy dll's to ecl directory and remove old libraries (if you want

$ cp libecl.dll.a /usr/local/lib/ecl
$ cp libecl.dll /usr/local/bin
$ cp ecl-dll.exe /usr/local/bin/ecl.exe

16) Put /usr/local/lib/ecl into your $PATH variable so it picks up the
   dll or put the libecl.dll into the same place that ecl is and
   ensure that the path variable is set accordingly.  Put the newly
   generated ecl.exe into the same place as well.

   $ cp ./ecl.exe /usr/local/bin

17) Nice to have.  I wish the gc and gmp headers would be included in
the /usr/local/lib/ecl/h directory as well so user code could more
easily access these headers when building your own code.


1) This build process is a mess.  Figure out the right way.

2) The init_[module name] function in a shared library seems to get called
twice.  This
   needs more investigation.

$cat compile-cygwin.lsp
;;; Configuration file for the bootstrapping version of ECL
(load "bare.lsp")

;;; ecl_min should have the DLOPEN flag defined in it's init_main()
;;; routine.  So add it now so that the cmp lisp files will load and
;;; add the code to do the shared library thing.  We comment out the
;;; dlopen build options below because we are still in static library
;;; build mode, but with the dlopen configuration inside the source
;;; files.  When this file is executed, we still have not generated
;;; the big DLL, so all we can do is build static libs.

;;; * Compile, load and link Common-Lisp base library
(setq si::*keep-documentation* nil)
(in-package "COMMON-LISP-USER")
(load "lsp/defsys.lsp")
(proclaim '(optimize (safety 2) (space 3)))
(sbt::operate-on-system lsp :library)
;(sbt::operate-on-system lsp :load)
(si::pathname-translations "SYS" '(("*.*" "./*.*")))
(setq compiler::*cc-flags* (concatenate 'string compiler::*cc-flags*
" -I/e/tmp/sandbox/ecls/src/h -I/e/tmp/sandbox/ecls/src/gmp -I/e/tmp/sandbox

;;; * Compile, load and link PCL based Common-Lisp Object System
(load "clos/defsys.lsp")
(proclaim '(optimize (safety 2) (space 3)))
(sbt::operate-on-system clos :library)
;(sbt::operate-on-system clos :load)

;;; * Compile, load and link Common-Lisp to C compiler
(load "cmp/defsys.lsp")
(proclaim '(optimize (safety 2) (space 3)))
;(sbt::operate-on-system cmp #-dlopen :library #+dlopen :shared-library)
(sbt::operate-on-system cmp :library)
;(sbt::operate-on-system cmp :load)


More information about the ecl-devel mailing list