2007-07-17 18:45:23 +00:00
# +------------------------------------+
# | Inspire Internet Relay Chat Daemon |
# +------------------------------------+
2007-07-16 17:30:04 +00:00
#
2009-01-24 13:31:09 +00:00
# InspIRCd: (C) 2002-2009 InspIRCd Development Team
2009-03-15 12:42:35 +00:00
# See: http://wiki.inspircd.org/Credits
2007-07-16 17:30:04 +00:00
#
2007-07-17 18:45:23 +00:00
# This program is free but copyrighted software; see
# the file COPYING for details.
2007-07-16 17:30:04 +00:00
#
2007-07-17 18:45:23 +00:00
# ---------------------------------------------------
2007-07-16 17:30:04 +00:00
package make::utilities ;
2007-08-25 10:36:20 +00:00
require 5.8 .0 ;
2008-01-17 21:36:02 +00:00
use strict ;
use warnings FATAL = > qw( all ) ;
2007-07-16 17:30:04 +00:00
use Exporter 'import' ;
use POSIX ;
use Getopt::Long ;
2008-01-17 21:36:02 +00:00
use Fcntl ;
our @ EXPORT = qw( make_rpath pkgconfig_get_include_dirs pkgconfig_get_lib_dirs pkgconfig_check_version translate_functions promptstring vcheck ) ;
2007-07-16 17:30:04 +00:00
# Parse the output of a *_config program,
# such as pcre_config, take out the -L
# directive and return an rpath for it.
2008-01-27 14:32:20 +00:00
# \e[1;32msrc/Makefile\e[0m
2007-07-16 17:30:04 +00:00
my % already_added = ( ) ;
2008-04-27 14:02:30 +00:00
my $ if_skip_lines = 0 ;
2007-07-16 17:30:04 +00:00
sub promptstring ($$$$$)
{
my ( $ prompt , $ configitem , $ default , $ package , $ commandlineswitch ) = @ _ ;
my $ var ;
if ( ! $ main:: interactive )
{
2008-01-17 21:36:02 +00:00
my $ opt_commandlineswitch ;
2007-07-16 17:30:04 +00:00
GetOptions ( "$commandlineswitch=s" = > \ $ opt_commandlineswitch ) ;
if ( defined $ opt_commandlineswitch )
{
2008-01-27 14:32:20 +00:00
print "\e[1;32m$opt_commandlineswitch\e[0m\n" ;
2007-07-16 17:30:04 +00:00
$ var = $ opt_commandlineswitch ;
}
else
{
2008-01-27 14:32:20 +00:00
die "Could not detect $package! Please specify the $prompt via the command line option \e[1;32m--$commandlineswitch=\"/path/to/file\"\e[0m" ;
2007-07-16 17:30:04 +00:00
}
}
else
{
print "\nPlease enter the $prompt?\n" ;
2008-01-27 14:32:20 +00:00
print "[\e[1;32m$default\e[0m] -> " ;
2007-07-16 17:30:04 +00:00
chomp ( $ var = <STDIN> ) ;
}
if ( $ var eq "" )
{
$ var = $ default ;
}
$ main:: config { $ configitem } = $ var ;
}
sub make_rpath ( $ ; $ )
{
my ( $ executable , $ module ) = @ _ ;
2008-01-17 21:36:02 +00:00
chomp ( my $ data = `$executable` ) ;
2007-07-16 17:30:04 +00:00
my $ output = "" ;
while ( $ data =~ /-L(\S+)/ )
{
2008-01-17 21:36:02 +00:00
my $ libpath = $ 1 ;
2007-07-16 17:30:04 +00:00
if ( ! exists $ already_added { $ libpath } )
{
2008-01-27 14:32:20 +00:00
print "Adding extra library path to \e[1;32m$module\e[0m ... \e[1;32m$libpath\e[0m\n" ;
2007-07-16 17:30:04 +00:00
$ already_added { $ libpath } = 1 ;
}
2007-11-03 18:09:26 +00:00
$ output . = "-Wl,--rpath -Wl,$libpath -L$libpath " unless defined $ main:: opt_disablerpath ;
2007-07-16 17:30:04 +00:00
$ data =~ s/-L(\S+)// ;
}
return $ output ;
}
sub extend_pkg_path ()
{
if ( ! exists $ ENV { PKG_CONFIG_PATH } )
{
$ ENV { PKG_CONFIG_PATH } = "/usr/lib/pkgconfig:/usr/local/lib/pkgconfig:/usr/local/libdata/pkgconfig:/usr/X11R6/libdata/pkgconfig" ;
}
else
{
$ ENV { PKG_CONFIG_PATH } . = ":/usr/local/lib/pkgconfig:/usr/local/libdata/pkgconfig:/usr/X11R6/libdata/pkgconfig" ;
}
}
sub pkgconfig_get_include_dirs ( $ $ $ ; $ )
{
my ( $ packagename , $ headername , $ defaults , $ module ) = @ _ ;
my $ key = "default_includedir_$packagename" ;
if ( exists $ main:: config { $ key } )
{
2008-01-27 14:32:20 +00:00
print "Locating include directory for package \e[1;32m$packagename\e[0m for module \e[1;32m$module\e[0m... " ;
2008-01-17 21:36:02 +00:00
my $ ret = $ main:: config { $ key } ;
2008-01-27 14:32:20 +00:00
print "\e[1;32m$ret\e[0m (cached)\n" ;
2007-07-16 17:30:04 +00:00
return $ ret ;
}
extend_pkg_path ( ) ;
2008-01-27 14:32:20 +00:00
print "Locating include directory for package \e[1;32m$packagename\e[0m for module \e[1;32m$module\e[0m... " ;
2007-07-16 17:30:04 +00:00
2008-01-17 21:36:02 +00:00
my $ v = `pkg-config --modversion $packagename 2>/dev/null` ;
my $ ret = `pkg-config --cflags $packagename 2>/dev/null` ;
my $ foo = "" ;
2007-07-16 17:30:04 +00:00
if ( ( ! defined $ v ) || ( $ v eq "" ) )
{
2009-06-26 12:10:16 +00:00
print "\e[31mCould not find $packagename via pkg-config\e[m (\e[1;32mplease install pkg-config\e[m)\n" ;
$ foo = `locate "$headername" 2>/dev/null | head -n 1` ;
my $ find = $ foo =~ /(.+)\Q$headername\E/ ? $ 1 : '' ;
2007-07-16 17:30:04 +00:00
chomp ( $ find ) ;
if ( ( defined $ find ) && ( $ find ne "" ) && ( $ find ne $ packagename ) )
{
2008-01-27 14:32:20 +00:00
print "(\e[1;32mFound via search\e[0m) " ;
2007-07-16 17:30:04 +00:00
$ foo = "-I$1" ;
}
else
{
$ foo = " " ;
undef $ v ;
}
$ ret = "$foo" ;
}
if ( ( $ defaults ne "" ) && ( ( $ ret eq "" ) || ( ! defined $ ret ) ) )
{
$ ret = "$foo " . $ defaults ;
}
chomp ( $ ret ) ;
if ( ( ( $ ret eq " " ) || ( ! defined $ ret ) ) && ( ( ! defined $ v ) || ( $ v eq "" ) ) )
{
my $ key = "default_includedir_$packagename" ;
if ( exists $ main:: config { $ key } )
{
$ ret = $ main:: config { $ key } ;
}
else
{
$ headername =~ s/^\/// ;
promptstring ( "path to the directory containing $headername" , $ key , "/usr/include" , $ packagename , "$packagename-includes" ) ;
$ packagename =~ tr /a-z/ A - Z / ;
2009-02-11 17:17:22 +00:00
if ( defined $ v )
{
$ main:: config { $ key } = "-I$main::config{$key}" . " $defaults -DVERSION_$packagename=\"$v\"" ;
}
else
{
$ main:: config { $ key } = "-I$main::config{$key}" . " $defaults -DVERSION_$packagename=\"0.0\"" ;
}
2007-07-16 17:30:04 +00:00
$ main:: config { $ key } =~ s/^\s+//g ;
$ ret = $ main:: config { $ key } ;
return $ ret ;
}
}
else
{
chomp ( $ v ) ;
my $ key = "default_includedir_$packagename" ;
$ packagename =~ tr /a-z/ A - Z / ;
$ main:: config { $ key } = "$ret -DVERSION_$packagename=\"$v\"" ;
$ main:: config { $ key } =~ s/^\s+//g ;
$ ret = $ main:: config { $ key } ;
2008-01-27 14:32:20 +00:00
print "\e[1;32m$ret\e[0m (version $v)\n" ;
2007-07-16 17:30:04 +00:00
}
$ ret =~ s/^\s+//g ;
return $ ret ;
}
sub vcheck ($$)
{
my ( $ version1 , $ version2 ) = @ _ ;
2008-01-17 21:36:02 +00:00
$ version1 =~ s/\-r(\d+)/\.$1/g ; # minor revs/patchlevels
$ version2 =~ s/\-r(\d+)/\.$1/g ;
$ version1 =~ s/p(\d+)/\.$1/g ;
$ version2 =~ s/p(\d+)/\.$1/g ;
2007-07-16 17:30:04 +00:00
$ version1 =~ s/\-//g ;
$ version2 =~ s/\-//g ;
2008-01-17 21:36:02 +00:00
$ version1 =~ s/[a-z]//g ;
$ version2 =~ s/[a-z]//g ;
2007-07-16 17:30:04 +00:00
my @ v1 = split ( '\.' , $ version1 ) ;
my @ v2 = split ( '\.' , $ version2 ) ;
2008-02-13 19:23:01 +00:00
for ( my $ curr = 0 ; $ curr < scalar ( @ v2 ) ; $ curr + + )
2007-07-16 17:30:04 +00:00
{
if ( $ v1 [ $ curr ] < $ v2 [ $ curr ] )
{
return 0 ;
}
}
return 1 ;
}
sub pkgconfig_check_version ( $ $ ; $ )
{
my ( $ packagename , $ version , $ module ) = @ _ ;
extend_pkg_path ( ) ;
2008-01-27 14:32:20 +00:00
print "Checking version of package \e[1;32m$packagename\e[0m is >= \e[1;32m$version\e[0m... " ;
2007-07-16 17:30:04 +00:00
2008-01-17 21:36:02 +00:00
my $ v = `pkg-config --modversion $packagename 2>/dev/null` ;
2007-07-16 17:30:04 +00:00
if ( defined $ v )
{
chomp ( $ v ) ;
}
if ( ( defined $ v ) && ( $ v ne "" ) )
{
if ( vcheck ( $ v , $ version ) == 1 )
{
2008-01-27 14:32:20 +00:00
print "\e[1;32mYes (version $v)\e[0m\n" ;
2007-07-16 17:30:04 +00:00
return 1 ;
}
else
{
2008-01-27 14:32:20 +00:00
print "\e[1;32mNo (version $v)\e[0m\n" ;
2007-07-16 17:30:04 +00:00
return 0 ;
}
}
# If we didnt find it, we cant definitively say its too old.
# Return ok, and let pkgconflibs() or pkgconfincludes() pick up
# the missing library later on.
2008-01-27 14:32:20 +00:00
print "\e[1;32mNo (not found)\e[0m\n" ;
2007-07-16 17:30:04 +00:00
return 1 ;
}
sub pkgconfig_get_lib_dirs ( $ $ $ ; $ )
{
my ( $ packagename , $ libname , $ defaults , $ module ) = @ _ ;
my $ key = "default_libdir_$packagename" ;
if ( exists $ main:: config { $ key } )
{
2008-01-27 14:32:20 +00:00
print "Locating library directory for package \e[1;32m$packagename\e[0m for module \e[1;32m$module\e[0m... " ;
2008-01-17 21:36:02 +00:00
my $ ret = $ main:: config { $ key } ;
2008-01-27 14:32:20 +00:00
print "\e[1;32m$ret\e[0m (cached)\n" ;
2007-07-16 17:30:04 +00:00
return $ ret ;
}
extend_pkg_path ( ) ;
2008-01-27 14:32:20 +00:00
print "Locating library directory for package \e[1;32m$packagename\e[0m for module \e[1;32m$module\e[0m... " ;
2007-07-16 17:30:04 +00:00
2008-01-17 21:36:02 +00:00
my $ v = `pkg-config --modversion $packagename 2>/dev/null` ;
my $ ret = `pkg-config --libs $packagename 2>/dev/null` ;
2007-07-16 17:30:04 +00:00
2008-01-17 21:36:02 +00:00
my $ foo = "" ;
2007-07-16 17:30:04 +00:00
if ( ( ! defined $ v ) || ( $ v eq "" ) )
{
$ foo = `locate "$libname" | head -n 1` ;
$ foo =~ /(.+)\Q$libname\E/ ;
2008-01-17 21:36:02 +00:00
my $ find = $ 1 ;
2007-07-16 17:30:04 +00:00
chomp ( $ find ) ;
if ( ( defined $ find ) && ( $ find ne "" ) && ( $ find ne $ packagename ) )
{
2008-01-27 14:32:20 +00:00
print "(\e[1;32mFound via search\e[0m) " ;
2007-07-16 17:30:04 +00:00
$ foo = "-L$1" ;
}
else
{
$ foo = " " ;
undef $ v ;
}
$ ret = "$foo" ;
}
if ( ( $ defaults ne "" ) && ( ( $ ret eq "" ) || ( ! defined $ ret ) ) )
{
$ ret = "$foo " . $ defaults ;
}
chomp ( $ ret ) ;
if ( ( ( $ ret eq " " ) || ( ! defined $ ret ) ) && ( ( ! defined $ v ) || ( $ v eq "" ) ) )
{
my $ key = "default_libdir_$packagename" ;
if ( exists $ main:: config { $ key } )
{
$ ret = $ main:: config { $ key } ;
}
else
{
$ libname =~ s/^\/// ;
promptstring ( "path to the directory containing $libname" , $ key , "/usr/lib" , $ packagename , "$packagename-libs" ) ;
$ main:: config { $ key } = "-L$main::config{$key}" . " $defaults" ;
$ main:: config { $ key } =~ s/^\s+//g ;
$ ret = $ main:: config { $ key } ;
return $ ret ;
}
}
else
{
chomp ( $ v ) ;
2008-01-27 14:32:20 +00:00
print "\e[1;32m$ret\e[0m (version $v)\n" ;
2007-07-16 17:30:04 +00:00
my $ key = "default_libdir_$packagename" ;
$ main:: config { $ key } = $ ret ;
$ main:: config { $ key } =~ s/^\s+//g ;
$ ret =~ s/^\s+//g ;
}
$ ret =~ s/^\s+//g ;
return $ ret ;
}
# Translate a $CompileFlags etc line and parse out function calls
# to functions within these modules at configure time.
sub translate_functions ($$)
{
my ( $ line , $ module ) = @ _ ;
eval
{
$ module =~ /modules*\/(.+?)$/ ;
$ module = $ 1 ;
# This is only a cursory check, just designed to catch casual accidental use of backticks.
# There are pleanty of ways around it, but its not supposed to be for security, just checking
# that people are using the new configuration api as theyre supposed to and not just using
# backticks instead of eval(), being as eval has accountability. People wanting to get around
# the accountability will do so anyway.
if ( ( $ line =~ /`/ ) && ( $ line !~ /eval\(.+?`.+?\)/ ) )
{
die "Developers should no longer use backticks in configuration macros. Please use exec() and eval() macros instead. Offending line: $line (In module: $module)" ;
}
2008-04-27 14:02:30 +00:00
2008-04-27 14:23:27 +00:00
if ( $ line =~ /ifuname\(\!"(\w+)"\)/ )
2008-04-27 14:02:30 +00:00
{
2008-04-27 14:23:27 +00:00
my $ uname = $ 1 ;
if ( $ uname eq $^O )
2008-04-27 14:02:30 +00:00
{
2008-04-27 14:23:27 +00:00
$ line = "" ;
return "" ;
2008-04-27 14:02:30 +00:00
}
2008-04-27 14:23:27 +00:00
$ line =~ s/ifuname\(\!"(.+?)"\)// ;
2008-04-27 14:02:30 +00:00
}
2008-04-27 14:23:27 +00:00
if ( $ line =~ /ifuname\("(\w+)"\)/ )
2008-04-27 14:02:30 +00:00
{
my $ uname = $ 1 ;
if ( $ uname ne $^O )
{
2008-04-27 14:23:27 +00:00
$ line = "" ;
return "" ;
2008-04-27 14:02:30 +00:00
}
2008-04-27 14:23:27 +00:00
$ line =~ s/ifuname\("(.+?)"\)// ;
2008-04-27 14:02:30 +00:00
}
2008-04-27 14:23:27 +00:00
if ( $ line =~ /if\("(\w+)"\)/ )
2008-04-27 14:02:30 +00:00
{
if ( defined $ main:: config { $ 1 } )
{
2008-04-27 14:46:33 +00:00
if ( ( $ main:: config { $ 1 } !~ /y/i ) and ( $ main:: config { $ 1 } ne "1" ) )
{
$ line = "" ;
return "" ;
}
2008-04-27 14:02:30 +00:00
}
2008-04-27 14:23:27 +00:00
$ line =~ s/if\("(.+?)"\)// ;
2008-04-27 14:02:30 +00:00
}
2008-04-27 17:17:59 +00:00
if ( $ line =~ /if\(\!"(\w+)"\)/ )
{
2008-04-27 17:37:50 +00:00
if ( ! exists $ main:: config { $ 1 } )
2008-04-27 17:17:59 +00:00
{
$ line = "" ;
return "" ;
}
else
{
2008-04-27 17:37:50 +00:00
if ( defined $ 1 )
2008-04-27 17:17:59 +00:00
{
2008-04-27 17:37:50 +00:00
if ( exists ( $ main:: config { $ 1 } ) and ( ( $ main:: config { $ 1 } =~ /y/i ) or ( $ main:: config { $ 1 } eq "1" ) ) )
{
$ line = "" ;
return "" ;
}
2008-04-27 17:17:59 +00:00
}
}
$ line =~ s/if\(\!"(.+?)"\)// ;
}
2007-07-16 17:30:04 +00:00
while ( $ line =~ /exec\("(.+?)"\)/ )
{
2008-01-27 14:32:20 +00:00
print "Executing program for module \e[1;32m$module\e[0m ... \e[1;32m$1\e[0m\n" ;
2007-07-16 17:30:04 +00:00
my $ replace = `$1` ;
2008-01-27 12:42:31 +00:00
die $ replace if ( $ replace =~ /Configuration failed/ ) ;
2007-07-16 17:30:04 +00:00
chomp ( $ replace ) ;
$ line =~ s/exec\("(.+?)"\)/$replace/ ;
}
2007-07-17 08:26:25 +00:00
while ( $ line =~ /execruntime\("(.+?)"\)/ )
{
2008-01-17 21:36:02 +00:00
$ line =~ s/execruntime\("(.+?)"\)/`$1`/ ;
2007-07-17 08:26:25 +00:00
}
2007-07-16 17:30:04 +00:00
while ( $ line =~ /eval\("(.+?)"\)/ )
{
2008-01-27 14:32:20 +00:00
print "Evaluating perl code for module \e[1;32m$module\e[0m ... " ;
2007-07-16 17:30:04 +00:00
my $ tmpfile ;
do
{
$ tmpfile = tmpnam ( ) ;
} until sysopen ( TF , $ tmpfile , O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW , 0700 ) ;
2008-01-27 14:32:20 +00:00
print "(Created and executed \e[1;32m$tmpfile\e[0m)\n" ;
2007-07-16 17:30:04 +00:00
print TF $ 1 ;
close TF ;
my $ replace = `perl $tmpfile` ;
chomp ( $ replace ) ;
$ line =~ s/eval\("(.+?)"\)/$replace/ ;
}
while ( $ line =~ /pkgconflibs\("(.+?)","(.+?)","(.+?)"\)/ )
{
my $ replace = pkgconfig_get_lib_dirs ( $ 1 , $ 2 , $ 3 , $ module ) ;
$ line =~ s/pkgconflibs\("(.+?)","(.+?)","(.+?)"\)/$replace/ ;
}
while ( $ line =~ /pkgconfversion\("(.+?)","(.+?)"\)/ )
{
if ( pkgconfig_check_version ( $ 1 , $ 2 , $ module ) != 1 )
{
2008-01-27 14:32:20 +00:00
die "Version of package $1 is too old. Please upgrade it to version \e[1;32m$2\e[0m or greater and try again." ;
2007-07-16 17:30:04 +00:00
}
# This doesnt actually get replaced with anything
$ line =~ s/pkgconfversion\("(.+?)","(.+?)"\)// ;
}
while ( $ line =~ /pkgconflibs\("(.+?)","(.+?)",""\)/ )
{
my $ replace = pkgconfig_get_lib_dirs ( $ 1 , $ 2 , "" , $ module ) ;
$ line =~ s/pkgconflibs\("(.+?)","(.+?)",""\)/$replace/ ;
}
while ( $ line =~ /pkgconfincludes\("(.+?)","(.+?)",""\)/ )
{
my $ replace = pkgconfig_get_include_dirs ( $ 1 , $ 2 , "" , $ module ) ;
$ line =~ s/pkgconfincludes\("(.+?)","(.+?)",""\)/$replace/ ;
}
while ( $ line =~ /pkgconfincludes\("(.+?)","(.+?)","(.+?)"\)/ )
{
my $ replace = pkgconfig_get_include_dirs ( $ 1 , $ 2 , $ 3 , $ module ) ;
$ line =~ s/pkgconfincludes\("(.+?)","(.+?)","(.+?)"\)/$replace/ ;
}
while ( $ line =~ /rpath\("(.+?)"\)/ )
{
my $ replace = make_rpath ( $ 1 , $ module ) ;
$ replace = "" if ( $^O =~ /darwin/i ) ;
$ line =~ s/rpath\("(.+?)"\)/$replace/ ;
}
} ;
if ( $@ )
{
2008-01-17 21:36:02 +00:00
my $ err = $@ ;
2008-04-27 14:46:33 +00:00
#$err =~ s/at .+? line \d+.*//g;
2007-07-16 17:30:04 +00:00
print "\n\nConfiguration failed. The following error occured:\n\n$err\n" ;
2009-01-04 19:34:03 +00:00
print "\nIn the case of gnutls configuration errors on debian,\n" ;
print "Ubuntu, etc, you should ensure that you have installed\n" ;
print "gnutls-bin as well as gnutls-dev and gnutls.\n" ;
2007-07-16 17:30:04 +00:00
exit ;
}
else
{
return $ line ;
}
}
1 ;