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";
184 if ($ENV{AUTOMATED_TESTING}) {
185 die "OS unsupported: no threading support code for this platform\n";
190 print "No threads\n";
191 push @objs, "mutexnull.o";
194 my @typemaps = qw(typemap.local typemap);
196 unshift @typemaps, "typemap.oldperl";
199 if ($trace_context) {
200 $CFLAGS .= " -DIMAGER_TRACE_CONTEXT";
206 'VERSION_FROM' => 'Imager.pm',
207 'LIBS' => "$LFLAGS -lm $lib_lflags $OSLIBS $F_LIBS",
208 'DEFINE' => "$OSDEF $CFLAGS",
209 'INC' => "$lib_cflags $DFLAGS $F_INC",
210 'OBJECT' => join(' ', @objs, $F_OBJECT),
211 clean => { FILES=>'testout rubthru.c scale.c conv.c filters.c gaussian.c render.c rubthru.c' },
215 'Test::More' => 0.47,
216 'Scalar::Util' => 1.00,
219 TYPEMAPS => \@typemaps,
223 if ($Config{gccversion}) {
224 push @ARGV, 'OPTIMIZE=-ftest-coverage -fprofile-arcs -g';
225 $opts{dynamic_lib} = { OTHERLDFLAGS => '-ftest-coverage -fprofile-arcs' };
228 die "Don't know the coverage C flags for your compiler\n";
232 # eval to prevent warnings about versions with _ in them
233 my $MM_ver = eval $ExtUtils::MakeMaker::VERSION;
234 if ($MM_ver > 6.06) {
235 $opts{AUTHOR} = 'Tony Cook <tonyc@cpan.org>, Arnar M. Hrafnkelsson';
236 $opts{ABSTRACT} = 'Perl extension for Generating 24 bit Images';
239 if ($MM_ver >= 6.46) {
244 "Parse::RecDescent" => 0
263 homepage => "http://imager.perl.org/",
264 repository => "git://git.imager.perl.org/imager.git",
265 bugtracker => "http://rt.cpan.org/NoAuth/Bugs.html?Dist=Imager",
270 make_imconfig(\@defines);
272 if ($VERBOSE) { print Dumper(\%opts); }
273 mkdir('testout',0777); # since we cannot include it in the archive.
275 -d "probe" and rmdir "probe";
277 WriteMakefile(%opts);
281 for my $name (sort { lc $a cmp lc $b } keys %IMAGER_LIBS) {
282 if ($IMAGER_LIBS{$name}) {
291 print "Libraries found:\n" if @good;
292 print " $_\n" for @good;
293 print "Libraries *not* found:\n" if @bad;
294 print " $_\n" for @bad;
301 my $perl = $self->{PERLRUN} ? '$(PERLRUN)' : '$(PERL)';
304 my @ims = grep /\.im$/, keys %$mani;
306 dyntest.$(MYEXTLIB) : dynfilt/Makefile
307 cd dynfilt && $(MAKE) $(PASTHRU)
309 lib/Imager/Regops.pm : regmach.h regops.perl
310 $(PERL) regops.perl regmach.h lib/Imager/Regops.pm
312 imconfig.h : Makefile.PL
313 $(ECHO) "imconfig.h out-of-date with respect to $?"
314 $(PERLRUN) Makefile.PL
315 $(ECHO) "==> Your Makefile has been rebuilt - re-run your make command <=="
317 lib/Imager/APIRef.pod : \$(C_FILES) \$(H_FILES) apidocs.perl
318 $perl apidocs.perl lib/Imager/APIRef.pod
320 !.join('', map _im_rule($perl, $_), @ims)
325 my ($perl, $im) = @_;
327 (my $c = $im) =~ s/\.im$/.c/;
330 $c: $im lib/Imager/Preprocess.pm
331 $perl -Ilib -MImager::Preprocess -epreprocess $im $c
337 # manual configuration of helper libraries
342 Please answer the following questions about
343 which formats are avaliable on your computer
345 press <return> to continue
348 <STDIN>; # eat one return
350 for my $frm(sort { $formats{$b}{order} <=> $formats{$a}{order} } keys %formats) {
352 if ($formats{$frm}{docs}) { print "\n",$formats{$frm}{docs},"\n\n"; }
353 print "Enable $frm support: ";
356 if ($gz =~ m/^(y|yes|n|no)/i) {
357 $gz=substr(lc($gz),0,1);
359 delete $formats{$frm};
366 # automatic configuration of helper libraries
369 print "Automatic probing:\n" if $VERBOSE;
370 for my $frm (sort { $formats{$a}{order} <=> $formats{$b}{order} } keys %formats) {
371 delete $formats{$frm} if !checkformat($frm);
378 # print "checking path $path\n";
379 if ( !opendir(DH,$path) ) {
380 warn "Cannot open dir $path: $!\n";
383 my @l=grep { $chk->($_) } readdir(DH);
386 return map $path, @l;
390 my ($format, $frm) = @_;
392 my $lib_check=$formats{$frm}{'libcheck'};
393 my $inc_check=$formats{$frm}{'inccheck'};
398 push(@l, grep_directory($lp,$lib_check));
403 push(@i, $ip) if $inc_check->($ip,$frm);
406 printf("%10s: includes %s - libraries %s\n",$frm,(@i?'found':'not found'),(@l?'found':'not found'));
407 $formats{$frm}{incdir} = \@i;
408 $formats{$frm}{libdir} = \@l;
409 return 1 if scalar(@i && @l);
412 printf("%10s: not available\n", $frm);
421 print " checkformat($frm)\n" if $VERBOSE;
423 my $format = $formats{$frm};
426 if (my $code = $format->{'code'}) {
427 if (ref $code eq 'ARRAY') {
428 push @probes, @$code;
434 push @probes, \&_probe_default;
436 print " Calling probe function\n" if $VERBOSE;
438 for my $func (@probes) {
439 if ($func->($format, $frm)) {
447 if ($format->{postcheck}) {
448 print " Calling postcheck function\n" if $VERBOSE;
449 $format->{postcheck}->($format, $frm)
460 print " Include paths:\n";
461 for (@incs) { print $_,"\n"; }
463 @incs=grep { -d $_ && -r _ && -x _ or ( print(" $_ doesnt exist or is unaccessible - removed.\n"),0) } @incs;
466 print "\nLibrary paths:\n";
467 for (@libs) { print $_,"\n"; }
469 @libs=grep { -d $_ && -r _ && -x _ or ( print(" $_ doesnt exist or is unaccessible - removed.\n"),0) } @libs;
474 # Format data initialization
476 # format definition is:
478 # default include path
479 # files needed for include (boolean perl code)
482 # files needed for link (boolean perl code)
483 # object files needed for the format
488 my @definc = qw(/usr/include);
489 @definc{@definc}=(1) x @definc;
492 split(/\Q$Config{path_sep}/, $INCPATH),
493 map _tilde_expand($_), map { split /\Q$Config{path_sep}/ } @incpaths
495 if ($Config{locincpth}) {
496 push @incs, grep -d, split ' ', $Config{locincpth};
498 if ($^O =~ /win32/i && $Config{cc} =~ /\bcl\b/i) {
499 push(@incs, split /;/, $ENV{INCLUDE}) if exists $ENV{INCLUDE};
501 if ($Config{incpath}) {
502 push @incs, grep -d, split /\Q$Config{path_sep}/, $Config{incpath};
506 /usr/include/freetype2
507 /usr/local/include/freetype2
508 /usr/local/include/freetype1/freetype
509 /usr/include /usr/local/include /usr/include/freetype
510 /usr/local/include/freetype);
511 if ($Config{ccflags}) {
512 my @hidden = map { /^-I(.*)$/ ? ($1) : () } split ' ', $Config{ccflags};
514 @definc{@hidden} = (1) x @hidden;
517 @libs= ( split(/\Q$Config{path_sep}/,$LIBPATH),
518 map _tilde_expand($_), map { split /\Q$Config{path_sep}/} @libpaths );
519 if ($Config{loclibpth}) {
520 push @libs, grep -d, split ' ', $Config{loclibpth};
523 push @libs, grep -d, qw(/sw/lib), split(/ /, $Config{'libpth'});
524 push @libs, grep -d, split / /, $Config{libspath} if $Config{libspath};
525 if ($^O =~ /win32/i && $Config{cc} =~ /\bcl\b/i) {
526 push(@libs, split /;/, $ENV{LIB}) if exists $ENV{LIB};
528 if ($^O eq 'cygwin') {
529 push(@libs, '/usr/lib/w32api') if -d '/usr/lib/w32api';
530 push(@incs, '/usr/include/w32api') if -d '/usr/include/w32api';
532 if ($Config{ldflags}) {
533 # some builds of perl put -Ldir into ldflags without putting it in
534 # loclibpth, let's extract them
535 my @hidden = grep -d, map { /^-L(.*)$/ ? ($1) : () }
536 split ' ', $Config{ldflags};
538 # don't mark them as seen - EU::MM will remove any libraries
539 # it can't find and it doesn't look for -L in ldflags
540 #@deflib{@hidden} = @hidden;
542 push @libs, grep -d, qw(/usr/local/lib);
544 $formats{'TT-fonts'}=
548 inccheck=>sub { -e catfile($_[0], 'freetype.h')
549 && !-e catfile($_[0], 'fterrors.h') },
550 libcheck=>sub { $_[0] eq "libttf$aext" or $_[0] eq "libttf.$lext" },
552 objfiles=>'fontft1.o',
553 code => \&freetype1_probe,
555 Truetype fonts are scalable fonts. They can include
556 kerning and hinting information and generally yield good
557 visual quality esp on low resultions. The freetype library is
558 used to rasterize for us. The only drawback is that there
559 are alot of badly designed fonts out there.}
562 for (keys %formats) { $formats{$_}->{docs} =~ s/^\s+/ /mg; }
569 defined($V) ? $V : "";
573 # Get information from environment variables
585 $DFLAGS) = map { gen $_ } qw(IM_VERBOSE
597 # populate the environment so that sub-modules get the same info
599 $ENV{IM_VERBOSE} = 1 if $VERBOSE;
600 $ENV{IM_INCPATH} = join $Config{path_sep}, @incpaths if @incpaths;
601 $ENV{IM_LIBPATH} = join $Config{path_sep}, @libpaths if @libpaths;
607 open CONFIG, "> imconfig.h"
608 or die "Cannot create imconfig.h: $!\n";
610 /* This file is automatically generated by Makefile.PL.
611 Don't edit this file, since any changes will be lost */
613 #ifndef IMAGER_IMCONFIG_H
614 #define IMAGER_IMCONFIG_H
616 for my $define (@$defines) {
618 print CONFIG "\n/*\n $define->[2]\n*/\n\n";
620 print CONFIG "#define $define->[0] $define->[1]\n";
622 if ($Config{gccversion} && $Config{gccversion} =~ /^([0-9]+)/ && $1 > 3) {
626 Compiler supports the GCC __attribute__((format...)) syntax.
630 #define IMAGER_FORMAT_ATTR 1
635 if ($Config{d_snprintf}) {
637 /* We can use snprintf() */
638 #define IMAGER_SNPRINTF 1
643 if ($Config{d_vsnprintf}) {
645 /* We can use vsnprintf() */
646 #define IMAGER_VSNPRINTF 1
653 Type and format code for formatted output as with printf.
655 This is intended for formatting i_img_dim values.
657 typedef $Config{ivtype} i_dim_format_t;
658 #define i_DF $Config{ivdformat}
661 print CONFIG "\n#endif\n";
665 # probes for freetype1 by scanning @incs for the includes and
666 # @libs for the libs. This is done separately because freetype's headers
667 # are stored in a freetype or freetype1 directory under PREFIX/include.
669 # we could find the files with the existing mechanism, but it won't set
670 # -I flags correctly.
672 # This could be extended to freetype2 too, but freetype-config catches
674 sub freetype1_probe {
675 my ($frm, $frmkey) = @_;
679 for my $inc (@incs) {
680 for my $subdir (qw/freetype freetype1/) {
681 my $path = File::Spec->catfile($inc, $subdir, 'freetype.h');
683 $path = File::Spec->catfile($inc, $subdir, 'fterrors.h');
686 $found_inc = File::Spec->catdir($inc, $subdir);
693 for my $lib (@libs) {
694 my $a_path = File::Spec->catfile($lib, "libttf$aext");
695 my $l_path = File::Spec->catfile($lib, "libttf.$lext");
696 if (-e $a_path || -e $l_path) {
702 return unless $found_inc && $found_lib;
703 printf("%10s: includes %s - libraries %s\n", $frmkey,
704 ($found_inc ? 'found' : 'not found'),
705 ($found_lib ? 'found' : 'not found'));
707 $frm->{cflags} = "-I$found_inc";
708 $frm->{libfiles} = "-lttf";
714 return File::Spec->catfile(@_);
719 Usage: $0 [--enable feature1,feature2,...] [other options]
720 $0 [--disable feature1,feature2,...] [other options]
722 Possible feature names are:
726 Verbose library probing (or set IM_VERBOSE in the environment)
728 Disable logging (or set IM_NOLOG in the environment)
730 Add to the include search path
732 Add to the library search path
734 Build for coverage testing.
736 Build with assertions active.
742 # generate the PM MM argument
743 # I'd prefer to modify the public version, but there doesn't seem to be
744 # a public API to do that
747 my $instbase = '$(INST_LIBDIR)';
749 # first the basics, .pm and .pod files
750 $pm{"Imager.pm"} = "$instbase/Imager.pm";
752 my $mani = maniread();
754 for my $filename (keys %$mani) {
755 if ($filename =~ m!^lib/! && $filename =~ /\.(pm|pod)$/) {
756 (my $work = $filename) =~ s/^lib//;
757 $pm{$filename} = $instbase . $work;
762 $pm{typemap} = $instbase . '/Imager/typemap';
764 # and the core headers
765 for my $filename (keys %$mani) {
766 if ($filename =~ /^\w+\.h$/) {
767 $pm{$filename} = $instbase . '/Imager/include/' . $filename;
771 # and the generated header
772 $pm{"imconfig.h"} = $instbase . '/Imager/include/imconfig.h';
781 if ($path =~ m!^~[/\\]!) {
782 defined $home or $home = $ENV{HOME};
783 if (!defined $home && $^O eq 'MSWin32'
784 && defined $ENV{HOMEDRIVE} && defined $ENV{HOMEPATH}) {
785 $home = $ENV{HOMEDRIVE} . $ENV{HOMEPATH};
787 unless (defined $home) {
788 $home = eval { (getpwuid($<))[7] };
790 defined $home or die "You supplied $path, but I can't find your home directory\n";
792 $path = File::Spec->catdir($home, $path);