Alien-gdal
view release on metacpan or search on metacpan
# make sure we get GEOS, PROJ and other support
foreach my $alien (@alien_deps) {
eval "require $alien";
my $e = $@;
warn $e if $e;
if (!$e && $alien->install_type eq 'share') {
log "Prepending $alien bin dir to path";
unshift @PATH, $alien->bin_dir;
}
}
my $have_spatialite = eval 'require
Alien::spatialite';
if ($have_spatialite && Alien::spatialite->version ge 5) {
if (!$on_windows and Alien::spatialite->install_type('share')
and $Alien::spatialite::VERSION lt 1.06) {
$have_spatialite = undef; # rpath issues before this
}
else {
log "Prepending Alien::spatialite bin dir to path";
unshift @PATH, Alien::spatialite->bin_dir;
push @alien_deps, 'Alien::spatialite' if Alien::spatialite->install_type eq 'share';
}
}
else {
$have_spatialite = undef;
}
# configure script does not seem to detect the proj lib distributed with Strawberry perl
#use FFI::CheckLib;
#my $proj_lib = FFI::CheckLib::find_lib (lib => 'proj');
Alien::Build->log ('$ENV{PROJ_LIB} IS ' . ($ENV{PROJ_LIB} // ''));
# make libtool noisy for debug purposes
#$ENV{LTFLAGS} = "--debug --verbose" if $on_windows;
use Cwd;
my $base_dir = getcwd();
my $min_target_version = '3.1.0';
plugin 'PkgConfig' => (
pkg_name => 'gdal',
minimum_version => $min_target_version,
);
share {
# add existing alien files to path etc
# not very elegant...
# disable for now - config tests fail
# it looks to be already noted in https://github.com/Perl5-Alien/Alien-Build/issues/12
# might also be able to access via old hash via https://metacpan.org/pod/Alien::Build#install_prop
my $have_alien_gdal = eval 'require Alien::gdal';
my $copy_from_dir;
if ($ENV{ALIEN_SHARE_RECYCLE} && $have_alien_gdal && Alien::gdal->install_type eq 'share') {
my $ag_version = Alien::gdal->version;
say "Found existing gdal via alien ($ag_version) in " . Alien::gdal->dist_dir;
# append the relevant path
if (versioncmp($ag_version, $min_target_version) >= 0) {
$copy_from_dir = Alien::gdal->dist_dir;
}
}
if ($copy_from_dir) {
# files are copied in the extract hook
meta->register_hook(download => sub {
Path::Tiny->new ('fauxdownload.txt')->touch;
});
if($^O eq 'MSWin32') {
meta->register_hook(extract => sub {
my($build) = @_;
$copy_from_dir =~ s|/|\\|g; # it seems that xcopy needs backslashes in paths
$build->system("xcopy $copy_from_dir . /E /Q");
});
}
else {
meta->register_hook(extract => sub {
my ($build) = @_;
"cp -aR $copy_from_dir .";
});
}
meta->after_hook( extract => sub {
my($build) = @_;
$build->log('CURRENTLY IN ' . cwd());
File::Path::rmtree '_alien';
});
plugin 'Build::Copy';
}
else {
my $with_local = '';
my $with_cpp11 = '';
requires 'Alien::cmake3';
requires 'Alien::MSYS' if $on_windows;
#requires 'Alien::patchelf' if !($on_windows || $^O =~ /darwin/i);
Alien::Build->log ("Proj library version is " . Alien::proj->version);
die "Proj version must be at least 6.0.0"
if not Alien::proj->atleast_version ('6.0.0');
plugin 'Build::SearchDep' => (
aliens => [grep {$_->install_type eq 'share'} @alien_deps],
public_I => 1,
public_l => 1,
);
start_url 'https://download.osgeo.org/gdal/CURRENT';
#start_url 'https://download.osgeo.org/gdal/3.6.0';
#start_url "file://$base_dir"; # debug
# Handle release candidates in the regex.
# These are checked occasionally for debug purposes.
my $RE_filter_version = qr/^gdal-([0-9\.]+)(?:rc\d\d)?\.tar\.gz$/;
plugin Download => (
filter => $RE_filter_version,
version => $RE_filter_version,
);
plugin Extract => (format => 'tar.gz');
#plugin 'Build::Autoconf' => ();
plugin 'Build::CMake' => ();
#my $build_static = ($^O =~ /mswin/i) ? '' : '--disable-shared';
#$build_static = '--enable-static=no'; # override - HUGE files if static
#$build_static = '' if $ENV{FORCE_DYNAMIC};
my $build_static = '';
if ($^O =~ /bsd|dragonfly/) {
requires "Alien::gmake";
plugin 'Build::Make' => 'gmake';
#if (-d '/usr/local') {
#$with_local = '--with-local=/usr/local';
#}
if (!-e '/usr/local/include/sqlite3.h' && Alien::sqlite->install_type eq 'system') {
warn '/usr/local/include/sqlite3.h does not exist, '
. 'you might need to install the sqlite package for your system, '
. 'or install a share version of Alien::sqlite';
}
}
my $make_cmd = '%{make}';
my $make_inst_cmd = '%{make} install';
my @automated_rig_config_args;
# try not to exceed the cpan-testers log limits
if ($on_automated_rig) {
say "Running under CI or automated testing";
$make_cmd .= q/ | perl -ne "BEGIN {$|=1; open our $log, q|>|, q|build.log|}; print qq|\n| if 0 == ($. %% 100); print q|.|; print {$log} $_;" /;
$make_inst_cmd .= q/ | perl -ne "BEGIN {$|=1; open our $log, q|>|, q|install.log|}; print qq|\n| if 0 == ($. %% 100); print q|.|; print {$log} $_;" /;
if (!$on_windows) {
$make_cmd =~ s/%%/%/;
$make_cmd =~ s/"/'/g;
$make_cmd .= ' || (E=$? && cat build.log && exit $E)';
$make_inst_cmd =~ s/%%/%/;
$make_inst_cmd =~ s/"/'/g;
$make_inst_cmd .= ' || (E=$? && cat install.log && exit $E)';
}
else {
# fake exit codes on failure, not sure how to get originals
$make_cmd .= q/ || perl -e"system ('type', 'build.log'); exit 1"/;
$make_inst_cmd .= q/ || perl -e"system ('type', 'install.log'); exit 1"/;
}
# clean up the build dir on cpan testers etc
plugin 'Cleanse::BuildDir';
}
my @with_args = (
#https://gdal.org/build_hints.html#cmdoption-arg-GDAL_USE_-Packagename_in_upper_case-BOOL
@automated_rig_config_args,
'-DGDAL_USE_GEOTIFF_INTERNAL:BOOL=ON', # until we have an alien
'-DGDAL_USE_MSSQL_ODBC=OFF',
'-DGDAL_USE_MSSQL_NCLI=OFF',
'-DGDAL_USE_MYSQL=OFF',
'-DBUILD_CSHARP_BINDINGS:BOOL=OFF',
'-DBUILD_PYTHON_BINDINGS:BOOL=OFF',
'-DBUILD_JAVA_BINDINGS:BOOL=OFF',
#'--without-pg',
#'--without-ogdi',
#'--with-mongocxxv3=no',
#$^O eq 'MSWin32' ? '--without-hdf5' : (), # issues with strawberry perl hdf5 dlls
'-DGDAL_SET_INSTALL_RELATIVE_RPATH=ON',
);
# need to disable these on Macs under Homebrew - see GH#37
if ($^O =~ /darwin/i && defined $ENV{HOMEBREW_PREFIX}) {
push @with_args, qw /-DCMAKE_DISABLE_FIND_PACKAGE_Arrow=ON -DGDAL_USE_LIBKML=OFF/;
}
Alien::Build->log('LD_LIBRARY_PATH: ' . join ':', map {defined $_ ? $_ : ''} @LD_LIBRARY_PATH);
my @ld_flags;
my @ld_lib_path;
my @cmake_prefix_path;
# system installs won't necessarily have dist dirs
if (Alien::proj->install_type eq 'share') {
push @cmake_prefix_path, path('Alien::proj'->dist_dir);
push @with_args, '-DPROJ_INCLUDE_DIR=' . path (Alien::proj->dist_dir . '/include')->stringify;
my $libfile = find_lib_file (
lib => 'proj',
alien => 'Alien::proj',
);
# windows proj has non-conformant lib name, libproj_9_0.dll
# and this fails the checks in FFI::CheckLib < 0.29
if ($on_windows && !$libfile) {
my @files = grep {/libproj/} glob (Alien::proj->bin_dir . '/*.dll');
$libfile = shift @files;
Alien::Build->log ("Secondary search for proj dynamic lib found $libfile");
"-DSQLite3_INCLUDE_DIR=$sqlite_include",
);
if (!$on_windows) {
push @ld_lib_path, (Alien::sqlite->dist_dir . '/lib');
}
}
if (Alien::geos::af->install_type eq 'share') {
push @cmake_prefix_path, path('Alien::geos::af'->dist_dir);
my $libfile = find_lib_file (
lib => 'geos',
alien => 'Alien::geos::af',
);
push @with_args, '-DGEOS_INCLUDE_DIR=' . path(Alien::geos::af->dist_dir . '/include')->stringify;
push @with_args, '-DGEOS_LIBRARY=' . $libfile;
# build weirdness on linux with geos under cmake
if (!$on_windows) {
my $dir = List::Util::first {-d $_} map {Alien::geos::af->dist_dir . "/$_"} (qw/lib lib64 lib32/);
push @ld_lib_path, $dir if $dir;
}
}
if ($^O eq 'MSWin32') {
# Should add an env flag for these.
# Disabling postgres due to issues with Strawberry Perl 5.42.
# Probably overkill but will do for now.
push @with_args, ('-DGDAL_USE_CURL=OFF', '-DGDAL_USE_POSTGRESQL=OFF');
}
my @env_args;
if (my $env_arg_str = $ENV{ALIEN_GDAL_CMAKE_ARGS} // '') {
Alien::Build->log("\$ENV{ALIEN_GDAL_CMAKE_ARGS} is $env_arg_str");
$env_arg_str =~ s/[^-\s\w:=]//g; # overkill?
# could use shellwords for the split
@env_args = grep {/^\-[UD]/} (split /\s+/, $env_arg_str);
}
Alien::Build->log('CMake args from env var: ' . join ' ', @env_args);
meta->around_hook( build => \&remove_gitfw_from_path );
plugin 'PkgConfig::PPWrapper';
meta->around_hook(
build => sub {
my ($orig, $build, @args) = @_;
$build->log("Setting CCACHE_BASEDIR to " . getcwd());
local $ENV{CCACHE_BASEDIR} = getcwd();
$orig->($build, @args);
}
);
my @drivers_to_disable = get_drivers_to_disable();
# not sure this is needed, or if it is to deal with a cirrus quirk
# hack
if ($^O =~ /darwin/) {
push @DYLD_LIBRARY_PATH, @ld_lib_path;
Alien::Build->log('DYLD_LIBRARY_PATH: ' . join ':', grep {defined} @DYLD_LIBRARY_PATH);
}
else {
push @LD_LIBRARY_PATH, @ld_lib_path;
Alien::Build->log('LD_LIBRARY_PATH: ' . join ':', grep {defined} @LD_LIBRARY_PATH);
}
#foreach my $env_var (qw /LD_LIBRARY_PATH DYLD_LIBRARY_PATH LDFLAGS CFLAGS CXXFLAGS/) {
# say "ENV: $env_var is " . ($ENV{$env_var} // '');
#}
if (@cmake_prefix_path) {
my $path = join $Config{path_sep}, @cmake_prefix_path;
meta->around_hook(
build => sub {
my ($orig, $build, @args) = @_;
$build->log("Setting CMAKE_PREFIX_PATH to $path");
local $ENV{CMAKE_PREFIX_PATH} = $path;
$orig->($build, @args);
}
);
}
my $cmake_cmd = [
'%{cmake}',
-G => '%{cmake_generator}',
'-DCMAKE_MAKE_PROGRAM=%{make}',
#'-DBUILD_DOCUMENTATION=NO',
'-DBUILD_TESTING=OFF',
'-DBUILD_SHARED_LIBS=ON',
@with_args,
'-DCMAKE_INSTALL_PREFIX:PATH=%{.install.prefix}',
'-DCMAKE_BUILD_TYPE=Release',
@drivers_to_disable,
@env_args,
'..'
];
build [
#\&pause,
#\&cleanup_ldflags,
'mkdir _build',
'cd _build',
$cmake_cmd,
$make_cmd,
\&patch_pkgconfig,
$make_inst_cmd,
\&patch_rpaths,
];
}
};
sub find_lib_file {
my %args = @_;
my(@lib_files) = find_lib(
%args,
systempath => $args{alien} ? [] : undef, # only search the alien if one is passed
);
# we grab the first, assuming they are
# all the same or point to the same origin
my $libfile = $lib_files[0] // '';
$libfile =~ s|\\|/|g if $on_windows;
Alien::Build->log ("Found $args{lib} dynamic lib: $libfile");
return $libfile;
}
sub patch_rpaths {
= capture {system $otool, '-l', $so_file};
#};
#$build->log ($@) if $@;
#$build->log (@errors) if @errors;
$build->log ($stderr) if $stderr;
#$build->log($otool_text); # debug
# now we need to extract the rpaths
my @lines = split "\n", $otool_text;
my @existing_paths;
while (defined (my $line = shift @lines)) {
if ($line =~ /RPATH/) {
shift @lines;
$line = shift @lines;
$line =~ s/^\s+path\s//;
$line =~ s/\s\(offset.+$//;
push @existing_paths, $line;
}
}
# remove existing
if (@existing_paths) {
$build->log ("removing existing rpaths " . join ' ', @existing_paths);
my @delete_args = map {; '-delete_rpath' => $_} @existing_paths;
($result, $stderr, @errors)
= capture {system $install_name_tool, @delete_args, $so_file};
#$build->log($result);
$build->log($stderr) if $stderr;
}
# now append the existing ones
push @inst_tool_rpath_args, map {; '-add_rpath' => $_} @existing_paths;
# prepend our paths
($result, $stderr, @errors)
= capture {system $install_name_tool, @inst_tool_rpath_args, $so_file};
#$build->log($result);
$build->log($stderr) if $stderr;
}
return;
}
# we can get dangling -L values
# bandaid until we find the source
sub cleanup_ldflags {
my ($build, @args) = @_;
if ($ENV{LDFLAGS} && $ENV{LDFLAGS} =~ /\s*-L\s*$/) {
$build->log("Trimming trailing -L from $ENV{LDFLAGS}");
$ENV{LDFLAGS} =~ s/\s*-L\s*$//;
}
#$orig->($build, @args);
return;
}
sub update_pkg_conf_path {
return if !$on_windows;
use Env qw /@PKG_CONFIG_PATH/;
say 'Modifying drive paths in PKG_CONFIG_PATH';
say $ENV{PKG_CONFIG_PATH};
# msys-ificate drive paths
@PKG_CONFIG_PATH = map {my $x = $_; $x =~ s{^([a-z]):}{/$1}i; $x} @PKG_CONFIG_PATH;
say $ENV{PKG_CONFIG_PATH};
return;
}
# git for windows clashes with MSYS
# if its /usr/bin dir is in the path
sub remove_gitfw_from_path {
my ($orig, $build, @args) = @_;
return $orig->($build, @args)
if !$on_windows;
local $ENV{PATH} = $ENV{PATH};
my $msys_path = eval {
path('Alien::MSYS'->msys_path())
};
return if !defined $msys_path;
my $count = @PATH;
@PATH
= grep {path($_)->stringify =~ m|/usr/bin$| && path($_) ne $msys_path ? () : $_}
@PATH;
my $removed = $count - @PATH;
if ($removed) {
$build->log ("$removed additional .../usr/bin dirs were removed from the path for compilation");
}
$orig->($build, @args);
}
sub pause {
return; # re-enable in case of debug
# return if $on_automated_rig;
# return if !$on_windows;
say "CONTINUE?";
my $response = <>;
while (not $response =~ /yes/) {
$response = <>;
}
}
sub patch_pkgconfig {
#my $gdal_config_file = 'bin/gdal-config';
#my $pkg_config_file = 'lib/pkgconfig/gdal.pc';
use File::Find::Rule;
my @gdal_configs
= File::Find::Rule->file()
->name( 'gdal-config' )
->in( '.' );
my @pkg_configs
= File::Find::Rule->file()
->name( 'gdal.pc' )
->in( '.' );
say 'gdal-configs: ' . join ' ', @gdal_configs;
say 'pkg-configs: ' . join ' ', @pkg_configs;
return if !@gdal_configs || !@pkg_configs;
open my $gc_fh, '<', $gdal_configs[0] or die $!;
my $dep_libs = '';
while (defined (my $line = <$gc_fh>)) {
if ($line =~ /CONFIG_DEP_LIBS=(.+)$/) {
$dep_libs = $1;
last;
}
}
close $gc_fh;
# trim quotes (could do in prev check, but...)
$dep_libs =~ s/^\"//;
$dep_libs =~ s/\"$//;
open my $pk_fh, '<', $pkg_configs[0] or die $!;
my @pkg_conf;
while (defined (my $line = <$pk_fh>)) {
push @pkg_conf, $line;
}
close $pk_fh;
# change all (we should be more nuanced and do only the one that matters)
foreach my $pkg_config_file (@pkg_configs) {
say "Adding gdal dep_libs to $pkg_config_file";
# now add the dep libs to the pkg_conf file
open $pk_fh, '>', $pkg_config_file or die $!;
foreach my $line (@pkg_conf) {
if ($line =~ /^CONFIG_INST_LIBS/) {
chomp $line;
$line .= " $dep_libs\n";
}
print {$pk_fh} $line;
}
close $pk_fh;
}
}
sub get_gdal_version {
my $h = get_alien_state_hash();
return $h->{runtime}{version};
}
sub get_alien_state_hash {
use JSON::PP;
my $root = "$base_dir/_alien";
my $f = "$root/state.json";
my $h = {};
if (-e $f) {
open my $fh, '<', $f or die $!;
my $d = do {
local $/ = undef;
<$fh>;
};
$h = JSON::PP::decode_json($d);
}
return $h;
}
sub get_drivers_to_disable {
#return;
my @gdal_drivers = qw /
jdem xpm zmap blx
cals ceos coasp
cosar ctg dimap elas
fit gff gxf
hf2 iris leveller
msgn prf
rmf rs2 sgi sigdem
stacta terragen til rik
ozi
/;
my @ogr_drivers = qw /
tiger edigeo wasp vdv
geoconcept georss gmt
jml
/;
my @args;
push @args, map {"-DGDAL_ENABLE_DRIVER_${_}_PLUGIN:BOOL=OFF"} map {uc} @gdal_drivers;
push @args, map {"-DOGR_ENABLE_DRIVER_${_}_PLUGIN:BOOL=OFF"} map {uc} @ogr_drivers;
return wantarray ? @args : \@args;
}
( run in 0.434 second using v1.01-cache-2.11-cpan-483215c6ad5 )