Stupid DynaLoader Tricks

pudge on 2002-11-12T14:54:36

In MacPerl, there's a neat little hack to make certain functions always available. Essentially, bootstrap is called for the MacPerl, OSA, and XL packages explicitly in runperl.c:

av_push(PL_preambleav, newSVpv("BEGIN { bootstrap MacPerl; bootstrap OSA; bootstrap XL; }",0));

All three packages are statically linked, and are a "part of" the MacPerl package (that is, they get compiled into the same static library file). When porting this to Mac OS X, it causes problems: in MacPerl.pm, no bootstrap is done because it is not necessary, having already been done.

Normally, one could just do a conditional bootstrap, but this is complicated by the fact that a bootsrap OSA (we skip XL for Mac OS X) will look for a dynamic library named "OSA.$dl_dlext". But we don't have that. So instead, we first bootstrap MacPerl, and then find the file that was used for MacPerl -- don't load the file, it's already been loaded -- and use that to install our OSA::boostrap, before finally calling it.

It's possible I am overcomplicating things or doing something wrong, but hey, it works ...

# bootstrap MacPerl is already implicitly done by your MacPerl binary unless ($^O eq 'MacOS') { # use Config; # my $dl_dlext = $Config::Config{'dlext'}; my $dl_dlext = 'bundle';

require DynaLoader; push @ISA, 'DynaLoader'; bootstrap MacPerl;

# because OSA is in MacPerl.bundle, not OSA.bundle my $file = "auto/MacPerl/MacPerl.$dl_dlext"; foreach (@INC) { $dir = "$_/auto/MacPerl"; next unless -d $dir; my $try = "$dir/MacPerl.$dl_dlext"; last if $file = -f $try && $try; }

for my $mod (qw(OSA)) { my($xs, $symref); for (@DynaLoader::dl_librefs) { last if $symref = DynaLoader::dl_find_symbol($_, "boot_$mod"); } next unless $symref; $xs = DynaLoader::dl_install_xsub("${mod}::bootstrap", $symref, $file); &$xs($mod); } }

Now Playing: Ribbon In The Sky - Stevie Wonder (Original Musiquarium I, Vol I)