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 # make sure --verbose will dump environment settings
40 if (grep $_ =~ /^--?v(?:erbose)?$/, @ARGV) {
44 getenv(); # get environment variables
46 my $lext=$Config{'so'}; # Get extensions of libraries
47 my $aext=$Config{'_a'};
49 my $help; # display help if set
50 my @enable; # list of drivers to enable
51 my @disable; # or list of drivers to disable
52 my @incpaths; # places to look for headers
53 my @libpaths; # places to look for libraries
54 my $coverage; # build for coverage testing
55 my $assert; # build with assertions
56 my $trace_context; # trace context management to stderr
57 GetOptions("help" => \$help,
58 "enable=s" => \@enable,
59 "disable=s" => \@disable,
60 "incpath=s", \@incpaths,
61 "libpath=s" => \@libpaths,
62 "verbose|v" => \$VERBOSE,
64 'coverage' => \$coverage,
65 "assert|a" => \$assert,
66 "tracecontext" => \$trace_context);
70 if ($ENV{AUTOMATED_TESTING}) {
75 print "Verbose mode\n";
77 import Data::Dumper qw(Dumper);
86 if ($NOLOG) { print "Logging not compiled into module\n"; }
88 push @defines, [ IMAGER_LOG => 1, "Logging system" ];
92 push @defines, [ IM_ASSERT => 1, "im_assert() are effective" ];
96 push @defines, [ IMAGER_DEBUG_MALLOC => 1, "Use Imager's DEBUG malloc()" ];
97 print "Malloc debugging enabled\n";
100 if (@enable && @disable) {
101 print STDERR "Only --enable or --disable can be used, not both, try --help\n";
107 my @incs; # all the places to look for headers
108 my @libs; # all the places to look for libraries
110 init(); # initialize global data
111 pathcheck(); # Check if directories exist
113 if (exists $ENV{IM_ENABLE}) {
114 my %en = map { $_, 1 } split ' ', $ENV{IM_ENABLE};
115 for my $key (keys %formats) {
116 delete $formats{$key} unless $en{$key};
120 my %en = map { $_ => 1 } map { split /,/ } @enable;
121 for my $key (keys %formats) {
122 delete $formats{$key} unless $en{$key};
126 delete @formats{map { split /,/ } @disable};
129 # Pick what libraries are used
140 for my $frmkey (sort { $formats{$a}{order} <=> $formats{$b}{order} } keys %formats) {
141 my $frm = $formats{$frmkey};
142 push @defines, [ $frm->{def}, 1, "$frmkey available" ];
143 $F_OBJECT .= ' ' .$frm->{objfiles};
144 if ($frm->{cflags}) {
145 $lib_cflags .= ' ' .$frm->{cflags};
146 ++$definc{$_} for map { /^-I(.*)$/ ? ($1) : () }
147 grep /^-I./, split ' ', $frm->{cflags};
149 if ($frm->{lflags}) {
150 $lib_lflags .= ' ' . $frm->{lflags};
153 $F_LIBS .= ' ' .$frm->{libfiles};
158 my $F_INC = join ' ', map "-I$_", map / / ? qq{"$_"} : $_,
159 grep !$definc{$_}, @incs;
160 $F_LIBS = join(' ',map "-L$_", map / / ? qq{"$_"} : $_,
161 grep !$deflib{$_}++, @libs) . $F_LIBS;
164 my $OSDEF = "-DOS_$^O";
166 if ($^O eq 'hpux') { $OSLIBS .= ' -ldld'; }
167 if (defined $Config{'d_dlsymun'}) { $OSDEF .= ' -DDLSYMUN'; }
169 my @objs = qw(Imager.o context.o draw.o polygon.o image.o io.o iolayer.o
170 log.o gaussian.o conv.o pnm.o raw.o feat.o combine.o
171 filters.o dynaload.o stackmach.o datatypes.o
172 regmach.o trans2.o quant.o error.o convert.o
173 map.o tags.o palimg.o maskimg.o img8.o img16.o rotate.o
174 bmp.o tga.o color.o fills.o imgdouble.o limits.o hlines.o
175 imext.o scale.o rubthru.o render.o paste.o compose.o flip.o
178 if ($Config{useithreads}) {
179 if ($Config{i_pthread}) {
180 print "POSIX threads\n";
181 push @objs, "mutexpthr.o";
183 elsif ($^O eq 'MSWin32') {
184 print "Win32 threads\n";
185 push @objs, "mutexwin.o";
188 print "Unsupported threading model\n";
189 push @objs, "mutexnull.o";
190 if ($ENV{AUTOMATED_TESTING}) {
191 die "OS unsupported: no threading support code for this platform\n";
196 print "No threads\n";
197 push @objs, "mutexnull.o";
200 my @typemaps = qw(typemap.local typemap);
202 unshift @typemaps, "typemap.oldperl";
205 if ($trace_context) {
206 $CFLAGS .= " -DIMAGER_TRACE_CONTEXT";
209 my $tests = 't/*.t t/*/*.t';
210 if (-d "xt" && scalar(() = glob("xt/*.t"))) {
217 'VERSION_FROM' => 'Imager.pm',
218 'LIBS' => "$LFLAGS -lm $lib_lflags $OSLIBS $F_LIBS",
219 'DEFINE' => "$OSDEF $CFLAGS",
220 'INC' => "$lib_cflags $DFLAGS $F_INC",
221 'OBJECT' => join(' ', @objs, $F_OBJECT),
222 clean => { FILES=>'testout rubthru.c scale.c conv.c filters.c gaussian.c render.c rubthru.c' },
226 'Test::More' => 0.47,
227 'Scalar::Util' => 1.00,
230 TYPEMAPS => \@typemaps,
231 test => { TESTS => $tests },
235 if ($Config{gccversion}) {
236 push @ARGV, 'OPTIMIZE=-ftest-coverage -fprofile-arcs -g';
237 $opts{dynamic_lib} = { OTHERLDFLAGS => '-ftest-coverage -fprofile-arcs' };
240 die "Don't know the coverage C flags for your compiler\n";
244 # eval to prevent warnings about versions with _ in them
245 my $MM_ver = eval $ExtUtils::MakeMaker::VERSION;
246 if ($MM_ver > 6.06) {
247 $opts{AUTHOR} = 'Tony Cook <tonyc@cpan.org>, Arnar M. Hrafnkelsson';
248 $opts{ABSTRACT} = 'Perl extension for Generating 24 bit Images';
251 if ($MM_ver >= 6.46) {
256 "Parse::RecDescent" => 0
275 homepage => "http://imager.perl.org/",
276 repository => "git://git.imager.perl.org/imager.git",
277 bugtracker => "http://rt.cpan.org/NoAuth/Bugs.html?Dist=Imager",
282 make_imconfig(\@defines);
284 if ($VERBOSE) { print Dumper(\%opts); }
285 mkdir('testout',0777); # since we cannot include it in the archive.
287 -d "probe" and rmdir "probe";
289 WriteMakefile(%opts);
293 for my $name (sort { lc $a cmp lc $b } keys %IMAGER_LIBS) {
294 if ($IMAGER_LIBS{$name}) {
303 print "Libraries found:\n" if @good;
304 print " $_\n" for @good;
305 print "Libraries *not* found:\n" if @bad;
306 print " $_\n" for @bad;
313 my $perl = $self->{PERLRUN} ? '$(PERLRUN)' : '$(PERL)';
316 my @ims = grep /\.im$/, keys %$mani;
318 dyntest.$(MYEXTLIB) : dynfilt/Makefile
319 cd dynfilt && $(MAKE) $(PASTHRU)
321 lib/Imager/Regops.pm : regmach.h regops.perl
322 $(PERL) regops.perl regmach.h lib/Imager/Regops.pm
324 imconfig.h : Makefile.PL
325 $(ECHO) "imconfig.h out-of-date with respect to $?"
326 $(PERLRUN) Makefile.PL
327 $(ECHO) "==> Your Makefile has been rebuilt - re-run your make command <=="
329 lib/Imager/APIRef.pod : \$(C_FILES) \$(H_FILES) apidocs.perl
330 $perl apidocs.perl lib/Imager/APIRef.pod
332 !.join('', map _im_rule($perl, $_), @ims)
337 my ($perl, $im) = @_;
339 (my $c = $im) =~ s/\.im$/.c/;
342 $c: $im lib/Imager/Preprocess.pm
343 $perl -Ilib -MImager::Preprocess -epreprocess $im $c
349 # manual configuration of helper libraries
354 Please answer the following questions about
355 which formats are avaliable on your computer
357 press <return> to continue
360 <STDIN>; # eat one return
362 for my $frm(sort { $formats{$b}{order} <=> $formats{$a}{order} } keys %formats) {
364 if ($formats{$frm}{docs}) { print "\n",$formats{$frm}{docs},"\n\n"; }
365 print "Enable $frm support: ";
368 if ($gz =~ m/^(y|yes|n|no)/i) {
369 $gz=substr(lc($gz),0,1);
371 delete $formats{$frm};
378 # automatic configuration of helper libraries
381 print "Automatic probing:\n" if $VERBOSE;
382 for my $frm (sort { $formats{$a}{order} <=> $formats{$b}{order} } keys %formats) {
383 delete $formats{$frm} if !checkformat($frm);
390 # print "checking path $path\n";
391 if ( !opendir(DH,$path) ) {
392 warn "Cannot open dir $path: $!\n";
395 my @l=grep { $chk->($_) } readdir(DH);
398 return map $path, @l;
402 my ($format, $frm) = @_;
404 my $lib_check=$formats{$frm}{'libcheck'};
405 my $inc_check=$formats{$frm}{'inccheck'};
410 push(@l, grep_directory($lp,$lib_check));
415 push(@i, $ip) if $inc_check->($ip,$frm);
418 printf("%10s: includes %s - libraries %s\n",$frm,(@i?'found':'not found'),(@l?'found':'not found'));
419 $formats{$frm}{incdir} = \@i;
420 $formats{$frm}{libdir} = \@l;
421 return 1 if scalar(@i && @l);
424 printf("%10s: not available\n", $frm);
433 print " checkformat($frm)\n" if $VERBOSE;
435 my $format = $formats{$frm};
438 if (my $code = $format->{'code'}) {
439 if (ref $code eq 'ARRAY') {
440 push @probes, @$code;
446 push @probes, \&_probe_default;
448 print " Calling probe function\n" if $VERBOSE;
450 for my $func (@probes) {
451 if ($func->($format, $frm)) {
459 if ($format->{postcheck}) {
460 print " Calling postcheck function\n" if $VERBOSE;
461 $format->{postcheck}->($format, $frm)
472 print " Include paths:\n";
473 for (@incs) { print $_,"\n"; }
475 @incs=grep { -d $_ && -r _ && -x _ or ( print(" $_ doesnt exist or is unaccessible - removed.\n"),0) } @incs;
478 print "\nLibrary paths:\n";
479 for (@libs) { print $_,"\n"; }
481 @libs=grep { -d $_ && -r _ && -x _ or ( print(" $_ doesnt exist or is unaccessible - removed.\n"),0) } @libs;
486 # Format data initialization
488 # format definition is:
490 # default include path
491 # files needed for include (boolean perl code)
494 # files needed for link (boolean perl code)
495 # object files needed for the format
500 my @definc = qw(/usr/include);
501 @definc{@definc}=(1) x @definc;
504 split(/\Q$Config{path_sep}/, $INCPATH),
505 map _tilde_expand($_), map { split /\Q$Config{path_sep}/ } @incpaths
507 if ($Config{locincpth}) {
508 push @incs, grep -d, split ' ', $Config{locincpth};
510 if ($^O =~ /win32/i && $Config{cc} =~ /\bcl\b/i) {
511 push(@incs, split /;/, $ENV{INCLUDE}) if exists $ENV{INCLUDE};
513 if ($Config{incpath}) {
514 push @incs, grep -d, split /\Q$Config{path_sep}/, $Config{incpath};
518 /usr/include/freetype2
519 /usr/local/include/freetype2
520 /usr/local/include/freetype1/freetype
521 /usr/include /usr/local/include /usr/include/freetype
522 /usr/local/include/freetype);
523 if ($Config{ccflags}) {
524 my @hidden = map { /^-I(.*)$/ ? ($1) : () } split ' ', $Config{ccflags};
526 @definc{@hidden} = (1) x @hidden;
529 @libs= ( split(/\Q$Config{path_sep}/,$LIBPATH),
530 map _tilde_expand($_), map { split /\Q$Config{path_sep}/} @libpaths );
531 if ($Config{loclibpth}) {
532 push @libs, grep -d, split ' ', $Config{loclibpth};
535 push @libs, grep -d, qw(/sw/lib), split(/ /, $Config{'libpth'});
536 push @libs, grep -d, split / /, $Config{libspath} if $Config{libspath};
537 if ($^O =~ /win32/i && $Config{cc} =~ /\bcl\b/i) {
538 push(@libs, split /;/, $ENV{LIB}) if exists $ENV{LIB};
540 if ($^O eq 'cygwin') {
541 push(@libs, '/usr/lib/w32api') if -d '/usr/lib/w32api';
542 push(@incs, '/usr/include/w32api') if -d '/usr/include/w32api';
544 if ($Config{ldflags}) {
545 # some builds of perl put -Ldir into ldflags without putting it in
546 # loclibpth, let's extract them
547 my @hidden = grep -d, map { /^-L(.*)$/ ? ($1) : () }
548 split ' ', $Config{ldflags};
550 # don't mark them as seen - EU::MM will remove any libraries
551 # it can't find and it doesn't look for -L in ldflags
552 #@deflib{@hidden} = @hidden;
554 push @libs, grep -d, qw(/usr/local/lib);
556 $formats{'TT-fonts'}=
560 inccheck=>sub { -e catfile($_[0], 'freetype.h')
561 && !-e catfile($_[0], 'fterrors.h') },
562 libcheck=>sub { $_[0] eq "libttf$aext" or $_[0] eq "libttf.$lext" },
564 objfiles=>'fontft1.o',
565 code => \&freetype1_probe,
567 Truetype fonts are scalable fonts. They can include
568 kerning and hinting information and generally yield good
569 visual quality esp on low resultions. The freetype library is
570 used to rasterize for us. The only drawback is that there
571 are alot of badly designed fonts out there.
573 This driver uses Freetype 1.x which is obsolete}
576 for (keys %formats) { $formats{$_}->{docs} =~ s/^\s+/ /mg; }
583 print " $_[0]: '$V'\n"
584 if $VERBOSE && defined $V;
585 defined($V) ? $V : "";
589 # Get information from environment variables
593 $VERBOSE ||= gen("IM_VERBOSE");
595 print "Environment config:\n" if $VERBOSE;
604 $DFLAGS) = map { gen $_ } qw(IM_INCPATH
614 # populate the environment so that sub-modules get the same info
616 $ENV{IM_VERBOSE} = 1 if $VERBOSE;
617 $ENV{IM_INCPATH} = join $Config{path_sep}, @incpaths if @incpaths;
618 $ENV{IM_LIBPATH} = join $Config{path_sep}, @libpaths if @libpaths;
624 open CONFIG, "> imconfig.h"
625 or die "Cannot create imconfig.h: $!\n";
627 /* This file is automatically generated by Makefile.PL.
628 Don't edit this file, since any changes will be lost */
630 #ifndef IMAGER_IMCONFIG_H
631 #define IMAGER_IMCONFIG_H
633 for my $define (@$defines) {
635 print CONFIG "\n/*\n $define->[2]\n*/\n\n";
637 print CONFIG "#define $define->[0] $define->[1]\n";
639 if ($Config{gccversion} && $Config{gccversion} =~ /^([0-9]+)/ && $1 > 3) {
643 Compiler supports the GCC __attribute__((format...)) syntax.
647 #define IMAGER_FORMAT_ATTR 1
652 if ($Config{d_snprintf}) {
654 /* We can use snprintf() */
655 #define IMAGER_SNPRINTF 1
660 if ($Config{d_vsnprintf}) {
662 /* We can use vsnprintf() */
663 #define IMAGER_VSNPRINTF 1
670 Type and format code for formatted output as with printf.
672 This is intended for formatting i_img_dim values.
674 typedef $Config{ivtype} i_dim_format_t;
675 #define i_DF $Config{ivdformat}
678 print CONFIG "\n#endif\n";
682 # probes for freetype1 by scanning @incs for the includes and
683 # @libs for the libs. This is done separately because freetype's headers
684 # are stored in a freetype or freetype1 directory under PREFIX/include.
686 # we could find the files with the existing mechanism, but it won't set
687 # -I flags correctly.
689 # This could be extended to freetype2 too, but freetype-config catches
691 sub freetype1_probe {
692 my ($frm, $frmkey) = @_;
696 for my $inc (@incs) {
697 for my $subdir (qw/freetype freetype1/) {
698 print "TT: include check ", File::Spec->catdir($inc, $subdir), "\n"
700 my $path = File::Spec->catfile($inc, $subdir, 'freetype.h');
702 $path = File::Spec->catfile($inc, $subdir, 'fterrors.h');
708 $found_inc = File::Spec->catdir($inc, $subdir);
715 for my $lib (@libs) {
716 my $a_path = File::Spec->catfile($lib, "libttf$aext");
717 my $l_path = File::Spec->catfile($lib, "libttf.$lext");
718 print "TT: lib check $lib\n"
720 if (-e $a_path || -e $l_path) {
728 return unless $found_inc && $found_lib;
729 printf("%10s: includes %s - libraries %s\n", $frmkey,
730 ($found_inc ? 'found' : 'not found'),
731 ($found_lib ? 'found' : 'not found'));
733 $frm->{cflags} = "-I$found_inc";
734 $frm->{libfiles} = "-lttf";
740 return File::Spec->catfile(@_);
745 Usage: $0 [--enable feature1,feature2,...] [other options]
746 $0 [--disable feature1,feature2,...] [other options]
748 Possible feature names are:
752 Verbose library probing (or set IM_VERBOSE in the environment)
754 Disable logging (or set IM_NOLOG in the environment)
756 Add to the include search path
758 Add to the library search path
760 Build for coverage testing.
762 Build with assertions active.
768 # generate the PM MM argument
769 # I'd prefer to modify the public version, but there doesn't seem to be
770 # a public API to do that
773 my $instbase = '$(INST_LIBDIR)';
775 # first the basics, .pm and .pod files
776 $pm{"Imager.pm"} = "$instbase/Imager.pm";
778 my $mani = maniread();
780 for my $filename (keys %$mani) {
781 if ($filename =~ m!^lib/! && $filename =~ /\.(pm|pod)$/) {
782 (my $work = $filename) =~ s/^lib//;
783 $pm{$filename} = $instbase . $work;
788 $pm{typemap} = $instbase . '/Imager/typemap';
790 # and the core headers
791 for my $filename (keys %$mani) {
792 if ($filename =~ /^\w+\.h$/) {
793 $pm{$filename} = $instbase . '/Imager/include/' . $filename;
797 # and the generated header
798 $pm{"imconfig.h"} = $instbase . '/Imager/include/imconfig.h';
807 if ($path =~ m!^~[/\\]!) {
808 defined $home or $home = $ENV{HOME};
809 if (!defined $home && $^O eq 'MSWin32'
810 && defined $ENV{HOMEDRIVE} && defined $ENV{HOMEPATH}) {
811 $home = $ENV{HOMEDRIVE} . $ENV{HOMEPATH};
813 unless (defined $home) {
814 $home = eval { (getpwuid($<))[7] };
816 defined $home or die "You supplied $path, but I can't find your home directory\n";
818 $path = File::Spec->catdir($home, $path);