3 use ExtUtils::MakeMaker;
8 use ExtUtils::Manifest qw(maniread);
10 use vars qw(%formats $VERBOSE $INCPATH $LIBPATH $NOLOG $DEBUG_MALLOC $MANUAL $CFLAGS $LFLAGS $DFLAGS);
14 # EU::MM runs Makefile.PL all in the same process, so sub-modules will
16 our $BUILDING_IMAGER = 1;
18 # used to display a summary after we've probed the world
22 # IM_INCPATH colon seperated list of paths to extra include paths
23 # IM_LIBPATH colon seperated list of paths to extra library paths
25 # IM_VERBOSE turns on verbose mode for the library finding and such
26 # IM_MANUAL to manually select which libraries are used and which not
27 # IM_ENABLE to programmatically select which libraries are used
29 # IM_NOLOG if true logging will not be compiled into the module
30 # IM_DEBUG_MALLOC if true malloc debbuging will be compiled into the module
31 # do not use IM_DEBUG_MALLOC in production - this slows
32 # everything down by alot
33 # IM_CFLAGS Extra flags to pass to the compiler
34 # IM_LFLAGS Extra flags to pass to the linker
35 # IM_DFLAGS Extra flags to pass to the preprocessor
37 my $KEEP_FILES = $ENV{IMAGER_KEEP_FILES};
39 getenv(); # get environment variables
41 my $lext=$Config{'so'}; # Get extensions of libraries
42 my $aext=$Config{'_a'};
44 my $help; # display help if set
45 my @enable; # list of drivers to enable
46 my @disable; # or list of drivers to disable
47 my @incpaths; # places to look for headers
48 my @libpaths; # places to look for libraries
49 my $coverage; # build for coverage testing
50 my $assert; # build with assertions
51 my $trace_context; # trace context management to stderr
52 GetOptions("help" => \$help,
53 "enable=s" => \@enable,
54 "disable=s" => \@disable,
55 "incpath=s", \@incpaths,
56 "libpath=s" => \@libpaths,
57 "verbose|v" => \$VERBOSE,
59 'coverage' => \$coverage,
60 "assert|a" => \$assert,
61 "tracecontext" => \$trace_context);
65 if ($ENV{AUTOMATED_TESTING}) {
70 print "Verbose mode\n";
72 import Data::Dumper qw(Dumper);
81 if ($NOLOG) { print "Logging not compiled into module\n"; }
83 push @defines, [ IMAGER_LOG => 1, "Logging system" ];
87 push @defines, [ IM_ASSERT => 1, "im_assert() are effective" ];
91 push @defines, [ IMAGER_DEBUG_MALLOC => 1, "Use Imager's DEBUG malloc()" ];
92 print "Malloc debugging enabled\n";
95 if (@enable && @disable) {
96 print STDERR "Only --enable or --disable can be used, not both, try --help\n";
102 my @incs; # all the places to look for headers
103 my @libs; # all the places to look for libraries
105 init(); # initialize global data
106 pathcheck(); # Check if directories exist
108 if (exists $ENV{IM_ENABLE}) {
109 my %en = map { $_, 1 } split ' ', $ENV{IM_ENABLE};
110 for my $key (keys %formats) {
111 delete $formats{$key} unless $en{$key};
115 my %en = map { $_ => 1 } map { split /,/ } @enable;
116 for my $key (keys %formats) {
117 delete $formats{$key} unless $en{$key};
121 delete @formats{map { split /,/ } @disable};
124 # Pick what libraries are used
135 for my $frmkey (sort { $formats{$a}{order} <=> $formats{$b}{order} } keys %formats) {
136 my $frm = $formats{$frmkey};
137 push @defines, [ $frm->{def}, 1, "$frmkey available" ];
138 $F_OBJECT .= ' ' .$frm->{objfiles};
139 if ($frm->{cflags}) {
140 $lib_cflags .= ' ' .$frm->{cflags};
141 ++$definc{$_} for map { /^-I(.*)$/ ? ($1) : () }
142 grep /^-I./, split ' ', $frm->{cflags};
144 if ($frm->{lflags}) {
145 $lib_lflags .= ' ' . $frm->{lflags};
148 $F_LIBS .= ' ' .$frm->{libfiles};
153 my $F_INC = join ' ', map "-I$_", map / / ? qq{"$_"} : $_,
154 grep !$definc{$_}, @incs;
155 $F_LIBS = join(' ',map "-L$_", map / / ? qq{"$_"} : $_,
156 grep !$deflib{$_}++, @libs) . $F_LIBS;
159 my $OSDEF = "-DOS_$^O";
161 if ($^O eq 'hpux') { $OSLIBS .= ' -ldld'; }
162 if (defined $Config{'d_dlsymun'}) { $OSDEF .= ' -DDLSYMUN'; }
164 my @objs = qw(Imager.o context.o draw.o polygon.o image.o io.o iolayer.o
165 log.o gaussian.o conv.o pnm.o raw.o feat.o combine.o
166 filters.o dynaload.o stackmach.o datatypes.o
167 regmach.o trans2.o quant.o error.o convert.o
168 map.o tags.o palimg.o maskimg.o img8.o img16.o rotate.o
169 bmp.o tga.o color.o fills.o imgdouble.o limits.o hlines.o
170 imext.o scale.o rubthru.o render.o paste.o compose.o flip.o);
172 if ($Config{useithreads}) {
173 if ($Config{i_pthread}) {
174 print "POSIX threads\n";
175 push @objs, "mutexpthr.o";
177 elsif ($^O eq 'MSWin32') {
178 print "Win32 threads\n";
179 push @objs, "mutexwin.o";
182 print "Unsupported threading model\n";
183 push @objs, "mutexnull.o";
187 print "No threads\n";
188 push @objs, "mutexnull.o";
191 my @typemaps = qw(typemap.local typemap);
193 unshift @typemaps, "typemap.oldperl";
196 if ($trace_context) {
197 $CFLAGS .= " -DIMAGER_TRACE_CONTEXT";
203 'VERSION_FROM' => 'Imager.pm',
204 'LIBS' => "$LFLAGS -lm $lib_lflags $OSLIBS $F_LIBS",
205 'DEFINE' => "$OSDEF $CFLAGS",
206 'INC' => "$lib_cflags $DFLAGS $F_INC",
207 'OBJECT' => join(' ', @objs, $F_OBJECT),
208 clean => { FILES=>'testout rubthru.c scale.c conv.c filters.c gaussian.c render.c rubthru.c' },
212 'Test::More' => 0.47,
213 'Scalar::Util' => 1.00,
216 TYPEMAPS => \@typemaps,
220 if ($Config{gccversion}) {
221 push @ARGV, 'OPTIMIZE=-ftest-coverage -fprofile-arcs -g';
222 $opts{dynamic_lib} = { OTHERLDFLAGS => '-ftest-coverage -fprofile-arcs' };
225 die "Don't know the coverage C flags for your compiler\n";
229 # eval to prevent warnings about versions with _ in them
230 my $MM_ver = eval $ExtUtils::MakeMaker::VERSION;
231 if ($MM_ver > 6.06) {
232 $opts{AUTHOR} = 'Tony Cook <tonyc@cpan.org>, Arnar M. Hrafnkelsson';
233 $opts{ABSTRACT} = 'Perl extension for Generating 24 bit Images';
236 if ($MM_ver >= 6.46) {
241 "Parse::RecDescent" => 0
260 homepage => "http://imager.perl.org/",
261 repository => "git://git.imager.perl.org/imager.git",
262 bugtracker => "http://rt.cpan.org/NoAuth/Bugs.html?Dist=Imager",
267 make_imconfig(\@defines);
269 if ($VERBOSE) { print Dumper(\%opts); }
270 mkdir('testout',0777); # since we cannot include it in the archive.
272 -d "probe" and rmdir "probe";
274 WriteMakefile(%opts);
278 for my $name (sort { lc $a cmp lc $b } keys %IMAGER_LIBS) {
279 if ($IMAGER_LIBS{$name}) {
288 print "Libraries found:\n" if @good;
289 print " $_\n" for @good;
290 print "Libraries *not* found:\n" if @bad;
291 print " $_\n" for @bad;
298 my $perl = $self->{PERLRUN} ? '$(PERLRUN)' : '$(PERL)';
301 my @ims = grep /\.im$/, keys %$mani;
303 dyntest.$(MYEXTLIB) : dynfilt/Makefile
304 cd dynfilt && $(MAKE) $(PASTHRU)
306 lib/Imager/Regops.pm : regmach.h regops.perl
307 $(PERL) regops.perl regmach.h lib/Imager/Regops.pm
309 imconfig.h : Makefile.PL
310 $(ECHO) "imconfig.h out-of-date with respect to $?"
311 $(PERLRUN) Makefile.PL
312 $(ECHO) "==> Your Makefile has been rebuilt - re-run your make command <=="
314 lib/Imager/APIRef.pod : \$(C_FILES) \$(H_FILES) apidocs.perl
315 $perl apidocs.perl lib/Imager/APIRef.pod
317 !.join('', map _im_rule($perl, $_), @ims)
322 my ($perl, $im) = @_;
324 (my $c = $im) =~ s/\.im$/.c/;
327 $c: $im lib/Imager/Preprocess.pm
328 $perl -Ilib -MImager::Preprocess -epreprocess $im $c
334 # manual configuration of helper libraries
339 Please answer the following questions about
340 which formats are avaliable on your computer
342 press <return> to continue
345 <STDIN>; # eat one return
347 for my $frm(sort { $formats{$b}{order} <=> $formats{$a}{order} } keys %formats) {
349 if ($formats{$frm}{docs}) { print "\n",$formats{$frm}{docs},"\n\n"; }
350 print "Enable $frm support: ";
353 if ($gz =~ m/^(y|yes|n|no)/i) {
354 $gz=substr(lc($gz),0,1);
356 delete $formats{$frm};
363 # automatic configuration of helper libraries
366 print "Automatic probing:\n" if $VERBOSE;
367 for my $frm (sort { $formats{$a}{order} <=> $formats{$b}{order} } keys %formats) {
368 delete $formats{$frm} if !checkformat($frm);
375 # print "checking path $path\n";
376 if ( !opendir(DH,$path) ) {
377 warn "Cannot open dir $path: $!\n";
380 my @l=grep { $chk->($_) } readdir(DH);
383 return map $path, @l;
387 my ($format, $frm) = @_;
389 my $lib_check=$formats{$frm}{'libcheck'};
390 my $inc_check=$formats{$frm}{'inccheck'};
395 push(@l, grep_directory($lp,$lib_check));
400 push(@i, $ip) if $inc_check->($ip,$frm);
403 printf("%10s: includes %s - libraries %s\n",$frm,(@i?'found':'not found'),(@l?'found':'not found'));
404 $formats{$frm}{incdir} = \@i;
405 $formats{$frm}{libdir} = \@l;
406 return 1 if scalar(@i && @l);
409 printf("%10s: not available\n", $frm);
418 print " checkformat($frm)\n" if $VERBOSE;
420 my $format = $formats{$frm};
423 if (my $code = $format->{'code'}) {
424 if (ref $code eq 'ARRAY') {
425 push @probes, @$code;
431 push @probes, \&_probe_default;
433 print " Calling probe function\n" if $VERBOSE;
435 for my $func (@probes) {
436 if ($func->($format, $frm)) {
444 if ($format->{postcheck}) {
445 print " Calling postcheck function\n" if $VERBOSE;
446 $format->{postcheck}->($format, $frm)
457 print " Include paths:\n";
458 for (@incs) { print $_,"\n"; }
460 @incs=grep { -d $_ && -r _ && -x _ or ( print(" $_ doesnt exist or is unaccessible - removed.\n"),0) } @incs;
463 print "\nLibrary paths:\n";
464 for (@libs) { print $_,"\n"; }
466 @libs=grep { -d $_ && -r _ && -x _ or ( print(" $_ doesnt exist or is unaccessible - removed.\n"),0) } @libs;
471 # Format data initialization
473 # format definition is:
475 # default include path
476 # files needed for include (boolean perl code)
479 # files needed for link (boolean perl code)
480 # object files needed for the format
485 my @definc = qw(/usr/include);
486 @definc{@definc}=(1) x @definc;
489 split(/\Q$Config{path_sep}/, $INCPATH),
490 map _tilde_expand($_), map { split /\Q$Config{path_sep}/ } @incpaths
492 if ($Config{locincpth}) {
493 push @incs, grep -d, split ' ', $Config{locincpth};
495 if ($^O =~ /win32/i && $Config{cc} =~ /\bcl\b/i) {
496 push(@incs, split /;/, $ENV{INCLUDE}) if exists $ENV{INCLUDE};
498 if ($Config{incpath}) {
499 push @incs, grep -d, split /\Q$Config{path_sep}/, $Config{incpath};
503 /usr/include/freetype2
504 /usr/local/include/freetype2
505 /usr/local/include/freetype1/freetype
506 /usr/include /usr/local/include /usr/include/freetype
507 /usr/local/include/freetype);
508 if ($Config{ccflags}) {
509 my @hidden = map { /^-I(.*)$/ ? ($1) : () } split ' ', $Config{ccflags};
511 @definc{@hidden} = (1) x @hidden;
514 @libs= ( split(/\Q$Config{path_sep}/,$LIBPATH),
515 map _tilde_expand($_), map { split /\Q$Config{path_sep}/} @libpaths );
516 if ($Config{loclibpth}) {
517 push @libs, grep -d, split ' ', $Config{loclibpth};
520 push @libs, grep -d, qw(/sw/lib), split(/ /, $Config{'libpth'});
521 push @libs, grep -d, split / /, $Config{libspath} if $Config{libspath};
522 if ($^O =~ /win32/i && $Config{cc} =~ /\bcl\b/i) {
523 push(@libs, split /;/, $ENV{LIB}) if exists $ENV{LIB};
525 if ($^O eq 'cygwin') {
526 push(@libs, '/usr/lib/w32api') if -d '/usr/lib/w32api';
527 push(@incs, '/usr/include/w32api') if -d '/usr/include/w32api';
529 if ($Config{ldflags}) {
530 # some builds of perl put -Ldir into ldflags without putting it in
531 # loclibpth, let's extract them
532 my @hidden = grep -d, map { /^-L(.*)$/ ? ($1) : () }
533 split ' ', $Config{ldflags};
535 # don't mark them as seen - EU::MM will remove any libraries
536 # it can't find and it doesn't look for -L in ldflags
537 #@deflib{@hidden} = @hidden;
539 push @libs, grep -d, qw(/usr/local/lib);
541 $formats{'TT-fonts'}=
545 inccheck=>sub { -e catfile($_[0], 'freetype.h')
546 && !-e catfile($_[0], 'fterrors.h') },
547 libcheck=>sub { $_[0] eq "libttf$aext" or $_[0] eq "libttf.$lext" },
549 objfiles=>'fontft1.o',
550 code => \&freetype1_probe,
552 Truetype fonts are scalable fonts. They can include
553 kerning and hinting information and generally yield good
554 visual quality esp on low resultions. The freetype library is
555 used to rasterize for us. The only drawback is that there
556 are alot of badly designed fonts out there.}
559 for (keys %formats) { $formats{$_}->{docs} =~ s/^\s+/ /mg; }
566 defined($V) ? $V : "";
570 # Get information from environment variables
582 $DFLAGS) = map { gen $_ } qw(IM_VERBOSE
594 # populate the environment so that sub-modules get the same info
596 $ENV{IM_VERBOSE} = 1 if $VERBOSE;
597 $ENV{IM_INCPATH} = join $Config{path_sep}, @incpaths if @incpaths;
598 $ENV{IM_LIBPATH} = join $Config{path_sep}, @libpaths if @libpaths;
604 open CONFIG, "> imconfig.h"
605 or die "Cannot create imconfig.h: $!\n";
607 /* This file is automatically generated by Makefile.PL.
608 Don't edit this file, since any changes will be lost */
610 #ifndef IMAGER_IMCONFIG_H
611 #define IMAGER_IMCONFIG_H
613 for my $define (@$defines) {
615 print CONFIG "\n/*\n $define->[2]\n*/\n\n";
617 print CONFIG "#define $define->[0] $define->[1]\n";
619 if ($Config{gccversion} && $Config{gccversion} =~ /^([0-9]+)/ && $1 > 3) {
623 Compiler supports the GCC __attribute__((format...)) syntax.
627 #define IMAGER_FORMAT_ATTR 1
632 if ($Config{d_snprintf}) {
634 /* We can use snprintf() */
635 #define IMAGER_SNPRINTF 1
640 if ($Config{d_vsnprintf}) {
642 /* We can use vsnprintf() */
643 #define IMAGER_VSNPRINTF 1
650 Type and format code for formatted output as with printf.
652 This is intended for formatting i_img_dim values.
654 typedef $Config{ivtype} i_dim_format_t;
655 #define i_DF $Config{ivdformat}
658 print CONFIG "\n#endif\n";
662 # probes for freetype1 by scanning @incs for the includes and
663 # @libs for the libs. This is done separately because freetype's headers
664 # are stored in a freetype or freetype1 directory under PREFIX/include.
666 # we could find the files with the existing mechanism, but it won't set
667 # -I flags correctly.
669 # This could be extended to freetype2 too, but freetype-config catches
671 sub freetype1_probe {
672 my ($frm, $frmkey) = @_;
676 for my $inc (@incs) {
677 for my $subdir (qw/freetype freetype1/) {
678 my $path = File::Spec->catfile($inc, $subdir, 'freetype.h');
680 $path = File::Spec->catfile($inc, $subdir, 'fterrors.h');
683 $found_inc = File::Spec->catdir($inc, $subdir);
690 for my $lib (@libs) {
691 my $a_path = File::Spec->catfile($lib, "libttf$aext");
692 my $l_path = File::Spec->catfile($lib, "libttf.$lext");
693 if (-e $a_path || -e $l_path) {
699 return unless $found_inc && $found_lib;
700 printf("%10s: includes %s - libraries %s\n", $frmkey,
701 ($found_inc ? 'found' : 'not found'),
702 ($found_lib ? 'found' : 'not found'));
704 $frm->{cflags} = "-I$found_inc";
705 $frm->{libfiles} = "-lttf";
711 return File::Spec->catfile(@_);
716 Usage: $0 [--enable feature1,feature2,...] [other options]
717 $0 [--disable feature1,feature2,...] [other options]
719 Possible feature names are:
723 Verbose library probing (or set IM_VERBOSE in the environment)
725 Disable logging (or set IM_NOLOG in the environment)
727 Add to the include search path
729 Add to the library search path
731 Build for coverage testing.
733 Build with assertions active.
739 # generate the PM MM argument
740 # I'd prefer to modify the public version, but there doesn't seem to be
741 # a public API to do that
744 my $instbase = '$(INST_LIBDIR)';
746 # first the basics, .pm and .pod files
747 $pm{"Imager.pm"} = "$instbase/Imager.pm";
749 my $mani = maniread();
751 for my $filename (keys %$mani) {
752 if ($filename =~ m!^lib/! && $filename =~ /\.(pm|pod)$/) {
753 (my $work = $filename) =~ s/^lib//;
754 $pm{$filename} = $instbase . $work;
759 $pm{typemap} = $instbase . '/Imager/typemap';
761 # and the core headers
762 for my $filename (keys %$mani) {
763 if ($filename =~ /^\w+\.h$/) {
764 $pm{$filename} = $instbase . '/Imager/include/' . $filename;
768 # and the generated header
769 $pm{"imconfig.h"} = $instbase . '/Imager/include/imconfig.h';
778 if ($path =~ m!^~[/\\]!) {
779 defined $home or $home = $ENV{HOME};
780 if (!defined $home && $^O eq 'MSWin32'
781 && defined $ENV{HOMEDRIVE} && defined $ENV{HOMEPATH}) {
782 $home = $ENV{HOMEDRIVE} . $ENV{HOMEPATH};
784 unless (defined $home) {
785 $home = eval { (getpwuid($<))[7] };
787 defined $home or die "You supplied $path, but I can't find your home directory\n";
789 $path = File::Spec->catdir($home, $path);