use Config;
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);
+use lib 'inc';
+use Devel::CheckLib;
#
# 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
+
+my $KEEP_FILES = $ENV{IMAGER_KEEP_FILES};
getenv(); # get environment variables
my @disable; # or list of drivers to disable
my @incpaths; # places to look for headers
my @libpaths; # places to look for libraries
-my $noprobe; # non-zero to disable newer probes
my $noexif; # non-zero to disable EXIF parsing of JPEGs
+my $no_gif_set_version; # disable calling EGifSetGifVersion
+my $coverage; # build for coverage testing
+my $assert; # build with assertions
GetOptions("help" => \$help,
"enable=s" => \@enable,
"disable=s" => \@disable,
"incpath=s", \@incpaths,
"libpath=s" => \@libpaths,
- "noprobe" => \$noprobe,
"verbose|v" => \$VERBOSE,
"nolog" => \$NOLOG,
- "noexif" => \$noexif);
+ "noexif" => \$noexif,
+ "nogifsetversion" => \$no_gif_set_version,
+ 'coverage' => \$coverage,
+ "assert|a" => \$assert);
+
+if ($ENV{AUTOMATED_TESTING}) {
+ $assert = 1;
+}
if ($VERBOSE) {
print "Verbose mode\n";
push @defines, [ IMAGER_LOG => 1, "Logging system" ];
}
+if ($assert) {
+ push @defines, [ IM_ASSERT => 1, "im_assert() are effective" ];
+}
+
if ($DEBUG_MALLOC) {
push @defines, [ IMAGER_DEBUG_MALLOC => 1, "Use Imager's DEBUG malloc()" ];
print "Malloc debugging enabled\n";
init(); # initialize global data
pathcheck(); # Check if directories exist
-distcheck(); # for building dists
if (exists $ENV{IM_ENABLE}) {
my %en = map { $_, 1 } split ' ', $ENV{IM_ENABLE};
gifcheck();
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_LIBS .= ' ' .$frm->{libfiles};
$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) {
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);
-
-$Recommends{Imager} =
- { 'Parse::RecDescent' => 0 };
+ bmp.o tga.o color.o fills.o imgdouble.o limits.o hlines.o
+ imext.o scale.o rubthru.o render.o paste.o compose.o flip.o);
my %opts=(
'NAME' => 'Imager',
'VERSION_FROM' => 'Imager.pm',
- 'LIBS' => "$LFLAGS -lm $OSLIBS $F_LIBS",
+ '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' },
+ clean => { FILES=>'testout rubthru.c scale.c conv.c filters.c gaussian.c render.c rubthru.c' },
PM => gen_PM(),
+ PREREQ_PM => { 'Test::More' => 0.47 },
);
-if ($ExtUtils::MakeMaker::VERSION > 6.06) {
+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 ($ExtUtils::MakeMaker::VERSION > 6.10) {
- $opts{NO_META} = 1;
+
+if ($MM_ver >= 6.46) {
+ $opts{META_MERGE} =
+ {
+ recommends =>
+ {
+ "Parse::RecDescent" => 0
+ },
+ license => "perl",
+ dynamic_config => 1,
+ };
}
make_imconfig(\@defines);
if ($VERBOSE) { print Dumper(\%opts); }
mkdir('testout',0777); # since we cannot include it in the archive.
-make_metafile(\%opts);
+-d "probe" and rmdir "probe";
WriteMakefile(%opts);
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)
$(PERLRUN) Makefile.PL
$(ECHO) "==> Your Makefile has been rebuilt - re-run your make command <=="
'.qq!
-lib/Imager/APIRef.pod : \$(C_FILES) apidocs.perl
+lib/Imager/APIRef.pod : \$(C_FILES) \$(H_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 lib/Imager/Preprocess.pm
+ $perl -Ilib -MImager::Preprocess -epreprocess $im $c
+
+MAKE
}
delete $formats{'ungif'};
}
- RETR:
- if (($formats{'gif'} or $formats{'ungif'}) && !$ENV{IM_SUPPRESS_PROMPT}) {
- my $msg = <<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 fail since
-they stress some parts of the buggy code.
-
-libungif or libguf 4.1.4 and later is safe.
-
-Of course it's possible your operating system distributor has patched
-all of these problems and you have nothing to worry about.
-
-Do you want to remove gif support? [Y/n]
-EOFF
- chomp $msg;
- my $resp = prompt($msg);
- 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});
}
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) ) {
return map $path, @l;
}
+sub _probe_default {
+ my ($format, $frm) = @_;
+
+ 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);
+ }
+
+ return 0;
+}
sub checkformat {
my $frm=shift;
print " checkformat($frm)\n" if $VERBOSE;
- my $code = $formats{$frm}{'code'};
- if ($code && !$noprobe) {
- print " Calling probe function\n" if $VERBOSE;
- return 1 if $code->($formats{$frm}, $frm);
- }
+ my $format = $formats{$frm};
- my $libchk=$formats{$frm}{'libcheck'};
- my $incchk=$formats{$frm}{'inccheck'};
+ my @probes;
+ if (my $code = $format->{'code'}) {
+ if (ref $code eq 'ARRAY') {
+ push @probes, @$code;
+ }
+ else {
+ push @probes, $code;
+ }
+ }
+ push @probes, \&_probe_default;
- my @l;
- for my $lp (@libs) {
- push(@l, gd($lp,$libchk));
+ print " Calling probe function\n" if $VERBOSE;
+ my $found;
+ for my $func (@probes) {
+ if ($func->($format, $frm)) {
+ ++$found;
+ last;
+ }
}
- my @i;
- for my $ip (@incs) {
- push(@i, $ip) if $incchk->($ip,$frm);
+ $found or return;
+
+ if ($format->{postcheck}) {
+ print " Calling postcheck function\n" if $VERBOSE;
+ $format->{postcheck}->($format, $frm)
+ or return;
}
- 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 1;
}
my @definc = qw(/usr/include);
@definc{@definc}=(1) x @definc;
- @incs=(split(/\Q$Config{path_sep}/, $INCPATH),
- map { split /\Q$Config{path_sep}/} @incpaths );
+ @incs=
+ (
+ split(/\Q$Config{path_sep}/, $INCPATH),
+ map _tilde_expand($_), 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
}
@libs= ( split(/\Q$Config{path_sep}/,$LIBPATH),
- map { split /\Q$Config{path_sep}/} @libpaths );
+ map _tilde_expand($_), map { split /\Q$Config{path_sep}/} @libpaths );
if ($Config{loclibpth}) {
push @libs, grep -d, split ' ', $Config{loclibpth};
}
# 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',
objfiles=>'tiff.o',
docs=>q{
In order to use tiff with this module you need to have libtiff
- installed on your computer}
+ installed on your computer},
+ postcheck => \&postcheck_tiff,
};
$formats{'png'}={
def=>'HAVE_LIBPNG',
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
This currently only works on under normal Win32 and cygwin.
DOCS
};
- $formats{'freetype2'} = {
- order=>'29',
- def=>'HAVE_FT2',
- 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,
+ $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. It also supports a variety of other fonts.
DOCS
- code => \&freetype2_probe,
- };
+ code =>
+ [
+ \&freetype2_probe_ftconfig,
+ \&freetype2_probe_scan
+ ],
+ };
# Make fix indent
for (keys %formats) { $formats{$_}->{docs} =~ s/^\s+/ /mg; }
}
# probes for freetype2 by trying to run freetype-config
-sub freetype2_probe {
+sub freetype2_probe_ftconfig {
my ($frm, $frmkey) = @_;
is_exe('freetype-config') or return;
map "-I$_", reverse @incdirs);
}
$frm->{cflags} = $cflags;
- $frm->{libfiles} = $lflags;
+ $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) = @_;
chomp $cflags;
chomp $lflags;
$frm->{cflags} = $cflags;
- $frm->{libfiles} = $lflags;
+ $frm->{lflags} = $lflags;
printf "%10s: configured via `pkg-config $config ...`\n", $frmkey;
sub is_exe {
my ($name) = @_;
+ my @exe_suffix = $Config{_exe};
+ if ($^O eq 'MSWin32') {
+ push @exe_suffix, qw/.bat .cmd/;
+ }
+
for my $dir (File::Spec->path) {
- -x catfile($dir, "$name$Config{_exe}")
- and return 1;
+ for my $suffix (@exe_suffix) {
+ -x catfile($dir, "$name$suffix")
+ and return 1;
+ }
}
return;
Add to the include search path
--libpath dir
Add to the library search path
- --noprobe
- Don't use pkg-config or freetype2-config to probe for freetype2 and libpng
+ --coverage
+ Build for coverage testing.
+ --assert
+ Build with assertions active.
+ --noexif
+ Disable EXIF parsing.
EOS
exit 1;
\%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";
-
- 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";
+my $home;
+sub _tilde_expand {
+ my ($path) = @_;
+
+ if ($path =~ m!^~[/\\]!) {
+ defined $home or $home = $ENV{HOME};
+ if (!defined $home && $^O eq 'MSWin32'
+ && defined $ENV{HOMEDRIVE} && defined $ENV{HOMEPATH}) {
+ $home = $ENV{HOMEDRIVE} . $ENV{HOMEPATH};
}
+ unless (defined $home) {
+ $home = eval { (getpwuid($<))[7] };
+ }
+ defined $home or die "You supplied $path, but I can't find your home directory\n";
+ $path =~ s/^~//;
+ $path = File::Spec->catdir($home, $path);
}
- $meta .= <<YAML;
-license: perl
-dynamic_config: 1
-distribution_type: module
-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;
+ $path;
+}
+
+sub postcheck_tiff {
+ my ($format, $frm) = @_;
+
+ -d "probe" or mkdir "probe";
+
+ my $tiffver_name = "probe/tiffver.txt";
+
+ my $lib;
+ if ($Config{cc} =~ /\b(cl|bcc)\b/) {
+ $lib = "libtiff";
}
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;
- }
-}
-
-# this is intended to only be running on the development
-# machines
-sub distcheck {
- if (-e '.svn') {
- # update Changes if needed
- my $write_changes;
- # get the last revision from Changes
- if (open CHANGES, "< Changes") {
- <CHANGES>;
- my ($changes_rev) = <CHANGES> =~ /^r(\d+)/
- or ++$write_changes;
-
- my ($revision) = grep s/^Revision: //, `svn info`
- or die "Could not get Revision from svn";
- chomp $revision;
-
- $write_changes ||= $changes_rev != $revision;
- close CHANGES;
- }
- else {
- ++$write_changes;
- }
- if ($write_changes) {
- print "Updating Changes file\n";
- system 'svn log -v -r HEAD:943 >Changes';
- }
+ $lib = "tiff";
+ }
+
+ my $good =
+ eval {
+ assert_lib
+ (
+ debug => $VERBOSE,
+ incpath => $format->{incdir},
+ libpath => $format->{libdir},
+ lib => $lib,
+ header => [ qw(stdio.h tiffio.h) ],
+ function => <<FUNCTION,
+ {
+ const char *vers = TIFFGetVersion();
+ FILE *f = fopen("$tiffver_name", "wb");
+ if (!f)
+ return 1;
+ fputs(vers, f);
+ if (fclose(f))
+ return 1;
+ return 0;
+ }
+FUNCTION
+ );
+ 1;
+ };
+
+ unless ($good && -s $tiffver_name
+ && open(VERS, "< probe/tiffver.txt")) {
+ unlink $tiffver_name unless $KEEP_FILES;
+ print <<EOS;
+ **tiff: cannot determine libtiff version number
+ tiff: DISABLED
+EOS
+ return;
}
+
+ # version file seems to be there, load it up
+ my $ver_str = do { local $/; <VERS> };
+ close VERS;
+ unlink $tiffver_name unless $KEEP_FILES;
+
+ my ($version) = $ver_str =~ /(\d+\.\d+\.\d+)/;
+
+ if ($version eq '3.9.0') {
+ print <<EOS;
+ **tiff: libtiff 3.9.0 introduced a serious bug, please install 3.9.1
+ tiff: DISABLED
+EOS
+ return;
+ }
+
+ return 1;
}
+
+# This isn't a module, but some broken tools, like
+# Module::Depends::Instrusive insist on treating it like one.
+#
+# http://rt.cpan.org/Public/Bug/Display.html?id=21229
+
+1;