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 font.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 my @typemaps = qw(typemap.local typemap);
174 unshift @typemaps, "typemap.oldperl";
177 if ($trace_context) {
178 $CFLAGS .= " -DIMAGER_TRACE_CONTEXT";
184 'VERSION_FROM' => 'Imager.pm',
185 'LIBS' => "$LFLAGS -lm $lib_lflags $OSLIBS $F_LIBS",
186 'DEFINE' => "$OSDEF $CFLAGS",
187 'INC' => "$lib_cflags $DFLAGS $F_INC",
188 'OBJECT' => join(' ', @objs, $F_OBJECT),
189 clean => { FILES=>'testout rubthru.c scale.c conv.c filters.c gaussian.c render.c rubthru.c' },
193 'Test::More' => 0.47,
194 'Scalar::Util' => 1.00,
197 TYPEMAPS => \@typemaps,
201 if ($Config{gccversion}) {
202 push @ARGV, 'OPTIMIZE=-ftest-coverage -fprofile-arcs -g';
203 $opts{dynamic_lib} = { OTHERLDFLAGS => '-ftest-coverage -fprofile-arcs' };
206 die "Don't know the coverage C flags for your compiler\n";
210 # eval to prevent warnings about versions with _ in them
211 my $MM_ver = eval $ExtUtils::MakeMaker::VERSION;
212 if ($MM_ver > 6.06) {
213 $opts{AUTHOR} = 'Tony Cook <tonyc@cpan.org>, Arnar M. Hrafnkelsson';
214 $opts{ABSTRACT} = 'Perl extension for Generating 24 bit Images';
217 if ($MM_ver >= 6.46) {
222 "Parse::RecDescent" => 0
241 homepage => "http://imager.perl.org/",
242 repository => "git://git.imager.perl.org/imager.git",
243 bugtracker => "http://rt.cpan.org/NoAuth/Bugs.html?Dist=Imager",
248 make_imconfig(\@defines);
250 if ($VERBOSE) { print Dumper(\%opts); }
251 mkdir('testout',0777); # since we cannot include it in the archive.
253 -d "probe" and rmdir "probe";
255 WriteMakefile(%opts);
259 for my $name (sort { lc $a cmp lc $b } keys %IMAGER_LIBS) {
260 if ($IMAGER_LIBS{$name}) {
269 print "Libraries found:\n" if @good;
270 print " $_\n" for @good;
271 print "Libraries *not* found:\n" if @bad;
272 print " $_\n" for @bad;
279 my $perl = $self->{PERLRUN} ? '$(PERLRUN)' : '$(PERL)';
282 my @ims = grep /\.im$/, keys %$mani;
284 dyntest.$(MYEXTLIB) : dynfilt/Makefile
285 cd dynfilt && $(MAKE) $(PASTHRU)
287 lib/Imager/Regops.pm : regmach.h regops.perl
288 $(PERL) regops.perl regmach.h lib/Imager/Regops.pm
290 imconfig.h : Makefile.PL
291 $(ECHO) "imconfig.h out-of-date with respect to $?"
292 $(PERLRUN) Makefile.PL
293 $(ECHO) "==> Your Makefile has been rebuilt - re-run your make command <=="
295 lib/Imager/APIRef.pod : \$(C_FILES) \$(H_FILES) apidocs.perl
296 $perl apidocs.perl lib/Imager/APIRef.pod
298 !.join('', map _im_rule($perl, $_), @ims)
303 my ($perl, $im) = @_;
305 (my $c = $im) =~ s/\.im$/.c/;
308 $c: $im lib/Imager/Preprocess.pm
309 $perl -Ilib -MImager::Preprocess -epreprocess $im $c
315 # manual configuration of helper libraries
320 Please answer the following questions about
321 which formats are avaliable on your computer
323 press <return> to continue
326 <STDIN>; # eat one return
328 for my $frm(sort { $formats{$b}{order} <=> $formats{$a}{order} } keys %formats) {
330 if ($formats{$frm}{docs}) { print "\n",$formats{$frm}{docs},"\n\n"; }
331 print "Enable $frm support: ";
334 if ($gz =~ m/^(y|yes|n|no)/i) {
335 $gz=substr(lc($gz),0,1);
337 delete $formats{$frm};
344 # automatic configuration of helper libraries
347 print "Automatic probing:\n" if $VERBOSE;
348 for my $frm (sort { $formats{$a}{order} <=> $formats{$b}{order} } keys %formats) {
349 delete $formats{$frm} if !checkformat($frm);
356 # print "checking path $path\n";
357 if ( !opendir(DH,$path) ) {
358 warn "Cannot open dir $path: $!\n";
361 my @l=grep { $chk->($_) } readdir(DH);
364 return map $path, @l;
368 my ($format, $frm) = @_;
370 my $lib_check=$formats{$frm}{'libcheck'};
371 my $inc_check=$formats{$frm}{'inccheck'};
376 push(@l, grep_directory($lp,$lib_check));
381 push(@i, $ip) if $inc_check->($ip,$frm);
384 printf("%10s: includes %s - libraries %s\n",$frm,(@i?'found':'not found'),(@l?'found':'not found'));
385 $formats{$frm}{incdir} = \@i;
386 $formats{$frm}{libdir} = \@l;
387 return 1 if scalar(@i && @l);
390 printf("%10s: not available\n", $frm);
399 print " checkformat($frm)\n" if $VERBOSE;
401 my $format = $formats{$frm};
404 if (my $code = $format->{'code'}) {
405 if (ref $code eq 'ARRAY') {
406 push @probes, @$code;
412 push @probes, \&_probe_default;
414 print " Calling probe function\n" if $VERBOSE;
416 for my $func (@probes) {
417 if ($func->($format, $frm)) {
425 if ($format->{postcheck}) {
426 print " Calling postcheck function\n" if $VERBOSE;
427 $format->{postcheck}->($format, $frm)
438 print " Include paths:\n";
439 for (@incs) { print $_,"\n"; }
441 @incs=grep { -d $_ && -r _ && -x _ or ( print(" $_ doesnt exist or is unaccessible - removed.\n"),0) } @incs;
444 print "\nLibrary paths:\n";
445 for (@libs) { print $_,"\n"; }
447 @libs=grep { -d $_ && -r _ && -x _ or ( print(" $_ doesnt exist or is unaccessible - removed.\n"),0) } @libs;
452 # Format data initialization
454 # format definition is:
456 # default include path
457 # files needed for include (boolean perl code)
460 # files needed for link (boolean perl code)
461 # object files needed for the format
466 my @definc = qw(/usr/include);
467 @definc{@definc}=(1) x @definc;
470 split(/\Q$Config{path_sep}/, $INCPATH),
471 map _tilde_expand($_), map { split /\Q$Config{path_sep}/ } @incpaths
473 if ($Config{locincpth}) {
474 push @incs, grep -d, split ' ', $Config{locincpth};
476 if ($^O =~ /win32/i && $Config{cc} =~ /\bcl\b/i) {
477 push(@incs, split /;/, $ENV{INCLUDE}) if exists $ENV{INCLUDE};
479 if ($Config{incpath}) {
480 push @incs, grep -d, split /\Q$Config{path_sep}/, $Config{incpath};
484 /usr/include/freetype2
485 /usr/local/include/freetype2
486 /usr/local/include/freetype1/freetype
487 /usr/include /usr/local/include /usr/include/freetype
488 /usr/local/include/freetype);
489 if ($Config{ccflags}) {
490 my @hidden = map { /^-I(.*)$/ ? ($1) : () } split ' ', $Config{ccflags};
492 @definc{@hidden} = (1) x @hidden;
495 @libs= ( split(/\Q$Config{path_sep}/,$LIBPATH),
496 map _tilde_expand($_), map { split /\Q$Config{path_sep}/} @libpaths );
497 if ($Config{loclibpth}) {
498 push @libs, grep -d, split ' ', $Config{loclibpth};
501 push @libs, grep -d, qw(/sw/lib), split(/ /, $Config{'libpth'});
502 push @libs, grep -d, split / /, $Config{libspath} if $Config{libspath};
503 if ($^O =~ /win32/i && $Config{cc} =~ /\bcl\b/i) {
504 push(@libs, split /;/, $ENV{LIB}) if exists $ENV{LIB};
506 if ($^O eq 'cygwin') {
507 push(@libs, '/usr/lib/w32api') if -d '/usr/lib/w32api';
508 push(@incs, '/usr/include/w32api') if -d '/usr/include/w32api';
510 if ($Config{ldflags}) {
511 # some builds of perl put -Ldir into ldflags without putting it in
512 # loclibpth, let's extract them
513 my @hidden = grep -d, map { /^-L(.*)$/ ? ($1) : () }
514 split ' ', $Config{ldflags};
516 # don't mark them as seen - EU::MM will remove any libraries
517 # it can't find and it doesn't look for -L in ldflags
518 #@deflib{@hidden} = @hidden;
520 push @libs, grep -d, qw(/usr/local/lib);
522 $formats{'TT-fonts'}=
526 inccheck=>sub { -e catfile($_[0], 'freetype.h')
527 && !-e catfile($_[0], 'fterrors.h') },
528 libcheck=>sub { $_[0] eq "libttf$aext" or $_[0] eq "libttf.$lext" },
531 code => \&freetype1_probe,
533 Truetype fonts are scalable fonts. They can include
534 kerning and hinting information and generally yield good
535 visual quality esp on low resultions. The freetype library is
536 used to rasterize for us. The only drawback is that there
537 are alot of badly designed fonts out there.}
540 for (keys %formats) { $formats{$_}->{docs} =~ s/^\s+/ /mg; }
547 defined($V) ? $V : "";
551 # Get information from environment variables
563 $DFLAGS) = map { gen $_ } qw(IM_VERBOSE
575 # populate the environment so that sub-modules get the same info
577 $ENV{IM_VERBOSE} = 1 if $VERBOSE;
578 $ENV{IM_INCPATH} = join $Config{path_sep}, @incpaths if @incpaths;
579 $ENV{IM_LIBPATH} = join $Config{path_sep}, @libpaths if @libpaths;
585 open CONFIG, "> imconfig.h"
586 or die "Cannot create imconfig.h: $!\n";
588 /* This file is automatically generated by Makefile.PL.
589 Don't edit this file, since any changes will be lost */
591 #ifndef IMAGER_IMCONFIG_H
592 #define IMAGER_IMCONFIG_H
594 for my $define (@$defines) {
596 print CONFIG "\n/*\n $define->[2]\n*/\n\n";
598 print CONFIG "#define $define->[0] $define->[1]\n";
600 if ($Config{gccversion} && $Config{gccversion} =~ /^([0-9]+)/ && $1 > 3) {
604 Compiler supports the GCC __attribute__((format...)) syntax.
608 #define IMAGER_FORMAT_ATTR 1
613 if ($Config{d_snprintf}) {
615 /* We can use snprintf() */
616 #define IMAGER_SNPRINTF 1
621 if ($Config{d_vsnprintf}) {
623 /* We can use vsnprintf() */
624 #define IMAGER_VSNPRINTF 1
631 Type and format code for formatted output as with printf.
633 This is intended for formatting i_img_dim values.
635 typedef $Config{ivtype} i_dim_format_t;
636 #define i_DF $Config{ivdformat}
639 print CONFIG "\n#endif\n";
643 # probes for freetype1 by scanning @incs for the includes and
644 # @libs for the libs. This is done separately because freetype's headers
645 # are stored in a freetype or freetype1 directory under PREFIX/include.
647 # we could find the files with the existing mechanism, but it won't set
648 # -I flags correctly.
650 # This could be extended to freetype2 too, but freetype-config catches
652 sub freetype1_probe {
653 my ($frm, $frmkey) = @_;
657 for my $inc (@incs) {
658 for my $subdir (qw/freetype freetype1/) {
659 my $path = File::Spec->catfile($inc, $subdir, 'freetype.h');
661 $path = File::Spec->catfile($inc, $subdir, 'fterrors.h');
664 $found_inc = File::Spec->catdir($inc, $subdir);
671 for my $lib (@libs) {
672 my $a_path = File::Spec->catfile($lib, "libttf$aext");
673 my $l_path = File::Spec->catfile($lib, "libttf.$lext");
674 if (-e $a_path || -e $l_path) {
680 return unless $found_inc && $found_lib;
681 printf("%10s: includes %s - libraries %s\n", $frmkey,
682 ($found_inc ? 'found' : 'not found'),
683 ($found_lib ? 'found' : 'not found'));
685 $frm->{cflags} = "-I$found_inc";
686 $frm->{libfiles} = "-lttf";
692 return File::Spec->catfile(@_);
697 Usage: $0 [--enable feature1,feature2,...] [other options]
698 $0 [--disable feature1,feature2,...] [other options]
700 Possible feature names are:
704 Verbose library probing (or set IM_VERBOSE in the environment)
706 Disable logging (or set IM_NOLOG in the environment)
708 Add to the include search path
710 Add to the library search path
712 Build for coverage testing.
714 Build with assertions active.
720 # generate the PM MM argument
721 # I'd prefer to modify the public version, but there doesn't seem to be
722 # a public API to do that
725 my $instbase = '$(INST_LIBDIR)';
727 # first the basics, .pm and .pod files
728 $pm{"Imager.pm"} = "$instbase/Imager.pm";
730 my $mani = maniread();
732 for my $filename (keys %$mani) {
733 if ($filename =~ m!^lib/! && $filename =~ /\.(pm|pod)$/) {
734 (my $work = $filename) =~ s/^lib//;
735 $pm{$filename} = $instbase . $work;
740 $pm{typemap} = $instbase . '/Imager/typemap';
742 # and the core headers
743 for my $filename (keys %$mani) {
744 if ($filename =~ /^\w+\.h$/) {
745 $pm{$filename} = $instbase . '/Imager/include/' . $filename;
749 # and the generated header
750 $pm{"imconfig.h"} = $instbase . '/Imager/include/imconfig.h';
759 if ($path =~ m!^~[/\\]!) {
760 defined $home or $home = $ENV{HOME};
761 if (!defined $home && $^O eq 'MSWin32'
762 && defined $ENV{HOMEDRIVE} && defined $ENV{HOMEPATH}) {
763 $home = $ENV{HOMEDRIVE} . $ENV{HOMEPATH};
765 unless (defined $home) {
766 $home = eval { (getpwuid($<))[7] };
768 defined $home or die "You supplied $path, but I can't find your home directory\n";
770 $path = File::Spec->catdir($home, $path);