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
173 if ($Config{useithreads}) {
174 if ($Config{i_pthread}) {
175 print "POSIX threads\n";
176 push @objs, "mutexpthr.o";
178 elsif ($^O eq 'MSWin32') {
179 print "Win32 threads\n";
180 push @objs, "mutexwin.o";
183 print "Unsupported threading model\n";
184 push @objs, "mutexnull.o";
185 if ($ENV{AUTOMATED_TESTING}) {
186 die "OS unsupported: no threading support code for this platform\n";
191 print "No threads\n";
192 push @objs, "mutexnull.o";
195 my @typemaps = qw(typemap.local typemap);
197 unshift @typemaps, "typemap.oldperl";
200 if ($trace_context) {
201 $CFLAGS .= " -DIMAGER_TRACE_CONTEXT";
204 my $tests = 't/*.t t/*/*.t';
205 if (-d "xt" && scalar(() = glob("xt/*.t"))) {
212 'VERSION_FROM' => 'Imager.pm',
213 'LIBS' => "$LFLAGS -lm $lib_lflags $OSLIBS $F_LIBS",
214 'DEFINE' => "$OSDEF $CFLAGS",
215 'INC' => "$lib_cflags $DFLAGS $F_INC",
216 'OBJECT' => join(' ', @objs, $F_OBJECT),
217 clean => { FILES=>'testout rubthru.c scale.c conv.c filters.c gaussian.c render.c rubthru.c' },
221 'Test::More' => 0.47,
222 'Scalar::Util' => 1.00,
225 TYPEMAPS => \@typemaps,
226 test => { TESTS => $tests },
230 if ($Config{gccversion}) {
231 push @ARGV, 'OPTIMIZE=-ftest-coverage -fprofile-arcs -g';
232 $opts{dynamic_lib} = { OTHERLDFLAGS => '-ftest-coverage -fprofile-arcs' };
235 die "Don't know the coverage C flags for your compiler\n";
239 # eval to prevent warnings about versions with _ in them
240 my $MM_ver = eval $ExtUtils::MakeMaker::VERSION;
241 if ($MM_ver > 6.06) {
242 $opts{AUTHOR} = 'Tony Cook <tonyc@cpan.org>, Arnar M. Hrafnkelsson';
243 $opts{ABSTRACT} = 'Perl extension for Generating 24 bit Images';
246 if ($MM_ver >= 6.46) {
251 "Parse::RecDescent" => 0
270 homepage => "http://imager.perl.org/",
271 repository => "git://git.imager.perl.org/imager.git",
272 bugtracker => "http://rt.cpan.org/NoAuth/Bugs.html?Dist=Imager",
277 make_imconfig(\@defines);
279 if ($VERBOSE) { print Dumper(\%opts); }
280 mkdir('testout',0777); # since we cannot include it in the archive.
282 -d "probe" and rmdir "probe";
284 WriteMakefile(%opts);
288 for my $name (sort { lc $a cmp lc $b } keys %IMAGER_LIBS) {
289 if ($IMAGER_LIBS{$name}) {
298 print "Libraries found:\n" if @good;
299 print " $_\n" for @good;
300 print "Libraries *not* found:\n" if @bad;
301 print " $_\n" for @bad;
308 my $perl = $self->{PERLRUN} ? '$(PERLRUN)' : '$(PERL)';
311 my @ims = grep /\.im$/, keys %$mani;
313 dyntest.$(MYEXTLIB) : dynfilt/Makefile
314 cd dynfilt && $(MAKE) $(PASTHRU)
316 lib/Imager/Regops.pm : regmach.h regops.perl
317 $(PERL) regops.perl regmach.h lib/Imager/Regops.pm
319 imconfig.h : Makefile.PL
320 $(ECHO) "imconfig.h out-of-date with respect to $?"
321 $(PERLRUN) Makefile.PL
322 $(ECHO) "==> Your Makefile has been rebuilt - re-run your make command <=="
324 lib/Imager/APIRef.pod : \$(C_FILES) \$(H_FILES) apidocs.perl
325 $perl apidocs.perl lib/Imager/APIRef.pod
327 !.join('', map _im_rule($perl, $_), @ims)
332 my ($perl, $im) = @_;
334 (my $c = $im) =~ s/\.im$/.c/;
337 $c: $im lib/Imager/Preprocess.pm
338 $perl -Ilib -MImager::Preprocess -epreprocess $im $c
344 # manual configuration of helper libraries
349 Please answer the following questions about
350 which formats are avaliable on your computer
352 press <return> to continue
355 <STDIN>; # eat one return
357 for my $frm(sort { $formats{$b}{order} <=> $formats{$a}{order} } keys %formats) {
359 if ($formats{$frm}{docs}) { print "\n",$formats{$frm}{docs},"\n\n"; }
360 print "Enable $frm support: ";
363 if ($gz =~ m/^(y|yes|n|no)/i) {
364 $gz=substr(lc($gz),0,1);
366 delete $formats{$frm};
373 # automatic configuration of helper libraries
376 print "Automatic probing:\n" if $VERBOSE;
377 for my $frm (sort { $formats{$a}{order} <=> $formats{$b}{order} } keys %formats) {
378 delete $formats{$frm} if !checkformat($frm);
385 # print "checking path $path\n";
386 if ( !opendir(DH,$path) ) {
387 warn "Cannot open dir $path: $!\n";
390 my @l=grep { $chk->($_) } readdir(DH);
393 return map $path, @l;
397 my ($format, $frm) = @_;
399 my $lib_check=$formats{$frm}{'libcheck'};
400 my $inc_check=$formats{$frm}{'inccheck'};
405 push(@l, grep_directory($lp,$lib_check));
410 push(@i, $ip) if $inc_check->($ip,$frm);
413 printf("%10s: includes %s - libraries %s\n",$frm,(@i?'found':'not found'),(@l?'found':'not found'));
414 $formats{$frm}{incdir} = \@i;
415 $formats{$frm}{libdir} = \@l;
416 return 1 if scalar(@i && @l);
419 printf("%10s: not available\n", $frm);
428 print " checkformat($frm)\n" if $VERBOSE;
430 my $format = $formats{$frm};
433 if (my $code = $format->{'code'}) {
434 if (ref $code eq 'ARRAY') {
435 push @probes, @$code;
441 push @probes, \&_probe_default;
443 print " Calling probe function\n" if $VERBOSE;
445 for my $func (@probes) {
446 if ($func->($format, $frm)) {
454 if ($format->{postcheck}) {
455 print " Calling postcheck function\n" if $VERBOSE;
456 $format->{postcheck}->($format, $frm)
467 print " Include paths:\n";
468 for (@incs) { print $_,"\n"; }
470 @incs=grep { -d $_ && -r _ && -x _ or ( print(" $_ doesnt exist or is unaccessible - removed.\n"),0) } @incs;
473 print "\nLibrary paths:\n";
474 for (@libs) { print $_,"\n"; }
476 @libs=grep { -d $_ && -r _ && -x _ or ( print(" $_ doesnt exist or is unaccessible - removed.\n"),0) } @libs;
481 # Format data initialization
483 # format definition is:
485 # default include path
486 # files needed for include (boolean perl code)
489 # files needed for link (boolean perl code)
490 # object files needed for the format
495 my @definc = qw(/usr/include);
496 @definc{@definc}=(1) x @definc;
499 split(/\Q$Config{path_sep}/, $INCPATH),
500 map _tilde_expand($_), map { split /\Q$Config{path_sep}/ } @incpaths
502 if ($Config{locincpth}) {
503 push @incs, grep -d, split ' ', $Config{locincpth};
505 if ($^O =~ /win32/i && $Config{cc} =~ /\bcl\b/i) {
506 push(@incs, split /;/, $ENV{INCLUDE}) if exists $ENV{INCLUDE};
508 if ($Config{incpath}) {
509 push @incs, grep -d, split /\Q$Config{path_sep}/, $Config{incpath};
513 /usr/include/freetype2
514 /usr/local/include/freetype2
515 /usr/local/include/freetype1/freetype
516 /usr/include /usr/local/include /usr/include/freetype
517 /usr/local/include/freetype);
518 if ($Config{ccflags}) {
519 my @hidden = map { /^-I(.*)$/ ? ($1) : () } split ' ', $Config{ccflags};
521 @definc{@hidden} = (1) x @hidden;
524 @libs= ( split(/\Q$Config{path_sep}/,$LIBPATH),
525 map _tilde_expand($_), map { split /\Q$Config{path_sep}/} @libpaths );
526 if ($Config{loclibpth}) {
527 push @libs, grep -d, split ' ', $Config{loclibpth};
530 push @libs, grep -d, qw(/sw/lib), split(/ /, $Config{'libpth'});
531 push @libs, grep -d, split / /, $Config{libspath} if $Config{libspath};
532 if ($^O =~ /win32/i && $Config{cc} =~ /\bcl\b/i) {
533 push(@libs, split /;/, $ENV{LIB}) if exists $ENV{LIB};
535 if ($^O eq 'cygwin') {
536 push(@libs, '/usr/lib/w32api') if -d '/usr/lib/w32api';
537 push(@incs, '/usr/include/w32api') if -d '/usr/include/w32api';
539 if ($Config{ldflags}) {
540 # some builds of perl put -Ldir into ldflags without putting it in
541 # loclibpth, let's extract them
542 my @hidden = grep -d, map { /^-L(.*)$/ ? ($1) : () }
543 split ' ', $Config{ldflags};
545 # don't mark them as seen - EU::MM will remove any libraries
546 # it can't find and it doesn't look for -L in ldflags
547 #@deflib{@hidden} = @hidden;
549 push @libs, grep -d, qw(/usr/local/lib);
551 $formats{'TT-fonts'}=
555 inccheck=>sub { -e catfile($_[0], 'freetype.h')
556 && !-e catfile($_[0], 'fterrors.h') },
557 libcheck=>sub { $_[0] eq "libttf$aext" or $_[0] eq "libttf.$lext" },
559 objfiles=>'fontft1.o',
560 code => \&freetype1_probe,
562 Truetype fonts are scalable fonts. They can include
563 kerning and hinting information and generally yield good
564 visual quality esp on low resultions. The freetype library is
565 used to rasterize for us. The only drawback is that there
566 are alot of badly designed fonts out there.}
569 for (keys %formats) { $formats{$_}->{docs} =~ s/^\s+/ /mg; }
576 defined($V) ? $V : "";
580 # Get information from environment variables
592 $DFLAGS) = map { gen $_ } qw(IM_VERBOSE
604 # populate the environment so that sub-modules get the same info
606 $ENV{IM_VERBOSE} = 1 if $VERBOSE;
607 $ENV{IM_INCPATH} = join $Config{path_sep}, @incpaths if @incpaths;
608 $ENV{IM_LIBPATH} = join $Config{path_sep}, @libpaths if @libpaths;
614 open CONFIG, "> imconfig.h"
615 or die "Cannot create imconfig.h: $!\n";
617 /* This file is automatically generated by Makefile.PL.
618 Don't edit this file, since any changes will be lost */
620 #ifndef IMAGER_IMCONFIG_H
621 #define IMAGER_IMCONFIG_H
623 for my $define (@$defines) {
625 print CONFIG "\n/*\n $define->[2]\n*/\n\n";
627 print CONFIG "#define $define->[0] $define->[1]\n";
629 if ($Config{gccversion} && $Config{gccversion} =~ /^([0-9]+)/ && $1 > 3) {
633 Compiler supports the GCC __attribute__((format...)) syntax.
637 #define IMAGER_FORMAT_ATTR 1
642 if ($Config{d_snprintf}) {
644 /* We can use snprintf() */
645 #define IMAGER_SNPRINTF 1
650 if ($Config{d_vsnprintf}) {
652 /* We can use vsnprintf() */
653 #define IMAGER_VSNPRINTF 1
660 Type and format code for formatted output as with printf.
662 This is intended for formatting i_img_dim values.
664 typedef $Config{ivtype} i_dim_format_t;
665 #define i_DF $Config{ivdformat}
668 print CONFIG "\n#endif\n";
672 # probes for freetype1 by scanning @incs for the includes and
673 # @libs for the libs. This is done separately because freetype's headers
674 # are stored in a freetype or freetype1 directory under PREFIX/include.
676 # we could find the files with the existing mechanism, but it won't set
677 # -I flags correctly.
679 # This could be extended to freetype2 too, but freetype-config catches
681 sub freetype1_probe {
682 my ($frm, $frmkey) = @_;
686 for my $inc (@incs) {
687 for my $subdir (qw/freetype freetype1/) {
688 my $path = File::Spec->catfile($inc, $subdir, 'freetype.h');
690 $path = File::Spec->catfile($inc, $subdir, 'fterrors.h');
693 $found_inc = File::Spec->catdir($inc, $subdir);
700 for my $lib (@libs) {
701 my $a_path = File::Spec->catfile($lib, "libttf$aext");
702 my $l_path = File::Spec->catfile($lib, "libttf.$lext");
703 if (-e $a_path || -e $l_path) {
709 return unless $found_inc && $found_lib;
710 printf("%10s: includes %s - libraries %s\n", $frmkey,
711 ($found_inc ? 'found' : 'not found'),
712 ($found_lib ? 'found' : 'not found'));
714 $frm->{cflags} = "-I$found_inc";
715 $frm->{libfiles} = "-lttf";
721 return File::Spec->catfile(@_);
726 Usage: $0 [--enable feature1,feature2,...] [other options]
727 $0 [--disable feature1,feature2,...] [other options]
729 Possible feature names are:
733 Verbose library probing (or set IM_VERBOSE in the environment)
735 Disable logging (or set IM_NOLOG in the environment)
737 Add to the include search path
739 Add to the library search path
741 Build for coverage testing.
743 Build with assertions active.
749 # generate the PM MM argument
750 # I'd prefer to modify the public version, but there doesn't seem to be
751 # a public API to do that
754 my $instbase = '$(INST_LIBDIR)';
756 # first the basics, .pm and .pod files
757 $pm{"Imager.pm"} = "$instbase/Imager.pm";
759 my $mani = maniread();
761 for my $filename (keys %$mani) {
762 if ($filename =~ m!^lib/! && $filename =~ /\.(pm|pod)$/) {
763 (my $work = $filename) =~ s/^lib//;
764 $pm{$filename} = $instbase . $work;
769 $pm{typemap} = $instbase . '/Imager/typemap';
771 # and the core headers
772 for my $filename (keys %$mani) {
773 if ($filename =~ /^\w+\.h$/) {
774 $pm{$filename} = $instbase . '/Imager/include/' . $filename;
778 # and the generated header
779 $pm{"imconfig.h"} = $instbase . '/Imager/include/imconfig.h';
788 if ($path =~ m!^~[/\\]!) {
789 defined $home or $home = $ENV{HOME};
790 if (!defined $home && $^O eq 'MSWin32'
791 && defined $ENV{HOMEDRIVE} && defined $ENV{HOMEPATH}) {
792 $home = $ENV{HOMEDRIVE} . $ENV{HOMEPATH};
794 unless (defined $home) {
795 $home = eval { (getpwuid($<))[7] };
797 defined $home or die "You supplied $path, but I can't find your home directory\n";
799 $path = File::Spec->catdir($home, $path);