Update metadata to meta-spec 2, include web view of repository, correct EUMM version...
[imager.git] / Makefile.PL
1 #!perl -w
2 use strict;
3 use ExtUtils::MakeMaker;
4 use Cwd;
5 use Config;
6 use File::Spec;
7 use Getopt::Long;
8 use ExtUtils::Manifest qw(maniread);
9 use ExtUtils::Liblist;
10 use vars qw(%formats $VERBOSE $INCPATH $LIBPATH $NOLOG $DEBUG_MALLOC $MANUAL $CFLAGS $LFLAGS $DFLAGS);
11 use lib 'inc', 'lib';
12 use Imager::Probe;
13
14 # EU::MM runs Makefile.PL all in the same process, so sub-modules will
15 # see this
16 our $BUILDING_IMAGER = 1;
17
18 # used to display a summary after we've probed the world
19 our %IMAGER_LIBS;
20
21 #
22 # IM_INCPATH      colon seperated list of paths to extra include paths
23 # IM_LIBPATH      colon seperated list of paths to extra library paths
24 #
25 # IM_VERBOSE      turns on verbose mode for the library finding and such
26 # IM_MANUAL       to manually select which libraries are used and which not
27 # IM_ENABLE       to programmatically select which libraries are used
28 #                 and which are not
29 # IM_NOLOG        if true logging will not be compiled into the module
30 # IM_DEBUG_MALLOC if true malloc debbuging will be compiled into the module
31 #                 do not use IM_DEBUG_MALLOC in production - this slows
32 #                 everything down by alot
33 # IM_CFLAGS       Extra flags to pass to the compiler
34 # IM_LFLAGS       Extra flags to pass to the linker
35 # IM_DFLAGS       Extra flags to pass to the preprocessor
36
37 my $KEEP_FILES = $ENV{IMAGER_KEEP_FILES};
38
39 # make sure --verbose will dump environment settings
40 if (grep $_ =~ /^--?v(?:erbose)?$/, @ARGV) {
41   $VERBOSE = 1;
42 }
43
44 # modules/features bundled with Imager that can be enabled/disabled
45 # withs --enable/--disable
46 my @bundled = qw(FT1 FT2 GIF JPEG PNG T1 TIFF W32);
47
48 # extra modules bundled with Imager not available on CPAN
49 my @extras = qw(CountColor DynTest ICO SGI Mandelbrot Flines);
50
51 # alternate names for modules
52 my %bundled_names = qw(win32 w32 tt ft1);
53
54 getenv();     # get environment variables
55
56 my $lext=$Config{'so'};   # Get extensions of libraries
57 my $aext=$Config{'_a'};
58
59 my $help; # display help if set
60 my @enable; # list of drivers to enable
61 my @disable; # or list of drivers to disable
62 my @incpaths; # places to look for headers
63 my @libpaths; # places to look for libraries
64 my $coverage; # build for coverage testing
65 my $assert; # build with assertions
66 my $trace_context; # trace context management to stderr
67 GetOptions("help" => \$help,
68            "enable=s" => \@enable,
69            "disable=s" => \@disable,
70            "incpath=s", \@incpaths,
71            "libpath=s" => \@libpaths,
72            "verbose|v" => \$VERBOSE,
73            "nolog" => \$NOLOG,
74            'coverage' => \$coverage,
75            "assert|a" => \$assert,
76            "tracecontext" => \$trace_context);
77
78 setenv();
79
80 if ($ENV{AUTOMATED_TESTING}) {
81   $assert = 1;
82 }
83
84 if ($VERBOSE) { 
85   print "Verbose mode\n"; 
86   require Data::Dumper; 
87   import Data::Dumper qw(Dumper);
88 }
89
90 if ($help) {
91   usage();
92 }
93
94 my @defines;
95
96 if ($NOLOG)   { print "Logging not compiled into module\n"; }
97 else { 
98   push @defines, [ IMAGER_LOG => 1, "Logging system" ];
99 }
100
101 if ($assert) {
102   push @defines, [ IM_ASSERT => 1, "im_assert() are effective" ];
103 }
104
105 if ($DEBUG_MALLOC) {
106   push @defines, [ IMAGER_DEBUG_MALLOC => 1, "Use Imager's DEBUG malloc()" ];
107   print "Malloc debugging enabled\n";
108 }
109
110 if (@enable && @disable) {
111   print STDERR "Only --enable or --disable can be used, not both, try --help\n";
112   exit 1;
113 }
114
115 my %definc;
116 my %deflib;
117 my @incs; # all the places to look for headers
118 my @libs; # all the places to look for libraries
119
120 init();       # initialize global data
121 pathcheck();  # Check if directories exist
122
123 my @enabled_bundled;
124 if (exists $ENV{IM_ENABLE}) {
125   push @enable, split ' ', $ENV{IM_ENABLE};
126 }
127 if (@enable) {
128   my %en = map { lc $_ => 1 } map_bundled(@enable);
129   @enabled_bundled = grep $en{lc $_}, @bundled;
130 }
131 elsif (@disable) {
132   my %dis = map { lc $_ => 1 } map_bundled(@disable);
133   @enabled_bundled = grep !$dis{lc $_}, @bundled;
134 }
135 else {
136   @enabled_bundled = @bundled;
137 }
138
139 # Pick what libraries are used
140 if ($MANUAL) {
141   manual();
142 } else {
143   automatic();
144 }
145
146 my @objs = qw(Imager.o context.o draw.o polygon.o image.o io.o iolayer.o
147               log.o gaussian.o conv.o pnm.o raw.o feat.o combine.o
148               filters.o dynaload.o stackmach.o datatypes.o
149               regmach.o trans2.o quant.o error.o convert.o
150               map.o tags.o palimg.o maskimg.o img8.o img16.o rotate.o
151               bmp.o tga.o color.o fills.o imgdouble.o limits.o hlines.o
152               imext.o scale.o rubthru.o render.o paste.o compose.o flip.o
153               perlio.o);
154
155 my $lib_define = '';
156 my $lib_inc = '';
157 my $lib_libs = '';
158 for my $frmkey (sort { $formats{$a}{order} <=> $formats{$b}{order} } keys %formats) {
159   my $frm = $formats{$frmkey};
160   if ($frm->{enabled}) {
161     push @defines, [ $frm->{def}, 1, "$frmkey available" ];
162     push @objs, $frm->{objfiles};
163     $lib_define .= " $frm->{DEFINE}" if $frm->{DEFINE};
164     $lib_inc    .= " $frm->{INC}"    if $frm->{INC};
165     $lib_libs   .= " $frm->{LIBS}"   if $frm->{LIBS};
166   }
167 }
168
169 my $OSLIBS = '';
170 my $OSDEF  = "-DOS_$^O";
171
172 if ($^O eq 'hpux')                { $OSLIBS .= ' -ldld'; }
173 if (defined $Config{'d_dlsymun'}) { $OSDEF  .= ' -DDLSYMUN'; }
174
175 if ($Config{useithreads}) {
176   if ($Config{i_pthread}) {
177     print "POSIX threads\n";
178     push @objs, "mutexpthr.o";
179   }
180   elsif ($^O eq 'MSWin32') {
181     print "Win32 threads\n";
182     push @objs, "mutexwin.o";
183   }
184   else {
185     print "Unsupported threading model\n";
186     push @objs, "mutexnull.o";
187     if ($ENV{AUTOMATED_TESTING}) {
188       die "OS unsupported: no threading support code for this platform\n";
189     }
190   }
191 }
192 else {
193   print "No threads\n";
194   push @objs, "mutexnull.o";
195 }
196
197 my @typemaps = qw(typemap.local typemap);
198 if ($] < 5.008) {
199     unshift @typemaps, "typemap.oldperl";
200 }
201
202 if ($trace_context) {
203   $CFLAGS .= " -DIMAGER_TRACE_CONTEXT";
204 }
205
206 my $tests = 't/*.t t/*/*.t';
207 if (-d "xt" && scalar(() = glob("xt/*.t"))) {
208   $tests .= " xt/*.t";
209 }
210
211 my %opts=
212   (
213    NAME         => 'Imager',
214    VERSION_FROM => 'Imager.pm',
215    LIBS         => "$LFLAGS -lm $lib_libs $OSLIBS",
216    DEFINE       => "$OSDEF $lib_define $CFLAGS",
217    INC          => "$lib_inc $DFLAGS",
218    OBJECT       => join(' ', @objs),
219    DIR          => [ sort grep -d, @enabled_bundled, @extras ],
220    clean          => { FILES=>'testout rubthru.c scale.c conv.c  filters.c gaussian.c render.c rubthru.c' },
221    PM             => gen_PM(),
222    PREREQ_PM      =>
223    { 
224     'Test::More' => 0.99,
225     'Scalar::Util' => 1.00,
226     'XSLoader'    => 0,
227    },
228    TYPEMAPS       => \@typemaps,
229    test =>        { TESTS => $tests },
230   );
231
232 if ($coverage) {
233     if ($Config{gccversion}) {
234         push @ARGV, 'OPTIMIZE=-ftest-coverage -fprofile-arcs -g';
235         $opts{dynamic_lib} = { OTHERLDFLAGS => '-ftest-coverage -fprofile-arcs' };
236     }
237     else {
238         die "Don't know the coverage C flags for your compiler\n";
239     }
240 }
241
242 if (eval { ExtUtils::MakeMaker->VERSION('6.06'); 1 }) {
243   $opts{AUTHOR} = 'Tony Cook <tonyc@cpan.org>, Arnar M. Hrafnkelsson';
244   $opts{ABSTRACT} = 'Perl extension for Generating 24 bit Images';
245 }
246
247 if (eval { ExtUtils::MakeMaker->VERSION('6.46'); 1 }) {
248   $opts{LICENSE} = "perl_5";
249   $opts{META_MERGE} =
250     {
251      'meta-spec' =>
252      {
253       version => "2",
254       url => "https://metacpan.org/pod/CPAN::Meta::Spec",
255      },
256      prereqs =>
257      {
258       runtime =>
259       {
260        recommends =>
261        {
262         "Parse::RecDescent" => 0
263        },
264       },
265      },
266      dynamic_config => 0,
267      no_index =>
268      {
269       directory =>
270       [
271        "PNG",
272        "GIF",
273        "TIFF",
274        "JPEG",
275        "W32",
276        "FT2",
277        "T1",
278       ],
279      },
280      resources =>
281      {
282       homepage => "http://imager.perl.org/",
283       repository =>
284       {
285        url => "git://git.imager.perl.org/imager.git",
286        web => "http://git.imager.perl.org/imager.git",
287        type => "git",
288       },
289       bugtracker =>
290       {
291        web => "https://rt.cpan.org/Dist/Display.html?Name=Imager",
292       },
293      },
294     };
295 }
296
297 make_imconfig(\@defines);
298
299 if ($VERBOSE) { print Dumper(\%opts); }
300 mkdir('testout',0777); # since we cannot include it in the archive.
301
302 -d "probe" and rmdir "probe";
303
304 WriteMakefile(%opts);
305
306 my @good;
307 my @bad;
308 for my $name (sort { lc $a cmp lc $b } keys %IMAGER_LIBS) {
309   if ($IMAGER_LIBS{$name}) {
310     push @good, $name;
311   }
312   else {
313     push @bad, $name;
314   }
315 }
316
317 print "\n";
318 print "Libraries found:\n" if @good;
319 print "  $_\n" for @good;
320 print "Libraries *not* found:\n" if @bad;
321 print "  $_\n" for @bad;
322
323 exit;
324
325
326 sub MY::postamble {
327     my $self = shift;
328     my $perl = $self->{PERLRUN} ? '$(PERLRUN)' : '$(PERL)';
329     my $mani = maniread;
330
331     my @ims = grep /\.im$/, keys %$mani;
332 '
333 dyntest.$(MYEXTLIB) : dynfilt/Makefile
334         cd dynfilt && $(MAKE) $(PASTHRU)
335
336 lib/Imager/Regops.pm : regmach.h regops.perl
337         $(PERL) regops.perl regmach.h lib/Imager/Regops.pm
338
339 imconfig.h : Makefile.PL
340         $(ECHO) "imconfig.h out-of-date with respect to $?"
341         $(PERLRUN) Makefile.PL
342         $(ECHO) "==> Your Makefile has been rebuilt - re-run your make command <=="
343 '.qq!
344 lib/Imager/APIRef.pod : \$(C_FILES) \$(H_FILES) apidocs.perl
345         $perl apidocs.perl lib/Imager/APIRef.pod
346
347 !.join('', map _im_rule($perl, $_), @ims)
348
349 }
350
351 sub _im_rule {
352   my ($perl, $im) = @_;
353
354   (my $c = $im) =~ s/\.im$/.c/;
355   return <<MAKE;
356
357 $c: $im lib/Imager/Preprocess.pm
358         $perl -Ilib -MImager::Preprocess -epreprocess $im $c
359
360 MAKE
361
362 }
363
364 # manual configuration of helper libraries
365
366 sub manual {
367   print <<EOF;
368
369       Please answer the following questions about
370       which formats are avaliable on your computer
371
372       Warning: if you use manual configuration you are responsible for
373       configuring extra include/library directories as necessary using
374       INC and LIBS command-line assignments.
375
376 press <return> to continue
377 EOF
378
379   <STDIN>; # eat one return
380
381   for my $frm(sort { $formats{$b}{order} <=> $formats{$a}{order} } keys %formats) {
382   SWX:
383     if ($formats{$frm}{docs}) { print "\n",$formats{$frm}{docs},"\n\n"; }
384     print "Enable $frm support: ";
385     my $gz = <STDIN>;
386     chomp($gz);
387     if ($gz =~ m/^(y|yes|n|no)/i) {
388       if ($gz =~ /y/i) {
389         $formats{$frm}{enabled} = 1;
390         $IMAGER_LIBS{$frm} = 1;
391       }
392     } else { goto SWX; }
393   }
394 }
395
396
397 # automatic configuration of helper libraries
398
399 sub automatic {
400   print "Automatic probing:\n" if $VERBOSE;
401
402   if (grep $_ eq "FT1", @enabled_bundled) {
403     my %probe =
404       (
405        name => "FT1",
406        inccheck => sub { -e File::Spec->catfile($_[0], "ftnameid.h") },
407        libbase => "ttf",
408        testcode => _ft1_test_code(),
409        testcodeheaders => [ "freetype.h", "stdio.h" ],
410        incpaths => \@incpaths,
411        libpaths => \@libpaths,
412        alternatives =>
413        [
414         {
415          incsuffix => "freetype",
416         }
417        ],
418        verbose => $VERBOSE,
419       );
420     my $probe_res = Imager::Probe->probe(\%probe);
421     $IMAGER_LIBS{FT1} = defined $probe_res;
422     if ($probe_res) {
423       $formats{FT1}{enabled} = 1;
424       @{$formats{FT1}}{qw/DEFINE INC LIBS/} =
425         @$probe_res{qw/DEFINE INC LIBS/};
426     }
427   }
428 }
429
430 sub pathcheck {
431   if ($VERBOSE) {
432     print "pathcheck\n";
433     print "  Include paths:\n";
434     for (@incs) { print $_,"\n"; }
435   }
436   @incs=grep { -d $_ && -r _ && -x _ or ( print("  $_ doesnt exist or is unaccessible - removed.\n"),0) } @incs;
437
438   if ($VERBOSE) {
439     print "\nLibrary paths:\n";
440     for (@libs) { print $_,"\n"; }
441   }
442   @libs=grep { -d $_ && -r _ && -x _ or ( print("  $_ doesnt exist or is unaccessible - removed.\n"),0) } @libs;
443   print "\ndone.\n";
444 }
445
446
447 # Format data initialization
448
449 # format definition is:
450 # defines needed
451 # default include path
452 # files needed for include (boolean perl code)
453 # default lib path
454 # libs needed
455 # files needed for link (boolean perl code)
456 # object files needed for the format
457
458
459 sub init {
460
461   my @definc = qw(/usr/include);
462   @definc{@definc}=(1) x @definc;
463   @incs=
464     (
465      split(/\Q$Config{path_sep}/, $INCPATH),
466      map _tilde_expand($_), map { split /\Q$Config{path_sep}/ } @incpaths 
467     );
468   if ($Config{locincpth}) {
469     push @incs, grep -d, split ' ', $Config{locincpth};
470   }
471   if ($^O =~ /win32/i && $Config{cc} =~ /\bcl\b/i) {
472     push(@incs, split /;/, $ENV{INCLUDE}) if exists $ENV{INCLUDE};
473   }
474   if ($Config{incpath}) {
475     push @incs, grep -d, split /\Q$Config{path_sep}/, $Config{incpath};
476   }
477   push @incs, grep -d,
478       qw(/sw/include 
479          /usr/include/freetype2
480          /usr/local/include/freetype2
481          /usr/local/include/freetype1/freetype
482          /usr/include /usr/local/include /usr/include/freetype
483          /usr/local/include/freetype);
484   if ($Config{ccflags}) {
485     my @hidden = map { /^-I(.*)$/ ? ($1) : () } split ' ', $Config{ccflags};
486     push @incs, @hidden;
487     @definc{@hidden} = (1) x @hidden;
488   }
489
490   @libs= ( split(/\Q$Config{path_sep}/,$LIBPATH),
491     map _tilde_expand($_), map { split /\Q$Config{path_sep}/} @libpaths );
492   if ($Config{loclibpth}) {
493     push @libs, grep -d, split ' ', $Config{loclibpth};
494   }
495   
496   push @libs, grep -d, qw(/sw/lib),  split(/ /, $Config{'libpth'});
497   push @libs, grep -d, split / /, $Config{libspath} if $Config{libspath};
498   if ($^O =~ /win32/i && $Config{cc} =~ /\bcl\b/i) {
499     push(@libs, split /;/, $ENV{LIB}) if exists $ENV{LIB};
500   }
501   if ($^O eq 'cygwin') {
502     push(@libs, '/usr/lib/w32api') if -d '/usr/lib/w32api';
503     push(@incs, '/usr/include/w32api') if -d '/usr/include/w32api';
504   }
505   if ($Config{ldflags}) {
506     # some builds of perl put -Ldir into ldflags without putting it in
507     # loclibpth, let's extract them
508     my @hidden = grep -d, map { /^-L(.*)$/ ? ($1) : () }
509       split ' ', $Config{ldflags};
510     push @libs, @hidden;
511     # don't mark them as seen - EU::MM will remove any libraries
512     # it can't find and it doesn't look for -L in ldflags
513     #@deflib{@hidden} = @hidden;
514   }
515   push @libs, grep -d, qw(/usr/local/lib);
516
517   $formats{FT1}=
518     {
519      order=>'31',
520      def=>'HAVE_LIBTT',
521      objfiles=>'fontft1.o',
522      LIBS => "-lttf",
523      docs=>q{
524 Freetype 1.x supports Truetype fonts and is obsoleted by Freetype 2.x.
525
526 It's probably insecure.
527 }
528                        };
529   # Make fix indent
530   for (keys %formats) { $formats{$_}->{docs} =~ s/^\s+/  /mg; }
531 }
532
533
534
535 sub gen {
536   my $V = $ENV{$_[0]};
537   print "  $_[0]: '$V'\n"
538       if $VERBOSE && defined $V;
539   defined($V) ? $V : "";
540 }
541
542
543 # Get information from environment variables
544
545 sub getenv {
546
547   $VERBOSE ||= gen("IM_VERBOSE");
548
549   print "Environment config:\n" if $VERBOSE;
550
551   ($INCPATH,
552    $LIBPATH,
553    $NOLOG,
554    $DEBUG_MALLOC,
555    $MANUAL,
556    $CFLAGS,
557    $LFLAGS,
558    $DFLAGS) = map { gen $_ } qw(IM_INCPATH
559                                 IM_LIBPATH
560                                 IM_NOLOG
561                                 IM_DEBUG_MALLOC
562                                 IM_MANUAL
563                                 IM_CFLAGS
564                                 IM_LFLAGS
565                                 IM_DFLAGS);
566 }
567
568 # populate the environment so that sub-modules get the same info
569 sub setenv {
570   $ENV{IM_VERBOSE} = 1 if $VERBOSE;
571   $ENV{IM_INCPATH} = join $Config{path_sep}, @incpaths if @incpaths;
572   $ENV{IM_LIBPATH} = join $Config{path_sep}, @libpaths if @libpaths;
573 }
574
575 sub make_imconfig {
576   my ($defines) = @_;
577
578   open CONFIG, "> imconfig.h"
579     or die "Cannot create imconfig.h: $!\n";
580   print CONFIG <<EOS;
581 /* This file is automatically generated by Makefile.PL.
582    Don't edit this file, since any changes will be lost */
583
584 #ifndef IMAGER_IMCONFIG_H
585 #define IMAGER_IMCONFIG_H
586 EOS
587   for my $define (@$defines) {
588     if ($define->[2]) {
589       print CONFIG "\n/*\n  $define->[2]\n*/\n\n";
590     }
591     print CONFIG "#define $define->[0] $define->[1]\n";
592   }
593   if ($Config{gccversion} && $Config{gccversion} =~ /^([0-9]+)/ && $1 > 3) {
594     print CONFIG <<EOS;
595 /*
596
597 Compiler supports the GCC __attribute__((format...)) syntax.
598
599 */
600
601 #define IMAGER_FORMAT_ATTR 1
602
603 EOS
604   }
605
606   if ($Config{d_snprintf}) {
607     print CONFIG <<EOS;
608 /* We can use snprintf() */
609 #define IMAGER_SNPRINTF 1
610
611 EOS
612   }
613
614   if ($Config{d_vsnprintf}) {
615     print CONFIG <<EOS;
616 /* We can use vsnprintf() */
617 #define IMAGER_VSNPRINTF 1
618
619 EOS
620   }
621
622   print CONFIG <<EOS;
623 /*
624  Type and format code for formatted output as with printf.
625
626  This is intended for formatting i_img_dim values.
627 */
628 typedef $Config{ivtype} i_dim_format_t;
629 #define i_DF $Config{ivdformat}
630 EOS
631
632   print CONFIG "\n#endif\n";
633   close CONFIG;
634 }
635
636 sub usage {
637   print STDERR <<EOS;
638 Usage: $0 [--enable feature1,feature2,...] [other options]
639        $0 [--disable feature1,feature2,...]  [other options]
640        $0 --help
641 Possible feature names are:
642   T1-fonts
643 Other options:
644   --verbose | -v
645     Verbose library probing (or set IM_VERBOSE in the environment)
646   --nolog
647     Disable logging (or set IM_NOLOG in the environment)
648   --incpath dir
649     Add to the include search path
650   --libpath dir
651     Add to the library search path
652   --coverage
653     Build for coverage testing.
654   --assert
655     Build with assertions active.
656 EOS
657   exit 1;
658
659 }
660
661 # generate the PM MM argument
662 # I'd prefer to modify the public version, but there doesn't seem to be 
663 # a public API to do that
664 sub gen_PM {
665   my %pm;
666   my $instbase = '$(INST_LIBDIR)';
667
668   # first the basics, .pm and .pod files
669   $pm{"Imager.pm"} = "$instbase/Imager.pm";
670
671   my $mani = maniread();
672
673   for my $filename (keys %$mani) {
674     if ($filename =~ m!^lib/! && $filename =~ /\.(pm|pod)$/) {
675       (my $work = $filename) =~ s/^lib//;
676       $pm{$filename} = $instbase . $work;
677     }
678   }
679
680   # need the typemap
681   $pm{typemap} = $instbase . '/Imager/typemap';
682
683   # and the core headers
684   for my $filename (keys %$mani) {
685     if ($filename =~ /^\w+\.h$/) {
686       $pm{$filename} = $instbase . '/Imager/include/' . $filename;
687     }
688   }
689
690   # and the generated header
691   $pm{"imconfig.h"} = $instbase . '/Imager/include/imconfig.h';
692
693   \%pm;
694 }
695
696 my $home;
697 sub _tilde_expand {
698   my ($path) = @_;
699
700   if ($path =~ m!^~[/\\]!) {
701     defined $home or $home = $ENV{HOME};
702     if (!defined $home && $^O eq 'MSWin32'
703        && defined $ENV{HOMEDRIVE} && defined $ENV{HOMEPATH}) {
704       $home = $ENV{HOMEDRIVE} . $ENV{HOMEPATH};
705     }
706     unless (defined $home) {
707       $home = eval { (getpwuid($<))[7] };
708     }
709     defined $home or die "You supplied $path, but I can't find your home directory\n";
710     $path =~ s/^~//;
711     $path = File::Spec->catdir($home, $path);
712   }
713
714   $path;
715 }
716
717 sub _ft1_test_code {
718   return <<'CODE';
719 TT_Engine engine;
720 TT_Error error;
721
722 error = TT_Init_FreeType(&engine);
723 if (error) {
724    printf("FT1: Could not initialize engine\n");
725    exit(1);
726 }
727
728 return 0;
729 CODE
730 }
731
732 sub map_bundled {
733   my (@names) = @_;
734
735   @names = map { split /,/ } @names;
736
737   my @outnames;
738   for my $name (@names) {
739     push @outnames, $name;
740     push @outnames, $bundled_names{$name}
741       if $bundled_names{$name};
742   }
743
744   @outnames;
745 }
746
747 1;