4 use Config qw(%Config);
6 use File::Path qw(mkpath);
7 use File::Spec::Functions qw(curdir catfile catdir);
9 our($VERSION, @ISA, @EXPORT, @EXPORT_OK, $Verbose, $Keep, $Maxlen,
10 $CheckForAutoloader, $CheckModTime);
14 @EXPORT = qw(&autosplit &autosplit_lib_modules);
15 @EXPORT_OK = qw($Verbose $Keep $Maxlen $CheckForAutoloader $CheckModTime);
19 AutoSplit - split a package for autoloading
23 autosplit($file, $dir, $keep, $check, $modtime);
25 autosplit_lib_modules(@modules);
29 This function will split up your program into files that the AutoLoader
30 module can handle. It is used by both the standard perl libraries and by
31 the MakeMaker utility, to automatically configure libraries for autoloading.
33 The C<autosplit> interface splits the specified file into a hierarchy
34 rooted at the directory C<$dir>. It creates directories as needed to reflect
35 class hierarchy, and creates the file F<autosplit.ix>. This file acts as
36 both forward declaration of all package routines, and as timestamp for the
37 last update of the hierarchy.
39 The remaining three arguments to C<autosplit> govern other options to
46 If the third argument, I<$keep>, is false, then any
47 pre-existing C<*.al> files in the autoload directory are removed if
48 they are no longer part of the module (obsoleted functions).
54 fourth argument, I<$check>, instructs C<autosplit> to check the module
55 currently being split to ensure that it includes a C<use>
56 specification for the AutoLoader module, and skips the module if
57 AutoLoader is not detected.
62 Lastly, the I<$modtime> argument specifies
63 that C<autosplit> is to check the modification time of the module
64 against that of the C<autosplit.ix> file, and only split the module if
66 $modtime defaults to 1.
70 Typical use of AutoSplit in the perl MakeMaker utility is via the command-line
73 perl -e 'use AutoSplit; autosplit($ARGV[0], $ARGV[1], 0, 1, 1)'
75 Defined as a Make macro, it is invoked with file and directory arguments;
76 C<autosplit> will split the specified file into the specified directory and
77 delete obsolete C<.al> files, after checking first that the module does use
78 the AutoLoader, and ensuring that the module is not already currently split
79 in its current form (the modtime test).
81 The C<autosplit_lib_modules> form is used in the building of perl. It takes
82 as input a list of files (modules) that are assumed to reside in a directory
83 B<lib> relative to the current directory. Each file is sent to the
84 autosplitter one at a time, to be split into the directory B<lib/auto>.
86 In both usages of the autosplitter, only subroutines defined following the
87 perl I<__END__> token are split out into separate files. Some
88 routines may be placed prior to this marker to force their immediate loading
91 =head2 Multiple packages
93 As of version 1.01 of the AutoSplit module it is possible to have
94 multiple packages within a single file. Both of the following cases
100 package NAME::option1;
102 package NAME::option2;
108 sub NAME::option1::BBB { ... }
109 sub NAME::option2::BBB { ... }
113 C<AutoSplit> will inform the user if it is necessary to create the
114 top-level directory specified in the invocation. It is preferred that
115 the script or installation process that invokes C<AutoSplit> have
116 created the full directory path ahead of time. This warning may
117 indicate that the module is being split into an incorrect path.
119 C<AutoSplit> will warn the user of all subroutines whose name causes
120 potential file naming conflicts on machines with drastically limited
121 (8 characters or less) file name length. Since the subroutine name is
122 used as the file name, these warnings can aid in portability to such
125 Warnings are issued and the file skipped if C<AutoSplit> cannot locate
126 either the I<__END__> marker or a "package Name;"-style specification.
128 C<AutoSplit> will also emit general diagnostics for inability to
129 create directories or files.
133 # for portability warn about names longer than $maxlen
134 $Maxlen = 8; # 8 for dos, 11 (14-".al") for SYSVR3
135 $Verbose = 1; # 0=none, 1=minimal, 2=list .al files
137 $CheckForAutoloader = 1;
140 my $IndexFile = "autosplit.ix"; # file also serves as timestamp
142 $maxflen = 14 if $Config{'d_flexfnam'} ne 'define';
143 if (defined (&Dos::UseLFN)) {
144 $maxflen = Dos::UseLFN() ? 255 : 11;
146 my $Is_VMS = ($^O eq 'VMS');
148 # allow checking for valid ': attrlist' attachments.
149 # extra jugglery required to support both 5.8 and 5.9/5.10 features
150 # (support for 5.8 required for cross-compiling environments)
161 (?<nested> \( (?: [^()]++ | (?&nested)++ )*+ \) ) ?
163 (?: \s* : \s* | \s+ (?! :) )
169 # In pre-5.9.5 world we have to do dirty tricks.
170 # (we use 'our' rather than 'my' here, due to the rather complex and buggy
171 # behaviour of lexicals with qr// and (??{$lex}) )
172 our $trick1; # yes, cannot our and assign at the same time.
173 $trick1 = qr{ \( (?: (?> [^()]+ ) | (??{ $trick1 }) )* \) }x;
174 our $trick2 = qr{ (?> (?! \d) \w+ (?:$trick1)? ) (?:\s*\:\s*|\s+(?!\:)) }x;
175 qr{ \s* : \s* (?: $trick2 )* }x;
179 my($file, $autodir, $keep, $ckal, $ckmt) = @_;
180 # $file - the perl source file to be split (after __END__)
181 # $autodir - the ".../auto" dir below which to write split subs
182 # Handle optional flags:
183 $keep = $Keep unless defined $keep;
184 $ckal = $CheckForAutoloader unless defined $ckal;
185 $ckmt = $CheckModTime unless defined $ckmt;
186 autosplit_file($file, $autodir, $keep, $ckal, $ckmt);
194 # This function is used during perl building/installation
195 # ./miniperl -e 'use AutoSplit; autosplit_lib_modules(@ARGV)' ...
197 sub autosplit_lib_modules {
198 my(@modules) = @_; # list of Module names
199 local $_; # Avoid clobber.
200 while (defined($_ = shift @modules)) {
201 while (m#([^:]+)::([^:].*)#) { # in case specified as ABC::XYZ
202 $_ = catfile($1, $2);
204 s|\\|/|g; # bug in ksh OS/2
205 s#^lib/##s; # incase specified as lib/*.pm
206 my($lib) = catfile(curdir(), "lib");
207 if ($Is_VMS) { # may need to convert VMS-style filespecs
208 $lib =~ s#^\[\]#.\/#;
210 s#^$lib\W+##s; # incase specified as ./lib/*.pm
211 if ($Is_VMS && /[:>\]]/) { # may need to convert VMS-style filespecs
212 my ($dir,$name) = (/(.*])(.*)/s);
213 $dir =~ s/.*lib[\.\]]//s;
214 $dir =~ s#[\.\]]#/#g;
217 autosplit_file(catfile($lib, $_), catfile($lib, "auto"),
218 $Keep, $CheckForAutoloader, $CheckModTime);
226 my $self_mod_time = (stat __FILE__)[9];
229 my($filename, $autodir, $keep, $check_for_autoloader, $check_mod_time)
235 # where to write output files
236 $autodir ||= catfile(curdir(), "lib", "auto");
238 ($autodir = VMS::Filespec::unixpath($autodir)) =~ s|/\z||;
239 $filename = VMS::Filespec::unixify($filename); # may have dirs
241 unless (-d $autodir){
242 mkpath($autodir,0,0755);
243 # We should never need to create the auto dir
244 # here. installperl (or similar) should have done
245 # it. Expecting it to exist is a valuable sanity check against
246 # autosplitting into some random directory by mistake.
247 print "Warning: AutoSplit had to create top-level " .
248 "$autodir unexpectedly.\n";
251 # allow just a package name to be used
252 $filename .= ".pm" unless ($filename =~ m/\.pm\z/);
254 open(my $in, "<$filename") or die "AutoSplit: Can't open $filename: $!\n";
255 my($pm_mod_time) = (stat($filename))[9];
256 my($autoloader_seen) = 0;
258 my($def_package,$last_package,$this_package,$fnr);
262 $in_pod = 1 if /^=\w/;
263 $in_pod = 0 if /^=cut/;
264 next if ($in_pod || /^=cut/);
267 # record last package name seen
268 $def_package = $1 if (m/^\s*package\s+([\w:]+)\s*;/);
269 ++$autoloader_seen if m/^\s*(use|require)\s+AutoLoader\b/;
270 ++$autoloader_seen if m/\bISA\s*=.*\bAutoLoader\b/;
273 if ($check_for_autoloader && !$autoloader_seen){
274 print "AutoSplit skipped $filename: no AutoLoader used\n"
278 $_ or die "Can't find __END__ in $filename\n";
280 $def_package or die "Can't find 'package Name;' in $filename\n";
282 my($modpname) = _modpname($def_package);
284 # this _has_ to match so we have a reasonable timestamp file
285 die "Package $def_package ($modpname.pm) does not ".
286 "match filename $filename"
287 unless ($filename =~ m/\Q$modpname.pm\E$/ or
288 ($^O eq 'dos') or ($^O eq 'MSWin32') or ($^O eq 'NetWare') or
289 $Is_VMS && $filename =~ m/$modpname.pm/i);
291 my($al_idx_file) = catfile($autodir, $modpname, $IndexFile);
293 if ($check_mod_time){
294 my($al_ts_time) = (stat("$al_idx_file"))[9] || 1;
295 if ($al_ts_time >= $pm_mod_time and
296 $al_ts_time >= $self_mod_time){
297 print "AutoSplit skipped ($al_idx_file newer than $filename)\n"
299 return undef; # one undef, not a list
303 my($modnamedir) = catdir($autodir, $modpname);
304 print "AutoSplitting $filename ($modnamedir)\n"
307 unless (-d $modnamedir){
308 mkpath($modnamedir,0,0777);
311 # We must try to deal with some SVR3 systems with a limit of 14
312 # characters for file names. Sadly we *cannot* simply truncate all
313 # file names to 14 characters on these systems because we *must*
314 # create filenames which exactly match the names used by AutoLoader.pm.
315 # This is a problem because some systems silently truncate the file
316 # names while others treat long file names as an error.
318 my $Is83 = $maxflen==11; # plain, case INSENSITIVE dos filenames
320 my(@subnames, $subname, %proto, %package);
327 $in_pod = 1 if /^=\w/;
328 $in_pod = 0 if /^=cut/;
329 next if ($in_pod || /^=cut/);
330 # the following (tempting) old coding gives big troubles if a
331 # cut is forgotten at EOF:
332 # next if /^=\w/ .. /^=cut/;
333 if (/^package\s+([\w:]+)\s*;/) {
334 $this_package = $def_package = $1;
337 if (/^sub\s+([\w:]+)(\s*(?:\(.*?\))?(?:$attr_list)?)/) {
338 print $out "# end of $last_package\::$subname\n1;\n"
341 my $proto = $2 || '';
342 if ($subname =~ s/(.*):://){
345 $this_package = $def_package;
347 my $fq_subname = "$this_package\::$subname";
348 $package{$fq_subname} = $this_package;
349 $proto{$fq_subname} = $proto;
350 push(@subnames, $fq_subname);
351 my($lname, $sname) = ($subname, substr($subname,0,$maxflen-3));
352 $modpname = _modpname($this_package);
353 my($modnamedir) = catdir($autodir, $modpname);
354 mkpath($modnamedir,0,0777);
355 my($lpath) = catfile($modnamedir, "$lname.al");
356 my($spath) = catfile($modnamedir, "$sname.al");
359 if (!$Is83 and open($out, ">$lpath")){
361 print " writing $lpath\n" if ($Verbose>=2);
363 open($out, ">$spath") or die "Can't create $spath: $!\n";
365 print " writing $spath (with truncated name)\n"
368 push(@outfiles, $path);
369 my $lineno = $fnr - @cache;
371 # NOTE: Derived from $filename.
372 # Changes made here will be lost when autosplit is run again.
374 package $this_package;
376 #line $lineno "$filename (autosplit into $path)"
383 push(@cache, $_) if @cache || /\S/;
395 $last_package = $this_package if defined $this_package;
398 print $out @cache,"1;\n# end of $last_package\::$subname\n";
403 if (!$keep){ # don't keep any obsolete *.al files in the directory
405 # @outfiles{@outfiles} = @outfiles;
406 # perl downcases all filenames on VMS (which upcases all filenames) so
407 # we'd better downcase the sub name list too, or subs with upper case
408 # letters in them will get their .al files deleted right after they're
409 # created. (The mixed case sub name won't match the all-lowercase
410 # filename, and so be cleaned up as a scrap file)
411 if ($Is_VMS or $Is83) {
412 %outfiles = map {lc($_) => lc($_) } @outfiles;
414 @outfiles{@outfiles} = @outfiles;
416 my(%outdirs,@outdirs);
418 $outdirs{File::Basename::dirname($_)}||=1;
420 for my $dir (keys %outdirs) {
421 opendir(my $outdir,$dir);
422 foreach (sort readdir($outdir)){
423 next unless /\.al\z/;
424 my($file) = catfile($dir, $_);
425 $file = lc $file if $Is83 or $Is_VMS;
426 next if $outfiles{$file};
427 print " deleting $file\n" if ($Verbose>=2);
428 my($deleted,$thistime); # catch all versions on VMS
429 do { $deleted += ($thistime = unlink $file) } while ($thistime);
430 carp ("Unable to delete $file: $!") unless $deleted;
436 open(my $ts,">$al_idx_file") or
437 carp ("AutoSplit: unable to create timestamp file ($al_idx_file): $!");
438 print $ts "# Index created by AutoSplit for $filename\n";
439 print $ts "# (file acts as timestamp)\n";
441 for my $fqs (@subnames) {
443 $subname =~ s/.*:://;
444 print $ts "package $package{$fqs};\n"
445 unless $last_package eq $package{$fqs};
446 print $ts "sub $subname $proto{$fqs};\n";
447 $last_package = $package{$fqs};
452 _check_unique($filename, $Maxlen, 1, @outfiles);
459 my $modpname = $package;
460 if ($^O eq 'MSWin32') {
461 $modpname =~ s#::#\\#g;
464 while ($modpname =~ m#(.*?[^:])::([^:].*)#) {
468 $modpname = catfile(@modpnames, $modpname);
471 $modpname = VMS::Filespec::unixify($modpname); # may have dirs
477 my($filename, $maxlen, $warn, @outfiles) = @_;
481 length(File::Basename::basename($_))
487 my($dir) = File::Basename::dirname($_);
488 my($file) = File::Basename::basename($_);
489 my($trunc) = substr($file,0,$maxlen);
490 $notuniq{$dir}{$trunc} = 1 if $shorts{$dir}{$trunc};
491 $shorts{$dir}{$trunc} = $shorts{$dir}{$trunc} ?
492 "$shorts{$dir}{$trunc}, $file" : $file;
494 if (%notuniq && $warn){
495 print "$filename: some names are not unique when " .
496 "truncated to $maxlen characters:\n";
497 foreach my $dir (sort keys %notuniq){
498 print " directory $dir:\n";
499 foreach my $trunc (sort keys %{$notuniq{$dir}}) {
500 print " $shorts{$dir}{$trunc} truncate to $trunc\n";
509 # test functions so AutoSplit.pm can be applied to itself:
510 sub test1 ($) { "test 1\n"; }
511 sub test2 ($$) { "test 2\n"; }
512 sub test3 ($$$) { "test 3\n"; }
513 sub testtesttesttest4_1 { "test 4\n"; }
514 sub testtesttesttest4_2 { "duplicate test 4\n"; }
515 sub Just::Another::test5 { "another test 5\n"; }
516 sub test6 { return join ":", __FILE__,__LINE__; }
517 package Yet::Another::AutoSplit;
518 sub testtesttesttest4_1 ($) { "another test 4\n"; }
519 sub testtesttesttest4_2 ($$) { "another duplicate test 4\n"; }
520 package Yet::More::Attributes;
521 sub test_a1 ($) : locked :locked { 1; }
522 sub test_a2 : locked { 1; }