]> git.imager.perl.org - imager.git/blob - Makefile.PL
probe to check if $Config{ivdformat} is correct for the built-in sprintf
[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 # eval to prevent warnings about versions with _ in them
243 my $MM_ver = eval $ExtUtils::MakeMaker::VERSION;
244 if ($MM_ver > 6.06) {
245   $opts{AUTHOR} = 'Tony Cook <tonyc@cpan.org>, Arnar M. Hrafnkelsson';
246   $opts{ABSTRACT} = 'Perl extension for Generating 24 bit Images';
247 }
248
249 if ($MM_ver >= 6.46) {
250   $opts{META_MERGE} =
251     {
252      recommends =>
253      {
254       "Parse::RecDescent" => 0
255      },
256      license => "perl",
257      dynamic_config => 1,
258      no_index =>
259      {
260       directory =>
261       [
262        "PNG",
263        "GIF",
264        "TIFF",
265        "JPEG",
266        "W32",
267        "FT2",
268        "T1",
269       ],
270      },
271      resources =>
272      {
273       homepage => "http://imager.perl.org/",
274       repository => "git://git.imager.perl.org/imager.git",
275       bugtracker => "http://rt.cpan.org/NoAuth/Bugs.html?Dist=Imager",
276      },
277     };
278 }
279
280 my $ivdformat = probe_ivdformat();
281
282 make_imconfig(\@defines, $ivdformat);
283
284 if ($VERBOSE) { print Dumper(\%opts); }
285 mkdir('testout',0777); # since we cannot include it in the archive.
286
287 -d "probe" and rmdir "probe";
288
289 WriteMakefile(%opts);
290
291 my @good;
292 my @bad;
293 for my $name (sort { lc $a cmp lc $b } keys %IMAGER_LIBS) {
294   if ($IMAGER_LIBS{$name}) {
295     push @good, $name;
296   }
297   else {
298     push @bad, $name;
299   }
300 }
301
302 print "\n";
303 print "Libraries found:\n" if @good;
304 print "  $_\n" for @good;
305 print "Libraries *not* found:\n" if @bad;
306 print "  $_\n" for @bad;
307
308 exit;
309
310
311 sub MY::postamble {
312     my $self = shift;
313     my $perl = $self->{PERLRUN} ? '$(PERLRUN)' : '$(PERL)';
314     my $mani = maniread;
315
316     my @ims = grep /\.im$/, keys %$mani;
317 '
318 dyntest.$(MYEXTLIB) : dynfilt/Makefile
319         cd dynfilt && $(MAKE) $(PASTHRU)
320
321 lib/Imager/Regops.pm : regmach.h regops.perl
322         $(PERL) regops.perl regmach.h lib/Imager/Regops.pm
323
324 imconfig.h : Makefile.PL
325         $(ECHO) "imconfig.h out-of-date with respect to $?"
326         $(PERLRUN) Makefile.PL
327         $(ECHO) "==> Your Makefile has been rebuilt - re-run your make command <=="
328 '.qq!
329 lib/Imager/APIRef.pod : \$(C_FILES) \$(H_FILES) apidocs.perl
330         $perl apidocs.perl lib/Imager/APIRef.pod
331
332 !.join('', map _im_rule($perl, $_), @ims)
333
334 }
335
336 sub _im_rule {
337   my ($perl, $im) = @_;
338
339   (my $c = $im) =~ s/\.im$/.c/;
340   return <<MAKE;
341
342 $c: $im lib/Imager/Preprocess.pm
343         $perl -Ilib -MImager::Preprocess -epreprocess $im $c
344
345 MAKE
346
347 }
348
349 # manual configuration of helper libraries
350
351 sub manual {
352   print <<EOF;
353
354       Please answer the following questions about
355       which formats are avaliable on your computer
356
357       Warning: if you use manual configuration you are responsible for
358       configuring extra include/library directories as necessary using
359       INC and LIBS command-line assignments.
360
361 press <return> to continue
362 EOF
363
364   <STDIN>; # eat one return
365
366   for my $frm(sort { $formats{$b}{order} <=> $formats{$a}{order} } keys %formats) {
367   SWX:
368     if ($formats{$frm}{docs}) { print "\n",$formats{$frm}{docs},"\n\n"; }
369     print "Enable $frm support: ";
370     my $gz = <STDIN>;
371     chomp($gz);
372     if ($gz =~ m/^(y|yes|n|no)/i) {
373       if ($gz =~ /y/i) {
374         $formats{$frm}{enabled} = 1;
375         $IMAGER_LIBS{$frm} = 1;
376       }
377     } else { goto SWX; }
378   }
379 }
380
381
382 # automatic configuration of helper libraries
383
384 sub automatic {
385   print "Automatic probing:\n" if $VERBOSE;
386
387   if (grep $_ eq "FT1", @enabled_bundled) {
388     my %probe =
389       (
390        name => "FT1",
391        inccheck => sub { -e File::Spec->catfile($_[0], "ftnameid.h") },
392        libbase => "ttf",
393        testcode => _ft1_test_code(),
394        testcodeheaders => [ "freetype.h", "stdio.h" ],
395        incpaths => \@incpaths,
396        libpaths => \@libpaths,
397        alternatives =>
398        [
399         {
400          incsuffix => "freetype",
401         }
402        ],
403        verbose => $VERBOSE,
404       );
405     my $probe_res = Imager::Probe->probe(\%probe);
406     $IMAGER_LIBS{FT1} = defined $probe_res;
407     if ($probe_res) {
408       $formats{FT1}{enabled} = 1;
409       @{$formats{FT1}}{qw/DEFINE INC LIBS/} =
410         @$probe_res{qw/DEFINE INC LIBS/};
411     }
412   }
413 }
414
415 sub pathcheck {
416   if ($VERBOSE) {
417     print "pathcheck\n";
418     print "  Include paths:\n";
419     for (@incs) { print $_,"\n"; }
420   }
421   @incs=grep { -d $_ && -r _ && -x _ or ( print("  $_ doesnt exist or is unaccessible - removed.\n"),0) } @incs;
422
423   if ($VERBOSE) {
424     print "\nLibrary paths:\n";
425     for (@libs) { print $_,"\n"; }
426   }
427   @libs=grep { -d $_ && -r _ && -x _ or ( print("  $_ doesnt exist or is unaccessible - removed.\n"),0) } @libs;
428   print "\ndone.\n";
429 }
430
431
432 # Format data initialization
433
434 # format definition is:
435 # defines needed
436 # default include path
437 # files needed for include (boolean perl code)
438 # default lib path
439 # libs needed
440 # files needed for link (boolean perl code)
441 # object files needed for the format
442
443
444 sub init {
445
446   my @definc = qw(/usr/include);
447   @definc{@definc}=(1) x @definc;
448   @incs=
449     (
450      split(/\Q$Config{path_sep}/, $INCPATH),
451      map _tilde_expand($_), map { split /\Q$Config{path_sep}/ } @incpaths 
452     );
453   if ($Config{locincpth}) {
454     push @incs, grep -d, split ' ', $Config{locincpth};
455   }
456   if ($^O =~ /win32/i && $Config{cc} =~ /\bcl\b/i) {
457     push(@incs, split /;/, $ENV{INCLUDE}) if exists $ENV{INCLUDE};
458   }
459   if ($Config{incpath}) {
460     push @incs, grep -d, split /\Q$Config{path_sep}/, $Config{incpath};
461   }
462   push @incs, grep -d,
463       qw(/sw/include 
464          /usr/include/freetype2
465          /usr/local/include/freetype2
466          /usr/local/include/freetype1/freetype
467          /usr/include /usr/local/include /usr/include/freetype
468          /usr/local/include/freetype);
469   if ($Config{ccflags}) {
470     my @hidden = map { /^-I(.*)$/ ? ($1) : () } split ' ', $Config{ccflags};
471     push @incs, @hidden;
472     @definc{@hidden} = (1) x @hidden;
473   }
474
475   @libs= ( split(/\Q$Config{path_sep}/,$LIBPATH),
476     map _tilde_expand($_), map { split /\Q$Config{path_sep}/} @libpaths );
477   if ($Config{loclibpth}) {
478     push @libs, grep -d, split ' ', $Config{loclibpth};
479   }
480   
481   push @libs, grep -d, qw(/sw/lib),  split(/ /, $Config{'libpth'});
482   push @libs, grep -d, split / /, $Config{libspath} if $Config{libspath};
483   if ($^O =~ /win32/i && $Config{cc} =~ /\bcl\b/i) {
484     push(@libs, split /;/, $ENV{LIB}) if exists $ENV{LIB};
485   }
486   if ($^O eq 'cygwin') {
487     push(@libs, '/usr/lib/w32api') if -d '/usr/lib/w32api';
488     push(@incs, '/usr/include/w32api') if -d '/usr/include/w32api';
489   }
490   if ($Config{ldflags}) {
491     # some builds of perl put -Ldir into ldflags without putting it in
492     # loclibpth, let's extract them
493     my @hidden = grep -d, map { /^-L(.*)$/ ? ($1) : () }
494       split ' ', $Config{ldflags};
495     push @libs, @hidden;
496     # don't mark them as seen - EU::MM will remove any libraries
497     # it can't find and it doesn't look for -L in ldflags
498     #@deflib{@hidden} = @hidden;
499   }
500   push @libs, grep -d, qw(/usr/local/lib);
501
502   $formats{FT1}=
503     {
504      order=>'31',
505      def=>'HAVE_LIBTT',
506      objfiles=>'fontft1.o',
507      LIBS => "-lttf",
508      docs=>q{
509 Freetype 1.x supports Truetype fonts and is obsoleted by Freetype 2.x.
510
511 It's probably insecure.
512 }
513                        };
514   # Make fix indent
515   for (keys %formats) { $formats{$_}->{docs} =~ s/^\s+/  /mg; }
516 }
517
518
519
520 sub gen {
521   my $V = $ENV{$_[0]};
522   print "  $_[0]: '$V'\n"
523       if $VERBOSE && defined $V;
524   defined($V) ? $V : "";
525 }
526
527
528 # Get information from environment variables
529
530 sub getenv {
531
532   $VERBOSE ||= gen("IM_VERBOSE");
533
534   print "Environment config:\n" if $VERBOSE;
535
536   ($INCPATH,
537    $LIBPATH,
538    $NOLOG,
539    $DEBUG_MALLOC,
540    $MANUAL,
541    $CFLAGS,
542    $LFLAGS,
543    $DFLAGS) = map { gen $_ } qw(IM_INCPATH
544                                 IM_LIBPATH
545                                 IM_NOLOG
546                                 IM_DEBUG_MALLOC
547                                 IM_MANUAL
548                                 IM_CFLAGS
549                                 IM_LFLAGS
550                                 IM_DFLAGS);
551 }
552
553 # populate the environment so that sub-modules get the same info
554 sub setenv {
555   $ENV{IM_VERBOSE} = 1 if $VERBOSE;
556   $ENV{IM_INCPATH} = join $Config{path_sep}, @incpaths if @incpaths;
557   $ENV{IM_LIBPATH} = join $Config{path_sep}, @libpaths if @libpaths;
558 }
559
560 sub make_imconfig {
561   my ($defines, $ivdformat) = @_;
562
563   open CONFIG, "> imconfig.h"
564     or die "Cannot create imconfig.h: $!\n";
565   print CONFIG <<EOS;
566 /* This file is automatically generated by Makefile.PL.
567    Don't edit this file, since any changes will be lost */
568
569 #ifndef IMAGER_IMCONFIG_H
570 #define IMAGER_IMCONFIG_H
571 EOS
572   for my $define (@$defines) {
573     if ($define->[2]) {
574       print CONFIG "\n/*\n  $define->[2]\n*/\n\n";
575     }
576     print CONFIG "#define $define->[0] $define->[1]\n";
577   }
578   if ($Config{gccversion} && $Config{gccversion} =~ /^([0-9]+)/ && $1 > 3) {
579     print CONFIG <<EOS;
580 /*
581
582 Compiler supports the GCC __attribute__((format...)) syntax.
583
584 */
585
586 #define IMAGER_FORMAT_ATTR 1
587
588 EOS
589   }
590
591   if ($Config{d_snprintf}) {
592     print CONFIG <<EOS;
593 /* We can use snprintf() */
594 #define IMAGER_SNPRINTF 1
595
596 EOS
597   }
598
599   if ($Config{d_vsnprintf}) {
600     print CONFIG <<EOS;
601 /* We can use vsnprintf() */
602 #define IMAGER_VSNPRINTF 1
603
604 EOS
605   }
606
607   print CONFIG <<EOS;
608 /*
609  Type and format code for formatted output as with printf.
610
611  This is intended for formatting i_img_dim values.
612 */
613 typedef $Config{ivtype} i_dim_format_t;
614 #define i_DF $ivdformat
615 EOS
616
617   print CONFIG "\n#endif\n";
618   close CONFIG;
619 }
620
621 sub usage {
622   print STDERR <<EOS;
623 Usage: $0 [--enable feature1,feature2,...] [other options]
624        $0 [--disable feature1,feature2,...]  [other options]
625        $0 --help
626 Possible feature names are:
627   T1-fonts
628 Other options:
629   --verbose | -v
630     Verbose library probing (or set IM_VERBOSE in the environment)
631   --nolog
632     Disable logging (or set IM_NOLOG in the environment)
633   --incpath dir
634     Add to the include search path
635   --libpath dir
636     Add to the library search path
637   --coverage
638     Build for coverage testing.
639   --assert
640     Build with assertions active.
641 EOS
642   exit 1;
643
644 }
645
646 # at least one CPAN tester has an incorrect ivdformat, make sure it's
647 # valid
648 sub probe_ivdformat {
649   if (_test_ivdformat($Config{ivdformat})) {
650     return $Config{ivdformat};
651   }
652   die "OS unsupported: Invalid ivdformat ($Config{ivdformat}) in this perl\n";
653 }
654
655 sub _test_ivdformat {
656   my ($fmt) = @_;
657   require Devel::CheckLib;
658   my $good =
659     Devel::CheckLib::check_lib
660       (
661        debug => $VERBOSE,
662        LIBS => [],
663        INC => "",
664        header => [ "stdio.h", "string.h" ],
665        function => <<CODE,
666 char buf[80];
667 $Config{ivtype} x = 10;
668 sprintf(buf, "%" $fmt " %" $fmt, x, x);
669 if (strcmp(buf, "10 10")) {
670     printf("ivformat: " $fmt " is invalid\n");
671     return 1;
672 }
673 CODE
674       );
675 }
676
677 # generate the PM MM argument
678 # I'd prefer to modify the public version, but there doesn't seem to be 
679 # a public API to do that
680 sub gen_PM {
681   my %pm;
682   my $instbase = '$(INST_LIBDIR)';
683
684   # first the basics, .pm and .pod files
685   $pm{"Imager.pm"} = "$instbase/Imager.pm";
686
687   my $mani = maniread();
688
689   for my $filename (keys %$mani) {
690     if ($filename =~ m!^lib/! && $filename =~ /\.(pm|pod)$/) {
691       (my $work = $filename) =~ s/^lib//;
692       $pm{$filename} = $instbase . $work;
693     }
694   }
695
696   # need the typemap
697   $pm{typemap} = $instbase . '/Imager/typemap';
698
699   # and the core headers
700   for my $filename (keys %$mani) {
701     if ($filename =~ /^\w+\.h$/) {
702       $pm{$filename} = $instbase . '/Imager/include/' . $filename;
703     }
704   }
705
706   # and the generated header
707   $pm{"imconfig.h"} = $instbase . '/Imager/include/imconfig.h';
708
709   \%pm;
710 }
711
712 my $home;
713 sub _tilde_expand {
714   my ($path) = @_;
715
716   if ($path =~ m!^~[/\\]!) {
717     defined $home or $home = $ENV{HOME};
718     if (!defined $home && $^O eq 'MSWin32'
719        && defined $ENV{HOMEDRIVE} && defined $ENV{HOMEPATH}) {
720       $home = $ENV{HOMEDRIVE} . $ENV{HOMEPATH};
721     }
722     unless (defined $home) {
723       $home = eval { (getpwuid($<))[7] };
724     }
725     defined $home or die "You supplied $path, but I can't find your home directory\n";
726     $path =~ s/^~//;
727     $path = File::Spec->catdir($home, $path);
728   }
729
730   $path;
731 }
732
733 sub _ft1_test_code {
734   return <<'CODE';
735 TT_Engine engine;
736 TT_Error error;
737
738 error = TT_Init_FreeType(&engine);
739 if (error) {
740    printf("FT1: Could not initialize engine\n");
741    return 1;
742 }
743
744 return 0;
745 CODE
746 }
747
748 sub map_bundled {
749   my (@names) = @_;
750
751   @names = map { split /,/ } @names;
752
753   my @outnames;
754   for my $name (@names) {
755     push @outnames, $name;
756     push @outnames, $bundled_names{$name}
757       if $bundled_names{$name};
758   }
759
760   @outnames;
761 }
762
763 1;