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 # modules/features bundled with Imager that can be enabled/disabled
45 # withs --enable/--disable
46 my @bundled = qw(FT1 FT2 GIF JPEG PNG T1 TIFF W32);
48 # extra modules bundled with Imager not available on CPAN
49 my @extras = qw(CountColor DynTest ICO SGI Mandelbrot Flines);
51 # alternate names for modules
52 my %bundled_names = qw(win32 w32 tt ft1);
54 getenv(); # get environment variables
56 my $lext=$Config{'so'}; # Get extensions of libraries
57 my $aext=$Config{'_a'};
59 my $help; # display help if set
60 my @enable; # list of drivers to enable
61 my @disable; # or list of drivers to disable
62 my @incpaths; # places to look for headers
63 my @libpaths; # places to look for libraries
64 my $coverage; # build for coverage testing
65 my $assert; # build with assertions
66 my $trace_context; # trace context management to stderr
67 GetOptions("help" => \$help,
68 "enable=s" => \@enable,
69 "disable=s" => \@disable,
70 "incpath=s", \@incpaths,
71 "libpath=s" => \@libpaths,
72 "verbose|v" => \$VERBOSE,
74 'coverage' => \$coverage,
75 "assert|a" => \$assert,
76 "tracecontext" => \$trace_context);
80 if ($ENV{AUTOMATED_TESTING}) {
85 print "Verbose mode\n";
87 import Data::Dumper qw(Dumper);
96 if ($NOLOG) { print "Logging not compiled into module\n"; }
98 push @defines, [ IMAGER_LOG => 1, "Logging system" ];
102 push @defines, [ IM_ASSERT => 1, "im_assert() are effective" ];
106 push @defines, [ IMAGER_DEBUG_MALLOC => 1, "Use Imager's DEBUG malloc()" ];
107 print "Malloc debugging enabled\n";
110 if (@enable && @disable) {
111 print STDERR "Only --enable or --disable can be used, not both, try --help\n";
117 my @incs; # all the places to look for headers
118 my @libs; # all the places to look for libraries
120 init(); # initialize global data
121 pathcheck(); # Check if directories exist
124 if (exists $ENV{IM_ENABLE}) {
125 push @enable, split ' ', $ENV{IM_ENABLE};
128 my %en = map { lc $_ => 1 } map_bundled(@enable);
129 @enabled_bundled = grep $en{lc $_}, @bundled;
132 my %dis = map { lc $_ => 1 } map_bundled(@disable);
133 @enabled_bundled = grep !$dis{lc $_}, @bundled;
136 @enabled_bundled = @bundled;
139 # Pick what libraries are used
146 my @objs = qw(Imager.o context.o draw.o polygon.o image.o io.o iolayer.o
147 log.o gaussian.o conv.o pnm.o raw.o feat.o combine.o
148 filters.o dynaload.o stackmach.o datatypes.o
149 regmach.o trans2.o quant.o error.o convert.o
150 map.o tags.o palimg.o maskimg.o img8.o img16.o rotate.o
151 bmp.o tga.o color.o fills.o imgdouble.o limits.o hlines.o
152 imext.o scale.o rubthru.o render.o paste.o compose.o flip.o
158 for my $frmkey (sort { $formats{$a}{order} <=> $formats{$b}{order} } keys %formats) {
159 my $frm = $formats{$frmkey};
160 if ($frm->{enabled}) {
161 push @defines, [ $frm->{def}, 1, "$frmkey available" ];
162 push @objs, $frm->{objfiles};
163 $lib_define .= " $frm->{DEFINE}" if $frm->{DEFINE};
164 $lib_inc .= " $frm->{INC}" if $frm->{INC};
165 $lib_libs .= " $frm->{LIBS}" if $frm->{LIBS};
170 my $OSDEF = "-DOS_$^O";
172 if ($^O eq 'hpux') { $OSLIBS .= ' -ldld'; }
173 if (defined $Config{'d_dlsymun'}) { $OSDEF .= ' -DDLSYMUN'; }
175 if ($Config{useithreads}) {
176 if ($Config{i_pthread}) {
177 print "POSIX threads\n";
178 push @objs, "mutexpthr.o";
180 elsif ($^O eq 'MSWin32') {
181 print "Win32 threads\n";
182 push @objs, "mutexwin.o";
185 print "Unsupported threading model\n";
186 push @objs, "mutexnull.o";
187 if ($ENV{AUTOMATED_TESTING}) {
188 die "OS unsupported: no threading support code for this platform\n";
193 print "No threads\n";
194 push @objs, "mutexnull.o";
197 my @typemaps = qw(typemap.local typemap);
199 unshift @typemaps, "typemap.oldperl";
202 if ($trace_context) {
203 $CFLAGS .= " -DIMAGER_TRACE_CONTEXT";
206 my $tests = 't/*.t t/*/*.t';
207 if (-d "xt" && scalar(() = glob("xt/*.t"))) {
214 VERSION_FROM => 'Imager.pm',
215 LIBS => "$LFLAGS -lm $lib_libs $OSLIBS",
216 DEFINE => "$OSDEF $lib_define $CFLAGS",
217 INC => "$lib_inc $DFLAGS",
218 OBJECT => join(' ', @objs),
219 DIR => [ sort grep -d, @enabled_bundled, @extras ],
220 clean => { FILES=>'testout rubthru.c scale.c conv.c filters.c gaussian.c render.c rubthru.c' },
224 'Test::More' => 0.99,
225 'Scalar::Util' => 1.00,
228 TYPEMAPS => \@typemaps,
229 test => { TESTS => $tests },
233 if ($Config{gccversion}) {
234 push @ARGV, 'OPTIMIZE=-ftest-coverage -fprofile-arcs -g';
235 $opts{dynamic_lib} = { OTHERLDFLAGS => '-ftest-coverage -fprofile-arcs' };
238 die "Don't know the coverage C flags for your compiler\n";
242 # eval to prevent warnings about versions with _ in them
243 my $MM_ver = eval $ExtUtils::MakeMaker::VERSION;
244 if ($MM_ver > 6.06) {
245 $opts{AUTHOR} = 'Tony Cook <tonyc@cpan.org>, Arnar M. Hrafnkelsson';
246 $opts{ABSTRACT} = 'Perl extension for Generating 24 bit Images';
249 if ($MM_ver >= 6.46) {
254 "Parse::RecDescent" => 0
273 homepage => "http://imager.perl.org/",
274 repository => "git://git.imager.perl.org/imager.git",
275 bugtracker => "http://rt.cpan.org/NoAuth/Bugs.html?Dist=Imager",
280 my $ivdformat = probe_ivdformat();
282 make_imconfig(\@defines, $ivdformat);
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 Warning: if you use manual configuration you are responsible for
358 configuring extra include/library directories as necessary using
359 INC and LIBS command-line assignments.
361 press <return> to continue
364 <STDIN>; # eat one return
366 for my $frm(sort { $formats{$b}{order} <=> $formats{$a}{order} } keys %formats) {
368 if ($formats{$frm}{docs}) { print "\n",$formats{$frm}{docs},"\n\n"; }
369 print "Enable $frm support: ";
372 if ($gz =~ m/^(y|yes|n|no)/i) {
374 $formats{$frm}{enabled} = 1;
375 $IMAGER_LIBS{$frm} = 1;
382 # automatic configuration of helper libraries
385 print "Automatic probing:\n" if $VERBOSE;
387 if (grep $_ eq "FT1", @enabled_bundled) {
391 inccheck => sub { -e File::Spec->catfile($_[0], "ftnameid.h") },
393 testcode => _ft1_test_code(),
394 testcodeheaders => [ "freetype.h", "stdio.h" ],
395 incpaths => \@incpaths,
396 libpaths => \@libpaths,
400 incsuffix => "freetype",
405 my $probe_res = Imager::Probe->probe(\%probe);
406 $IMAGER_LIBS{FT1} = defined $probe_res;
408 $formats{FT1}{enabled} = 1;
409 @{$formats{FT1}}{qw/DEFINE INC LIBS/} =
410 @$probe_res{qw/DEFINE INC LIBS/};
418 print " Include paths:\n";
419 for (@incs) { print $_,"\n"; }
421 @incs=grep { -d $_ && -r _ && -x _ or ( print(" $_ doesnt exist or is unaccessible - removed.\n"),0) } @incs;
424 print "\nLibrary paths:\n";
425 for (@libs) { print $_,"\n"; }
427 @libs=grep { -d $_ && -r _ && -x _ or ( print(" $_ doesnt exist or is unaccessible - removed.\n"),0) } @libs;
432 # Format data initialization
434 # format definition is:
436 # default include path
437 # files needed for include (boolean perl code)
440 # files needed for link (boolean perl code)
441 # object files needed for the format
446 my @definc = qw(/usr/include);
447 @definc{@definc}=(1) x @definc;
450 split(/\Q$Config{path_sep}/, $INCPATH),
451 map _tilde_expand($_), map { split /\Q$Config{path_sep}/ } @incpaths
453 if ($Config{locincpth}) {
454 push @incs, grep -d, split ' ', $Config{locincpth};
456 if ($^O =~ /win32/i && $Config{cc} =~ /\bcl\b/i) {
457 push(@incs, split /;/, $ENV{INCLUDE}) if exists $ENV{INCLUDE};
459 if ($Config{incpath}) {
460 push @incs, grep -d, split /\Q$Config{path_sep}/, $Config{incpath};
464 /usr/include/freetype2
465 /usr/local/include/freetype2
466 /usr/local/include/freetype1/freetype
467 /usr/include /usr/local/include /usr/include/freetype
468 /usr/local/include/freetype);
469 if ($Config{ccflags}) {
470 my @hidden = map { /^-I(.*)$/ ? ($1) : () } split ' ', $Config{ccflags};
472 @definc{@hidden} = (1) x @hidden;
475 @libs= ( split(/\Q$Config{path_sep}/,$LIBPATH),
476 map _tilde_expand($_), map { split /\Q$Config{path_sep}/} @libpaths );
477 if ($Config{loclibpth}) {
478 push @libs, grep -d, split ' ', $Config{loclibpth};
481 push @libs, grep -d, qw(/sw/lib), split(/ /, $Config{'libpth'});
482 push @libs, grep -d, split / /, $Config{libspath} if $Config{libspath};
483 if ($^O =~ /win32/i && $Config{cc} =~ /\bcl\b/i) {
484 push(@libs, split /;/, $ENV{LIB}) if exists $ENV{LIB};
486 if ($^O eq 'cygwin') {
487 push(@libs, '/usr/lib/w32api') if -d '/usr/lib/w32api';
488 push(@incs, '/usr/include/w32api') if -d '/usr/include/w32api';
490 if ($Config{ldflags}) {
491 # some builds of perl put -Ldir into ldflags without putting it in
492 # loclibpth, let's extract them
493 my @hidden = grep -d, map { /^-L(.*)$/ ? ($1) : () }
494 split ' ', $Config{ldflags};
496 # don't mark them as seen - EU::MM will remove any libraries
497 # it can't find and it doesn't look for -L in ldflags
498 #@deflib{@hidden} = @hidden;
500 push @libs, grep -d, qw(/usr/local/lib);
506 objfiles=>'fontft1.o',
509 Freetype 1.x supports Truetype fonts and is obsoleted by Freetype 2.x.
511 It's probably insecure.
515 for (keys %formats) { $formats{$_}->{docs} =~ s/^\s+/ /mg; }
522 print " $_[0]: '$V'\n"
523 if $VERBOSE && defined $V;
524 defined($V) ? $V : "";
528 # Get information from environment variables
532 $VERBOSE ||= gen("IM_VERBOSE");
534 print "Environment config:\n" if $VERBOSE;
543 $DFLAGS) = map { gen $_ } qw(IM_INCPATH
553 # populate the environment so that sub-modules get the same info
555 $ENV{IM_VERBOSE} = 1 if $VERBOSE;
556 $ENV{IM_INCPATH} = join $Config{path_sep}, @incpaths if @incpaths;
557 $ENV{IM_LIBPATH} = join $Config{path_sep}, @libpaths if @libpaths;
561 my ($defines, $ivdformat) = @_;
563 open CONFIG, "> imconfig.h"
564 or die "Cannot create imconfig.h: $!\n";
566 /* This file is automatically generated by Makefile.PL.
567 Don't edit this file, since any changes will be lost */
569 #ifndef IMAGER_IMCONFIG_H
570 #define IMAGER_IMCONFIG_H
572 for my $define (@$defines) {
574 print CONFIG "\n/*\n $define->[2]\n*/\n\n";
576 print CONFIG "#define $define->[0] $define->[1]\n";
578 if ($Config{gccversion} && $Config{gccversion} =~ /^([0-9]+)/ && $1 > 3) {
582 Compiler supports the GCC __attribute__((format...)) syntax.
586 #define IMAGER_FORMAT_ATTR 1
591 if ($Config{d_snprintf}) {
593 /* We can use snprintf() */
594 #define IMAGER_SNPRINTF 1
599 if ($Config{d_vsnprintf}) {
601 /* We can use vsnprintf() */
602 #define IMAGER_VSNPRINTF 1
609 Type and format code for formatted output as with printf.
611 This is intended for formatting i_img_dim values.
613 typedef $Config{ivtype} i_dim_format_t;
614 #define i_DF $ivdformat
617 print CONFIG "\n#endif\n";
623 Usage: $0 [--enable feature1,feature2,...] [other options]
624 $0 [--disable feature1,feature2,...] [other options]
626 Possible feature names are:
630 Verbose library probing (or set IM_VERBOSE in the environment)
632 Disable logging (or set IM_NOLOG in the environment)
634 Add to the include search path
636 Add to the library search path
638 Build for coverage testing.
640 Build with assertions active.
646 # at least one CPAN tester has an incorrect ivdformat, make sure it's
648 # Or at least it isn't valid with the built-in sprintf()
649 sub probe_ivdformat {
650 if (_test_ivdformat($Config{ivdformat})) {
651 return $Config{ivdformat};
653 my @test_fmt = grep $_ ne $Config{ivdformat}, qw(ld d lld zd I64d);
654 for my $fmt (@test_fmt) {
655 if (_test_ivdformat($fmt)) {
656 print "ivdformat: Found a valid ivdformat\n";
660 die "OS unsupported: Invalid ivdformat ($Config{ivdformat}) in this perl\n";
663 sub _test_ivdformat {
665 require Devel::CheckLib;
666 my @headers = ( "stdio.h", "string.h" );
667 if ($Config{i_inttypes}) {
668 push @headers, "inttypes.h";
671 Devel::CheckLib::check_lib
679 $Config{ivtype} x = 10;
680 sprintf(buf, "%" $fmt " %" $fmt, x, x);
681 if (strcmp(buf, "10 10")) {
682 printf("ivformat: " $fmt " is invalid\n");
689 # generate the PM MM argument
690 # I'd prefer to modify the public version, but there doesn't seem to be
691 # a public API to do that
694 my $instbase = '$(INST_LIBDIR)';
696 # first the basics, .pm and .pod files
697 $pm{"Imager.pm"} = "$instbase/Imager.pm";
699 my $mani = maniread();
701 for my $filename (keys %$mani) {
702 if ($filename =~ m!^lib/! && $filename =~ /\.(pm|pod)$/) {
703 (my $work = $filename) =~ s/^lib//;
704 $pm{$filename} = $instbase . $work;
709 $pm{typemap} = $instbase . '/Imager/typemap';
711 # and the core headers
712 for my $filename (keys %$mani) {
713 if ($filename =~ /^\w+\.h$/) {
714 $pm{$filename} = $instbase . '/Imager/include/' . $filename;
718 # and the generated header
719 $pm{"imconfig.h"} = $instbase . '/Imager/include/imconfig.h';
728 if ($path =~ m!^~[/\\]!) {
729 defined $home or $home = $ENV{HOME};
730 if (!defined $home && $^O eq 'MSWin32'
731 && defined $ENV{HOMEDRIVE} && defined $ENV{HOMEPATH}) {
732 $home = $ENV{HOMEDRIVE} . $ENV{HOMEPATH};
734 unless (defined $home) {
735 $home = eval { (getpwuid($<))[7] };
737 defined $home or die "You supplied $path, but I can't find your home directory\n";
739 $path = File::Spec->catdir($home, $path);
750 error = TT_Init_FreeType(&engine);
752 printf("FT1: Could not initialize engine\n");
763 @names = map { split /,/ } @names;
766 for my $name (@names) {
767 push @outnames, $name;
768 push @outnames, $bundled_names{$name}
769 if $bundled_names{$name};