simpler creation of coverage reports
[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 vars qw(%Recommends);
9 use ExtUtils::Manifest qw(maniread);
10 use vars qw(%formats $VERBOSE $INCPATH $LIBPATH $NOLOG $DEBUG_MALLOC $MANUAL $CFLAGS $LFLAGS $DFLAGS);
11
12 #
13 # IM_INCPATH      colon seperated list of paths to extra include paths
14 # IM_LIBPATH      colon seperated list of paths to extra library paths
15 #
16 # IM_VERBOSE      turns on verbose mode for the library finding and such
17 # IM_MANUAL       to manually select which libraries are used and which not
18 # IM_ENABLE       to programmatically select which libraries are used
19 #                 and which are not
20 # IM_NOLOG        if true logging will not be compiled into the module
21 # IM_DEBUG_MALLOC if true malloc debbuging will be compiled into the module
22 #                 do not use IM_DEBUG_MALLOC in production - this slows
23 #                 everything down by alot
24 # IM_CFLAGS       Extra flags to pass to the compiler
25 # IM_LFLAGS       Extra flags to pass to the linker
26 # IM_DFLAGS       Extra flags to pass to the preprocessor
27 # IM_SUPPRESS_PROMPT  Suppress the prompt asking about gif support
28
29 getenv();     # get environment variables
30
31 my $lext=$Config{'so'};   # Get extensions of libraries
32 my $aext=$Config{'_a'};
33
34 my $help; # display help if set
35 my @enable; # list of drivers to enable
36 my @disable; # or list of drivers to disable
37 my @incpaths; # places to look for headers
38 my @libpaths; # places to look for libraries
39 my $noprobe; # non-zero to disable newer probes
40 my $noexif; # non-zero to disable EXIF parsing of JPEGs
41 my $no_gif_set_version; # disable calling EGifSetGifVersion
42 my $coverage; # build for coverage testing
43 GetOptions("help" => \$help,
44            "enable=s" => \@enable,
45            "disable=s" => \@disable,
46            "incpath=s", \@incpaths,
47            "libpath=s" => \@libpaths,
48            "noprobe" => \$noprobe,
49            "verbose|v" => \$VERBOSE,
50            "nolog" => \$NOLOG,
51            "noexif" => \$noexif,
52            "nogifsetversion" => \$no_gif_set_version,
53            'coverage' => \$coverage);
54
55 if ($VERBOSE) { 
56   print "Verbose mode\n"; 
57   require Data::Dumper; 
58   import Data::Dumper qw(Dumper);
59 }
60
61 if ($help) {
62   usage();
63 }
64
65 my @defines;
66
67 if ($NOLOG)   { print "Logging not compiled into module\n"; }
68 else { 
69   push @defines, [ IMAGER_LOG => 1, "Logging system" ];
70 }
71
72 if ($DEBUG_MALLOC) {
73   push @defines, [ IMAGER_DEBUG_MALLOC => 1, "Use Imager's DEBUG malloc()" ];
74   print "Malloc debugging enabled\n";
75 }
76
77 if (@enable && @disable) {
78   print STDERR "Only --enable or --disable can be used, not both, try --help\n";
79   exit 1;
80 }
81
82 my %definc;
83 my %deflib;
84 my @incs; # all the places to look for headers
85 my @libs; # all the places to look for libraries
86
87 init();       # initialize global data
88 pathcheck();  # Check if directories exist
89 distcheck();  # for building dists
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 rgb.o color.o fills.o imgdouble.o limits.o hlines.o
162               imext.o scale.o rubthru.o render.o);
163
164 $Recommends{Imager} =
165   { 'Parse::RecDescent' => 0 };
166
167 my %opts=(
168           'NAME'         => 'Imager',
169           'VERSION_FROM' => 'Imager.pm',
170           'LIBS'         => "$LFLAGS -lm $lib_lflags $OSLIBS $F_LIBS",
171           'DEFINE'       => "$OSDEF $CFLAGS",
172           'INC'          => "$lib_cflags $DFLAGS $F_INC",
173           'OBJECT'       => join(' ', @objs, $F_OBJECT),
174           clean          => { FILES=>'testout meta.tmp rubthru.c scale.c' },
175           PM             => gen_PM(),
176           PREREQ_PM      => { 'Test::More' => 0.47 },
177          );
178
179 if ($coverage) {
180     if ($Config{gccversion}) {
181         push @ARGV, 'OPTIMIZE=-ftest-coverage -fprofile-arcs';
182         #$opts{dynamic_lib} = { OTHERLDFLAGS => '-ftest-coverage -fprofile-arcs' };
183     }
184     else {
185         die "Don't know the coverage C flags for your compiler\n";
186     }
187 }
188
189 # eval to prevent warnings about versions with _ in them
190 my $MM_ver = eval $ExtUtils::MakeMaker::VERSION;
191 if ($MM_ver > 6.06) {
192   $opts{AUTHOR} = 'Tony Cook <tony@imager.perl.org>, Arnar M. Hrafnkelsson';
193   $opts{ABSTRACT} = 'Perl extension for Generating 24 bit Images';
194 }
195 if ($MM_ver > 6.10) {
196   $opts{NO_META} = 1;
197 }
198
199 make_imconfig(\@defines);
200
201 if ($VERBOSE) { print Dumper(\%opts); }
202 mkdir('testout',0777); # since we cannot include it in the archive.
203
204 make_metafile(\%opts);
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 imtoc.perl
243         $perl imtoc.perl $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 gd {
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 $code = $formats{$frm}{'code'};
348   if ($code && !$noprobe) {
349     print "    Calling probe function\n" if $VERBOSE;
350     return 1 if $code->($formats{$frm}, $frm);
351   }
352
353   my $libchk=$formats{$frm}{'libcheck'};
354   my $incchk=$formats{$frm}{'inccheck'};
355
356   my @l;
357   for my $lp (@libs) {
358     push(@l, gd($lp,$libchk));
359   }
360
361   my @i;
362   for my $ip (@incs) {
363     push(@i, $ip) if $incchk->($ip,$frm);
364   }
365
366   printf("%10s: includes %s - libraries %s\n",$frm,(@i?'found':'not found'),(@l?'found':'not found'));
367   $formats{$frm}{incdir} = \@i;
368   $formats{$frm}{libdir} = \@l;
369   return scalar(@i && @l);
370 }
371
372
373 sub pathcheck {
374   if ($VERBOSE) {
375     print "pathcheck\n";
376     print "  Include paths:\n";
377     for (@incs) { print $_,"\n"; }
378   }
379   @incs=grep { -d $_ && -r _ && -x _ or ( print("  $_ doesnt exist or is unaccessible - removed.\n"),0) } @incs;
380
381   if ($VERBOSE) {
382     print "\nLibrary paths:\n";
383     for (@libs) { print $_,"\n"; }
384   }
385   @libs=grep { -d $_ && -r _ && -x _ or ( print("  $_ doesnt exist or is unaccessible - removed.\n"),0) } @libs;
386   print "\ndone.\n";
387 }
388
389
390 # Format data initialization
391
392 # format definition is:
393 # defines needed
394 # default include path
395 # files needed for include (boolean perl code)
396 # default lib path
397 # libs needed
398 # files needed for link (boolean perl code)
399 # object files needed for the format
400
401
402 sub init {
403
404   my @definc = qw(/usr/include);
405   @definc{@definc}=(1) x @definc;
406   @incs=(split(/\Q$Config{path_sep}/, $INCPATH),
407         map { split /\Q$Config{path_sep}/} @incpaths );
408   if ($Config{locincpth}) {
409     push @incs, grep -d, split ' ', $Config{locincpth};
410   }
411   if ($^O =~ /win32/i && $Config{cc} =~ /\bcl\b/i) {
412     push(@incs, split /;/, $ENV{INCLUDE}) if exists $ENV{INCLUDE};
413   }
414   if ($Config{incpath}) {
415     push @incs, grep -d, split /\Q$Config{path_sep}/, $Config{incpath};
416   }
417   push @incs, grep -d,
418       qw(/sw/include 
419          /usr/include/freetype2
420          /usr/local/include/freetype2
421          /usr/local/include/freetype1/freetype
422          /usr/include /usr/local/include /usr/include/freetype
423          /usr/local/include/freetype);
424   if ($Config{ccflags}) {
425     my @hidden = map { /^-I(.*)$/ ? ($1) : () } split ' ', $Config{ccflags};
426     push @incs, @hidden;
427     @definc{@hidden} = (1) x @hidden;
428   }
429
430   @libs= ( split(/\Q$Config{path_sep}/,$LIBPATH),
431     map { split /\Q$Config{path_sep}/} @libpaths );
432   if ($Config{loclibpth}) {
433     push @libs, grep -d, split ' ', $Config{loclibpth};
434   }
435   
436   push @libs, grep -d, qw(/sw/lib),  split(/ /, $Config{'libpth'});
437   push @libs, grep -d, split / /, $Config{libspath} if $Config{libspath};
438   if ($^O =~ /win32/i && $Config{cc} =~ /\bcl\b/i) {
439     push(@libs, split /;/, $ENV{LIB}) if exists $ENV{LIB};
440   }
441   if ($^O eq 'cygwin') {
442     push(@libs, '/usr/lib/w32api') if -d '/usr/lib/w32api';
443     push(@incs, '/usr/include/w32api') if -d '/usr/include/w32api';
444   }
445   if ($Config{ldflags}) {
446     # some builds of perl put -Ldir into ldflags without putting it in
447     # loclibpth, let's extract them
448     my @hidden = grep -d, map { /^-L(.*)$/ ? ($1) : () }
449       split ' ', $Config{ldflags};
450     push @libs, @hidden;
451     # don't mark them as seen - EU::MM will remove any libraries
452     # it can't find and it doesn't look for -L in ldflags
453     #@deflib{@hidden} = @hidden;
454   }
455   push @libs, grep -d, qw(/usr/local/lib);
456
457   $formats{'jpeg'}={
458                     order=>'21',
459                     def=>'HAVE_LIBJPEG',
460                     inccheck=>sub { -e catfile($_[0], 'jpeglib.h') },
461                     libcheck=>sub { $_[0] eq "libjpeg$aext" or $_ eq "libjpeg.$lext" },
462                     libfiles=>'-ljpeg',
463                     objfiles=>'jpeg.o',
464                     docs=>q{
465                             In order to use jpeg with this module you need to have libjpeg
466                             installed on your computer}
467                    };
468
469   $formats{'tiff'}={
470                     order=>'23',
471                     def=>'HAVE_LIBTIFF',
472                     inccheck=>sub { -e catfile($_[0], 'tiffio.h') },
473                     libcheck=>sub { $_[0] eq "libtiff$aext" or $_ eq "libtiff.$lext" },
474                     libfiles=>'-ltiff',
475                     objfiles=>'tiff.o',
476                     docs=>q{
477                             In order to use tiff with this module you need to have libtiff
478                             installed on your computer}
479                    };
480
481   $formats{'png'}={
482                    order=>'22',
483                    def=>'HAVE_LIBPNG',
484                    inccheck=>sub { -e catfile($_[0], 'png.h') },
485                    libcheck=>sub { $_[0] eq "libpng$aext" or $_[0] eq "libpng.$lext" },
486                    libfiles=>$^O eq 'MSWin32' ? '-lpng -lzlib' : '-lpng -lz',
487                    objfiles=>'png.o',
488                    docs=>q{
489                            Png stands for Portable Network Graphics and is intended as
490                            a replacement for gif on the web. It is patent free and
491                            is recommended by the w3c, you need libpng to use these formats},
492                    code => \&png_probe,
493                   };
494
495   $formats{'gif'}={
496                    order=>'20',
497                    def=>'HAVE_LIBGIF',
498                    inccheck=>sub { -e catfile($_[0], 'gif_lib.h') },
499                    libcheck=>sub { $_[0] eq "libgif$aext" or $_[0] eq "libgif.$lext" },
500                    libfiles=>'-lgif',
501                    objfiles=>'gif.o',
502                    docs=>q{
503                            gif is the de facto standard for webgraphics at the moment,
504                            it does have some patent problems. If you have giflib and
505                            are not in violation with the unisys patent you should use
506                            this instead of the 'ungif' option.  Note that they cannot
507                            be in use at the same time}
508                   };
509
510   $formats{'ungif'}={
511                      order=>'21',
512                      def=>'HAVE_LIBGIF',
513                      inccheck=>sub { -e catfile($_[0], 'gif_lib.h') },
514                      libcheck=>sub { $_[0] eq "libungif$aext" or $_[0] eq "libungif.$lext" },
515                      libfiles=>'-lungif',
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 libungif and
520                              want to create images free from LZW patented compression you
521                              should use this option instead of the 'gif' option}
522                     };
523
524   $formats{'T1-fonts'}={
525                         order=>'30',
526                         def=>'HAVE_LIBT1',
527                         inccheck=>sub { -e catfile($_[0], 't1lib.h') },
528                         libcheck=>sub { $_[0] eq "libt1$aext" or $_[0] eq "libt1.$lext" },
529                         libfiles=>'-lt1',
530                         objfiles=>'',
531                         docs=>q{
532                                 postscript t1 fonts are scalable fonts. They can include 
533                                 ligatures and kerning information and generally yield good
534                                 visual quality. We depend on libt1 to rasterize the fonts
535                                 for use in images.}
536                        };
537
538   $formats{'TT-fonts'}=
539     {
540      order=>'31',
541      def=>'HAVE_LIBTT',
542      inccheck=>sub { -e catfile($_[0], 'freetype.h')
543                        && !-e catfile($_[0], 'fterrors.h') },
544      libcheck=>sub { $_[0] eq "libttf$aext" or $_[0] eq "libttf.$lext" },
545      libfiles=>'-lttf',
546      objfiles=>'',
547      code => \&freetype1_probe,
548      docs=>q{
549 Truetype fonts are scalable fonts. They can include 
550 kerning and hinting information and generally yield good
551 visual quality esp on low resultions. The freetype library is
552 used to rasterize for us. The only drawback is that there
553 are alot of badly designed fonts out there.}
554                        };
555   $formats{'w32'} = {
556                      order=>40,
557                      def=>'HAVE_WIN32',
558                      inccheck=>sub { -e catfile($_[0], 'windows.h') },
559                      libcheck=>sub { lc $_[0] eq 'gdi32.lib' 
560                                        || lc $_[0] eq 'libgdi32.a' },
561                      libfiles=>$^O eq 'cygwin' ? '-lgdi32' : '',
562                      objfiles=>'win32.o',
563                      docs => <<DOCS
564 Uses the Win32 GDI for rendering text.
565
566 This currently only works on under normal Win32 and cygwin.
567 DOCS
568                     };
569   $formats{'freetype2'} = {
570                            order=>'29',
571                            def=>'HAVE_FT2',
572                            inccheck=>sub { -e catfile($_[0], 'ft2build.h') },
573                            libcheck=>sub { $_[0] eq "libfreetype$aext" or $_[0] eq "libfreetype.$lext" },
574                            libfiles=>'-lfreetype',
575                            objfiles=>'freetyp2.o',
576                            docs=><<DOCS,
577 Freetype 2 supports both Truetype and Type 1 fonts, both of which are
578 scalable.  It also supports a variety of other fonts.
579 DOCS
580                            code => \&freetype2_probe,
581                           };
582
583   # Make fix indent
584   for (keys %formats) { $formats{$_}->{docs} =~ s/^\s+/  /mg; }
585 }
586
587
588
589 sub gen {
590   my $V = $ENV{$_[0]};
591   defined($V) ? $V : "";
592 }
593
594
595 # Get information from environment variables
596
597 sub getenv {
598
599   ($VERBOSE,
600    $INCPATH,
601    $LIBPATH,
602    $NOLOG,
603    $DEBUG_MALLOC,
604    $MANUAL,
605    $CFLAGS,
606    $LFLAGS,
607    $DFLAGS) = map { gen $_ } qw(IM_VERBOSE
608                                 IM_INCPATH
609                                 IM_LIBPATH
610                                 IM_NOLOG
611                                 IM_DEBUG_MALLOC
612                                 IM_MANUAL
613                                 IM_CFLAGS
614                                 IM_LFLAGS
615                                 IM_DFLAGS);
616
617 }
618
619 sub make_imconfig {
620   my ($defines) = @_;
621
622   open CONFIG, "> imconfig.h"
623     or die "Cannot create imconfig.h: $!\n";
624   print CONFIG <<EOS;
625 /* This file is automatically generated by Makefile.PL.
626    Don't edit this file, since any changes will be lost */
627
628 #ifndef IMAGER_IMCONFIG_H
629 #define IMAGER_IMCONFIG_H
630 EOS
631   for my $define (@$defines) {
632     if ($define->[2]) {
633       print CONFIG "\n/*\n  $define->[2]\n*/\n\n";
634     }
635     print CONFIG "#define $define->[0] $define->[1]\n";
636   }
637   print CONFIG "\n#endif\n";
638   close CONFIG;
639 }
640
641 # use pkg-config to probe for libraries
642 # works around the junk that pkg-config dumps on FreeBSD
643 sub _pkg_probe {
644   my ($pkg) = @_;
645
646   is_exe('pkg-config') or return;
647
648   my $redir = $^O eq 'MSWin32' ? '' : '2>/dev/null';
649
650   !system("pkg-config $pkg --exists $redir");
651 }
652
653 # probes for freetype1 by scanning @incs for the includes and 
654 # @libs for the libs.  This is done separately because freetype's headers
655 # are stored in a freetype or freetype1 directory under PREFIX/include.
656 #
657 # we could find the files with the existing mechanism, but it won't set
658 # -I flags correctly.
659 #
660 # This could be extended to freetype2 too, but freetype-config catches
661 # that
662 sub freetype1_probe {
663   my ($frm, $frmkey) = @_;
664
665   my $found_inc;
666  INCS:
667   for my $inc (@incs) {
668     for my $subdir (qw/freetype freetype1/) {
669       my $path = File::Spec->catfile($inc, $subdir, 'freetype.h');
670       -e $path or next;
671       $path = File::Spec->catfile($inc, $subdir, 'fterrors.h');
672       -e $path and next;
673
674       $found_inc = File::Spec->catdir($inc, $subdir);
675       last INCS;
676     }
677   }
678
679   my $found_lib;
680  LIBS:
681   for my $lib (@libs) {
682     my $a_path = File::Spec->catfile($lib, "libttf$aext");
683     my $l_path = File::Spec->catfile($lib, "libttf.$lext");
684     if (-e $a_path || -e $l_path) {
685       $found_lib = $lib;
686       last LIBS;
687     }
688   }
689
690   return unless $found_inc && $found_lib;
691   printf("%10s: includes %s - libraries %s\n", $frmkey,
692          ($found_inc ? 'found' : 'not found'), 
693          ($found_lib ? 'found' : 'not found'));
694
695   $frm->{cflags} = "-I$found_inc";
696   $frm->{libfiles} = "-lttf";
697
698   return 1;
699 }
700
701 # probes for freetype2 by trying to run freetype-config
702 sub freetype2_probe {
703   my ($frm, $frmkey) = @_;
704
705   is_exe('freetype-config') or return;
706
707   my $cflags = `freetype-config --cflags`
708     and !$? or return;
709   chomp $cflags;
710
711   my $lflags = `freetype-config --libs`
712     and !$? or return;
713   chomp $lflags;
714
715   # before 2.1.5 freetype-config --cflags could output
716   # the -I options in the wrong order, causing a conflict with
717   # freetype1.x installed with the same --prefix
718   #
719   # can happen iff:
720   #  - both -Iprefix/include and -Iprefix/include/freetype2 are in cflags
721   #    in that order
722   #  - freetype 1.x headers are in prefix/include/freetype
723   my @incdirs = map substr($_, 2), grep /^-I/, split ' ', $cflags;
724   if (@incdirs == 2 
725       && $incdirs[1] eq "$incdirs[0]/freetype2"
726       && -e "$incdirs[0]/freetype/freetype.h"
727       && -e "$incdirs[0]/freetype/fterrid.h") {
728     print "** freetype-config provided -I options out of order, correcting\n"
729       if $VERBOSE;
730     $cflags = join(' ', grep(!/-I/, split ' ', $cflags),
731                    map "-I$_", reverse @incdirs);
732   }
733   $frm->{cflags} = $cflags;
734   $frm->{lflags} = $lflags;
735
736   printf "%10s: configured via freetype-config\n", $frmkey;
737
738   return 1;
739 }
740
741 # probes for libpng via pkg-config
742 sub png_probe {
743   my ($frm, $frmkey) = @_;
744
745   is_exe('pkg-config') or return;
746
747   my $config;
748   for my $check_conf (qw(libpng libpng12 libpng10)) {
749     if (_pkg_probe($check_conf)) {
750       $config = $check_conf;
751       last;
752     }
753   }
754   $config or return;
755
756   my $cflags = `pkg-config $config --cflags`
757     and !$? or return;
758
759   my $lflags = `pkg-config $config --libs`
760     and !$? or return;
761
762   chomp $cflags;
763   chomp $lflags;
764   $frm->{cflags} = $cflags;
765   $frm->{lflags} = $lflags;
766
767   printf "%10s: configured via `pkg-config $config ...`\n", $frmkey;
768
769   return 1;
770 }
771
772 sub catfile {
773   return File::Spec->catfile(@_);
774 }
775
776 sub is_exe {
777   my ($name) = @_;
778
779   for my $dir (File::Spec->path) {
780     -x catfile($dir, "$name$Config{_exe}")
781       and return 1;
782   }
783
784   return;
785 }
786
787 sub usage {
788   print STDERR <<EOS;
789 Usage: $0 [--enable feature1,feature2,...] [other options]
790        $0 [--disable feature1,feature2,...]  [other options]
791        $0 --help
792 Possible feature names are:
793   png gif ungif jpeg tiff T1-fonts TT-fonts freetype2
794 Other options:
795   --verbose | -v
796     Verbose library probing (or set IM_VERBOSE in the environment)
797   --nolog
798     Disable logging (or set IM_NOLOG in the environment)
799   --incpath dir
800     Add to the include search path
801   --libpath dir
802     Add to the library search path
803   --noprobe
804     Don't use pkg-config or freetype2-config to probe for freetype2 and libpng
805 EOS
806   exit 1;
807
808 }
809
810 # generate the PM MM argument
811 # I'd prefer to modify the public version, but there doesn't seem to be 
812 # a public API to do that
813 sub gen_PM {
814   my %pm;
815   my $instbase = '$(INST_LIBDIR)';
816
817   # first the basics, .pm and .pod files
818   $pm{"Imager.pm"} = "$instbase/Imager.pm";
819
820   my $mani = maniread();
821
822   for my $filename (keys %$mani) {
823     if ($filename =~ m!^lib/! && $filename =~ /\.(pm|pod)$/) {
824       (my $work = $filename) =~ s/^lib//;
825       $pm{$filename} = $instbase . $work;
826     }
827   }
828
829   # need the typemap
830   $pm{typemap} = $instbase . '/Imager/typemap';
831
832   # and the core headers
833   for my $filename (keys %$mani) {
834     if ($filename =~ /^\w+\.h$/) {
835       $pm{$filename} = $instbase . '/Imager/include/' . $filename;
836     }
837   }
838
839   # and the generated header
840   $pm{"imconfig.h"} = $instbase . '/Imager/include/imconfig.h';
841
842   \%pm;
843 }
844
845 sub make_metafile {
846   my ($opts) = @_;
847
848   # extract the version
849   my $version = MM->parse_version($opts->{VERSION_FROM})
850     or die "Could not extract version number from $opts->{VERSION_FROM}\n";
851
852   # we don't set this on older EU::MM and it corrupts META.yml
853   # so don't generate it
854   return unless $opts->{AUTHOR};
855
856   my $meta = <<YAML;
857 --- #YAML:1.0
858 name: $opts->{NAME}
859 version: $version
860 version_from: $opts->{VERSION_FROM}
861 author: $opts->{AUTHOR}
862 abstract: $opts->{ABSTRACT}
863 installdirs: site
864 YAML
865   if (keys %{$Recommends{$opts->{NAME}}}) {
866     $meta .= "recommends:\n";
867     while (my ($module, $version) = each %{$Recommends{$opts->{NAME}}}) {
868       $meta .= "  $module: $version\n";
869     }
870   }
871   if ($opts->{PREREQ_PM}) {
872     $meta .= "requires:\n";
873     while (my ($module, $version) = each %{$opts->{PREREQ_PM}}) {
874       $meta .= "  $module: $version\n";
875     }
876   }
877   $meta .= <<YAML;
878 license: perl
879 dynamic_config: 1
880 distribution_type: module
881 meta-spec:
882   version: 1.3
883   url: http://module-build.sourceforge.net/META-spec-v1.3.html
884 generated_by: $opts->{NAME} version $version
885 YAML
886   my $save_meta;
887   if (open META, "< META.yml") {
888     my $old_meta = do { local $/; <META> };
889     close META;
890
891     $save_meta = $old_meta ne $meta;
892   }
893   else {
894     ++$save_meta;
895   }
896   if ($save_meta) {
897     print "Updating META.yml\n";
898     open META, "> META.yml" or die "Cannot create META.yml: $!";
899     print META $meta;
900     close META;
901   }
902 }
903
904 # this is intended to only be running on the development
905 # machines
906 sub distcheck {
907   if (-e '.svn') {
908     # update Changes if needed
909     my $write_changes;
910     # get the last revision from Changes
911     if (open CHANGES, "< Changes") {
912       <CHANGES>;
913       my ($changes_rev) = <CHANGES> =~ /^r(\d+)/
914         or ++$write_changes;
915
916       my ($revision) = grep s/^Revision: //, `svn info`
917         or die "Could not get Revision from svn";
918       chomp $revision;
919
920       $write_changes ||= $changes_rev != $revision;
921       close CHANGES;
922     }
923     else {
924       ++$write_changes;
925     }
926     if ($write_changes) {
927       print "Updating Changes file\n";
928       system 'svn log -v -r HEAD:943 >Changes';
929     }
930   }
931 }