From 4c24b43755d550c21425a0a3fe6bec884db54529 Mon Sep 17 00:00:00 2001 From: Juan Jose Garcia Ripoll Date: Sat, 25 Jun 2011 23:07:33 +0200 Subject: [PATCH] Add an extra function to the shared and statically linked libraries to allow for initialization of ECL and loading of the library. --- src/CHANGELOG | 157 ++------------------------------------------ src/cmp/cmpmain.lsp | 58 +++++++++++----- src/cmp/cmpname.lsp | 19 ++++-- 3 files changed, 60 insertions(+), 174 deletions(-) diff --git a/src/CHANGELOG b/src/CHANGELOG index 17c5a086d..24717b592 100755 --- a/src/CHANGELOG +++ b/src/CHANGELOG @@ -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 *** diff --git a/src/cmp/cmpmain.lsp b/src/cmp/cmpmain.lsp index 3fe75ee1e..8bebe5478 100755 --- a/src/cmp/cmpmain.lsp +++ b/src/cmp/cmpmain.lsp @@ -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 @@ -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))) diff --git a/src/cmp/cmpname.lsp b/src/cmp/cmpname.lsp index 6ad9cdf9a..b9d06c3a9 100644 --- a/src/cmp/cmpname.lsp +++ b/src/cmp/cmpname.lsp @@ -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)))))