-
+#!perl -w
+use strict;
use ExtUtils::MakeMaker;
use Cwd;
use Config;
-
-$lext=$Config{'so'}; # Get extensions of libraries
-$aext=$Config{'_a'};
+use File::Spec;
+use Getopt::Long;
+use vars qw(%Recommends);
+use ExtUtils::Manifest qw(maniread);
+use vars qw(%formats $VERBOSE $INCPATH $LIBPATH $NOLOG $DEBUG_MALLOC $MANUAL $CFLAGS $LFLAGS $DFLAGS);
#
# IM_INCPATH colon seperated list of paths to extra include paths
# IM_CFLAGS Extra flags to pass to the compiler
# IM_LFLAGS Extra flags to pass to the linker
# IM_DFLAGS Extra flags to pass to the preprocessor
-
+# IM_SUPPRESS_PROMPT Suppress the prompt asking about gif support
getenv(); # get environment variables
+
+my $lext=$Config{'so'}; # Get extensions of libraries
+my $aext=$Config{'_a'};
+
+my $help; # display help if set
+my @enable; # list of drivers to enable
+my @disable; # or list of drivers to disable
+my @incpaths; # places to look for headers
+my @libpaths; # places to look for libraries
+my $noexif; # non-zero to disable EXIF parsing of JPEGs
+my $no_gif_set_version; # disable calling EGifSetGifVersion
+my $coverage; # build for coverage testing
+GetOptions("help" => \$help,
+ "enable=s" => \@enable,
+ "disable=s" => \@disable,
+ "incpath=s", \@incpaths,
+ "libpath=s" => \@libpaths,
+ "verbose|v" => \$VERBOSE,
+ "nolog" => \$NOLOG,
+ "noexif" => \$noexif,
+ "nogifsetversion" => \$no_gif_set_version,
+ 'coverage' => \$coverage);
+
+if ($VERBOSE) {
+ print "Verbose mode\n";
+ require Data::Dumper;
+ import Data::Dumper qw(Dumper);
+}
+
+if ($help) {
+ usage();
+}
+
+my @defines;
+
+if ($NOLOG) { print "Logging not compiled into module\n"; }
+else {
+ push @defines, [ IMAGER_LOG => 1, "Logging system" ];
+}
+
+if ($DEBUG_MALLOC) {
+ push @defines, [ IMAGER_DEBUG_MALLOC => 1, "Use Imager's DEBUG malloc()" ];
+ print "Malloc debugging enabled\n";
+}
+
+if (@enable && @disable) {
+ print STDERR "Only --enable or --disable can be used, not both, try --help\n";
+ exit 1;
+}
+
+my %definc;
+my %deflib;
+my @incs; # all the places to look for headers
+my @libs; # all the places to look for libraries
+
init(); # initialize global data
pathcheck(); # Check if directories exist
+if (exists $ENV{IM_ENABLE}) {
+ my %en = map { $_, 1 } split ' ', $ENV{IM_ENABLE};
+ for my $key (keys %formats) {
+ delete $formats{$key} unless $en{$key};
+ }
+}
+if (@enable) {
+ my %en = map { $_ => 1 } map { split /,/ } @enable;
+ for my $key (keys %formats) {
+ delete $formats{$key} unless $en{$key};
+ }
+}
+elsif (@disable) {
+ delete @formats{map { split /,/ } @disable};
+}
+
# Pick what libraries are used
if ($MANUAL) {
manual();
} else {
automatic();
- if (exists $ENV{IM_ENABLE}) {
- my %en = map { $_, 1 } split ' ', $ENV{IM_ENABLE};
- for my $key (keys %formats) {
- delete $formats{$key} unless $en{$key};
- }
- }
}
# Make sure there isn't a clash between the gif libraries.
gifcheck();
-for $frm(values %formats) {
- $F_DEFINE .= ' -D'.$frm->{def};
- $F_LIBS .= ' ' .$frm->{libfiles};
+my $lib_cflags = '';
+my $lib_lflags = '';
+my $F_LIBS = '';
+my $F_OBJECT = '';
+for my $frmkey (sort { $formats{$a}{order} <=> $formats{$b}{order} } keys %formats) {
+ my $frm = $formats{$frmkey};
+ push @defines, [ $frm->{def}, 1, "$frmkey available" ];
$F_OBJECT .= ' ' .$frm->{objfiles};
+ if ($frm->{cflags}) {
+ $lib_cflags .= ' ' .$frm->{cflags};
+ ++$definc{$_} for map { /^-I(.*)$/ ? ($1) : () }
+ grep /^-I./, split ' ', $frm->{cflags};
+ }
+ if ($frm->{lflags}) {
+ $lib_lflags .= ' ' . $frm->{lflags};
+ }
+ else {
+ $F_LIBS .= ' ' .$frm->{libfiles};
+ }
+
+}
+
+unless ($noexif) {
+ print "EXIF support enabled\n";
+ push @defines, [ 'IMEXIF_ENABLE', 1, "Enable experimental EXIF support" ];
+ $F_OBJECT .= ' imexif.o';
}
-$F_INC = join(" ",map { (exists $definc{$_})?'':'-I'.$_ } @incs);
-$F_LIBS = join(" ",map { '-L'.$_ } @libs).' '.$F_LIBS;
+my $F_INC = join ' ', map "-I$_", map / / ? qq{"$_"} : $_,
+ grep !$definc{$_}, @incs;
+$F_LIBS = join(' ',map "-L$_", map / / ? qq{"$_"} : $_,
+ grep !$deflib{$_}++, @libs) . $F_LIBS;
-$OSLIBS = '';
-$OSDEF = "-DOS_$^O";
+my $OSLIBS = '';
+my $OSDEF = "-DOS_$^O";
if ($^O eq 'hpux') { $OSLIBS .= ' -ldld'; }
if (defined $Config{'d_dlsymun'}) { $OSDEF .= ' -DDLSYMUN'; }
-@objs = qw(Imager.o draw.o image.o io.o iolayer.o log.o
- gaussian.o conv.o pnm.o raw.o feat.o font.o
- filters.o dynaload.o stackmach.o datatypes.o
- regmach.o trans2.o quant.o error.o convert.o
- map.o tags.o palimg.o maskimg.o img16.o rotate.o
- bmp.o tga.o color.o fills.o);
-
-%opts=(
- 'NAME' => 'Imager',
- 'VERSION_FROM' => 'Imager.pm',
- 'LIBS' => "$LFLAGS -lm $OSLIBS $F_LIBS",
- 'DEFINE' => "$F_DEFINE $EXTDEF $OSDEF $CFLAGS",
- 'INC' => "$DFLAGS $F_INC",
- 'OBJECT' => join(' ', @objs, $F_OBJECT),
- clean => { FILES=>'testout' },
- );
-
-if ($] ge '5.005') {
- $opts{AUTHOR} = 'Arnar M. Hrafnkelsson, addi@umich.edu';
+my @objs = qw(Imager.o draw.o polygon.o image.o io.o iolayer.o
+ log.o gaussian.o conv.o pnm.o raw.o feat.o font.o
+ filters.o dynaload.o stackmach.o datatypes.o
+ regmach.o trans2.o quant.o error.o convert.o
+ map.o tags.o palimg.o maskimg.o img16.o rotate.o
+ bmp.o tga.o rgb.o color.o fills.o imgdouble.o limits.o hlines.o
+ imext.o scale.o rubthru.o render.o);
+
+$Recommends{Imager} =
+ { 'Parse::RecDescent' => 0 };
+
+my %opts=(
+ 'NAME' => 'Imager',
+ 'VERSION_FROM' => 'Imager.pm',
+ 'LIBS' => "$LFLAGS -lm $lib_lflags $OSLIBS $F_LIBS",
+ 'DEFINE' => "$OSDEF $CFLAGS",
+ 'INC' => "$lib_cflags $DFLAGS $F_INC",
+ 'OBJECT' => join(' ', @objs, $F_OBJECT),
+ clean => { FILES=>'testout meta.tmp rubthru.c scale.c' },
+ PM => gen_PM(),
+ PREREQ_PM => { 'Test::More' => 0.47 },
+ );
+
+if ($coverage) {
+ if ($Config{gccversion}) {
+ push @ARGV, 'OPTIMIZE=-ftest-coverage -fprofile-arcs';
+ #$opts{dynamic_lib} = { OTHERLDFLAGS => '-ftest-coverage -fprofile-arcs' };
+ }
+ else {
+ die "Don't know the coverage C flags for your compiler\n";
+ }
+}
+
+# eval to prevent warnings about versions with _ in them
+my $MM_ver = eval $ExtUtils::MakeMaker::VERSION;
+if ($MM_ver > 6.06) {
+ $opts{AUTHOR} = 'Tony Cook <tony@imager.perl.org>, Arnar M. Hrafnkelsson';
$opts{ABSTRACT} = 'Perl extension for Generating 24 bit Images';
}
+if ($MM_ver > 6.10) {
+ $opts{NO_META} = 1;
+}
+
+make_imconfig(\@defines);
if ($VERBOSE) { print Dumper(\%opts); }
mkdir('testout',0777); # since we cannot include it in the archive.
+
+make_metafile(\%opts);
+
WriteMakefile(%opts);
exit;
sub MY::postamble {
+ my $self = shift;
+ my $perl = $self->{PERLRUN} ? '$(PERLRUN)' : '$(PERL)';
+ my $mani = maniread;
+
+ my @ims = grep /\.im$/, keys %$mani;
'
dyntest.$(MYEXTLIB) : dynfilt/Makefile
cd dynfilt && $(MAKE) $(PASTHRU)
lib/Imager/Regops.pm : regmach.h regops.perl
$(PERL) regops.perl regmach.h lib/Imager/Regops.pm
-';
+
+imconfig.h : Makefile.PL
+ $(ECHO) "imconfig.h out-of-date with respect to $?"
+ $(PERLRUN) Makefile.PL
+ $(ECHO) "==> Your Makefile has been rebuilt - re-run your make command <=="
+'.qq!
+lib/Imager/APIRef.pod : \$(C_FILES) apidocs.perl
+ $perl apidocs.perl lib/Imager/APIRef.pod
+
+!.join('', map _im_rule($perl, $_), @ims)
+
+}
+
+sub _im_rule {
+ my ($perl, $im) = @_;
+
+ (my $c = $im) =~ s/\.im$/.c/;
+ return <<MAKE;
+
+$c: $im imtoc.perl
+ $perl imtoc.perl $im $c
+
+MAKE
+
}
# manual configuration of helper libraries
<STDIN>; # eat one return
- for $frm(sort { $formats{$b}{order} <=> $formats{$a}{order} } keys %formats) {
+ for my $frm(sort { $formats{$b}{order} <=> $formats{$a}{order} } keys %formats) {
SWX:
if ($formats{$frm}{docs}) { print "\n",$formats{$frm}{docs},"\n\n"; }
print "Enable $frm support: ";
- $gz = <STDIN>;
+ my $gz = <STDIN>;
chomp($gz);
if ($gz =~ m/^(y|yes|n|no)/i) {
$gz=substr(lc($gz),0,1);
# automatic configuration of helper libraries
sub automatic {
- for $frm(keys %formats) {
+ print "Automatic probing:\n" if $VERBOSE;
+ for my $frm (sort { $formats{$a}{order} <=> $formats{$b}{order} } keys %formats) {
delete $formats{$frm} if !checkformat($frm);
}
}
delete $formats{'ungif'};
}
- RETR:
- if ($formats{'gif'} or $formats{'ungif'}) {
- print <<EOFF;
-
-You have libgif or libungif installed. They are both known to have
-bugs. Imager can crash or display other strange behaviour after
-reading or writing gif images. Some of the gif tests can even fail
-since they stress some parts of the buggy code.
-
-Do you want to remove gif support? [Y/n]
-EOFF
- my $resp = <STDIN>;
- chomp($resp);
- if ($resp ne "n") {
- delete $formats{'gif'};
- delete $formats{'ungif'};
- return;
- }
- }
-
for my $frm (qw(gif ungif)) {
checkformat($frm) if ($MANUAL and $formats{$frm});
}
# we need the version in a #ifdefable form
- $F_DEFINE .= "-DIM_GIFMAJOR=$major -DIM_GIFMINOR=$minor";
+ push @defines, [ IM_GIFMAJOR => $major, "Parsed giflib version" ];
+ push @defines, [ IM_GIFMINOR => $minor ];
+ push @defines, [ IM_NO_SET_GIF_VERSION => 1, "Disable EGifSetGifVersion" ]
+ if $no_gif_set_version;
}
-sub gd {
- my($path,$chk)=@_;
+sub grep_directory {
+ my($path, $chk)=@_;
# print "checking path $path\n";
if ( !opendir(DH,$path) ) {
sub checkformat {
my $frm=shift;
- my $libchk=$formats{$frm}{'libcheck'};
- my $incchk=$formats{$frm}{'inccheck'};
- my @l;
- for my $lp (@libs) {
- push(@l, gd($lp,$libchk));
+ print " checkformat($frm)\n" if $VERBOSE;
+
+ my $probe_array = $formats{$frm}{'code'};
+ if ($probe_array) {
+ print " Calling probe function\n" if $VERBOSE;
+ if (ref $probe_array ne 'ARRAY') {
+ $probe_array = [ $probe_array ];
+ }
+ for my $func (@$probe_array) {
+ return 1 if $func->($formats{$frm}, $frm);
+ }
}
- my @i;
- for my $ip (@incs) {
- push(@i, gd($ip,$incchk));
+ my $lib_check=$formats{$frm}{'libcheck'};
+ my $inc_check=$formats{$frm}{'inccheck'};
+
+ if ($lib_check) {
+ my @l;
+ for my $lp (@libs) {
+ push(@l, grep_directory($lp,$lib_check));
+ }
+
+ my @i;
+ for my $ip (@incs) {
+ push(@i, $ip) if $inc_check->($ip,$frm);
+ }
+
+ printf("%10s: includes %s - libraries %s\n",$frm,(@i?'found':'not found'),(@l?'found':'not found'));
+ $formats{$frm}{incdir} = \@i;
+ $formats{$frm}{libdir} = \@l;
+ return 1 if scalar(@i && @l);
+ }
+ else {
+ printf("%10s: not available\n", $frm);
}
- printf("%10s: includes %s - libraries %s\n",$frm,(@i?'found':'not found'),(@l?'found':'not found'));
- $formats{$frm}{incdir} = \@i;
- $formats{$frm}{libdir} = \@l;
- return scalar(@i && @l);
+ return 0;
}
-
-
sub pathcheck {
if ($VERBOSE) {
print "pathcheck\n";
print " Include paths:\n";
for (@incs) { print $_,"\n"; }
}
- @incs=grep { -d $_ && -r _ && -x _ or ( print(" $_ doesnt exist or is unaccessible - removed."),0) } @incs;
+ @incs=grep { -d $_ && -r _ && -x _ or ( print(" $_ doesnt exist or is unaccessible - removed.\n"),0) } @incs;
if ($VERBOSE) {
print "\nLibrary paths:\n";
- for (@incs) { print $_,"\n"; }
+ for (@libs) { print $_,"\n"; }
}
- @libs=grep { -d $_ && -r _ && -x _ or ( print(" $_ doesnt exist or is unaccessible - removed."),0) } @libs;
+ @libs=grep { -d $_ && -r _ && -x _ or ( print(" $_ doesnt exist or is unaccessible - removed.\n"),0) } @libs;
print "\ndone.\n";
}
sub init {
- @definc{'/usr/include'}=();
- @incs=(qw(/usr/include /usr/local/include /usr/include/freetype /usr/local/include/freetype /usr/include/freetype2 /usr/local/include/freetype2), split /:/, $INCPATH );
- @libs=(split(/ /, $Config{'libpth'}), split(/:/, $LIBPATH) );
+ my @definc = qw(/usr/include);
+ @definc{@definc}=(1) x @definc;
+ @incs=(split(/\Q$Config{path_sep}/, $INCPATH),
+ map { split /\Q$Config{path_sep}/} @incpaths );
+ if ($Config{locincpth}) {
+ push @incs, grep -d, split ' ', $Config{locincpth};
+ }
if ($^O =~ /win32/i && $Config{cc} =~ /\bcl\b/i) {
push(@incs, split /;/, $ENV{INCLUDE}) if exists $ENV{INCLUDE};
+ }
+ if ($Config{incpath}) {
+ push @incs, grep -d, split /\Q$Config{path_sep}/, $Config{incpath};
+ }
+ push @incs, grep -d,
+ qw(/sw/include
+ /usr/include/freetype2
+ /usr/local/include/freetype2
+ /usr/local/include/freetype1/freetype
+ /usr/include /usr/local/include /usr/include/freetype
+ /usr/local/include/freetype);
+ if ($Config{ccflags}) {
+ my @hidden = map { /^-I(.*)$/ ? ($1) : () } split ' ', $Config{ccflags};
+ push @incs, @hidden;
+ @definc{@hidden} = (1) x @hidden;
+ }
+
+ @libs= ( split(/\Q$Config{path_sep}/,$LIBPATH),
+ map { split /\Q$Config{path_sep}/} @libpaths );
+ if ($Config{loclibpth}) {
+ push @libs, grep -d, split ' ', $Config{loclibpth};
+ }
+
+ push @libs, grep -d, qw(/sw/lib), split(/ /, $Config{'libpth'});
+ push @libs, grep -d, split / /, $Config{libspath} if $Config{libspath};
+ if ($^O =~ /win32/i && $Config{cc} =~ /\bcl\b/i) {
push(@libs, split /;/, $ENV{LIB}) if exists $ENV{LIB};
}
if ($^O eq 'cygwin') {
push(@libs, '/usr/lib/w32api') if -d '/usr/lib/w32api';
- push(@incs, '/usr/include/w32api') if -d '/usr/lib/w32api';
+ push(@incs, '/usr/include/w32api') if -d '/usr/include/w32api';
+ }
+ if ($Config{ldflags}) {
+ # some builds of perl put -Ldir into ldflags without putting it in
+ # loclibpth, let's extract them
+ my @hidden = grep -d, map { /^-L(.*)$/ ? ($1) : () }
+ split ' ', $Config{ldflags};
+ push @libs, @hidden;
+ # don't mark them as seen - EU::MM will remove any libraries
+ # it can't find and it doesn't look for -L in ldflags
+ #@deflib{@hidden} = @hidden;
}
+ push @libs, grep -d, qw(/usr/local/lib);
$formats{'jpeg'}={
order=>'21',
def=>'HAVE_LIBJPEG',
- inccheck=>sub { $_[0] eq 'jpeglib.h' },
+ inccheck=>sub { -e catfile($_[0], 'jpeglib.h') },
libcheck=>sub { $_[0] eq "libjpeg$aext" or $_ eq "libjpeg.$lext" },
libfiles=>'-ljpeg',
objfiles=>'jpeg.o',
$formats{'tiff'}={
order=>'23',
def=>'HAVE_LIBTIFF',
- inccheck=>sub { $_[0] eq 'tiffio.h' },
+ inccheck=>sub { -e catfile($_[0], 'tiffio.h') },
libcheck=>sub { $_[0] eq "libtiff$aext" or $_ eq "libtiff.$lext" },
libfiles=>'-ltiff',
objfiles=>'tiff.o',
$formats{'png'}={
order=>'22',
def=>'HAVE_LIBPNG',
- inccheck=>sub { $_[0] eq 'png.h' },
+ inccheck=>sub { -e catfile($_[0], 'png.h') },
libcheck=>sub { $_[0] eq "libpng$aext" or $_[0] eq "libpng.$lext" },
- libfiles=>'-lpng -lz',
+ libfiles=>$^O eq 'MSWin32' ? '-lpng -lzlib' : '-lpng -lz',
objfiles=>'png.o',
docs=>q{
Png stands for Portable Network Graphics and is intended as
a replacement for gif on the web. It is patent free and
- is recommended by the w3c, you need libpng to use these formats}
+ is recommended by the w3c, you need libpng to use these formats},
+ code => \&png_probe,
};
$formats{'gif'}={
order=>'20',
def=>'HAVE_LIBGIF',
- inccheck=>sub { $_[0] eq 'gif_lib.h' },
+ inccheck=>sub { -e catfile($_[0], 'gif_lib.h') },
libcheck=>sub { $_[0] eq "libgif$aext" or $_[0] eq "libgif.$lext" },
libfiles=>'-lgif',
objfiles=>'gif.o',
$formats{'ungif'}={
order=>'21',
def=>'HAVE_LIBGIF',
- inccheck=>sub { $_[0] eq 'gif_lib.h' },
+ inccheck=>sub { -e catfile($_[0], 'gif_lib.h') },
libcheck=>sub { $_[0] eq "libungif$aext" or $_[0] eq "libungif.$lext" },
libfiles=>'-lungif',
objfiles=>'gif.o',
$formats{'T1-fonts'}={
order=>'30',
def=>'HAVE_LIBT1',
- inccheck=>sub { $_[0] eq 't1lib.h' },
+ inccheck=>sub { -e catfile($_[0], 't1lib.h') },
libcheck=>sub { $_[0] eq "libt1$aext" or $_[0] eq "libt1.$lext" },
libfiles=>'-lt1',
objfiles=>'',
for use in images.}
};
- $formats{'TT-fonts'}={
- order=>'31',
- def=>'HAVE_LIBTT',
- inccheck=>sub { $_[0] eq 'freetype.h' },
- libcheck=>sub { $_[0] eq "libttf$aext" or $_[0] eq "libttf.$lext" },
- libfiles=>'-lttf',
- objfiles=>'',
- docs=>q{
- Truetype fonts are scalable fonts. They can include
- kerning and hinting information and generally yield good
- visual quality esp on low resultions. The freetype library is
- used to rasterize for us. The only drawback is that there
- are alot of badly designed fonts out there.}
+ $formats{'TT-fonts'}=
+ {
+ order=>'31',
+ def=>'HAVE_LIBTT',
+ inccheck=>sub { -e catfile($_[0], 'freetype.h')
+ && !-e catfile($_[0], 'fterrors.h') },
+ libcheck=>sub { $_[0] eq "libttf$aext" or $_[0] eq "libttf.$lext" },
+ libfiles=>'-lttf',
+ objfiles=>'',
+ code => \&freetype1_probe,
+ docs=>q{
+Truetype fonts are scalable fonts. They can include
+kerning and hinting information and generally yield good
+visual quality esp on low resultions. The freetype library is
+used to rasterize for us. The only drawback is that there
+are alot of badly designed fonts out there.}
};
$formats{'w32'} = {
order=>40,
def=>'HAVE_WIN32',
- inccheck=>sub { lc $_[0] eq 'windows.h' },
+ inccheck=>sub { -e catfile($_[0], 'windows.h') },
libcheck=>sub { lc $_[0] eq 'gdi32.lib'
|| lc $_[0] eq 'libgdi32.a' },
libfiles=>$^O eq 'cygwin' ? '-lgdi32' : '',
This currently only works on under normal Win32 and cygwin.
DOCS
};
- $formats{'freetype2'} = {
- order=>'29',
- def=>'HAVE_FT2',
- inccheck=>sub { lc $_[0] eq 'ft2build.h' },
- libcheck=>sub { $_[0] eq "libfreetype$aext" or $_[0] eq "libfreetype.$lext" },
- libfiles=>'-lfreetype',
- objfiles=>'freetyp2.o',
- docs=><<DOCS
+ $formats{'freetype2'} =
+ {
+ order=>'29',
+ def=>'HAVE_FT2',
+ # we always use a probe function
+ #inccheck=>sub { -e catfile($_[0], 'ft2build.h') },
+ #libcheck=>sub { $_[0] eq "libfreetype$aext" or $_[0] eq "libfreetype.$lext" },
+ libfiles=>'-lfreetype',
+ objfiles=>'freetyp2.o',
+ docs=><<DOCS,
Freetype 2 supports both Truetype and Type 1 fonts, both of which are
-scalable.
+scalable. It also supports a variety of other fonts.
DOCS
- };
+ code =>
+ [
+ \&freetype2_probe_ftconfig,
+ \&freetype2_probe_scan
+ ],
+ };
+
# Make fix indent
for (keys %formats) { $formats{$_}->{docs} =~ s/^\s+/ /mg; }
}
IM_LFLAGS
IM_DFLAGS);
- if ($VERBOSE) { print "Verbose mode\n"; require Data::Dumper; import Data::Dumper qw(Dumper);}
+}
+
+sub make_imconfig {
+ my ($defines) = @_;
+
+ open CONFIG, "> imconfig.h"
+ or die "Cannot create imconfig.h: $!\n";
+ print CONFIG <<EOS;
+/* This file is automatically generated by Makefile.PL.
+ Don't edit this file, since any changes will be lost */
+
+#ifndef IMAGER_IMCONFIG_H
+#define IMAGER_IMCONFIG_H
+EOS
+ for my $define (@$defines) {
+ if ($define->[2]) {
+ print CONFIG "\n/*\n $define->[2]\n*/\n\n";
+ }
+ print CONFIG "#define $define->[0] $define->[1]\n";
+ }
+ print CONFIG "\n#endif\n";
+ close CONFIG;
+}
+
+# use pkg-config to probe for libraries
+# works around the junk that pkg-config dumps on FreeBSD
+sub _pkg_probe {
+ my ($pkg) = @_;
- if ($NOLOG) { print "Logging not compiled into module\n"; }
- else { $EXTDEF.=' -DIMAGER_LOG'; }
+ is_exe('pkg-config') or return;
- if ($DEBUG_MALLOC) {
- $EXTDEF.=' -DIMAGER_DEBUG_MALLOC';
- print "Malloc debugging enabled\n";
+ my $redir = $^O eq 'MSWin32' ? '' : '2>/dev/null';
+
+ !system("pkg-config $pkg --exists $redir");
+}
+
+# probes for freetype1 by scanning @incs for the includes and
+# @libs for the libs. This is done separately because freetype's headers
+# are stored in a freetype or freetype1 directory under PREFIX/include.
+#
+# we could find the files with the existing mechanism, but it won't set
+# -I flags correctly.
+#
+# This could be extended to freetype2 too, but freetype-config catches
+# that
+sub freetype1_probe {
+ my ($frm, $frmkey) = @_;
+
+ my $found_inc;
+ INCS:
+ for my $inc (@incs) {
+ for my $subdir (qw/freetype freetype1/) {
+ my $path = File::Spec->catfile($inc, $subdir, 'freetype.h');
+ -e $path or next;
+ $path = File::Spec->catfile($inc, $subdir, 'fterrors.h');
+ -e $path and next;
+
+ $found_inc = File::Spec->catdir($inc, $subdir);
+ last INCS;
+ }
+ }
+
+ my $found_lib;
+ LIBS:
+ for my $lib (@libs) {
+ my $a_path = File::Spec->catfile($lib, "libttf$aext");
+ my $l_path = File::Spec->catfile($lib, "libttf.$lext");
+ if (-e $a_path || -e $l_path) {
+ $found_lib = $lib;
+ last LIBS;
+ }
+ }
+
+ return unless $found_inc && $found_lib;
+ printf("%10s: includes %s - libraries %s\n", $frmkey,
+ ($found_inc ? 'found' : 'not found'),
+ ($found_lib ? 'found' : 'not found'));
+
+ $frm->{cflags} = "-I$found_inc";
+ $frm->{libfiles} = "-lttf";
+
+ return 1;
+}
+
+# probes for freetype2 by trying to run freetype-config
+sub freetype2_probe_ftconfig {
+ my ($frm, $frmkey) = @_;
+
+ is_exe('freetype-config') or return;
+
+ my $cflags = `freetype-config --cflags`
+ and !$? or return;
+ chomp $cflags;
+
+ my $lflags = `freetype-config --libs`
+ and !$? or return;
+ chomp $lflags;
+
+ # before 2.1.5 freetype-config --cflags could output
+ # the -I options in the wrong order, causing a conflict with
+ # freetype1.x installed with the same --prefix
+ #
+ # can happen iff:
+ # - both -Iprefix/include and -Iprefix/include/freetype2 are in cflags
+ # in that order
+ # - freetype 1.x headers are in prefix/include/freetype
+ my @incdirs = map substr($_, 2), grep /^-I/, split ' ', $cflags;
+ if (@incdirs == 2
+ && $incdirs[1] eq "$incdirs[0]/freetype2"
+ && -e "$incdirs[0]/freetype/freetype.h"
+ && -e "$incdirs[0]/freetype/fterrid.h") {
+ print "** freetype-config provided -I options out of order, correcting\n"
+ if $VERBOSE;
+ $cflags = join(' ', grep(!/-I/, split ' ', $cflags),
+ map "-I$_", reverse @incdirs);
+ }
+ $frm->{cflags} = $cflags;
+ $frm->{lflags} = $lflags;
+
+ printf "%10s: configured via freetype-config\n", $frmkey;
+
+ return 1;
+}
+
+# attempt to probe for freetype2 by scanning directories
+# we can't use the normal scan since we need to find the directory
+# containing most of the includes
+sub freetype2_probe_scan {
+ my ($frm, $frmkey) = @_;
+
+ my $found_inc;
+ my $found_inc2;
+ INCS:
+ for my $inc (@incs) {
+ my $path = File::Spec->catfile($inc, 'ft2build.h');
+ -e $path or next;
+
+ # try to find what it's including
+ my $ftheader;
+ open FT2BUILD, "< $path"
+ or next;
+ while (<FT2BUILD>) {
+ if (m!^\s*\#\s*include\s+<([\w/.]+)>!
+ || m!^\s*\#\s*include\s+"([\w/.]+)"!) {
+ $ftheader = $1;
+ last;
+ }
+ }
+ close FT2BUILD;
+ $ftheader
+ or next;
+ # non-Unix installs put this directly under the same directory in
+ # theory
+ if (-e File::Spec->catfile($inc, $ftheader)) {
+ $found_inc = $inc;
+ last INCS;
+ }
+ for my $subdir (qw/freetype2 freetype/) {
+ $path = File::Spec->catfile($inc, $subdir, 'fterrors.h');
+ -e $path and next;
+
+ $found_inc = $inc;
+ $found_inc2 = File::Spec->catdir($inc, $subdir);
+ last INCS;
+ }
}
+ my $found_lib;
+ LIBS:
+ for my $lib (@libs) {
+ my $a_path = File::Spec->catfile($lib, "libfreetype$aext");
+ my $l_path = File::Spec->catfile($lib, "libfreetype.$lext");
+ if (-e $a_path || -e $l_path) {
+ $found_lib = $lib;
+ last LIBS;
+ }
+ }
+
+ printf("%10s: includes %s - libraries %s\n", $frmkey,
+ ($found_inc ? 'found' : 'not found'),
+ ($found_lib ? 'found' : 'not found'));
+
+ return unless $found_inc && $found_lib;
+
+ $frm->{cflags} = _make_I($found_inc);
+ $frm->{cflags} .= " " . _make_I($found_inc2) if $found_inc2;
+ $frm->{libfiles} = "-lfreetype";
+
+ return 1;
+}
+
+sub _make_I {
+ my ($inc_dir) = @_;
+
+ $definc{$inc_dir}
+ and return '';
+
+ $inc_dir =~ / / ? qq!-I"$inc_dir"! : "-I$inc_dir";
}
+
+# probes for libpng via pkg-config
+sub png_probe {
+ my ($frm, $frmkey) = @_;
+
+ is_exe('pkg-config') or return;
+
+ my $config;
+ for my $check_conf (qw(libpng libpng12 libpng10)) {
+ if (_pkg_probe($check_conf)) {
+ $config = $check_conf;
+ last;
+ }
+ }
+ $config or return;
+
+ my $cflags = `pkg-config $config --cflags`
+ and !$? or return;
+
+ my $lflags = `pkg-config $config --libs`
+ and !$? or return;
+
+ chomp $cflags;
+ chomp $lflags;
+ $frm->{cflags} = $cflags;
+ $frm->{lflags} = $lflags;
+
+ printf "%10s: configured via `pkg-config $config ...`\n", $frmkey;
+
+ return 1;
+}
+
+sub catfile {
+ return File::Spec->catfile(@_);
+}
+
+sub is_exe {
+ my ($name) = @_;
+
+ for my $dir (File::Spec->path) {
+ -x catfile($dir, "$name$Config{_exe}")
+ and return 1;
+ }
+
+ return;
+}
+
+sub usage {
+ print STDERR <<EOS;
+Usage: $0 [--enable feature1,feature2,...] [other options]
+ $0 [--disable feature1,feature2,...] [other options]
+ $0 --help
+Possible feature names are:
+ png gif ungif jpeg tiff T1-fonts TT-fonts freetype2
+Other options:
+ --verbose | -v
+ Verbose library probing (or set IM_VERBOSE in the environment)
+ --nolog
+ Disable logging (or set IM_NOLOG in the environment)
+ --incpath dir
+ Add to the include search path
+ --libpath dir
+ Add to the library search path
+EOS
+ exit 1;
+
+}
+
+# generate the PM MM argument
+# I'd prefer to modify the public version, but there doesn't seem to be
+# a public API to do that
+sub gen_PM {
+ my %pm;
+ my $instbase = '$(INST_LIBDIR)';
+
+ # first the basics, .pm and .pod files
+ $pm{"Imager.pm"} = "$instbase/Imager.pm";
+
+ my $mani = maniread();
+
+ for my $filename (keys %$mani) {
+ if ($filename =~ m!^lib/! && $filename =~ /\.(pm|pod)$/) {
+ (my $work = $filename) =~ s/^lib//;
+ $pm{$filename} = $instbase . $work;
+ }
+ }
+
+ # need the typemap
+ $pm{typemap} = $instbase . '/Imager/typemap';
+
+ # and the core headers
+ for my $filename (keys %$mani) {
+ if ($filename =~ /^\w+\.h$/) {
+ $pm{$filename} = $instbase . '/Imager/include/' . $filename;
+ }
+ }
+
+ # and the generated header
+ $pm{"imconfig.h"} = $instbase . '/Imager/include/imconfig.h';
+
+ \%pm;
+}
+
+sub make_metafile {
+ my ($opts) = @_;
+
+ # extract the version
+ my $version = MM->parse_version($opts->{VERSION_FROM})
+ or die "Could not extract version number from $opts->{VERSION_FROM}\n";
+
+ # we don't set this on older EU::MM and it corrupts META.yml
+ # so don't generate it
+ return unless $opts->{AUTHOR};
+
+ my $meta = <<YAML;
+--- #YAML:1.0
+name: $opts->{NAME}
+version: $version
+version_from: $opts->{VERSION_FROM}
+author: $opts->{AUTHOR}
+abstract: $opts->{ABSTRACT}
+installdirs: site
+YAML
+ if (keys %{$Recommends{$opts->{NAME}}}) {
+ $meta .= "recommends:\n";
+ while (my ($module, $version) = each %{$Recommends{$opts->{NAME}}}) {
+ $meta .= " $module: $version\n";
+ }
+ }
+ if ($opts->{PREREQ_PM}) {
+ $meta .= "requires:\n";
+ while (my ($module, $version) = each %{$opts->{PREREQ_PM}}) {
+ $meta .= " $module: $version\n";
+ }
+ }
+ $meta .= <<YAML;
+license: perl
+dynamic_config: 1
+distribution_type: module
+meta-spec:
+ version: 1.3
+ url: http://module-build.sourceforge.net/META-spec-v1.3.html
+generated_by: $opts->{NAME} version $version
+YAML
+ my $save_meta;
+ if (open META, "< META.yml") {
+ my $old_meta = do { local $/; <META> };
+ close META;
+
+ $save_meta = $old_meta ne $meta;
+ }
+ else {
+ ++$save_meta;
+ }
+ if ($save_meta) {
+ print "Updating META.yml\n";
+ open META, "> META.yml" or die "Cannot create META.yml: $!";
+ print META $meta;
+ close META;
+ }
+}
+