Add an extra function to the shared and statically linked libraries to allow for initialization of ECL and loading of the library.

This commit is contained in:
Juan Jose Garcia Ripoll 2011-06-25 23:07:33 +02:00
parent 111bf7e942
commit 4c24b43755
3 changed files with 60 additions and 174 deletions

View file

@ -1,153 +1,4 @@
ECL 11.1.1:
===========
* Bugs fixed:
- Several autoconf tests in src/aclocal.in did not work when cross compiling.
- ECL defines the feature LONG-LONG when this type is available in the
C compiler.
- When LIST, LIST*, and some other functions appeared as toplevel forms, the
interpreter compiled its arguments also as toplevel forms, causing their
execution in the wrong order.
- EXT:MAKE-FOREIGN-DATA-FROM-ARRAY now supports all unboxed types.
- ECL did not properly compute the alignment of foreign types in structures.
This is now done using standard C constructs in a portable and robust way.
- Even if a function was compiled with a given set of optimizations, a call
to PROCLAIM which appeared after the function could change the value of
those optimizations and influence what the emitted C code looked like.
- Solved a problem with type intersections between SIMPLE-ARRAY and ARRAY.
- Logical pathnames are now translated to uppercase and, when converted
into physical pathnames, translated back using case :common This means
that #P"sys:foo.fas" is parsed as
(make-pathname :host "SYS" :name "FOO" :type "FAS")
and then
(translate-logical-pathname #P"SYS:FOO.FAS")
=> "where/ecl/lives/foo.fas"
- RENAME-FILE was not able to rename directories.
- Detection of missing packages in the reader was accidentally deactivated.
- When entering the debugger the reader/printer environment is now reset
using with-standard-io-syntax. Formerly this was only done at a later
stage, causing the list of restarts to show garbage.
- We have removed the variable si::*break-enable* that was causing
INVOKE-DEBUGGER to return.
- ECL's support of :CASE has improved. Filenames preferred case is downcase,
as in every Unix, while logical pathname's case is uppercase. Conversion
between cases has also been fixed: formerly, MAKE-PATHNAME did not interpret
:CASE as the original path case, but as the destination.
- Out of the many pathname translations which are possible, ECL did not allow the
one in which missing components are replaced by the original ones, as in
'(("HM:HOME;*.*.*" "/home/user/")))
- Reduced the clutter generated by SETF expansions.
* Visible changes:
- "fasb" is now a valid FASL file type, accepted by ECL even in absence of
ASDF.
- EXT:GC ignores any argument passed to it.
- ECL's compiler now understands the unboxed type :long-long.
- A new special form, EXT:WITH-BACKEND allows us to select the code depending
on whether it is going to be processed by the interpreter or by the C
compiler.
(defun example ()
(ext:with-backend
:bytecodes (print 3)
:c/c++ (print 2)))
The two currently available backends are :bytecodes and :c/c++.
- Added accurate type proclamations for all functions in the ANSI CL
specification.
- The compiler is now shipped as a single FASL file, cmp.fas, without
extra files such as sysfun.lsp
- DECLAIM proclamation and toplevel DEFMACRO definitions do not propagate
beyond the compiled file.
- AREF/ASET can now be open-coded by the C compiler.
- Compilation policies (including optimization and safety checks) are now
defined as flags that are activated and deactivated by certain optimization
levels. In order for the flag to be active, all conditions have to be
matched. For instance
(define-policy inline-slot-access :on speed 1 :off debug 2 :off safety 2
"Inline access to structures and sealed classes")
slot inlining would be activated by a SPEED of 1, but only if DEBUG and
SAFETY are below 2.
- Important performance improvements in sequence functions, such as FIND,
SEARCH, REPLACE, POSITION, COUNT, REMOVE, DELETE, SUBSTITUTE, NSUBSTITUTE,
DELETE-DUPLICATES, REMOVE-DUPLICATES and their possible IF/IF-NOT
variants. Except COUNT, for efficiency, some of the previously mentioned
functions may run through the sequences in arbitrary orders one or more
times.
- LOOP is now capable of declaring an iteration variable to have a
more precise type (fixnum, single-float, etc), when the iteration limits
are known, as in (LOOP FOR I FROM 0 TO 1000 ....)
- ASSERT is now "cheaper", delegating the job on an auxiliary function and
not creating any nonlocal jump structures (TAGBODY, etc).
- ECL's dynamic foreign function interface, that is the FFI that works for
interpreted and evaluated code and that does not need a C compiler, now
depends on libffi -- without it, it will refuse to build.
- ECL exports a new feature, :C++, when it is built with a C++ compiler.
- Function proclamations and declarations are also used to deduce the type
of their arguments.
- (EXPT 2 -2.0d0) is now computed in double precision.
- When building programs with ASDF:MAKE-BUILD, "prebuilt-asdf" may be listed
in the dependencies, as the last one, so that ASDF is linked in. It is
required by some packages that do not distinguish between compilation and
distribution.
- ECL now captures SIGPIPE.
- In DEFMACRO forms, the &WHOLE argument may now be declared
ignorable. Formerly it was always referenced by the destructuring code of
the macro.
- ECL mistakenly allowed the rational denominator to carry a sign, as in 1/-2.
- When used with -debug and the command line options cause some error ECL
oferts an ABORT and a CONTINUE restarts.
- Loading binary files is no longer locking and can be done from several
threads simultaneously. Note, however, that this may have unexpected
consequences regarding things like creation of packages or class and
function definition.
- ECL will use long double whenever the type is avalailable AND the special
functions cosl, sinl and similar are defined.
- A new function, (EXT:DUMP-C-BACKTRACE suggested-depth) tries to print out
the sequence of compiled and C functions called up to the current point.
- --enable-rpath now defaults to YES.
- ECL now ships a Windows icon which is added to the executable at build time.
ECL 11.1.2
ECL 11.7.1:
==========
* Bugs fixed:
@ -218,6 +69,12 @@ ECL 11.1.2
- ECL no longer relies on "git" being installed to gather the git commit id
and setting (ext:lisp-implementation-vcs-id).
- When building shared and statically linked libraries, ECL creates an
extra function that performs two tasks: initializing ECL if it wasn't done
before, and initializing the library. This can be used to create standalone
libraries to be linked with other programs. The name of the function typically
begins with main_dll or main_lib but it is output by ECL on screen.
;;; Local Variables: ***
;;; mode:text ***
;;; fill-column:79 ***

View file

@ -148,6 +148,21 @@ the environment variable TMPDIR to a different value." template))
,@(split-program-options *user-ld-flags*)
,@ld-flags)))
(defun linker-ar (output-name o-name ld-flags)
#-msvc
(static-lib-ar (namestring output-name)
(list* (brief-namestring o-name) ld-flags))
#+msvc
(unwind-protect
(progn
(with-open-file (f "static_lib.tmp" :direction :output
:if-does-not-exist :create :if-exists :supersede)
(format f "/DEBUGTYPE:CV /OUT:~A ~A ~{~&\"~A\"~}"
output-name o-name ld-flags))
(safe-run-program "link" '("-lib" "@static_lib.tmp")))
(when (probe-file "static_lib.tmp")
(cmp-delete-file "static_lib.tmp"))))
(defun static-lib-ar (lib object-files)
(let ((lib (brief-namestring lib)))
(safe-run-program *ar* (list* "cr" lib (mapcar #'brief-namestring object-files)))
@ -247,7 +262,7 @@ void ~A(cl_object cblock)
}")
(defconstant +lisp-program-main+ "
int
extern int
main(int argc, char **argv)
{
cl_boot(argc, argv);
@ -259,6 +274,18 @@ main(int argc, char **argv)
si_exit(0);
}")
(defconstant +lisp-library-main+ "
extern int
~A(int argc, char **argv)
{
cl_boot(argc, argv);
CL_CATCH_ALL_BEGIN(ecl_process_env()) {
~A
read_VV(OBJNULL, ~A);
~A
} CL_CATCH_ALL_END;
}")
#+:win32
(defconstant +lisp-program-winmain+ "
#include <windows.h>
@ -302,9 +329,9 @@ or a loadable module."
(brief-namestring pathname))
((:fasl :fas)
nil)
((:static-library :lib)
((:static-library :lib :standalone-static-library :standalone-lib)
(brief-namestring pathname))
((:shared-library :dll)
((:shared-library :dll :standalone-shared-library :standalone-dll)
(brief-namestring pathname))
((:program)
nil)
@ -337,6 +364,7 @@ filesystem or in the database of ASDF modules."
(defun builder (target output-name &key lisp-files ld-flags
(init-name nil)
(main-name nil)
(prologue-code "")
(epilogue-code (when (eq target :program) '(SI::TOP-LEVEL T)))
#+:win32 (system :console)
@ -432,39 +460,35 @@ output = si_safe_eval(2, ecl_read_from_cstring(lisp_code), Cnil);
(setf output-name (compile-file-pathname output-name :type target)))
(unless init-name
(setf init-name (compute-init-name output-name :kind target)))
(unless main-name
(setf main-name (compute-main-name output-name :kind target)))
(ecase target
(:program
(format c-file +lisp-program-init+ init-name "" submodules "")
(format c-file #+:win32 (ecase system (:console +lisp-program-main+)
(:windows +lisp-program-winmain+))
#-:win32 +lisp-program-main+
prologue-code init-name epilogue-code)
prologue-code init-name epilogue-code)
(close c-file)
(compiler-cc c-name o-name)
(linker-cc output-name (list* (namestring o-name) ld-flags)))
((:library :static-library :lib)
(format c-file +lisp-program-init+ init-name prologue-code
submodules epilogue-code)
(cmpnote "Library initialization function is ~A" main-name)
(format c-file +lisp-library-main+
main-name prologue-code init-name epilogue-code)
(close c-file)
(compiler-cc c-name o-name)
(when (probe-file output-name) (delete-file output-name))
#-msvc
(static-lib-ar (namestring output-name)
(list* (brief-namestring o-name) ld-flags))
#+msvc
(unwind-protect
(progn
(with-open-file (f "static_lib.tmp" :direction :output
:if-does-not-exist :create :if-exists :supersede)
(format f "/DEBUGTYPE:CV /OUT:~A ~A ~{~&\"~A\"~}"
output-name o-name ld-flags))
(safe-run-program "link" '("-lib" "@static_lib.tmp")))
(when (probe-file "static_lib.tmp")
(cmp-delete-file "static_lib.tmp"))))
(linker-ar output-name o-name ld-flags))
#+dlopen
((:shared-library :dll)
(format c-file +lisp-program-init+ init-name prologue-code
submodules epilogue-code)
(cmpnote "Library initialization function is ~A" main-name)
(format c-file +lisp-library-main+
main-name prologue-code init-name epilogue-code)
(close c-file)
(compiler-cc c-name o-name)
(shared-cc output-name (list* o-name ld-flags)))

View file

@ -103,25 +103,30 @@ the function name it precedes."
(error "Cannot find out entry point for binary file ~A" pathname))
(compute-init-name pathname :kind kind)))
(defun compute-init-name (pathname &key (kind (guess-kind pathname)))
(defun compute-init-name (pathname &key (kind (guess-kind pathname)) (prefix nil))
(let ((filename (pathname-name (translate-logical-pathname pathname))))
(case kind
((:object :c)
(unique-init-name pathname))
((:fasl :fas)
(init-function-name "CODE" :kind :fas))
(init-function-name "CODE" :kind :fas :prefix prefix))
((:static-library :lib)
(init-function-name (remove-prefix +static-library-prefix+ filename)
:kind :lib))
:kind :lib
:prefix prefix))
((:shared-library :dll)
(init-function-name (remove-prefix +shared-library-prefix+ filename)
:kind :dll))
:kind :dll
:prefix prefix))
((:program)
"init_ECL_PROGRAM")
(concatenate 'string (or prefix "init_") "ECL_PROGRAM"))
(otherwise
(error "C::BUILDER cannot accept files of kind ~s" kind)))))
(defun init-function-name (s &key (kind :object))
(defun compute-main-name (pathname &rest args)
(apply #'compute-init-name pathname :prefix "main_" args))
(defun init-function-name (s &key (kind :object) (prefix nil))
(flet ((translate-char (c)
(cond ((and (char>= c #\a) (char<= c #\z))
(char-upcase c))
@ -148,6 +153,6 @@ the function name it precedes."
kind)))))
(setq s (map 'string #'translate-char (string s)))
(concatenate 'string
"init_"
(or prefix "init_")
(disambiguation kind)
(map 'string #'translate-char (string s)))))