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