Arjen Markus (9 september 2002) Being an enthousiastic user of Critcl, I ran into a small problem the other day: I needed to use a set of static (archive) libraries and the UNIX operating system I used (SUN Solaris) did not allow me to use them as part of a dynamic (shared) library.
So, the solution was to create a "custom shell", with the static libraries linked into the shell, instead of them being a loadable extension.
This page describes how I did this.
The first step was to use Critcl with the option "-keepsrc 1" to keep the generated C source file. I renamed the file to "glue.c", this being the (unimaginative) name of the package I wanted.
The second step was editing the file "tclAppInit.c", so that it would initialise my package as a static package:
int Tcl_AppInit(interp) Tcl_Interp *interp; /* Interpreter for application. */ { ... /* | Call the init procedures for included packages. Each call should | look like this: | | if (Mod_Init(interp) == TCL_ERROR) { | return TCL_ERROR; | } | | where "Mod" is the name of the module. */ if (Glue_Init(interp) == TCL_ERROR) { return TCL_ERROR; } ... }
(This required little more than copying and editing the example in the very file.)
With the following commands, I got the custom shell I needed:
cc -g -c tclAppInit.c -DUSE_TCL_STUBS cc -g -c glue.c -DUSE_TCL_STUBS f77 -g -o gluesh tclAppInit.o glue.o -L$TCLLIBPATH \ -ltcl8.3 -ltclstub8.3 libreader1.a libreader2.a -lm
(slightly edited, irrelevant details have been omitted)
Notes:
Running this custom shell requires, however, two more actions:
I'm surprised to see TCLLIBPATH in the example above. It may work, but I don't think it's being used as intended.
What you really want is probably TCL_LIB_SPEC as recorded in the file tclConfig.sh.
The variable TCLLIBPATH isn't for compile time issues at all; it's for runtime control over where the default [package unknown] and [auto_load] look for packages and auto-loadable files.
For the LD_LIBRARY_PATH point, there is an easier way: Use the linker's rpath directive. rpath means runtime path, and you can specify a colon separated list of directories ld(_elf).so searches for the fitting libraries. E.g. suppose you have your tcl libraries in /usr/somewhere/tcl/lib, you'd change the linking step to include something like:
-Wl,-R/usr/lib:/lib:/usr/somewhere/tcl/lib
or
-Wl,-rpath/usr/lib:/lib:/usr/somewhere/tcl/lib
depending on your compiler (-Wl, passes all stuff after the comma to the linker itself - older linkers implement -R, newer implement -rpath in addition to -R.) This is true for gcc (and ld), I have to admit that I have no idea of f77 :) (but if you use g77, it is basically a wrapper around gcc, which allows you to use those -Wl, ... options again)
-Martin
AM On the subject of g77 being a wrapper for gcc, I think many users of g77 would disagree. There is considerable confusion, as some systems offered a script "g77" that invoked the well-known Fortran-to-C converter, f2c. But as far as I understand it, g77 is an independent product that simply happens to share a lot with gcc.
If it were so, the writers of the g77 manpage were obviously drunk when they wrote the following:
DESCRIPTION
The C and F77 compilers are integrated; g77 is a program to call gcc with options to recognize programs written in Fortran (ANSI FORTRAN 77, also called F77). gcc processes input files through one or more of four stages: prepro- cessing, compilation, assembly, and linking. This man page contains full descriptions for only F77-specific aspects of the compiler, though it also contains summaries of some general-purpose options. For a fuller explanation of the compiler, see gcc(1).
If you want to argue that the manpage might be out of date wrt to this, check your info files.
Quote: In a non-Fortran installation, `gcc' recognizes C, C++, and Objective-C source files. In a GNU Fortran installation, `gcc' also recognizes Fortran source files and accepts Fortran-specific command-line options, plus some command-line options that are designed to cater to Fortran users but apply to other languages as well.
-Martin
See also: Building a custom tclsh