[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A feature of the Sic interpreter is that it will use the ‘unknown’ built-in to handle any command line which is not handled by any of the other registered built-in callback functions. This mechanism is very powerful, and allows me to lookup unhandled built-ins in the user’s ‘PATH’, for instance.
Before adding any modules to the project, I have created a separate
subdirectory, ‘modules’, to put the module source code into. Not
forgetting to list this new subdirectory in the AC_OUTPUT
macro
in ‘configure.in’, and the SUBDIRS
macro in the top level
‘Makefile.am’, a new ‘Makefile.am’ is needed to build the
loadable modules:
pkglibdir
is a Sic specific directory where modules will be
installed, See section Installing and Uninstalling Configured Packages.
For a library to be maximally portable, it should be written so that it does not require back-linking(47) to resolve its own symbols. That is, if at all possible you should design all of your libraries (not just dynamic modules) so that all of their symbols can be resolved at linktime. Sometimes, it is impossible or undesirable to architect your libraries and modules in this way. In that case you sacrifice the portability of your project to platforms such as AIX and Windows.
The key to building modules with libtool is in the options that are specified when the module is linked. This is doubly true when the module must work with libltdl’s dlpreopening mechanism.
Sic modules are built without a ‘lib’ prefix (‘-module’), and without version suffixes (‘-avoid-version’). All of the undefined symbols are resolved at linktime by ‘libsic.la’, hence ‘-no-undefined’.
Having added ‘ltdl.c’ to the ‘sic’ subdirectory, and called
the AC_LIB_LTDL
macro in ‘configure.in’, ‘libsic.la’
cannot build correctly on those architectures which do not support
back-linking. This is because ‘ltdl.c’ simply abstracts the native
dlopen
API with a common interface, and that local interface
often requires that a special library be linked – ‘-ldl’ on linux,
for example. AC_LIB_LTDL
probes the system to determine the name
of any such dlopen library, and allows you to depend on it in a portable
way by using the configure substitution macro, ‘@LIBADD_DL@’. If
I were linking a libtool
compiled libltdl at this
juncture, the system library details would have already been taken care
of. In this project, I have bypassed that mechanism by compiling and
linking ‘ltdl.c’ myself, so I have altered ‘sic/Makefile.am’
to use ‘@LIBADD_DL@’:
Having put all this infrastructure in place, the code for the ‘unknown’ module is a breeze (helper functions omitted for brevity):
In the first instance, notice that I have used the preprocessor to
redefine the entry point functions to be compatible with libltdls
dlpreopen
, hence the unknown_LTX_builtin_table
cpp
macro. The ‘unknown’ handler function itself looks
for a suitable executable in the user’s path, and if something suitable
is found, executes it.
Notice that Libtool doesn’t relink dependent libraries (‘libsic’ depends on ‘libcommon’, for example) on my GNU/Linux system, since they are not required for the static library in any case, and because the dependencies are also encoded directly into the shared archive, ‘libsic.so’, by the original link. On the other hand, Libtool will relink the dependent libraries if that is necessary for the target host.
$ make /bin/sh ../libtool --mode=compile gcc -DHAVE_CONFIG_H -I. -I. -I.. \ -I.. -I.. -I../sic -I../sic -I../src -I../src -g -O2 -c unknown.c mkdir .libs gcc -DHAVE_CONFIG_H -I. -I. -I.. -I.. -I.. -I../sic -I../sic -I../src \ -I../src -g -O2 -Wp,-MD,.deps/unknown.pp -c unknown.c -fPIC -DPIC \ -o .libs/unknown.lo gcc -DHAVE_CONFIG_H -I. -I. -I.. -I.. -I.. -I../sic -I../sic -I../src \ I../src -g -O2 -Wp,-MD,.deps/unknown.pp -c unknown.c -o unknown.o \ >/dev/null 2>&1 mv -f .libs/unknown.lo unknown.lo /bin/sh ../libtool --mode=link gcc -g -O2 -o unknown.la -rpath \ /usr/local/lib/sic -no-undefined -module -avoid-version unknown.lo \ ../sic/libsic.la rm -fr .libs/unknown.la .libs/unknown.* .libs/unknown.* gcc -shared unknown.lo -L/tmp/sic/sic/.libs ../sic/.libs/libsic.so \ -lc -Wl,-soname -Wl,unknown.so -o .libs/unknown.so ar cru .libs/unknown.a unknown.o creating unknown.la (cd .libs && rm -f unknown.la && ln -s ../unknown.la unknown.la) $ ./libtool --mode=execute ldd ./unknown.la libsic.so.0 => /tmp/sic/.libs/libsic.so.0 (0x40002000) libc.so.6 => /lib/libc.so.6 (0x4000f000) libcommon.so.0 => /tmp/sic/.libs/libcommon.so.0 (0x400ec000) libdl.so.2 => /lib/libdl.so.2 (0x400ef000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x80000000) |
After compiling the rest of the tree, I can now use the ‘unknown’ module:
$ SIC_MODULE_PATH=`cd ../modules; pwd` ./sic ] echo hello! command "echo" not found. ] load unknown ] echo hello! hello! ] unload unknown ] echo hello! command "echo" not found. ] exit $ |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] |
This document was generated by Ben Elliston on July 10, 2015 using texi2html 1.82.