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