---- Shells 1.1 -------------------------------------------------------------- This package implements multiple extensions management and dynamic linking for Tcl/Tk as suggested in "Tcl Future Directions Session #2 Notes" (see doc/session2.txt for details). We've tried to follow as closely as possible the suggested solutions, but in a few occasions interpolation was required: * the notes don't explicitly define the return type for Tcl_AppInit() and for the extension-specific initialization functions. We've decide to have them return TCL_OK or TCL_ERROR to report success or failure. * a policy about application and extension initialization scripts is still to be defined: it's up to you choosing between: 1. organizing your code as suggested by J.O. in the book: - compile a standard path for the script library in the sources and allow the user to modify it using an environment variable (LIB) - in _Init() look for the init file in LIB and at the hard-coded path; then call Tcl_EvalFile() to source it. 2. using autoloading - define in the script library an initialization Tcl procedures (_Init) - include the directory containing the script library in auto_path/TCLLIBPATH - in _Init() call Tcl_GlobalEval(interp, "_Init [ ...]") and let the standard auto-loader find the proper file to source. ---- Dynamic Loading ---------------------------------------------------------- The dynamic extension module takes advantage of dynamic loading of shared libraries under some OS's to load extensions in tcl/tk shells at run-time. Supported operating systems are: * SunOs 4.x (sunos.c, probably also Solaris 1.0) * HP-UX 8.x/9.x (hpux.c) * Solaris2 (solaris.c) * OSF-1 (osf1.c) Use the included Makefile to build and install dynamically extensible shells for tcl (dtclsh) and tk (dwish) and related manual pages. The code provides a general-purpose Tcl_AppInit() function that creates a new Tcl command (load). Extensions to be loaded at run-time should be compiled as shared libraries and should define a public initialization function taking as argument a pointer to the Tcl interpreter to be extended and returning TCL_OK or TCL_ERROR to report success or failure. Extension complying with these rules can be loaded using the 'load' Tcl command: it takes as argument the path of the shared library to load. Dynamic loading can be hacked quite effectively in the standard auto-loading scheme: in this way it should be possible to load multiple libraries without much trouble. In the demo directory you'll find an example of compiling and installing shared auto-loadable librarys: included are a fact(orial) command and the sample Tk square widget. The Makefiles therein are meant to be used as templates to build real dynamic_loadable tcl extensions. ---- To Install --------------------------------------------------------------- To build dynamic shells on your system and try out dynamic loading: * edit Makefile * 'make' to build dtclsh and dwish * cd to demo/ * edit Makefile.cfg * 'make' to build the "fact" tcl demo and the "square" tk demo (have a look into libfact.tcl and at the man page for the load command to see how auto-loading works). * run ../dwish * insert the current directory in the auto-loading path with the tcl command "lappend auto_path ." * enjoy (hopefully :-)): wish: fact 5 wish: source square.tcl * when satisfied 'cd ..' and 'make install' to install executables and man pages. ---- Porting ----------------------------------------------------------------- It shouldn't be difficult to port 'shells' to different architectures, provided they support dynamic loading at the system level. In order to do that, you need functions to load a library (dlopen() under SunOs), to fetch a pointer to a given symbol (dlsym()) and to find out what went wrong after an error (dlerror()). GNU's dld, the dynamic loading support for Python and for the Class language in the Andrew ToolKit may provide useful ideas to start with. We are willing to maintain the package (no hot-line support :-)) until this stuff gets included into the base Tcl library, so if you succeed in porting the load command to other systems please send us: * new code, * patches to *AppInit.c and Makefiles, * compiler and loader flags for building shells and shared libraries, * a shells script named is_$(MyArchitecture) which should return 1 if it is running on $(MyArchitecture), 0 otherwise. * relevant documentation. To ease configuration and maintenance we suggest you should try to confine system-dependent stuff in a file $MyArchitecture.c, defining a single interface function: int Tcl_LoadCmd(dummy, interp, argc, argv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */ It is a standard Tcl_CmdProc, and should take a single argument on the command line - the path of the library to load. It should return TCL_OK or TCL_ERROR, leaving an error message in interp->result in the latter case. You may want to use sunos.c as a template to develop your own version of Tcl_LoadCmd(). ---- Patching the Tcl release ------------------------------------------------ In this package you find a file load.patch, which can be used to patch the Tcl release. This can be useful if you want dynamic-loading to be part of your default tcl library, and thus appear in any tcl-app you happen to build on your system. You can skip this step if you're unsure about it. 1- Copy the right C source file to your tcl source directory, and name it tclLoad.c eg: "cp sunos.c /home/develop/tools/tcl7.1/tclLoad.c" 2- Cd to the tcl sources and apply the patch. This modifies the following files: tclBasic.c -- it adds an entry in the main command table Makefile.in -- it adds the tclLoad.c source file tclInt.h -- it adds the prototype for Tcl_LoadCmd() library/init.tcl -- fixes use of TCLLIBPATH env variable eg: "cd ../tcl7.1; patch -p < ../Shells-1.1/load.patch" 3- Fix Makefile.in by adding the additional flags your system requires when executables are built (line 133 and 136 in tcl-7.1) eg: on hpux add "-ldld" 4- Build the tcl package 4b- Test it out with the fact demo and fix your problems, if any. - on hpux 8.x you need to build a dynamic libtcl, since static libs don't export their symbols. 5- If you want to rebuild wish now, you should add the needed compiler flags to Makefile.in in the Tk source dir, repeating step 3. The same compiler flags must be provided to any application using the new dynamic tcl as well. ---- What's new from 1.0 ----------------------------------------------------- * tcl.c and tk.c have been replaced by tclAppInit.c and tkAppInit.c. To build extended dynamic shells you should modify this files according to the included instructions, rather than writing your own Tcl_AppInit() and Tk_AppInit() functions. * Tk_MainWindow() is gone since it's now part of the tk library (with a different interface, however; refer to tk documentation for details). * interpreter initialization comes now from the standard init.tcl, which ignores the TCLLIBPATH environment variable. Since this is quite annoying when using multiple dynamic extensions you may want to edit it and change (at line 29) set auto_path [info library] to if [info exists env(TCLLIBPATH)] { set auto_path $env(TCLLIBPATH) } lappend auto_path [info library] Be also aware that the current auto_loading scheme doesn't update the current directory '.' in auto_path. We've been told this should be fixed in the next release of Tcl. ---- Acknowledgements -------------------------------------------------------- Michael Moore (mdm@cis.ohio-state.edu) contributed the HP-UX support and helped us with beta testing. Sanjay Ghemawat (sanjay@clef.lcs.mit.edu) ported shells-1.0 to OSF/1. ------------------------------------------------------------------------------ Comments and suggestions to: ------------------------------------------------------------------------------ Alessandro Bollini --- bollini@ipvvis.unipv.it Alessandro Rubini --- rubini@ipvvis.unipv.it Dipartimento di Informatica e Sistemistica - Universita` di Pavia Via Abbiategrasso 209 - 27100 Pavia - Italy