use strict;
use warnings;
use File::Basename;
use ExtUtils::MakeMaker;
use Config;
use Cwd;
# pick up our parameters from @ARGV
my %ARGV;
for (@ARGV) {
if (/^(.*?)\=(.*)/) {
$ARGV{$1} = $2;
} else {
$ARGV{$_} = 1;
}
$_ = '' if /^--gdal-source-tree/;
$_ = '' if /^--gdal-config/;
$_ = '' if /^--no-version-check/;
$_ = '' if /^--no-downloads/;
print STDERR "Warning: unknown parameter: '$_'.\n" if $_;
}
# ... or from the environment
$ARGV{'--gdal-source-tree'} = $ENV{PERL_GDAL_SOURCE_TREE} if $ENV{PERL_GDAL_SOURCE_TREE};
$ARGV{'--gdal-config'} = $ENV{PERL_GDAL_CONFIG} if $ENV{PERL_GDAL_CONFIG};
$ARGV{'--no-version-check'} = 1 if $ENV{PERL_GDAL_NO_VERSION_CHECK};
$ARGV{'--no-downloads'} = 1 if $ENV{PERL_GDAL_NO_DOWNLOADS};
if ($ARGV{'--help'}) {
print <<end;
'perl Makefile.pl' configures this package to many kinds of systems.
Usage: perl Makefile.pl [OPTION]
To assign environment variables, specify them as VAR=VALUE.
Control the GDAL that this module is built against:
--gdal-source-tree=PATH use PATH as the gdal source
the same as environment variable PERL_GDAL_SOURCE_TREE=PATH
--gdal-config=PATH use PATH as the gdal-config
the same as environment variable PERL_GDAL_CONFIG=PATH
--no-version-check allow building against GDAL with different version
the same as setting environment variable PERL_GDAL_NO_VERSION_CHECK=1
--no-downloads disable fetching GDAL source code as a last resort
the same as setting environment variable PERL_GDAL_NO_DOWNLOADS=1
More information is available at ExtUtils-MakeMaker documentation.
end
exit;
}
my $source_tree;
if ($ARGV{'--gdal-source-tree'}) {
$source_tree = $ARGV{'--gdal-source-tree'};
# hack to force downloading of the source
if ($ARGV{'--gdal-source-tree'} eq 'download') {
$source_tree = '';
} else {
die "Path '$source_tree' does not exist." unless -e $source_tree && -d $source_tree;
}
}
elsif (-r '../../GDALmake.opt.in') {
$source_tree = '../..';
print "Building in source tree.\n" if $source_tree;
}
# Obtain the version of GDAL for this module distribution.
my $my_gdal_version;
if (open(my $fh, "lib/Geo/GDAL.pm")) {
for (<$fh>) {
($my_gdal_version) = /(\d+\.\d+\.\d+)/ if /GDAL_VERSION/;
}
close $fh;
} else {
die "GDAL Perl modules not found, perhaps you need to run make generate?";
}
# search and decide which GDAL (gdal-config) to build against if not given
my $versions_may_differ = $ARGV{'--no-version-check'};
my $downloads_are_ok = !$source_tree && !$ARGV{'--no-downloads'};
my $gdal_config;
if ($source_tree) {
$gdal_config = "$source_tree/apps/gdal-config";
die "There is no gdal-config in '$source_tree'.\n".
"You have to first say \"cd $source_tree; make\"." unless -r $gdal_config;
}
elsif ($ARGV{'--gdal-config'}) {
$gdal_config = $ARGV{'--gdal-config'};
}
my $config;
if ($gdal_config) {
if (-r $gdal_config) {
$config = $gdal_config;
} else {
die "The gdal-config '$gdal_config' does not exist or is unreadable.\n";
}
} else {
# scan known possible locations in the order of preference:
my @configs;
for ('c:/msys/1.0/local/bin/gdal-config',
'/usr/local/bin/gdal-config',
'/usr/bin/gdal-config') {
push @configs, $_ if -r $_;
}
if (@configs) {
$config = $configs[0];
if (@configs) {
print "Found gdal-config(s): '",join("', '", @configs),"'.\n";
print "Will try '$config'.\n";
} else {
print STDERR "Did not find any gdal-config(s)\n";
}
}
}
if (!$config && $downloads_are_ok) {
$source_tree = "./gdal";
$config = "$source_tree/apps/gdal-config";
unless (-e $config) {
$source_tree = download_and_compile_gdal($my_gdal_version);
$config = "$source_tree/apps/gdal-config";
}
}
my $uri = gdal_source_location($my_gdal_version);
my $gdal_version = get_gdal_version($config);
my $different_versions = $my_gdal_version ne $gdal_version;
my $msg = <<end;
The version of the GDAL development files you spefied is different
from the version these bindings were developed for (I have
$my_gdal_version and $config has $gdal_version).
You can either
- get GDAL development files from $uri or from wherever you get
development files for your system,
- specify another gdal-config,
- allow building against a different version of GDAL development files
(with --no-version-check or by setting the environment variable
PERL_GDAL_NO_VERSION_CHECK to a true value) - this is however not
recommended, or
- let me download and build GDAL for you. It will happen automatically
if you clear the command line and remove environment variables that
may prevent it (see --help).
end
die $msg if ($gdal_config && $different_versions && !$versions_may_differ) ||
(!$downloads_are_ok && $different_versions && !$versions_may_differ);
if ($different_versions && !$gdal_config && !$versions_may_differ && $downloads_are_ok) {
$source_tree = download_and_compile_gdal($my_gdal_version, $gdal_version);
$config = "$source_tree/apps/gdal-config";
}
# still in the game?
my $have_gnm = `grep "CONFIG_GNM_ENABLED" $config`;
my $have_ogr = `grep "CONFIG_OGR_ENABLED" $config`;
for ($have_gnm, $have_ogr) {
chomp;
$_ = /yes/ ? 1 : 0;
}
my ($INC, $LIB) = get_gdal_inc_lib($config);
my %object = ( 'Geo::GDAL' => 'gdal_wrap.o',
'Geo::GDAL::Const' => 'gdalconst_wrap.o',
'Geo::OSR' => 'osr_wrap.o' );
$object{'Geo::OGR'} = 'ogr_wrap.o' if $have_ogr;
$object{'Geo::GNM'} = 'gnm_wrap.o' if $have_gnm;
if ($ARGV{'--debug'}) {
print "LIB = $LIB\n";
print "INC = $INC\n";
}
for my $module (sort keys %object) {
my $add = $module;
$add =~ s/:/_/g;
my $LD = $Config{ld};
$LD .= ' '.$ENV{CFLAGS} if $ENV{CFLAGS};
$LD .= ' '.$ENV{LDFLAGS} if $ENV{LDFLAGS};
my $OPTIMIZE = '';
$OPTIMIZE .= ' '.$ENV{CFLAGS} if $ENV{CFLAGS};
$OPTIMIZE .= ' '.$ENV{CPPFLAGS} if $ENV{CFLAGS};
my %PM = ( 'lib/Geo/GDAL.pm' => '$(INST_LIBDIR)/GDAL.pm',
'lib/Geo/OSR.pm' => '$(INST_LIBDIR)/OSR.pm',
'lib/Geo/GDAL/Const.pm' => '$(INST_LIBDIR)/GDAL/Const.pm' );
$PM{'lib/Geo/OGR.pm'} = '$(INST_LIBDIR)/OGR.pm' if $have_ogr;
$PM{'lib/Geo/GNM.pm'} = '$(INST_LIBDIR)/GNM.pm' if $have_gnm;
WriteMakefile( NAME => $module,
VERSION_FROM => 'lib/Geo/GDAL.pm',
ABSTRACT_FROM => 'lib/Geo/GDAL.pm',
AUTHOR => 'Ari Jolma <ari.jolma at gmail.com>',
LICENSE => 'mit',
META_MERGE => {
'meta-spec' => { version => 2 },
resources => {
repository => {
type => 'svn',
url => 'https://svn.osgeo.org/gdal/trunk/gdal/swig/perl',
web => 'https://trac.osgeo.org/gdal/browser/trunk/gdal/swig/perl',
},
},
},
MAKEFILE => 'Makefile_'.$add,
LIBS => $LIB,
INC => $INC,
OPTIMIZE => $OPTIMIZE,
LD => $LD,
OBJECT => $object{$module},
PM => \%PM,
CONFIGURE_REQUIRES => {
'strict' => 0,
'warnings' => 0,
'File::Basename' => 0,
'ExtUtils::MakeMaker' => 0,
'Config' => 0,
'Cwd' => 0,
'File::Fetch' => 0,
'Capture::Tiny' => 0,
},
BUILD_REQUIRES => {
'strict' => 0,
'warnings' => 0,
'File::Basename' => 0,
'ExtUtils::MakeMaker' => 0,
'Config' => 0,
'File::Fetch' => 0,
'Capture::Tiny' => 0,
'Cwd' => 0
},
PREREQ_PM => {
Carp => 0,
Encode => 0,
'Scalar::Util' => 0,
POSIX => 0
},
TEST_REQUIRES => {
'Scalar::Util' => 0,
'Test::More' => 0,
'Encode' => 0,
POSIX => 0
}
);
}
sub gdal_source_location {
my $version = shift;
return "http://download.osgeo.org/gdal/$version/gdal-$version.tar.gz";
}
sub download_and_compile_gdal {
my ($version, $got_version) = @_;
if (not defined $got_version) {
print STDERR <<end;
I did not find GDAL development files. I am going to try to download
and compile GDAL for you. You can prevent this happening by a command
line argument --no-downloads or by setting the environment variable
PERL_GDAL_NO_DOWNLOADS to a true value, or by specifying a good
gdal-config with --gdal-config or the environment variable
PERL_GDAL_CONFIG. If the version of the GDAL development files is
different from what this module was built against ($version) I will be
back here.
end
} else {
print STDERR <<end;
The GDAL development files you gave or I found have a different
version ($got_version) than what this module was built against
($version). I am going to try to download and compile GDAL for you.
You can prevent this happening by pointing me to good GDAL development
files, with a command line argument --no-downloads or by setting the
environment variable PERL_GDAL_NO_DOWNLOADS to a true value, or by
being adventurous by specifying --no-version-check or setting the
environment variable PERL_GDAL_NO_VERSION_CHECK.
end
}
print STDERR <<end;
Note that this automatic download and compile is mostly meant for
automatic tests etc. It is recommended that you download and configure
GDAL by hand. This may take a very long time. I will capture the
output from the build and put it into gdal-build.log and
gdal-build.err. You can look into them while this goes on but the
output will be buffered.
end
{
require File::Fetch;
require Capture::Tiny;
Capture::Tiny->import(':all');
my $pwd = cwd();
open(my $log, ">", "gdal-build.log")
or die "Can't open gdal-build.log: $!.";
open(my $err, ">", "gdal-build.err")
or die "Can't open gdal-build.err: $!.";
my $step = sub {
my @cmd = @_;
my $ret;
print "@cmd\n";
my $code = sub {
if ($cmd[0] eq 'cd') {
$ret = chdir($cmd[1]);
} else {
$ret = open(my $cmd, '-|', @cmd);
if ($ret) {
my $flush = $|;
$| = 1;
my $i = 0;
while (<$cmd>) {
print $log $_;
print "#" if $i % 50 == 0;
$i++;
}
print "\n";
$| = $flush;
close($cmd);
} else {
print STDERR "'@cmd' returned $ret\n";
}
}
};
my ($stderr, $result) = capture_stderr($code);
print $err $stderr;
return $ret;
};
my $gdal = "gdal-$version";
my $uri = gdal_source_location($version);
my $ok = 1;
print "get GDAL version $version\n";
my $code = sub {
if ($version eq '2.0.0' or $version eq '2.0.1') {
print "$version is buggy, get latest from 2.0 branch.\n";
$ok = $step->("svn", "checkout", "https://svn.osgeo.org/gdal/branches/2.0/gdal", "gdal");
$gdal = "gdal";
}
elsif (-r "gdal-$version.tar.gz" and -s "gdal-$version.tar.gz") { # fetch leaves a zero sized file even when it fails
print "Using existing \"$gdal.tar.gz\"\n";
# extract into gdal
$ok = $step->("mkdir", "gdal");
$ok = $step->("tar", "zxf", "$gdal.tar.gz", "-C", "gdal", "--strip-components=1");
}
else {
print "Attempting to fetch '$uri'\n";
my $ff = File::Fetch->new(uri => $uri);
$ok = $ff->fetch() if $ff;
if ($ok) {
# extract into gdal
$ok = $step->("mkdir", "gdal");
$ok = $step->("tar", "zxf", "$gdal.tar.gz", "-C", "gdal", "--strip-components=1");
} else {
print "No luck. Maybe this is the development version?\n";
$ok = $step->("svn", "checkout", "https://svn.osgeo.org/gdal/trunk/gdal", "gdal");
$gdal = "gdal";
}
}
};
my ($stdout, $stderr, $exit) = capture($code);
print $err $stderr;
print $log $stdout;
if ($ok) {
for my $cmd (["cd", "gdal"],
["./configure"],
[($^O =~ /bsd/i ? "gmake" : "make"), "-j4"],
["cd", ".."])
{
$ok = $step->(@$cmd);
last unless $ok;
}
}
close $log;
close $err;
return "./gdal" if $ok;
chdir($pwd);
open($err, "<", "gdal-build.err")
or die "Can't open gdal-build.err: $!.";
my @err = <$err>;
close $err;
die "Downloading and compiling of GDAL failed.\n".
"The error is probably explained by the error log.\n".
"It is '$pwd/gdal-build.err'.\n".
"@err\n";
}}
sub get_gdal_version {
my $config = shift;
my $version;
if (-x $config) {
chomp($version = `$config --version`);
}
else {
if (open(my $fh, $config) || die "Can't open '$config': $!") {
for (<$fh>) {
($version) = /(\d+\.\d+\.\d+)/ if /^CONFIG_VERSION/;
}
close $fh;
}
die "Can't find version from '$config'." unless $version;
}
return $version;
}
sub get_gdal_inc_lib {
my $config = shift;
my ($INC, $LIB) = ('', '');
if ($source_tree) {
$LIB = "-L$source_tree/.libs -L$source_tree -lgdal ";
chomp($INC = `$config --cflags`);
$INC .= " -I$source_tree/gnm " if $have_gnm;
}
elsif (-x $config) {
chomp($INC = `$config --cflags`);
chomp($LIB = `$config --libs`);
}
else {
if (open(my $fh, $config) || die "Can't open '$config': $!") {
for (<$fh>) {
if (/^CONFIG_LIBS/) {
s/^CONFIG_LIBS="//;
s/"\s*$//;
if ($_ =~ /\.la$/) {
$LIB .= parse_libtool_library_file_for_l($_);
} else {
$LIB .= $_;
}
$LIB .= ' ';
}
if (/^CONFIG_DEP_LIBS/) {
s/^CONFIG_DEP_LIBS="//;
s/"\s*$//;
$LIB .= $_;
}
if (/^CONFIG_CFLAGS/) {
s/^CONFIG_CFLAGS="//;
s/"\s*$//;
$INC .= $_;
}
}
close $fh;
}
}
return ($INC, $LIB);
}
sub parse_libtool_library_file_for_l {
my $fn = shift;
my $fh;
my $l = '';
if (open($fh, $fn)) {
while (<$fh>) {
if (/^dlname=(.*)/) {
$l = $1;
$l =~ s/^'//;
$l =~ s/^lib/\-l/;
$l =~ s/\..*$//;
last;
}
}
close $fh;
}
return $l;
}