Subject: | Making PHP::Interpreter easier to install - a stricter Makefile.PL |
I initially found PHP::Interpreter difficult to install, and I made
some changes to the Makefile.PL so to make it more obvious what is
wrong in case of failure. The main changes are:
* Use strict and warnings.
* Die unless 'php-config' is found in path.
* Removed hard coded default path prefix (e.g. usr/local).
* Rely on 'php-config' to determine includes, prefix, version and ldflags.
* Die unless 10 php and zend header files are present if File::Find is
installed.
Please find attached the revised Makefile.PL.
Tested with perl, v5.8.5, on linux 2.6.9 i386.
Best regards,
Andreas Faafeng
Subject: | Makefile.PL |
use strict;
use warnings;
use ExtUtils::MakeMaker;
use Config;
use File::Spec::Functions qw(catdir);
# Check if File::Find is present
eval { use File::Find; };
my $filefind = (!$@) ? 1 : 0;
# These header files must be present for PHP::Interpreter to compile
my %headers = map { $_ => 1 } qw (
php_config.h php.h php_ini.h php_main.h zend.h
zend_API.h zend_compile.h zend_ini.h SAPI.h TSRM.h
zend_interfaces.h
);
# Return true if files in headers hash are found, otherwise die
sub check_headers {
my $inc = shift;
die "Need an argument" if !$inc;
print "Checking header files...\n";
# Replace -I at beginning of string and chop of newline character
my @incdirs = map { s/^-I//g; chomp; $_ } split(/ /, $inc);
for (@incdirs) {
die "No such directory: '$_'" if (!-d);
print "using incdir '$_'\n";
}
# Make sure header files are present
my $finder = sub {
return if (!-f $_ or !exists($headers{$_}));
print "Found $File::Find::name\n";
delete $headers{$_};
};
# Try to find all files in headers - delete hash entries when found.
# Any remaining hash key indicates a necessary file is missing.
find(\&$finder, @incdirs);
die "Missing header files: " . join(q{, }, keys %headers) .
"\nDo you have PHP source installed?" if (keys %headers);
return 1;
}
# Die unless 'php-config' is found
`php-config` or die "Failed to find the 'php-config' executable. " .
"Make sure you have PHP and PHP sources installed, ".
"and that 'php-config' is in PATH.";
# Execute 'php-config' for each variable. Dies if executable is not
# in path.
my %conf = map {
my $a = `php-config --$_`;
die "Error: php-config --$_ failed\n" unless $a;
chomp $a;
$_ => $a;
} qw(includes prefix version ldflags);
# Get php version
print "using php version $conf{version}\n";
$conf{version} =~ s/^(\d+).*/$1/; # Need major version only
die "Unsupported PHP version" if ($conf{version} != 5);
# Get prefix. Use script argument as prefix, otherwise use value from
# 'php-config'
my $prefix = shift @ARGV || ($conf{prefix});
die "Failed to find php prefix" if (!defined($prefix) or !-d $prefix);
print "using prefix $prefix\n";
# Get include directories
my $includes = "-I" . catdir($prefix, 'include') . " " . $conf{includes};
print "using includes $includes\n";
# Get libraries
my @lddlflags = ($Config{lddlflags}, $conf{ldflags});
push @lddlflags, "-L" . catdir $prefix, "lib";
my $php_embedlib_path = "-L" . catdir $prefix, "lib";
push @lddlflags, $php_embedlib_path;
print "using lddlflags " . join(q{ }, @lddlflags) . "\n";
# Libs = lddlflags + php-version
my @libs = ("$php_embedlib_path");
push @libs, "-lphp$conf{version}";
print "using libs " . join(q{ }, @libs) . "\n";
my @ofiles = ('PHP.o', 'phpinterp.o', 'phpfuncs.o');
# Check that header files are present if File::Find is installed
($filefind)
? check_headers($includes)
: print "Module File::Find not installed. Header files check skipped.\n";
WriteMakefile(
CCFLAGS => '-g',
OBJECT => join(' ', @ofiles),
NAME => 'PHP::Interpreter',
LIBS => join(' ', @libs),
LDDLFLAGS => join(' ', @lddlflags),
INC => $includes,
VERSION_FROM => 'lib/PHP/Interpreter.pm',
PREREQ_PM => {
# Just required for testing.
'Test::More' => 0,
'IO::File' => 0
},
);
__END__
=pod
=head1 NAME
Makefile.PL - Makefile for PHP::Interpreter
=head1 SYNOPSIS
perl Makefile.PL [prefix]
=head1 OPTIONS
prefix - directory root for PHP install, e.g. /usr/local or
C:\\Program Files\\PHP
=head1 DESCRIPTION
This creates a makefile for PHP::Interpreter. PHP::Interpreter
depends on having both PHP and PHP sources installed.
This script uses the executable I<php-config> to determine how PHP is
configured. This script will die unless I<php-config> is installed.
PHP::Interpreter works with PHP5 only.
This script will perform header files check if module I<File::Find> is
installed
=head1 SEE ALSO
php
php-config
=cut