2ea3019dcfba5f25b05022e7567c63fa1c085144
[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 vars qw(%formats $VERBOSE $INCPATH $LIBPATH $NOLOG $DEBUG_MALLOC $MANUAL $CFLAGS $LFLAGS $DFLAGS);
10
11 #
12 # IM_INCPATH      colon seperated list of paths to extra include paths
13 # IM_LIBPATH      colon seperated list of paths to extra library paths
14 #
15 # IM_VERBOSE      turns on verbose mode for the library finding and such
16 # IM_MANUAL       to manually select which libraries are used and which not
17 # IM_ENABLE       to programmatically select which libraries are used
18 #                 and which are not
19 # IM_NOLOG        if true logging will not be compiled into the module
20 # IM_DEBUG_MALLOC if true malloc debbuging will be compiled into the module
21 #                 do not use IM_DEBUG_MALLOC in production - this slows
22 #                 everything down by alot
23 # IM_CFLAGS       Extra flags to pass to the compiler
24 # IM_LFLAGS       Extra flags to pass to the linker
25 # IM_DFLAGS       Extra flags to pass to the preprocessor
26 # IM_SUPPRESS_PROMPT  Suppress the prompt asking about gif support
27
28 getenv();     # get environment variables
29
30 my $lext=$Config{'so'};   # Get extensions of libraries
31 my $aext=$Config{'_a'};
32
33 my $help; # display help if set
34 my @enable; # list of drivers to enable
35 my @disable; # or list of drivers to disable
36 my @incpaths; # places to look for headers
37 my @libpaths; # places to look for libraries
38 my $noexif; # non-zero to disable EXIF parsing of JPEGs
39 my $no_gif_set_version; # disable calling EGifSetGifVersion
40 my $coverage; # build for coverage testing
41 GetOptions("help" => \$help,
42            "enable=s" => \@enable,
43            "disable=s" => \@disable,
44            "incpath=s", \@incpaths,
45            "libpath=s" => \@libpaths,
46            "verbose|v" => \$VERBOSE,
47            "nolog" => \$NOLOG,
48            "noexif" => \$noexif,
49            "nogifsetversion" => \$no_gif_set_version,
50            'coverage' => \$coverage);
51
52 if ($VERBOSE) { 
53   print "Verbose mode\n"; 
54   require Data::Dumper; 
55   import Data::Dumper qw(Dumper);
56 }
57
58 if ($help) {
59   usage();
60 }
61
62 my @defines;
63
64 if ($NOLOG)   { print "Logging not compiled into module\n"; }
65 else { 
66   push @defines, [ IMAGER_LOG => 1, "Logging system" ];
67 }
68
69 if ($DEBUG_MALLOC) {
70   push @defines, [ IMAGER_DEBUG_MALLOC => 1, "Use Imager's DEBUG malloc()" ];
71   print "Malloc debugging enabled\n";
72 }
73
74 if (@enable && @disable) {
75   print STDERR "Only --enable or --disable can be used, not both, try --help\n";
76   exit 1;
77 }
78
79 my %definc;
80 my %deflib;
81 my @incs; # all the places to look for headers
82 my @libs; # all the places to look for libraries
83
84 init();       # initialize global data
85 pathcheck();  # Check if directories exist
86
87 if (exists $ENV{IM_ENABLE}) {
88   my %en = map { $_, 1 } split ' ', $ENV{IM_ENABLE};
89   for my $key (keys %formats) {
90     delete $formats{$key} unless $en{$key};
91   }
92 }
93 if (@enable) {
94   my %en = map { $_ => 1 } map { split /,/ } @enable;
95   for my $key (keys %formats) {
96     delete $formats{$key} unless $en{$key};
97   }
98 }
99 elsif (@disable) {
100   delete @formats{map { split /,/ } @disable};
101 }
102
103 # Pick what libraries are used
104 if ($MANUAL) {
105   manual();
106 } else {
107   automatic();
108 }
109
110 # Make sure there isn't a clash between the gif libraries.
111 gifcheck();
112
113 my $lib_cflags = '';
114 my $lib_lflags = '';
115 my $F_LIBS = '';
116 my $F_OBJECT = '';
117 for my $frmkey (sort { $formats{$a}{order} <=> $formats{$b}{order} } keys %formats) {
118   my $frm = $formats{$frmkey};
119   push @defines, [ $frm->{def}, 1, "$frmkey available" ];
120   $F_OBJECT .= ' '  .$frm->{objfiles};
121   if ($frm->{cflags}) {
122     $lib_cflags   .= ' '  .$frm->{cflags};
123     ++$definc{$_} for map { /^-I(.*)$/ ? ($1) : () }
124       grep /^-I./, split ' ', $frm->{cflags};
125   }
126   if ($frm->{lflags}) {
127     $lib_lflags .= ' ' . $frm->{lflags};
128   }
129   else {
130     $F_LIBS   .= ' '  .$frm->{libfiles};
131   }
132
133 }
134
135 unless ($noexif) {
136   print "EXIF support enabled\n";
137   push @defines, [ 'IMEXIF_ENABLE', 1, "Enable experimental EXIF support" ];
138   $F_OBJECT .= ' imexif.o';
139 }
140
141 my $F_INC  = join ' ', map "-I$_", map / / ? qq{"$_"} : $_, 
142   grep !$definc{$_}, @incs;
143 $F_LIBS = join(' ',map "-L$_", map / / ? qq{"$_"} : $_, 
144                grep !$deflib{$_}++, @libs) . $F_LIBS;
145
146 my $OSLIBS = '';
147 my $OSDEF  = "-DOS_$^O";
148
149 if ($^O eq 'hpux')                { $OSLIBS .= ' -ldld'; }
150 if (defined $Config{'d_dlsymun'}) { $OSDEF  .= ' -DDLSYMUN'; }
151
152 my @objs = qw(Imager.o draw.o polygon.o image.o io.o iolayer.o
153               log.o gaussian.o conv.o pnm.o raw.o feat.o font.o
154               filters.o dynaload.o stackmach.o datatypes.o
155               regmach.o trans2.o quant.o error.o convert.o
156               map.o tags.o palimg.o maskimg.o img16.o rotate.o
157               bmp.o tga.o color.o fills.o imgdouble.o limits.o hlines.o
158               imext.o scale.o rubthru.o render.o paste.o compose.o);
159
160 my %opts=(
161           'NAME'         => 'Imager',
162           'VERSION_FROM' => 'Imager.pm',
163           'LIBS'         => "$LFLAGS -lm $lib_lflags $OSLIBS $F_LIBS",
164           'DEFINE'       => "$OSDEF $CFLAGS",
165           'INC'          => "$lib_cflags $DFLAGS $F_INC",
166           'OBJECT'       => join(' ', @objs, $F_OBJECT),
167           clean          => { FILES=>'testout rubthru.c scale.c conv.c  filters.c gaussian.c render.c rubthru.c' },
168           PM             => gen_PM(),
169           PREREQ_PM      => { 'Test::More' => 0.47 },
170          );
171
172 if ($coverage) {
173     if ($Config{gccversion}) {
174         push @ARGV, 'OPTIMIZE=-ftest-coverage -fprofile-arcs';
175         #$opts{dynamic_lib} = { OTHERLDFLAGS => '-ftest-coverage -fprofile-arcs' };
176     }
177     else {
178         die "Don't know the coverage C flags for your compiler\n";
179     }
180 }
181
182 # eval to prevent warnings about versions with _ in them
183 my $MM_ver = eval $ExtUtils::MakeMaker::VERSION;
184 if ($MM_ver > 6.06) {
185   $opts{AUTHOR} = 'Tony Cook <tony@imager.perl.org>, Arnar M. Hrafnkelsson';
186   $opts{ABSTRACT} = 'Perl extension for Generating 24 bit Images';
187 }
188
189 if ($MM_ver >= 6.46) {
190   $opts{META_MERGE} =
191     {
192      recommends =>
193      {
194       "Parse::RecDescent" => 0
195      },
196      license => "perl",
197      dynamic_config => 1,
198     };
199 }
200
201 make_imconfig(\@defines);
202
203 if ($VERBOSE) { print Dumper(\%opts); }
204 mkdir('testout',0777); # since we cannot include it in the archive.
205
206 WriteMakefile(%opts);
207
208 exit;
209
210
211 sub MY::postamble {
212     my $self = shift;
213     my $perl = $self->{PERLRUN} ? '$(PERLRUN)' : '$(PERL)';
214     my $mani = maniread;
215
216     my @ims = grep /\.im$/, keys %$mani;
217 '
218 dyntest.$(MYEXTLIB) : dynfilt/Makefile
219         cd dynfilt && $(MAKE) $(PASTHRU)
220
221 lib/Imager/Regops.pm : regmach.h regops.perl
222         $(PERL) regops.perl regmach.h lib/Imager/Regops.pm
223
224 imconfig.h : Makefile.PL
225         $(ECHO) "imconfig.h out-of-date with respect to $?"
226         $(PERLRUN) Makefile.PL
227         $(ECHO) "==> Your Makefile has been rebuilt - re-run your make command <=="
228 '.qq!
229 lib/Imager/APIRef.pod : \$(C_FILES) apidocs.perl
230         $perl apidocs.perl lib/Imager/APIRef.pod
231
232 !.join('', map _im_rule($perl, $_), @ims)
233
234 }
235
236 sub _im_rule {
237   my ($perl, $im) = @_;
238
239   (my $c = $im) =~ s/\.im$/.c/;
240   return <<MAKE;
241
242 $c: $im lib/Imager/Preprocess.pm
243         $perl -Ilib -MImager::Preprocess -epreprocess $im $c
244
245 MAKE
246
247 }
248
249 # manual configuration of helper libraries
250
251 sub manual {
252   print <<EOF;
253
254       Please answer the following questions about
255       which formats are avaliable on your computer
256
257 press <return> to continue
258 EOF
259
260   <STDIN>; # eat one return
261
262   for my $frm(sort { $formats{$b}{order} <=> $formats{$a}{order} } keys %formats) {
263   SWX:
264     if ($formats{$frm}{docs}) { print "\n",$formats{$frm}{docs},"\n\n"; }
265     print "Enable $frm support: ";
266     my $gz = <STDIN>;
267     chomp($gz);
268     if ($gz =~ m/^(y|yes|n|no)/i) {
269       $gz=substr(lc($gz),0,1);
270       if ($gz eq 'n') {
271         delete $formats{$frm};
272       }
273     } else { goto SWX; }
274   }
275 }
276
277
278 # automatic configuration of helper libraries
279
280 sub automatic {
281   print "Automatic probing:\n" if $VERBOSE;
282   for my $frm (sort { $formats{$a}{order} <=> $formats{$b}{order} } keys %formats) {
283     delete $formats{$frm} if !checkformat($frm);        
284   }
285 }
286
287
288 sub gifcheck {
289   if ($formats{'gif'} and $formats{'ungif'}) {
290     print "ungif and gif can not coexist - removing ungif support\n";
291     delete $formats{'ungif'};
292   }
293
294   for my $frm (qw(gif ungif)) {
295     checkformat($frm) if ($MANUAL and $formats{$frm});
296   }
297
298   my @dirs;
299   for my $frm (grep $formats{$_}, qw(gif ungif)) {
300     push(@dirs, @{$formats{$frm}{incdir}}) if $formats{$frm}{incdir};
301   }
302   my $minor = 0;
303   my $major = 0;
304   FILES: for my $dir (@dirs) {
305     my $h = "$dir/gif_lib.h";
306     open H, "< $h" or next;
307     while (<H>) {
308       if (/GIF_LIB_VERSION\s+"\s*version\s*(\d+)\.(\d+)/i) {
309         $major = $1;
310         $minor = $2;
311         close H;
312         last FILES;
313       }
314     }
315     close H;
316   }
317
318   # we need the version in a #ifdefable form
319
320   push @defines, [ IM_GIFMAJOR => $major, "Parsed giflib version" ];
321   push @defines, [ IM_GIFMINOR => $minor ];
322   push @defines, [ IM_NO_SET_GIF_VERSION => 1, "Disable EGifSetGifVersion" ]
323     if $no_gif_set_version;
324 }
325
326
327 sub grep_directory {
328   my($path, $chk)=@_;
329
330 #    print "checking path $path\n";
331   if ( !opendir(DH,$path) ) {
332     warn "Cannot open dir $path: $!\n";
333     return;
334   }
335   my @l=grep { $chk->($_) } readdir(DH);
336   #    print @l;
337   close(DH);
338   return map $path, @l;
339 }
340
341
342 sub checkformat {
343   my $frm=shift;
344
345   print "  checkformat($frm)\n" if $VERBOSE;
346   
347   my $probe_array = $formats{$frm}{'code'};
348   if ($probe_array) {
349     print "    Calling probe function\n" if $VERBOSE;
350     if (ref $probe_array ne 'ARRAY') {
351       $probe_array = [ $probe_array ];
352     }
353     for my $func (@$probe_array) {
354       return 1 if $func->($formats{$frm}, $frm);
355     }
356   }
357
358   my $lib_check=$formats{$frm}{'libcheck'};
359   my $inc_check=$formats{$frm}{'inccheck'};
360
361   if ($lib_check) {
362     my @l;
363     for my $lp (@libs) {
364       push(@l, grep_directory($lp,$lib_check));
365     }
366     
367     my @i;
368     for my $ip (@incs) {
369       push(@i, $ip) if $inc_check->($ip,$frm);
370     }
371     
372     printf("%10s: includes %s - libraries %s\n",$frm,(@i?'found':'not found'),(@l?'found':'not found'));
373     $formats{$frm}{incdir} = \@i;
374     $formats{$frm}{libdir} = \@l;
375     return 1 if scalar(@i && @l);
376   }
377   else {
378     printf("%10s: not available\n", $frm);
379   }
380
381   return 0;
382 }
383
384
385 sub pathcheck {
386   if ($VERBOSE) {
387     print "pathcheck\n";
388     print "  Include paths:\n";
389     for (@incs) { print $_,"\n"; }
390   }
391   @incs=grep { -d $_ && -r _ && -x _ or ( print("  $_ doesnt exist or is unaccessible - removed.\n"),0) } @incs;
392
393   if ($VERBOSE) {
394     print "\nLibrary paths:\n";
395     for (@libs) { print $_,"\n"; }
396   }
397   @libs=grep { -d $_ && -r _ && -x _ or ( print("  $_ doesnt exist or is unaccessible - removed.\n"),0) } @libs;
398   print "\ndone.\n";
399 }
400
401
402 # Format data initialization
403
404 # format definition is:
405 # defines needed
406 # default include path
407 # files needed for include (boolean perl code)
408 # default lib path
409 # libs needed
410 # files needed for link (boolean perl code)
411 # object files needed for the format
412
413
414 sub init {
415
416   my @definc = qw(/usr/include);
417   @definc{@definc}=(1) x @definc;
418   @incs=
419     (
420      split(/\Q$Config{path_sep}/, $INCPATH),
421      map _tilde_expand($_), map { split /\Q$Config{path_sep}/ } @incpaths 
422     );
423   if ($Config{locincpth}) {
424     push @incs, grep -d, split ' ', $Config{locincpth};
425   }
426   if ($^O =~ /win32/i && $Config{cc} =~ /\bcl\b/i) {
427     push(@incs, split /;/, $ENV{INCLUDE}) if exists $ENV{INCLUDE};
428   }
429   if ($Config{incpath}) {
430     push @incs, grep -d, split /\Q$Config{path_sep}/, $Config{incpath};
431   }
432   push @incs, grep -d,
433       qw(/sw/include 
434          /usr/include/freetype2
435          /usr/local/include/freetype2
436          /usr/local/include/freetype1/freetype
437          /usr/include /usr/local/include /usr/include/freetype
438          /usr/local/include/freetype);
439   if ($Config{ccflags}) {
440     my @hidden = map { /^-I(.*)$/ ? ($1) : () } split ' ', $Config{ccflags};
441     push @incs, @hidden;
442     @definc{@hidden} = (1) x @hidden;
443   }
444
445   @libs= ( split(/\Q$Config{path_sep}/,$LIBPATH),
446     map _tilde_expand($_), map { split /\Q$Config{path_sep}/} @libpaths );
447   if ($Config{loclibpth}) {
448     push @libs, grep -d, split ' ', $Config{loclibpth};
449   }
450   
451   push @libs, grep -d, qw(/sw/lib),  split(/ /, $Config{'libpth'});
452   push @libs, grep -d, split / /, $Config{libspath} if $Config{libspath};
453   if ($^O =~ /win32/i && $Config{cc} =~ /\bcl\b/i) {
454     push(@libs, split /;/, $ENV{LIB}) if exists $ENV{LIB};
455   }
456   if ($^O eq 'cygwin') {
457     push(@libs, '/usr/lib/w32api') if -d '/usr/lib/w32api';
458     push(@incs, '/usr/include/w32api') if -d '/usr/include/w32api';
459   }
460   if ($Config{ldflags}) {
461     # some builds of perl put -Ldir into ldflags without putting it in
462     # loclibpth, let's extract them
463     my @hidden = grep -d, map { /^-L(.*)$/ ? ($1) : () }
464       split ' ', $Config{ldflags};
465     push @libs, @hidden;
466     # don't mark them as seen - EU::MM will remove any libraries
467     # it can't find and it doesn't look for -L in ldflags
468     #@deflib{@hidden} = @hidden;
469   }
470   push @libs, grep -d, qw(/usr/local/lib);
471
472   $formats{'jpeg'}={
473                     order=>'21',
474                     def=>'HAVE_LIBJPEG',
475                     inccheck=>sub { -e catfile($_[0], 'jpeglib.h') },
476                     libcheck=>sub { $_[0] eq "libjpeg$aext" or $_ eq "libjpeg.$lext" },
477                     libfiles=>'-ljpeg',
478                     objfiles=>'jpeg.o',
479                     docs=>q{
480                             In order to use jpeg with this module you need to have libjpeg
481                             installed on your computer}
482                    };
483
484   $formats{'tiff'}={
485                     order=>'23',
486                     def=>'HAVE_LIBTIFF',
487                     inccheck=>sub { -e catfile($_[0], 'tiffio.h') },
488                     libcheck=>sub { $_[0] eq "libtiff$aext" or $_ eq "libtiff.$lext" },
489                     libfiles=>'-ltiff',
490                     objfiles=>'tiff.o',
491                     docs=>q{
492                             In order to use tiff with this module you need to have libtiff
493                             installed on your computer}
494                    };
495
496   $formats{'png'}={
497                    order=>'22',
498                    def=>'HAVE_LIBPNG',
499                    inccheck=>sub { -e catfile($_[0], 'png.h') },
500                    libcheck=>sub { $_[0] eq "libpng$aext" or $_[0] eq "libpng.$lext" },
501                    libfiles=>$^O eq 'MSWin32' ? '-lpng -lzlib' : '-lpng -lz',
502                    objfiles=>'png.o',
503                    docs=>q{
504                            Png stands for Portable Network Graphics and is intended as
505                            a replacement for gif on the web. It is patent free and
506                            is recommended by the w3c, you need libpng to use these formats},
507                    code => \&png_probe,
508                   };
509
510   $formats{'gif'}={
511                    order=>'20',
512                    def=>'HAVE_LIBGIF',
513                    inccheck=>sub { -e catfile($_[0], 'gif_lib.h') },
514                    libcheck=>sub { $_[0] eq "libgif$aext" or $_[0] eq "libgif.$lext" },
515                    libfiles=>'-lgif',
516                    objfiles=>'gif.o',
517                    docs=>q{
518                            gif is the de facto standard for webgraphics at the moment,
519                            it does have some patent problems. If you have giflib and
520                            are not in violation with the unisys patent you should use
521                            this instead of the 'ungif' option.  Note that they cannot
522                            be in use at the same time}
523                   };
524
525   $formats{'ungif'}={
526                      order=>'21',
527                      def=>'HAVE_LIBGIF',
528                      inccheck=>sub { -e catfile($_[0], 'gif_lib.h') },
529                      libcheck=>sub { $_[0] eq "libungif$aext" or $_[0] eq "libungif.$lext" },
530                      libfiles=>'-lungif',
531                      objfiles=>'gif.o',
532                      docs=>q{
533                              gif is the de facto standard for webgraphics at the moment,
534                              it does have some patent problems. If you have libungif and
535                              want to create images free from LZW patented compression you
536                              should use this option instead of the 'gif' option}
537                     };
538
539   $formats{'T1-fonts'}={
540                         order=>'30',
541                         def=>'HAVE_LIBT1',
542                         inccheck=>sub { -e catfile($_[0], 't1lib.h') },
543                         libcheck=>sub { $_[0] eq "libt1$aext" or $_[0] eq "libt1.$lext" },
544                         libfiles=>'-lt1',
545                         objfiles=>'',
546                         docs=>q{
547                                 postscript t1 fonts are scalable fonts. They can include 
548                                 ligatures and kerning information and generally yield good
549                                 visual quality. We depend on libt1 to rasterize the fonts
550                                 for use in images.}
551                        };
552
553   $formats{'TT-fonts'}=
554     {
555      order=>'31',
556      def=>'HAVE_LIBTT',
557      inccheck=>sub { -e catfile($_[0], 'freetype.h')
558                        && !-e catfile($_[0], 'fterrors.h') },
559      libcheck=>sub { $_[0] eq "libttf$aext" or $_[0] eq "libttf.$lext" },
560      libfiles=>'-lttf',
561      objfiles=>'',
562      code => \&freetype1_probe,
563      docs=>q{
564 Truetype fonts are scalable fonts. They can include 
565 kerning and hinting information and generally yield good
566 visual quality esp on low resultions. The freetype library is
567 used to rasterize for us. The only drawback is that there
568 are alot of badly designed fonts out there.}
569                        };
570   $formats{'w32'} = {
571                      order=>40,
572                      def=>'HAVE_WIN32',
573                      inccheck=>sub { -e catfile($_[0], 'windows.h') },
574                      libcheck=>sub { lc $_[0] eq 'gdi32.lib' 
575                                        || lc $_[0] eq 'libgdi32.a' },
576                      libfiles=>$^O eq 'cygwin' ? '-lgdi32' : '',
577                      objfiles=>'win32.o',
578                      docs => <<DOCS
579 Uses the Win32 GDI for rendering text.
580
581 This currently only works on under normal Win32 and cygwin.
582 DOCS
583                     };
584   $formats{'freetype2'} = 
585   {
586    order=>'29',
587    def=>'HAVE_FT2',
588    # we always use a probe function
589    #inccheck=>sub { -e catfile($_[0], 'ft2build.h') },
590    #libcheck=>sub { $_[0] eq "libfreetype$aext" or $_[0] eq "libfreetype.$lext" },
591    libfiles=>'-lfreetype',
592    objfiles=>'freetyp2.o',
593    docs=><<DOCS,
594 Freetype 2 supports both Truetype and Type 1 fonts, both of which are
595 scalable.  It also supports a variety of other fonts.
596 DOCS
597    code =>
598    [ 
599     \&freetype2_probe_ftconfig,
600     \&freetype2_probe_scan
601    ],
602   };
603
604   # Make fix indent
605   for (keys %formats) { $formats{$_}->{docs} =~ s/^\s+/  /mg; }
606 }
607
608
609
610 sub gen {
611   my $V = $ENV{$_[0]};
612   defined($V) ? $V : "";
613 }
614
615
616 # Get information from environment variables
617
618 sub getenv {
619
620   ($VERBOSE,
621    $INCPATH,
622    $LIBPATH,
623    $NOLOG,
624    $DEBUG_MALLOC,
625    $MANUAL,
626    $CFLAGS,
627    $LFLAGS,
628    $DFLAGS) = map { gen $_ } qw(IM_VERBOSE
629                                 IM_INCPATH
630                                 IM_LIBPATH
631                                 IM_NOLOG
632                                 IM_DEBUG_MALLOC
633                                 IM_MANUAL
634                                 IM_CFLAGS
635                                 IM_LFLAGS
636                                 IM_DFLAGS);
637
638 }
639
640 sub make_imconfig {
641   my ($defines) = @_;
642
643   open CONFIG, "> imconfig.h"
644     or die "Cannot create imconfig.h: $!\n";
645   print CONFIG <<EOS;
646 /* This file is automatically generated by Makefile.PL.
647    Don't edit this file, since any changes will be lost */
648
649 #ifndef IMAGER_IMCONFIG_H
650 #define IMAGER_IMCONFIG_H
651 EOS
652   for my $define (@$defines) {
653     if ($define->[2]) {
654       print CONFIG "\n/*\n  $define->[2]\n*/\n\n";
655     }
656     print CONFIG "#define $define->[0] $define->[1]\n";
657   }
658   print CONFIG "\n#endif\n";
659   close CONFIG;
660 }
661
662 # use pkg-config to probe for libraries
663 # works around the junk that pkg-config dumps on FreeBSD
664 sub _pkg_probe {
665   my ($pkg) = @_;
666
667   is_exe('pkg-config') or return;
668
669   my $redir = $^O eq 'MSWin32' ? '' : '2>/dev/null';
670
671   !system("pkg-config $pkg --exists $redir");
672 }
673
674 # probes for freetype1 by scanning @incs for the includes and 
675 # @libs for the libs.  This is done separately because freetype's headers
676 # are stored in a freetype or freetype1 directory under PREFIX/include.
677 #
678 # we could find the files with the existing mechanism, but it won't set
679 # -I flags correctly.
680 #
681 # This could be extended to freetype2 too, but freetype-config catches
682 # that
683 sub freetype1_probe {
684   my ($frm, $frmkey) = @_;
685
686   my $found_inc;
687  INCS:
688   for my $inc (@incs) {
689     for my $subdir (qw/freetype freetype1/) {
690       my $path = File::Spec->catfile($inc, $subdir, 'freetype.h');
691       -e $path or next;
692       $path = File::Spec->catfile($inc, $subdir, 'fterrors.h');
693       -e $path and next;
694
695       $found_inc = File::Spec->catdir($inc, $subdir);
696       last INCS;
697     }
698   }
699
700   my $found_lib;
701  LIBS:
702   for my $lib (@libs) {
703     my $a_path = File::Spec->catfile($lib, "libttf$aext");
704     my $l_path = File::Spec->catfile($lib, "libttf.$lext");
705     if (-e $a_path || -e $l_path) {
706       $found_lib = $lib;
707       last LIBS;
708     }
709   }
710
711   return unless $found_inc && $found_lib;
712   printf("%10s: includes %s - libraries %s\n", $frmkey,
713          ($found_inc ? 'found' : 'not found'), 
714          ($found_lib ? 'found' : 'not found'));
715
716   $frm->{cflags} = "-I$found_inc";
717   $frm->{libfiles} = "-lttf";
718
719   return 1;
720 }
721
722 # probes for freetype2 by trying to run freetype-config
723 sub freetype2_probe_ftconfig {
724   my ($frm, $frmkey) = @_;
725
726   is_exe('freetype-config') or return;
727
728   my $cflags = `freetype-config --cflags`
729     and !$? or return;
730   chomp $cflags;
731
732   my $lflags = `freetype-config --libs`
733     and !$? or return;
734   chomp $lflags;
735
736   # before 2.1.5 freetype-config --cflags could output
737   # the -I options in the wrong order, causing a conflict with
738   # freetype1.x installed with the same --prefix
739   #
740   # can happen iff:
741   #  - both -Iprefix/include and -Iprefix/include/freetype2 are in cflags
742   #    in that order
743   #  - freetype 1.x headers are in prefix/include/freetype
744   my @incdirs = map substr($_, 2), grep /^-I/, split ' ', $cflags;
745   if (@incdirs == 2 
746       && $incdirs[1] eq "$incdirs[0]/freetype2"
747       && -e "$incdirs[0]/freetype/freetype.h"
748       && -e "$incdirs[0]/freetype/fterrid.h") {
749     print "** freetype-config provided -I options out of order, correcting\n"
750       if $VERBOSE;
751     $cflags = join(' ', grep(!/-I/, split ' ', $cflags),
752                    map "-I$_", reverse @incdirs);
753   }
754   $frm->{cflags} = $cflags;
755   $frm->{lflags} = $lflags;
756
757   printf "%10s: configured via freetype-config\n", $frmkey;
758
759   return 1;
760 }
761
762 # attempt to probe for freetype2 by scanning directories
763 # we can't use the normal scan since we need to find the directory
764 # containing most of the includes
765 sub freetype2_probe_scan {
766   my ($frm, $frmkey) = @_;
767
768   my $found_inc;
769   my $found_inc2;
770  INCS:
771   for my $inc (@incs) {
772     my $path = File::Spec->catfile($inc, 'ft2build.h');
773     -e $path or next;
774
775     # try to find what it's including
776     my $ftheader;
777     open FT2BUILD, "< $path"
778       or next;
779     while (<FT2BUILD>) {
780       if (m!^\s*\#\s*include\s+<([\w/.]+)>!
781           || m!^\s*\#\s*include\s+"([\w/.]+)"!) {
782         $ftheader = $1;
783         last;
784       }
785     }
786     close FT2BUILD;
787     $ftheader
788       or next;
789     # non-Unix installs put this directly under the same directory in
790     # theory
791     if (-e File::Spec->catfile($inc, $ftheader)) {
792       $found_inc = $inc;
793       last INCS;
794     }
795     for my $subdir (qw/freetype2 freetype/) {
796       $path = File::Spec->catfile($inc, $subdir, 'fterrors.h');
797       -e $path and next;
798
799       $found_inc = $inc;
800       $found_inc2 = File::Spec->catdir($inc, $subdir);
801       last INCS;
802     }
803   }
804
805   my $found_lib;
806  LIBS:
807   for my $lib (@libs) {
808     my $a_path = File::Spec->catfile($lib, "libfreetype$aext");
809     my $l_path = File::Spec->catfile($lib, "libfreetype.$lext");
810     if (-e $a_path || -e $l_path) {
811       $found_lib = $lib;
812       last LIBS;
813     }
814   }
815
816   printf("%10s: includes %s - libraries %s\n", $frmkey,
817          ($found_inc ? 'found' : 'not found'), 
818          ($found_lib ? 'found' : 'not found'));
819
820   return unless $found_inc && $found_lib;
821
822   $frm->{cflags} = _make_I($found_inc);
823   $frm->{cflags} .= " " . _make_I($found_inc2) if $found_inc2;
824   $frm->{libfiles} = "-lfreetype";
825
826   return 1;
827 }
828
829 sub _make_I {
830   my ($inc_dir) = @_;
831
832   $definc{$inc_dir}
833     and return '';
834
835   $inc_dir =~ / / ? qq!-I"$inc_dir"! : "-I$inc_dir";
836 }
837
838 # probes for libpng via pkg-config
839 sub png_probe {
840   my ($frm, $frmkey) = @_;
841
842   is_exe('pkg-config') or return;
843
844   my $config;
845   for my $check_conf (qw(libpng libpng12 libpng10)) {
846     if (_pkg_probe($check_conf)) {
847       $config = $check_conf;
848       last;
849     }
850   }
851   $config or return;
852
853   my $cflags = `pkg-config $config --cflags`
854     and !$? or return;
855
856   my $lflags = `pkg-config $config --libs`
857     and !$? or return;
858
859   chomp $cflags;
860   chomp $lflags;
861   $frm->{cflags} = $cflags;
862   $frm->{lflags} = $lflags;
863
864   printf "%10s: configured via `pkg-config $config ...`\n", $frmkey;
865
866   return 1;
867 }
868
869 sub catfile {
870   return File::Spec->catfile(@_);
871 }
872
873 sub is_exe {
874   my ($name) = @_;
875
876   my @exe_suffix = $Config{_exe};
877   if ($^O eq 'MSWin32') {
878     push @exe_suffix, qw/.bat .cmd/;
879   }
880
881   for my $dir (File::Spec->path) {
882     for my $suffix (@exe_suffix) {
883       -x catfile($dir, "$name$suffix")
884         and return 1;
885     }
886   }
887
888   return;
889 }
890
891 sub usage {
892   print STDERR <<EOS;
893 Usage: $0 [--enable feature1,feature2,...] [other options]
894        $0 [--disable feature1,feature2,...]  [other options]
895        $0 --help
896 Possible feature names are:
897   png gif ungif jpeg tiff T1-fonts TT-fonts freetype2
898 Other options:
899   --verbose | -v
900     Verbose library probing (or set IM_VERBOSE in the environment)
901   --nolog
902     Disable logging (or set IM_NOLOG in the environment)
903   --incpath dir
904     Add to the include search path
905   --libpath dir
906     Add to the library search path
907 EOS
908   exit 1;
909
910 }
911
912 # generate the PM MM argument
913 # I'd prefer to modify the public version, but there doesn't seem to be 
914 # a public API to do that
915 sub gen_PM {
916   my %pm;
917   my $instbase = '$(INST_LIBDIR)';
918
919   # first the basics, .pm and .pod files
920   $pm{"Imager.pm"} = "$instbase/Imager.pm";
921
922   my $mani = maniread();
923
924   for my $filename (keys %$mani) {
925     if ($filename =~ m!^lib/! && $filename =~ /\.(pm|pod)$/) {
926       (my $work = $filename) =~ s/^lib//;
927       $pm{$filename} = $instbase . $work;
928     }
929   }
930
931   # need the typemap
932   $pm{typemap} = $instbase . '/Imager/typemap';
933
934   # and the core headers
935   for my $filename (keys %$mani) {
936     if ($filename =~ /^\w+\.h$/) {
937       $pm{$filename} = $instbase . '/Imager/include/' . $filename;
938     }
939   }
940
941   # and the generated header
942   $pm{"imconfig.h"} = $instbase . '/Imager/include/imconfig.h';
943
944   \%pm;
945 }
946
947 my $home;
948 sub _tilde_expand {
949   my ($path) = @_;
950
951   if ($path =~ m!^~[/\\]!) {
952     defined $home or $home = $ENV{HOME};
953     if (!defined $home && $^O eq 'MSWin32'
954        && defined $ENV{HOMEDRIVE} && defined $ENV{HOMEPATH}) {
955       $home = $ENV{HOMEDRIVE} . $ENV{HOMEPATH};
956     }
957     unless (defined $home) {
958       $home = eval { (getpwuid($<))[7] };
959     }
960     defined $home or die "You supplied $path, but I can't find your home directory\n";
961     $path =~ s/^~//;
962     $path = File::Spec->catdir($home, $path);
963   }
964
965   $path;
966 }
967
968 # This isn't a module, but some broken tools, like
969 # Module::Depends::Instrusive insist on treating it like one.
970 #
971 # http://rt.cpan.org/Public/Bug/Display.html?id=21229
972
973 1;