Hi Jeff,
I'm pretty sure stubs aren't the problem since neither BLT nor the perl
Tcl module are compiled against the stub libraries. They are compiled
against exactly the same version of libtcl8.4.so.
When I examine the perl Tcl module library, I see a dependence on
libtcl8.4.so:
ldd
<blah>/perl/5.8.2/lib/site_perl/5.8.2/i686-linux-thread-multi/auto/Tcl/Tcl.so
libtcl8.4.so => <blah>/tcl/8.4/lib/libtcl8.4.so (0x00b62000)
libc.so.6 => /lib/tls/libc.so.6 (0x00577000)
libdl.so.2 => /lib/libdl.so.2 (0x00e83000)
libpthread.so.0 => /lib/tls/libpthread.so.0 (0x00708000)
libm.so.6 => /lib/tls/libm.so.6 (0x00144000)
/lib/ld-linux.so.2 (0x00785000)
So as I understand it, when perl loads Tcl.so, that should force the
dynamic loader to also load libtcl8.4.so. When I look at our BLT library:
ldd <blah>/tcl/8.4/lib/libBLT24.so
libc.so.6 => /lib/tls/libc.so.6 (0x0050d000)
/lib/ld-linux.so.2 (0x00785000)
It does not show any dependence on libtcl8.4.so (but I am certain that
this is the version of Tcl against which it was compiled).
However, when perl tries to load BLT inside the Tcl module, there are
unresolved symbols. This script:
#!<blah>/perl/5.8.2/bin/perl
use Tcl::Tk;
my $m = Tcl::Tk::MainWindow->new();
my $i = $m->interp();
$i->Eval('package require BLT');
gives this error:
ERROR: couldn't load file "<blah>/tcl/8.4/lib/libBLT24.so":
<blah>/tcl/8.4/lib/libBLT24.so: undefined symbol: TclpRealloc
If I use just Tcl rather than Tcl::Tk I get the same error. The missing
symbol TclpRealloc is found in libtcl8.4.so:
nm <blah>/tcl/8.4/lib/libtcl8.4.so | grep TclpRealloc
0007ade8 T TclpRealloc
So my conclusion is that libBLT24.so needs to have libtcl8.4.so loaded
even though it doesn't ask for it explicitly. Perl should be loading
libtcl8.4.so since it is asked for by perl's Tcl.so. However, for some
reason when I "use Tcl" from perl, libtcl8.4.so does not get loaded, and
hence it is not there when libBLT24.so needs it.
I think this confirmed by the fact that everything works if I force the
loading of libtcl8.4.so like so:
#!<blah>/perl/5.8.2/bin/perl
use Tcl::Tk;
my $m = Tcl::Tk::MainWindow->new();
my $i = $m->interp();
$i->Eval('load /usr/csite/pubtools/tcl/8.4/lib/libtcl8.4.so Tcl');
$i->Eval('package require BLT');
Then I get no error. What I don't understand is why I have to do that.
Perl should be loading libtcl8.4.so automatically, but for some reason
it doesn't.
Is there any way to get perl to tell me exactly what libraries have been
loaded? In Tcl I would use "info loaded" for this purpose.
--Brian
Jeff Hobbs wrote:
Hi Brian,
This is a dangerous path on several levels. If the libtcl.so you load
isn't the exact same one used by Tcl::Tk, you can have all sorts of
conflicting library issues. The issue that you are hitting is
regarding Tcl's stubs mechanism. This is the mechanism that provides
a high level of binary version independent, but also enables the
single-file dll/executable features of Tcl. More about stubs at:
http://wiki.tcl.tk/285
BLT, while a nice fancy widget package, is well known to not support
the stubs interface (in large part because it pokes deeply into Tcl/Tk
internals, which mostly aren't exposed by stubs). If you are using a
Tcl/Tk through Tcl::Tk that isn't a single-file dll (such as the one
shipped in ActivePerl for user convenience), then you should be OK, as
long as you compile BLT against that Tcl/Tk.
Let me know if you have any more questions on that.
Regards,
Jeff
Brian Bevins wrote:
Vadim and Jeff,
I am a colleague of Michele's here at Jefferson Lab. I built the
versions of Tcl and Tcl::Tk that she is having trouble with. Thank
you for responding so promptly to our questions.
Our initial build of Tcl:Tk 0.97 failed because our version of Perl
(5.8.2) has an Exporter that lacks the import method. That method was
introduced with the Exporter that shipped with Perl 5.8.3. I had to
go back to Tcl::Tk 0.91 to find a version that did not require the
Exporter->import() method. That one built just fine and passed all
its tests. We can use this until our sysadmins give us a new version
of Perl.
The problem loading BLT under Tcl or Tcl::Tk is completely separate.
It seems that both libblt24.so and libbltlite24.so depend on symbols
from libtcl8.4.so. As built out of the box, the BLT libraries do not
explicitly force the Tcl library to be loaded. They seem to expect
that Tcl will already be loaded. Normally this is the case and BLT
works fine when used directly from tclsh or wish, but for some reason
under Tcl and Tcl::Tk this is not the case.
When I look at the Tcl.so library for Perl, it does indicate an
explicit dependency on libtcl8.4.so. But for some reason "use Tcl"
(or "use Tcl::Tk") does not force libtcl8.4.so to load. I have worked
around this in Perl for the time being by loading it explicitly as:
use Tcl::Tk;
my $m = Tcl::Tk::MainWindow->new();
my $i = $m->interp();
$i->Eval('load /usr/csite/pubtools/tcl/8.4/lib/libtcl8.4.so Tcl');
$i->Eval('package require BLT; blt::tabnotebook .bltnbook1; pack
.bltnbook1');
$i->MainLoop();
This makes it work, but I do not know why the explicit load command
is necessary. The dynamic loader should be doing that for me.
Many thanks,
--Brian
--
Brian S. Bevins, PE
Computer Scientist / Mechanical Engineer
Thomas Jefferson National Accelerator Facility
"Nothing in all the world is more dangerous than
sincere ignorance and conscientious stupidity."
--Martin Luther King Jr.