use
5.010;
use
File::Which
qw /which/;
use
FFI::CheckLib;
my
$on_windows
= $^O =~ /mswin/i;
my
$on_automated_rig
=
$ENV
{PERL_CPAN_REPORTER_DIR}
||
$ENV
{PERL_CPAN_REPORTER_CONFIG}
||
$ENV
{AUTOMATED_TESTING}
||
$ENV
{TRAVIS}
||
$ENV
{APPVEYOR}
||
$ENV
{CI};
my
$base_dir
= getcwd();
use
Env
qw( @PATH @PKG_CONFIG_PATH )
;
unshift
@PATH
, Alien::sqlite->bin_dir;
my
@dep_aliens
= (
'Alien::sqlite'
);
my
%have
;
my
$lib
=
'Alien::curl'
;
$have
{
$lib
} =
eval
"require $lib"
;
if
(
$have
{
$lib
}) {
unshift
@PATH
,
$lib
->dist_dir .
'/dynamic'
;
}
$lib
=
'Alien::libtiff'
;
$have
{
$lib
} =
eval
"require $lib"
;
if
(
$have
{
$lib
}) {
unshift
@PATH
,
$lib
->bin_dir;
push
@dep_aliens
,
$lib
if
$lib
->install_type eq
'share'
;
my
$p
;
if
(
$on_windows
&&
$lib
->install_type eq
'system'
) {
$p
= path ($^X)->parent->parent->parent .
'/c/lib/pkgconfig'
;
}
elsif
(
$lib
->install_type eq
'share'
) {
$p
= path (
$lib
->dist_dir,
'lib'
,
'pkgconfig'
);
}
if
(
$p
&& -e
$p
) {
push
@PKG_CONFIG_PATH
,
$p
;
say
join
' '
,
@PKG_CONFIG_PATH
;
}
}
say
"Alien::sqlite has sqlite version "
. Alien::sqlite->version;
my
$min_target_version
=
'7.1'
;
plugin
'PkgConfig'
=> (
pkg_name
=>
'proj'
,
minimum_version
=>
$min_target_version
,
);
if
(
$on_windows
) {
if
(
my
$path
= `where geos_c.dll`) {
Alien::Build->
log
(
'Found possible GIS Internals build'
);
$path
= Path::Tiny::path (
$path
)->parent;
my
@proj_dlls
=
map
{
$_
->[0]}
sort
{ versioncmp(
$a
->[-1],
$b
->[-1]) }
map
{
$_
=~ /(\d+)_(\d+)/; [
$_
,
"$1.$2"
] }
glob
(
"$path/proj*.dll"
);
$proj_dlls
[-1] =~ /(\d+)_(\d+)/;
my
$version
=
"$1.$2"
;
if
(versioncmp (
$version
,
$min_target_version
) > 0) {
$path
= Path::Tiny::path(
$proj_dlls
[-1])->parent->stringify;
$path
=~ s|\\|/|g;
Alien::Build->
log
(
"Probe::CBuilder checking $path"
);
plugin
'Probe::CBuilder'
=> (
cflags
=>
"-I$path/include"
,
libs
=>
"-L$path/lib -lproj"
,
);
}
}
}
share {
plugin
'Build::SearchDep'
=> (
aliens
=> [
grep
{
$_
->install_type eq
'share'
}
@dep_aliens
],
public_I
=> 1,
public_l
=> 1,
);
if
(
$on_windows
) {
plugin
'Prefer::BadVersion'
=>
'7.1.0'
;
}
plugin
Download
=> (
filter
=>
qr/^proj-([0-9\.]+)\.tar\.gz$/
,
version
=>
qr/^proj-([0-9\.]+)\.tar\.gz$/
,
);
my
$proj_version
= get_proj_version() //
'not yet defined'
;
say
"Downloaded proj version is $proj_version"
;
die
"Downloaded proj version $proj_version is too low "
.
"(should be >= $min_target_version).\n"
.
"Please update your Alien::Build::Fetch::Cache if using one."
if
defined
$proj_version
&& versioncmp (
$proj_version
,
$min_target_version
) < 0;
plugin
Extract
=> (
format
=>
'tar.gz'
);
plugin
'Build::CMake'
=> ();
plugin
'Build::MSYS'
;
if
($^O =~ /bsd|dragonfly/) {
plugin
'Build::Make'
=>
'gmake'
;
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'
;
}
}
elsif
($^O eq
'MSWin32'
) {
plugin
'Build::Make'
=>
'gmake'
;
}
my
$make_cmd
=
'%{make}'
;
my
$make_inst_cmd
=
'%{make} install'
;
my
@make_clean
;
if
(
$on_automated_rig
) {
say
"Running under CI or automated testing"
;
if
(!
$ENV
{CI}) {
plugin
'Cleanse::BuildDir'
;
}
}
my
$config_args
=
$ENV
{ALIEN_PROJ_CONFIG_ARGS} //
''
;
$config_args
=~ s/[^-\s\w,=]//g;
my
$enable_tiff
=
'OFF'
;
my
$enable_curl
=
'OFF'
;
my
@curl_extra_args
;
my
@tiff_extra_args
;
my
@alien_rpaths
;
if
(
$proj_version
ge 7) {
if
(!
$have
{
'Alien::libtiff'
} or
$config_args
=~ /--(without-tiff|
with
-tiff=
no
)/) {
$enable_tiff
=
'OFF'
;
Alien::Build->
log
(
'Disabling TIFF support'
);
}
else
{
$enable_tiff
=
'ON'
;
Alien::Build->
log
(
'Enabling TIFF support'
);
my
$libtiff_include
;
my
$libtiff_rpath
= ();
if
(Alien::libtiff->install_type (
'share'
)) {
$libtiff_include
= path (
'Alien::libtiff'
->dist_dir .
'/include'
)->stringify;
$libtiff_rpath
= Alien::libtiff->dist_dir .
'/lib'
;
}
else
{
if
(
$on_windows
) {
my
$p
= path ($^X)->parent->parent->parent .
'/c/include'
;
if
(path(
$p
)->
exists
) {
$libtiff_include
=
$p
;
}
}
else
{
my
$libfile
= find_lib (
lib
=>
'tiff'
);
push
@tiff_extra_args
,
"-DTIFF_LIBRARY=$libfile"
;
}
}
if
(
$libtiff_include
) {
my
$libfile
= find_lib_file (
lib
=>
'tiff'
,
alien
=>
'Alien::libtiff'
,
);
push
@tiff_extra_args
, (
"-DTIFF_LIBRARY=$libfile"
,
"-DTIFF_INCLUDE_DIR=$libtiff_include"
,
);
push
@alien_rpaths
,
$libtiff_rpath
;
}
if
(!
@tiff_extra_args
) {
Alien::Build->
log
(
'Disabling TIFF support'
);
$enable_tiff
=
'OFF'
;
}
}
if
(!
$have
{
'Alien::curl'
} or
$config_args
=~ /--(without-curl|
with
-curl=
no
)/ ) {
$enable_curl
=
'OFF'
;
}
else
{
my
$dynamic_config
= path (
'Alien::curl'
->dist_dir .
'/dynamic/curl-config'
);
if
(-e
$dynamic_config
) {
Alien::Build->
log
(
"Adding curl support from "
.
'Alien::curl'
->dist_dir .
"/dynamic"
);
$enable_curl
=
"ON"
;
push
@PATH
, path (
'Alien::curl'
->dist_dir .
'/dynamic'
);
my
$curl_include
= path (
'Alien::curl'
->dist_dir .
'/include'
)->stringify;
my
$libfile
= find_lib_file (
lib
=>
'curl'
,
alien
=>
'Alien::curl'
,
);
push
@curl_extra_args
, (
"-DCURL_LIBRARY=$libfile"
,
"-DCURL_INCLUDE_DIR=$curl_include"
,
);
push
@alien_rpaths
, Alien::curl->dist_dir .
'/dynamic'
;
}
elsif
(
'Alien::curl'
->install_type eq
'system'
) {
if
(
'Alien::curl'
->cflags =~ /STATIC_LIB/) {
$enable_curl
=
'OFF'
;
Alien::Build->
log
(
'Disabling curl support. You have Alien::curl but it lacks a dynamic curl-config'
);
}
else
{
Alien::Build->
log
(
'Adding curl support from system'
);
$enable_curl
=
"ON"
;
my
$libfile
= find_lib_file (
lib
=>
'curl'
,
);
my
$curl_include
= Alien::curl->cflags;
$curl_include
=~s/^-I//g;
push
@curl_extra_args
, (
"-DCURL_LIBRARY=$libfile"
,
"-DCURL_INCLUDE_DIR=$curl_include"
,
);
}
}
else
{
Alien::Build->
log
(
'Disabling curl support. You have Alien::curl, but it lacks a dynamic curl-config'
);
$enable_curl
=
'OFF'
;
}
}
}
my
@sqlite_extra_args
;
if
(Alien::sqlite->install_type (
'share'
)) {
Alien::Build->
log
(
'Shared Alien::sqlite found, adding sqlite3 components to configure call'
);
my
$sqlite_include
= path (
'Alien::sqlite'
->dist_dir .
'/include'
)->stringify;
my
$libfile
= find_lib_file (
lib
=>
'sqlite3'
,
alien
=>
'Alien::sqlite'
,
);
my
$exe_extension
= (
$on_windows
?
'.exe'
:
''
);
my
$sqlite_exe
= path (
'Alien::sqlite'
->dist_dir .
"/bin/sqlite3$exe_extension"
);
push
@sqlite_extra_args
, (
"-DEXE_SQLITE3=$sqlite_exe"
,
"-DSQLite3_LIBRARY=$libfile"
,
"-DSQLite3_INCLUDE_DIR=$sqlite_include"
,
);
push
@alien_rpaths
, Alien::sqlite->dist_dir .
'/lib'
;
}
plugin
'PkgConfig::PPWrapper'
;
meta->around_hook(
build
=> \
&remove_gitfw_from_path
);
meta->around_hook(
build
=> \
&update_cmake_lists_file
);
meta->around_hook(
build
=>
sub
{
my
(
$orig
,
$build
,
@args
) =
@_
;
$build
->
log
(
"Setting CCACHE_BASEDIR to "
. getcwd());
local
$ENV
{CCACHE_BASEDIR} = getcwd();
$orig
->(
$build
,
@args
);
}
);
Alien::Build->
log
(
'PKG_CONFIG_PATH:'
.
join
' '
,
grep
{
defined
}
@PKG_CONFIG_PATH
);
foreach
my
$env_var
(
qw /LD_LIBRARY_PATH
LDFLAGS CFLAGS CXXFLAGS/) {
say
"ENV: $env_var is "
. (
$ENV
{
$env_var
} //
''
);
}
my
$h
= get_alien_state_hash();
my
$install_path
=
$h
->{install}{prefix};
my
@rpath
;
if
(!
$on_windows
&&
defined
$install_path
&&
@alien_rpaths
) {
my
$origin_string
= $^O =~ /darwin/ ?
'@loader_path'
:
'\$ORIGIN'
;
my
$alien_rpath_text
=
join
':'
,
(
map
{
$origin_string
.
'/../'
. path (
$_
)->relative(
$install_path
)->stringify}
@alien_rpaths
),
@alien_rpaths
;
@rpath
= (
qq{-DCMAKE_INSTALL_RPATH='$alien_rpath_text'}
);
}
my
$cmake_cmd
= [
'%{cmake}'
,
-G
=>
'%{cmake_generator}'
,
'-DCMAKE_MAKE_PROGRAM=%{make}'
,
'-DBUILD_TESTING=OFF'
,
'-DBUILD_SHARED_LIBS=ON'
,
@sqlite_extra_args
,
"-DENABLE_CURL=$enable_curl"
,
$enable_curl
eq
'ON'
?
@curl_extra_args
: (),
"-DENABLE_TIFF=$enable_tiff"
,
$enable_tiff
eq
'ON'
?
@tiff_extra_args
: (),
'-DBUILD_PROJSYNC=OFF'
,
'-DCMAKE_INSTALL_PREFIX:PATH=%{.install.prefix}'
,
'-DCMAKE_BUILD_TYPE=Release'
,
@rpath
,
'..'
];
build [
'mkdir _build'
,
'cd _build'
,
$cmake_cmd
,
$make_cmd
,
$make_inst_cmd
,
];
};
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
update_pkg_conf_path {
return
;
return
if
!
$on_windows
;
use
Env
qw /@PKG_CONFIG_PATH/;
say
'Modifying drive paths in PKG_CONFIG_PATH'
;
say
$ENV
{PKG_CONFIG_PATH};
@PKG_CONFIG_PATH
=
map
{
my
$r
=
$_
;
$r
=~s{^([a-z]):}{/$1}i;
$r
}
@PKG_CONFIG_PATH
;
@PKG_CONFIG_PATH
=
map
{
my
$r
=
$_
;
$r
=~s{Alien-curl[/\\]lib[/\\]pkgconfig}{Alien-curl/dynamic/pkgconfig}i;
$r
}
@PKG_CONFIG_PATH
;
$ENV
{PKG_CONFIG_PATH} =
join
':'
,
@PKG_CONFIG_PATH
;
say
$ENV
{PKG_CONFIG_PATH};
return
;
}
sub
pause {
return
;
return
if
$on_automated_rig
;
return
if
!
$on_windows
;
say
"CONTINUE?"
;
my
$response
= <>;
while
(not
$response
=~ /yes/) {
$response
= <>;
}
}
sub
update_cmake_lists_file {
my
(
$orig
,
$build
,
@args
) =
@_
;
return
$orig
->(
$build
,
@args
)
if
$on_windows
and versioncmp (get_proj_version(),
'9.0.0'
) < 0;
$build
->
log
(
'updating CMakeLists.txt to properly handle proj.pc'
);
my
(
$cmake_lists_file
)
= File::Find::Rule
->file()
->name(
'CMakeLists.txt'
)
->in(
$build
->install_prop->{extract} );
open
my
$fh
,
'<'
,
$cmake_lists_file
or
die
"Could not open $cmake_lists_file for reading, $!"
;
my
$file_contents
;
my
$define_check
=
<<EOD
if(NOT DEFINED CMAKE_INSTALL_LIBDIR)
set(CMAKE_INSTALL_LIBDIR lib)
endif(NOT DEFINED CMAKE_INSTALL_LIBDIR)
EOD
;
while
(
my
$line
= <
$fh
>) {
if
(
$line
=~ /^\s
*configure_proj_pc
/) {
$line
.=
$define_check
;
}
$file_contents
.=
$line
;
}
$fh
->
close
;
rename
$cmake_lists_file
,
"$cmake_lists_file.bak"
;
open
my
$ofh
,
'>'
,
$cmake_lists_file
or
die
"Could not open $cmake_lists_file for writing, $!"
;
print
{
$ofh
}
$file_contents
;
$ofh
->
close
or
die
$!;
$orig
->(
$build
,
@args
);
}
sub
find_lib_file {
my
%args
=
@_
;
my
(
@lib_files
) = find_lib(
%args
,
systempath
=>
$args
{alien} ? [] :
undef
,
);
my
$libfile
=
$lib_files
[0];
$libfile
=~ s|\\|/|g
if
$on_windows
;
Alien::Build->
log
(
"Found $args{lib} dynamic lib: $libfile"
);
return
$libfile
;
}
sub
get_proj_version {
my
$h
= get_alien_state_hash();
return
$h
->{runtime}{version};
}
sub
get_alien_state_hash {
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
;
}