newdoc: add chapter about building

Covers c::build-* functions.
This commit is contained in:
Daniel Kochmański 2016-11-27 22:13:27 +01:00
parent e7122e49e9
commit 0caefbabcd
2 changed files with 286 additions and 2 deletions

View file

@ -0,0 +1,284 @@
@node System building
@section System building
@menu
* Compiling with ECL::
@c * Compiling with Matroska::
@c * Compiling with ASDF::
@end menu
@cindex System building
@cindex Creating executables and libraries
@node Compiling with ECL
@subsection Compiling with ECL
In this section we will introduce topics on compiling Lisp programs. ECL
is especially powerful on combining lisp programs with C programs. You
can embed ECL as a lisp engine in C programs, or call C functions via
@ref{Foreign Function Interface}. We explain file types generated by
some compilation approaches. GNU/Linux system and gcc as a development
environment are assumed.
You can generate following files with ECL.
@enumerate
@item Portable FASL file (.fasc)
@item Native FASL file (.fas, .fasb)
@item Object file (.o)
@item Static library
@item Shared library
@item Executable file
@end enumerate
Relations among them are depicted below:
@float Figure,fig:file_types
@caption{Build file types}
@image{figures/file-types}
@end float
@node Portable FASL (fasc)
@subsubsection Portable FASL
@cindex Portable FASL
ECL provides two compilers (bytecodes compiler, and C/C++
compieler). Portable FASL files are build from source lisp files by the
bytecodes compiler. Generally FASC files are portable across
architectures and operating systems providing convenient way of shipping
portable modules. Portable FASL files may be concatenated, what leads to
bundles. FASC files are faster to compile, but generally slower to run.
@exindex Building Portable FASL file
@lisp
;; install bytecodes compiler
(ext:install-bytecodes-compiler)
;; compile hello.lisp file to hello.fasc
(compile-file "hello1.lisp")
(compile-file "hello2.lisp")
;; reinitialize C/C++ compiler back
(ext:install-c-compiler)
;; FASC file may be loaded dynamically from lisp program
(load "hello1.fasc")
;; ... concatenated into a bundle with other FASC
(with-open-file (output "hello.fasc"
:direction :output
:if-exists :supersede)
(ext:run-program
"cat" '("hello1.fasc" "hello2.fasc") :output output))
;; ... and loaded dynamically from lisp program
(load "hello.fasc")
@end lisp
@node Native FASL
@subsubsection Native FASL
@cindex Native FASL
@ftindex DLOPEN
@cfindex --enable-shared [YES|no]]
If you want to make a library which is loaded dynamically from lisp
program, you should choose fasl file format. Under the hood native fasls
are just a shared library files.
This means you can load fasl files with @code{dlopen} and initialize it
by calling a init function from C programs, but this is not an intended
usage. Recommended usage is loading fasl files by calling load lisp
function. To work with @emph{Native FASL files} ECL has to be compiled
with @code{--enable-shared} configure option (enabled by default).
Creating a fasl file from one lisp file is very easy.
@lisp
(compile-file "hello.lisp")
@end lisp
To create a fasl file from more lisp files, firstly you have to compile
each lisp file into an object file, and then combine them with
c:build-fasl.
@exindex Building native FASL
@lisp
;; generates hello.o
(compile-file "hello.lisp" :system-p t)
;; generates goodbye.o
(compile-file "goodbye.lisp" :system-p t)
;; generates hello-goodbye.fas
(c:build-fasl "hello-goodbye"
:lisp-files '("hello.o" "goodbye.o"))
;; fasls may be built from mix of objects and libraries (both shared and
;; static)
(c:build-fasl "mixed-bundle"
:lisp-files '("hello1.o" "hello2.a" "hello3.so"))
@end lisp
@node Object file
@subsubsection Object file
Object file works as an intermediate file format. If you want to compile
more than two lisp files, you might better to compile with a :system-p t
option, which generates object files (instead of a fasl).
On linux systems, ECL invokes gcc -c for generating object files.
An object file consists of some functions in C:
@itemize
@item Functions corresponding to Lisp functions
@item The initialization function which registers defined functions on the lisp environment
@end itemize
Consider the example below.
@lisp
(defun say-hello ()
(print "Hello, world"))
@end lisp
@cindex Object file internal layout
During compilation, this simple lisp program is translated into the C
program, and then compiled into the object file. The C program contains
two functions:
@itemize
@item @code{static cl_object L1say_hello}:
'say-hello' function
@item @code{ECL_DLLEXPORT void _eclwm2nNauJEfEnD_CLSxi0z(cl_object flag)}:
initialization function
@end itemize
In order to use these object files from your C program, you have to call
initialization functions before using lisp functions (such as
@code{say-hello}). However the name of an init function is seemed to be
randomized and not user-friendly. This is because object files are not
intended to be used directly.
ECL provides other user-friendly ways to generate compiled lisp programs
(as static/shared libraries or executable), and in each approach, object
files act as intermediate files.
@node Static library
@subsubsection Static library
ECL can compile lisp programs to static libraries, which can be linked
with C programs. A static library is created by c:build-static-library
with some compiled object files.
@exindex Building static library
@lisp
;; generates hello.o
(compile-file "hello.lsp" :system-p t)
;; generates goodbye.o
(compile-file "goodbye.lsp" :system-p t)
;; generates libhello-goodbye.a
(c:build-static-library "hello-goodbye"
:lisp-files '("hello.o" "goodbye.o")
:init-name "init_hello_goodbye")
@end lisp
When you use static/shared library, you have to call init functions. The
name of the function is specified by @code{:init-name} option. In this
example, @code{init_hello_goodbye} is it. The usage of this function is
shown below:
@exindex Initializing static/shared library in C/C++
@example
@verbatim
#include <ecl/ecl.h>
extern void init_hello_goodbye(cl_object cblock);
int
main(int argc, char **argv)
{
/* setup the lisp runtime */
cl_boot(argc, argv);
/* call the init function via read_VV */
read_VV(OBJNULL, init_hello_goodbye);
/* ... */
/* shutdown the lisp runtime */
cl_shutdown();
return 0;
}
@end verbatim
@end example
Because the program itself does not know the type of the init function,
a prototype declaration is inserted. After booting up the lisp
environment, invoke @code{init_hello_goodbye} via
@code{read_VV}. @code{init_hello_goodbye} takes a argument, and read_VV
supplies an appropriate one. Now that the initialization is finished, we
can use functions and other stuffs defined in the library.
@node Shared library
@subsubsection Shared library
Almost the same as the case of static library. User has to use
@code{c:build-shared-library}:
@exindex Building shared library
@lisp
;; generates hello.o
(compile-file "hello.lsp" :system-p t)
;; generates goodbye.o
(compile-file "goodbye.lsp" :system-p t)
;; generates libhello-goodbye.so
(c:build-shared-library "hello-goodbye"
:lisp-files '("hello.o" "goodbye.o")
:init-name "init_hello_goodbye")
@end lisp
@node Executable
@subsubsection Executable
ECL supports executable file generation. To create a standalone
executable from lisp programs, compile all lisp files to object
files. After that, calling @code{c:build-program} creates the
executable.
@exindex Building executable
@lisp
;; generates hello.o
(compile-file "hello.lsp" :system-p t)
;; generates goodbye.o
(compile-file "goodbye.lsp" :system-p t)
;; generates hello-goodbye
(c:build-program "hello-goodbye"
:lisp-files '("hello.o" "goodbye.o"))
@end lisp
Like native FASL, program may be built also from libraries.
@node Summary
@subsubsection Summary
In this post, some file types that can be compiled to with ECL were introduced. Each file type has adequate purpose:
@itemize
@item Object file: intermediate file format for others
@item Fasl files: loaded dynamically via load lisp function
@item Static library: linked with and used from C programs
@item Shared library: loaded dynamically and used from C programs
@item Executable: standalone executable
@end itemize
ECL provides a high-level interface @code{c:build-*} for each native
format. In case of @emph{Portable FASL} bytecodes compiler is needed.

View file

@ -23,8 +23,8 @@
* CDR Extensions::
@end menu
@node System building
@section System building
@ System building
@include extensions/building.txi
@node Operating System Interface
@section Operating System Interface