b7828fd47cab01a65127db4ff61877fd2f423f5d
[imager.git] / Makefile.PL
1 #!perl -w
2 use ExtUtils::MakeMaker;
3 use Cwd;
4 use Config;
5 use File::Spec;
6 use Getopt::Long;
7
8 #
9 # IM_INCPATH      colon seperated list of paths to extra include paths
10 # IM_LIBPATH      colon seperated list of paths to extra library paths
11 #
12 # IM_VERBOSE      turns on verbose mode for the library finding and such
13 # IM_MANUAL       to manually select which libraries are used and which not
14 # IM_ENABLE       to programmatically select which libraries are used
15 #                 and which are not
16 # IM_NOLOG        if true logging will not be compiled into the module
17 # IM_DEBUG_MALLOC if true malloc debbuging will be compiled into the module
18 #                 do not use IM_DEBUG_MALLOC in production - this slows
19 #                 everything down by alot
20 # IM_CFLAGS       Extra flags to pass to the compiler
21 # IM_LFLAGS       Extra flags to pass to the linker
22 # IM_DFLAGS       Extra flags to pass to the preprocessor
23 # IM_SUPPRESS_PROMPT  Suppress the prompt asking about gif support
24
25 getenv();     # get environment variables
26
27 my $help;
28 my @enable;
29 my @disable;
30 my @incpaths;
31 my @libpaths;
32 my $noprobe;
33 GetOptions("help" => \$help,
34            "enable=s" => \@enable,
35            "disable=s" => \@disable,
36            "incpath=s", \@incpaths,
37            "libpath=s" => \@libpaths,
38            "noprobe" => \$noprobe,
39            "verbose|v" => \$VERBOSE,
40            "nolog" => \$NOLOG);
41
42 if ($VERBOSE) { 
43   print "Verbose mode\n"; 
44   require Data::Dumper; 
45   import Data::Dumper qw(Dumper);
46 }
47
48 if ($help) {
49   usage();
50 }
51
52 if ($NOLOG)   { print "Logging not compiled into module\n"; }
53 else { 
54   push @defines, [ IMAGER_LOG => 1, "Logging system" ];
55 }
56
57 if ($DEBUG_MALLOC) {
58   push @defines, [ IMAGER_DEBUG_MALLOC => 1, "Use Imager's DEBUG malloc()" ];
59   print "Malloc debugging enabled\n";
60 }
61
62 if (@enable && @disable) {
63   print STDERR "Only --enable or --disable can be used, not both, try --help\n";
64   exit 1;
65 }
66
67 init();       # initialize global data
68 pathcheck();  # Check if directories exist
69
70 if (exists $ENV{IM_ENABLE}) {
71   my %en = map { $_, 1 } split ' ', $ENV{IM_ENABLE};
72   for my $key (keys %formats) {
73     delete $formats{$key} unless $en{$key};
74   }
75 }
76 if (@enable) {
77   my %en = map { $_ => 1 } map { split /,/ } @enable;
78   for my $key (keys %formats) {
79     delete $formats{$key} unless $en{$key};
80   }
81 }
82 elsif (@disable) {
83   delete @formats{map { split /,/ } @disable};
84 }
85
86 my @defines;
87
88 # Pick what libraries are used
89 if ($MANUAL) {
90   manual();
91 } else {
92   automatic();
93 }
94
95 # Make sure there isn't a clash between the gif libraries.
96 gifcheck();
97
98 my $lib_cflags = '';
99 my $F_LIBS = '';
100 my $F_OBJECT = '';
101 for my $frmkey (keys %formats) {
102   my $frm = $formats{$frmkey};
103   push @defines, [ $frm->{def}, 1, "$frmkey available" ];
104   $F_LIBS   .= ' '  .$frm->{libfiles};
105   $F_OBJECT .= ' '  .$frm->{objfiles};
106   $lib_cflags   .= ' '  .$frm->{cflags} if $frm->{cflags};
107 }
108
109 $F_INC  = join ' ', map "-I$_", map / / ? qq{"$_"} : $_, 
110   grep !exists $definc{$_}, @incs;
111 $F_LIBS = join(' ',map "-L$_", map / / ? qq{"$_"} : $_, @libs) . $F_LIBS;
112
113 $OSLIBS = '';
114 $OSDEF  = "-DOS_$^O";
115
116 if ($^O eq 'hpux')                { $OSLIBS .= ' -ldld'; }
117 if (defined $Config{'d_dlsymun'}) { $OSDEF  .= ' -DDLSYMUN'; }
118
119 @objs = qw(Imager.o draw.o polygon.o image.o io.o iolayer.o
120            log.o gaussian.o conv.o pnm.o raw.o feat.o font.o
121            filters.o dynaload.o stackmach.o datatypes.o
122            regmach.o trans2.o quant.o error.o convert.o
123            map.o tags.o palimg.o maskimg.o img16.o rotate.o
124            bmp.o tga.o rgb.o color.o fills.o imgdouble.o limits.o hlines.o);
125
126 %opts=(
127        'NAME'         => 'Imager',
128        'VERSION_FROM' => 'Imager.pm',
129        'LIBS'         => "$LFLAGS -lm $OSLIBS $F_LIBS",
130        'DEFINE'       => "$OSDEF $CFLAGS",
131        'INC'          => "$lib_cflags $DFLAGS $F_INC",
132        'OBJECT'       => join(' ', @objs, $F_OBJECT),
133        clean          => { FILES=>'testout meta.tmp' },
134       );
135
136 if ($ExtUtils::MakeMaker::VERSION > 6.06) {
137   $opts{AUTHOR} = 'Tony Cook <tony@imager.perl.org>, Arnar M. Hrafnkelsson';
138   $opts{ABSTRACT} = 'Perl extension for Generating 24 bit Images';
139 }
140
141 make_imconfig(\@defines);
142
143 if ($VERBOSE) { print Dumper(\%opts); }
144 mkdir('testout',0777); # since we cannot include it in the archive.
145 WriteMakefile(%opts);
146
147 exit;
148
149
150 sub MY::postamble {
151 '
152 dyntest.$(MYEXTLIB) : dynfilt/Makefile
153         cd dynfilt && $(MAKE) $(PASTHRU)
154
155 lib/Imager/Regops.pm : regmach.h regops.perl
156         $(PERL) regops.perl regmach.h lib/Imager/Regops.pm
157
158 imconfig.h: Makefile.PL
159         $(ECHO) "imconfig.h out-of-date with respect to $?"
160         $(PERLRUN) Makefile.PL
161         $(ECHO) "==> Your Makefile has been rebuilt - re-run your make command <=="
162 ';
163 }
164
165 sub MY::metafile {
166   my ($self) = @_;
167
168   my $meta = <<YAML;
169 --- #YAML:1.0
170 name: Imager
171 version: $self->{VERSION}
172 version_from: $self->{VERSION_FROM}
173 author: $self->{AUTHOR}
174 abstract: $self->{ABSTRACT}
175 installdirs: $self->{INSTALLDIRS}
176 recommends:
177   Parse::RecDescent: 0
178 license: perl
179 dynamic_config: 1
180 distribution_type: module
181 generated_by: Imager version $self->{VERSION}
182 YAML
183   open META, "> meta.tmp" or die "Cannot create meta.tmp: $!";
184   print META $meta;
185   close META;
186   
187   return sprintf "metafile :\n\t\$(CP) meta.tmp META.yml\n";
188 }
189
190 # manual configuration of helper libraries
191
192 sub manual {
193   print <<EOF;
194
195       Please answer the following questions about
196       which formats are avaliable on your computer
197
198 press <return> to continue
199 EOF
200
201   <STDIN>; # eat one return
202
203   for my $frm(sort { $formats{$b}{order} <=> $formats{$a}{order} } keys %formats) {
204   SWX:
205     if ($formats{$frm}{docs}) { print "\n",$formats{$frm}{docs},"\n\n"; }
206     print "Enable $frm support: ";
207     $gz = <STDIN>;
208     chomp($gz);
209     if ($gz =~ m/^(y|yes|n|no)/i) {
210       $gz=substr(lc($gz),0,1);
211       if ($gz eq 'n') {
212         delete $formats{$frm};
213       }
214     } else { goto SWX; }
215   }
216 }
217
218
219 # automatic configuration of helper libraries
220
221 sub automatic {
222   for $frm(keys %formats) {
223     delete $formats{$frm} if !checkformat($frm);        
224   }
225 }
226
227
228 sub gifcheck {
229   if ($formats{'gif'} and $formats{'ungif'}) {
230     print "ungif and gif can not coexist - removing ungif support\n";
231     delete $formats{'ungif'};
232   }
233
234  RETR:
235   if (($formats{'gif'} or $formats{'ungif'}) && !$ENV{IM_SUPPRESS_PROMPT}) {
236     print <<EOFF;
237
238 You have libgif or libungif installed.  They are both known to have
239 bugs.  Imager can crash or display other strange behaviour after
240 reading or writing gif images.  Some of the gif tests can even fail
241 since they stress some parts of the buggy code.
242
243 libungif 4.1.2 and later is safe.  giflib 4.1.3 needs at least one
244 patch to have all the bugs fixed, see README for details.
245
246 Of course it's possible your operating system distributor has patched
247 all of these problems and you have nothing to worry about.
248
249 Do you want to remove gif support? [Y/n]
250 EOFF
251     my $resp = <STDIN>;
252     chomp($resp);
253     if ($resp ne "n") {
254       delete $formats{'gif'};
255       delete $formats{'ungif'};
256       return;
257     }
258   }
259
260   for my $frm (qw(gif ungif)) {
261     checkformat($frm) if ($MANUAL and $formats{$frm});
262   }
263
264   my @dirs;
265   for my $frm (grep $formats{$_}, qw(gif ungif)) {
266     push(@dirs, @{$formats{$frm}{incdir}}) if $formats{$frm}{incdir};
267   }
268   my $minor = 0;
269   my $major = 0;
270   FILES: for my $dir (@dirs) {
271     my $h = "$dir/gif_lib.h";
272     open H, "< $h" or next;
273     while (<H>) {
274       if (/GIF_LIB_VERSION\s+"\s*version\s*(\d+)\.(\d+)/i) {
275         $major = $1;
276         $minor = $2;
277         close H;
278         last FILES;
279       }
280     }
281     close H;
282   }
283
284   # we need the version in a #ifdefable form
285
286   push @defines, [ IM_GIFMAJOR, $major, "Parsed giflib version" ];
287   push @defines, [ IM_GIFMINOR, $minor ];
288 }
289
290
291 sub gd {
292   my($path,$chk)=@_;
293
294 #    print "checking path $path\n";
295   if ( !opendir(DH,$path) ) {
296     warn "Cannot open dir $path: $!\n";
297     return;
298   }
299   my @l=grep { $chk->($_) } readdir(DH);
300   #    print @l;
301   close(DH);
302   return map $path, @l;
303 }
304
305
306 sub checkformat {
307   my $frm=shift;
308   
309   my $code = $formats{$frm}{'code'};
310   if ($code && !$noprobe) {
311     return 1 if $code->($formats{$frm}, $frm);
312   }
313
314   my $libchk=$formats{$frm}{'libcheck'};
315   my $incchk=$formats{$frm}{'inccheck'};
316
317   my @l;
318   for my $lp (@libs) {
319     push(@l, gd($lp,$libchk));
320   }
321
322   my @i;
323   for my $ip (@incs) {
324     push(@i, $ip) if $incchk->($ip,$frm);
325   }
326
327   printf("%10s: includes %s - libraries %s\n",$frm,(@i?'found':'not found'),(@l?'found':'not found'));
328   $formats{$frm}{incdir} = \@i;
329   $formats{$frm}{libdir} = \@l;
330   return scalar(@i && @l);
331 }
332
333
334 sub pathcheck {
335   if ($VERBOSE) {
336     print "pathcheck\n";
337     print "  Include paths:\n";
338     for (@incs) { print $_,"\n"; }
339   }
340   @incs=grep { -d $_ && -r _ && -x _ or ( print("  $_ doesnt exist or is unaccessible - removed.\n"),0) } @incs;
341
342   if ($VERBOSE) {
343     print "\nLibrary paths:\n";
344     for (@libs) { print $_,"\n"; }
345   }
346   @libs=grep { -d $_ && -r _ && -x _ or ( print("  $_ doesnt exist or is unaccessible - removed.\n"),0) } @libs;
347   print "\ndone.\n";
348 }
349
350
351 # Format data initialization
352
353 # format definition is:
354 # defines needed
355 # default include path
356 # files needed for include (boolean perl code)
357 # default lib path
358 # libs needed
359 # files needed for link (boolean perl code)
360 # object files needed for the format
361
362
363 sub init {
364
365   @definc{'/usr/include'}=();
366   @incs=(split(/\Q$Config{path_sep}/, $INCPATH),
367         map { split /\Q$Config{path_sep}/} @incpaths );
368   if ($Config{locincpth}) {
369     push @incs, grep -d, split ' ', $Config{locincpth};
370   }
371   if ($^O =~ /win32/i && $Config{cc} =~ /\bcl\b/i) {
372     push(@incs, split /;/, $ENV{INCLUDE}) if exists $ENV{INCLUDE};
373   }
374   push @incs, grep -d,
375       qw(/sw/include 
376          /usr/include/freetype2
377          /usr/local/include/freetype2
378          /usr/local/include/freetype1/freetype
379          /usr/include /usr/local/include /usr/include/freetype
380          /usr/local/include/freetype);
381
382   @libs= ( split(/\Q$Config{path_sep}/,$LIBPATH),
383     map { split /\Q$Config{path_sep}/} @libpaths );
384   if ($Config{loclibpth}) {
385     push @libs, grep -d, split ' ', $Config{loclibpth};
386   }
387   push @libs, grep -d, qw(/sw/lib),  split(/ /, $Config{'libpth'});
388   if ($^O =~ /win32/i && $Config{cc} =~ /\bcl\b/i) {
389     push(@libs, split /;/, $ENV{LIB}) if exists $ENV{LIB};
390   }
391   if ($^O eq 'cygwin') {
392     push(@libs, '/usr/lib/w32api') if -d '/usr/lib/w32api';
393     push(@incs, '/usr/include/w32api') if -d '/usr/include/w32api';
394   }
395
396   my $lext=$Config{'so'};   # Get extensions of libraries
397   my $aext=$Config{'_a'};
398
399   $formats{'jpeg'}={
400                     order=>'21',
401                     def=>'HAVE_LIBJPEG',
402                     inccheck=>sub { -e catfile($_[0], 'jpeglib.h') },
403                     libcheck=>sub { $_[0] eq "libjpeg$aext" or $_ eq "libjpeg.$lext" },
404                     libfiles=>'-ljpeg',
405                     objfiles=>'jpeg.o',
406                     docs=>q{
407                             In order to use jpeg with this module you need to have libjpeg
408                             installed on your computer}
409                    };
410
411   $formats{'tiff'}={
412                     order=>'23',
413                     def=>'HAVE_LIBTIFF',
414                     inccheck=>sub { -e catfile($_[0], 'tiffio.h') },
415                     libcheck=>sub { $_[0] eq "libtiff$aext" or $_ eq "libtiff.$lext" },
416                     libfiles=>'-ltiff',
417                     objfiles=>'tiff.o',
418                     docs=>q{
419                             In order to use tiff with this module you need to have libtiff
420                             installed on your computer}
421                    };
422
423   $formats{'png'}={
424                    order=>'22',
425                    def=>'HAVE_LIBPNG',
426                    inccheck=>sub { -e catfile($_[0], 'png.h') },
427                    libcheck=>sub { $_[0] eq "libpng$aext" or $_[0] eq "libpng.$lext" },
428                    libfiles=>'-lpng -lz',
429                    objfiles=>'png.o',
430                    docs=>q{
431                            Png stands for Portable Network Graphics and is intended as
432                            a replacement for gif on the web. It is patent free and
433                            is recommended by the w3c, you need libpng to use these formats},
434                    code => \&png_probe,
435                   };
436
437   $formats{'gif'}={
438                    order=>'20',
439                    def=>'HAVE_LIBGIF',
440                    inccheck=>sub { -e catfile($_[0], 'gif_lib.h') },
441                    libcheck=>sub { $_[0] eq "libgif$aext" or $_[0] eq "libgif.$lext" },
442                    libfiles=>'-lgif',
443                    objfiles=>'gif.o',
444                    docs=>q{
445                            gif is the de facto standard for webgraphics at the moment,
446                            it does have some patent problems. If you have giflib and
447                            are not in violation with the unisys patent you should use
448                            this instead of the 'ungif' option.  Note that they cannot
449                            be in use at the same time}
450                   };
451
452   $formats{'ungif'}={
453                      order=>'21',
454                      def=>'HAVE_LIBGIF',
455                      inccheck=>sub { -e catfile($_[0], 'gif_lib.h') },
456                      libcheck=>sub { $_[0] eq "libungif$aext" or $_[0] eq "libungif.$lext" },
457                      libfiles=>'-lungif',
458                      objfiles=>'gif.o',
459                      docs=>q{
460                              gif is the de facto standard for webgraphics at the moment,
461                              it does have some patent problems. If you have libungif and
462                              want to create images free from LZW patented compression you
463                              should use this option instead of the 'gif' option}
464                     };
465
466   $formats{'T1-fonts'}={
467                         order=>'30',
468                         def=>'HAVE_LIBT1',
469                         inccheck=>sub { -e catfile($_[0], 't1lib.h') },
470                         libcheck=>sub { $_[0] eq "libt1$aext" or $_[0] eq "libt1.$lext" },
471                         libfiles=>'-lt1',
472                         objfiles=>'',
473                         docs=>q{
474                                 postscript t1 fonts are scalable fonts. They can include 
475                                 ligatures and kerning information and generally yield good
476                                 visual quality. We depend on libt1 to rasterize the fonts
477                                 for use in images.}
478                        };
479
480   $formats{'TT-fonts'}=
481     {
482      order=>'31',
483      def=>'HAVE_LIBTT',
484      inccheck=>sub { -e catfile($_[0], 'freetype.h')
485                        && !-e catfile($_[0], 'fterrors.h') },
486      libcheck=>sub { $_[0] eq "libttf$aext" or $_[0] eq "libttf.$lext" },
487      libfiles=>'-lttf',
488      objfiles=>'',
489      docs=>q{
490 Truetype fonts are scalable fonts. They can include 
491 kerning and hinting information and generally yield good
492 visual quality esp on low resultions. The freetype library is
493 used to rasterize for us. The only drawback is that there
494 are alot of badly designed fonts out there.}
495                        };
496   $formats{'w32'} = {
497                      order=>40,
498                      def=>'HAVE_WIN32',
499                      inccheck=>sub { -e catfile($_[0], 'windows.h') },
500                      libcheck=>sub { lc $_[0] eq 'gdi32.lib' 
501                                        || lc $_[0] eq 'libgdi32.a' },
502                      libfiles=>$^O eq 'cygwin' ? '-lgdi32' : '',
503                      objfiles=>'win32.o',
504                      docs => <<DOCS
505 Uses the Win32 GDI for rendering text.
506
507 This currently only works on under normal Win32 and cygwin.
508 DOCS
509                     };
510   $formats{'freetype2'} = {
511                            order=>'29',
512                            def=>'HAVE_FT2',
513                            inccheck=>sub { -e catfile($_[0], 'ft2build.h') },
514                            libcheck=>sub { $_[0] eq "libfreetype$aext" or $_[0] eq "libfreetype.$lext" },
515                            libfiles=>'-lfreetype',
516                            objfiles=>'freetyp2.o',
517                            docs=><<DOCS,
518 Freetype 2 supports both Truetype and Type 1 fonts, both of which are
519 scalable.  It also supports a variety of other fonts.
520 DOCS
521                            code => \&freetype2_probe,
522                           };
523   # Make fix indent
524   for (keys %formats) { $formats{$_}->{docs} =~ s/^\s+/  /mg; }
525 }
526
527
528
529 sub gen {
530   my $V = $ENV{$_[0]};
531   defined($V) ? $V : "";
532 }
533
534
535 # Get information from environment variables
536
537 sub getenv {
538
539   ($VERBOSE,
540    $INCPATH,
541    $LIBPATH,
542    $NOLOG,
543    $DEBUG_MALLOC,
544    $MANUAL,
545    $CFLAGS,
546    $LFLAGS,
547    $DFLAGS) = map { gen $_ } qw(IM_VERBOSE
548                                 IM_INCPATH
549                                 IM_LIBPATH
550                                 IM_NOLOG
551                                 IM_DEBUG_MALLOC
552                                 IM_MANUAL
553                                 IM_CFLAGS
554                                 IM_LFLAGS
555                                 IM_DFLAGS);
556
557 }
558
559 sub make_imconfig {
560   my ($defines) = @_;
561
562   open CONFIG, "> imconfig.h"
563     or die "Cannot create imconfig.h: $!\n";
564   print CONFIG <<EOS;
565 /* This file is automatically generated by Makefile.PL.
566    Don't edit this file, since any changes will be lost */
567
568 #ifndef IMAGER_IMCONFIG_H
569 #define IMAGER_IMCONFIG_H
570 EOS
571   for my $define (@$defines) {
572     if ($define->[2]) {
573       print CONFIG "\n/*\n  $define->[2]\n*/\n\n";
574     }
575     print CONFIG "#define $define->[0] $define->[1]\n";
576   }
577   print CONFIG "\n#endif\n";
578   close CONFIG;
579 }
580
581 # use pkg-config to probe for libraries
582 # works around the junk that pkg-config dumps on FreeBSD
583 sub _pkg_probe {
584   my ($pkg) = @_;
585
586   is_exe('pkg-config') or return;
587
588   my $redir = $^O eq 'MSWin32' ? '' : '2>/dev/null';
589
590   !system("pkg-config $pkg --exists $redir");
591 }
592
593 # probes for freetype2 by trying to run freetype-config
594 sub freetype2_probe {
595   my ($frm, $frmkey) = @_;
596
597   is_exe('freetype-config') or return;
598
599   my $cflags = `freetype-config --cflags`
600     and !$? or return;
601   chomp $cflags;
602   
603   $frm->{cflags} = $cflags;
604   my $lflags = `freetype-config --libs`
605     and !$? or return;
606   chomp $lflags;
607   $frm->{libfiles} = $lflags;
608
609   printf "%10s: configured via freetype-config\n", $frmkey;
610
611   return 1;
612 }
613
614 # probes for libpng via pkg-config
615 sub png_probe {
616   my ($frm, $frmkey) = @_;
617
618   is_exe('pkg-config') or return;
619
620   my $config;
621   for my $check_conf (qw(libpng libpng12 libpng10)) {
622     if (_pkg_probe($check_conf)) {
623       $config = $check_conf;
624       last;
625     }
626   }
627   $config or return;
628
629   my $cflags = `pkg-config $config --cflags`
630     and !$? or return;
631
632   my $lflags = `pkg-config $config --libs`
633     and !$? or return;
634
635   chomp $cflags;
636   chomp $lflags;
637   $frm->{cflags} = $cflags;
638   $frm->{libfiles} = $lflags;
639
640   printf "%10s: configured via `pkg-config $config ...`\n", $frmkey;
641
642   return 1;
643 }
644
645 sub catfile {
646   return File::Spec->catfile(@_);
647 }
648
649 sub is_exe {
650   my ($name) = @_;
651
652   for my $dir (File::Spec->path) {
653     -x catfile($dir, "$name$Config{_exe}")
654       and return 1;
655   }
656
657   return;
658 }
659
660 sub usage {
661   print STDERR <<EOS;
662 Usage: $0 [--enable feature1,feature2,...] [other options]
663        $0 [--disable feature1,feature2,...]  [other options]
664        $0 --help
665 Possible feature names are:
666   png gif ungif jpeg tiff T1-fonts TT-fonts freetype2
667 Other options:
668   --verbose | -v
669     Verbose library probing (or set IM_VERBOSE in the environment)
670   --nolog
671     Disable logging (or set IM_NOLOG in the environment)
672   --incpath dir
673     Add to the include search path
674   --libpath dir
675     Add to the library search path
676   --noprobe
677     Don't use pkg-config or freetype2-config to probe for freetype2 and libpng
678 EOS
679   exit 1;
680
681 }