]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - make/utilities.pm
dc286da5ed5e2029c0bdf56a41955870c954013a
[user/henk/code/inspircd.git] / make / utilities.pm
1 #
2 # InspIRCd -- Internet Relay Chat Daemon
3 #
4 #   Copyright (C) 2010 Daniel De Graaf <danieldg@inspircd.org>
5 #   Copyright (C) 2007-2008 Craig Edwards <craigedwards@brainbox.cc>
6 #   Copyright (C) 2008 Thomas Stagner <aquanight@inspircd.org>
7 #   Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
8 #
9 # This file is part of InspIRCd.  InspIRCd is free software: you can
10 # redistribute it and/or modify it under the terms of the GNU General Public
11 # License as published by the Free Software Foundation, version 2.
12 #
13 # This program is distributed in the hope that it will be useful, but WITHOUT
14 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
16 # details.
17 #
18 # You should have received a copy of the GNU General Public License
19 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 #
21
22
23 BEGIN {
24         require 5.8.0;
25 }
26
27 package make::utilities;
28
29 use strict;
30 use warnings FATAL => qw(all);
31
32 use Exporter 'import';
33 use Fcntl;
34 use File::Path;
35 use Getopt::Long;
36 use POSIX;
37
38 our @EXPORT = qw(make_rpath pkgconfig_get_include_dirs pkgconfig_get_lib_dirs pkgconfig_check_version translate_functions promptstring);
39
40 my %already_added = ();
41
42 sub promptstring($$$$$)
43 {
44         my ($prompt, $configitem, $default, $package, $commandlineswitch) = @_;
45         my $var;
46         if (!$main::interactive)
47         {
48                 my $opt_commandlineswitch;
49                 GetOptions ("$commandlineswitch=s" => \$opt_commandlineswitch);
50                 if (defined $opt_commandlineswitch)
51                 {
52                         print "\e[1;32m$opt_commandlineswitch\e[0m\n";
53                         $var = $opt_commandlineswitch;
54                 }
55                 else
56                 {
57                         die "Could not detect $package! Please specify the $prompt via the command line option \e[1;32m--$commandlineswitch=\"/path/to/file\"\e[0m";
58                 }
59         }
60         else
61         {
62                 print "\nPlease enter the $prompt?\n";
63                 print "[\e[1;32m$default\e[0m] -> ";
64                 chomp($var = <STDIN>);
65         }
66         if ($var eq "")
67         {
68                 $var = $default;
69         }
70         $main::config{$configitem} = $var;
71 }
72
73 sub make_rpath($;$)
74 {
75         my ($executable, $module) = @_;
76         return "" if defined $ENV{DISABLE_RPATH};
77         chomp(my $data = `$executable`);
78         my $output = "";
79         while ($data =~ /-L(\S+)/)
80         {
81                 my $libpath = $1;
82                 if (!exists $already_added{$libpath})
83                 {
84                         print "Adding runtime library path to \e[1;32m$module\e[0m ... \e[1;32m$libpath\e[0m\n";
85                         $already_added{$libpath} = 1;
86                 }
87                 $output .= "-Wl,-rpath -Wl,$libpath -L$libpath ";
88                 $data =~ s/-L(\S+)//;
89         }
90         return $output;
91 }
92
93 sub extend_pkg_path()
94 {
95         if (!exists $ENV{PKG_CONFIG_PATH})
96         {
97                 $ENV{PKG_CONFIG_PATH} = "/usr/lib/pkgconfig:/usr/local/lib/pkgconfig:/usr/local/libdata/pkgconfig:/usr/X11R6/libdata/pkgconfig";
98         }
99         else
100         {
101                 $ENV{PKG_CONFIG_PATH} .= ":/usr/local/lib/pkgconfig:/usr/local/libdata/pkgconfig:/usr/X11R6/libdata/pkgconfig";
102         }
103 }
104
105 sub pkgconfig_get_include_dirs($$$;$)
106 {
107         my ($packagename, $headername, $defaults, $module) = @_;
108
109         extend_pkg_path();
110
111         print "Locating include directory for package \e[1;32m$packagename\e[0m for module \e[1;32m$module\e[0m... ";
112
113         my $v = `pkg-config --modversion $packagename 2>/dev/null`;
114         my $ret = `pkg-config --cflags $packagename 2>/dev/null`;
115         my $foo = "";
116         if ((!defined $v) || ($v eq ""))
117         {
118                 print "\e[31mCould not find $packagename via pkg-config\e[m (\e[1;32mplease install pkg-config\e[m)\n";
119                 my $locbin = $^O eq 'solaris' ? 'slocate' : 'locate';
120                 $foo = `$locbin "$headername" 2>/dev/null | head -n 1`;
121                 my $find = $foo =~ /(.+)\Q$headername\E/ ? $1 : '';
122                 chomp($find);
123                 if ((defined $find) && ($find ne "") && ($find ne $packagename))
124                 {
125                         print "(\e[1;32mFound via search\e[0m) ";
126                         $foo = "-I$1";
127                 }
128                 else
129                 {
130                         $foo = " ";
131                         undef $v;
132                 }
133                 $ret = "$foo";
134         }
135         if (($defaults ne "") && (($ret eq "") || (!defined $ret)))
136         {
137                 $ret = "$foo " . $defaults;
138         }
139         chomp($ret);
140         if ((($ret eq " ") || (!defined $ret)) && ((!defined $v) || ($v eq "")))
141         {
142                 my $key = "default_includedir_$packagename";
143                 if (exists $main::config{$key})
144                 {
145                         $ret = $main::config{$key};
146                 }
147                 else
148                 {
149                         $headername =~ s/^\///;
150                         promptstring("path to the directory containing $headername", $key, "/usr/include",$packagename,"$packagename-includes");
151                         $packagename =~ tr/a-z/A-Z/;
152                         if (defined $v)
153                         {
154                                 $main::config{$key} = "-I$main::config{$key}" . " $defaults -DVERSION_$packagename=\"$v\"";
155                         }
156                         else
157                         {
158                                 $main::config{$key} = "-I$main::config{$key}" . " $defaults -DVERSION_$packagename=\"0.0\"";
159                         }
160                         $main::config{$key} =~ s/^\s+//g;
161                         $ret = $main::config{$key};
162                         return $ret;
163                 }
164         }
165         else
166         {
167                 chomp($v);
168                 my $key = "default_includedir_$packagename";
169                 $packagename =~ tr/a-z/A-Z/;
170                 $main::config{$key} = "$ret -DVERSION_$packagename=\"$v\"";
171                 $main::config{$key} =~ s/^\s+//g;
172                 $ret = $main::config{$key};
173                 print "\e[1;32m$ret\e[0m (version $v)\n";
174         }
175         $ret =~ s/^\s+//g;
176         return $ret;
177 }
178
179 sub pkgconfig_check_version($$;$)
180 {
181         my ($packagename, $version, $module) = @_;
182
183         extend_pkg_path();
184
185         print "Checking version of package \e[1;32m$packagename\e[0m is >= \e[1;32m$version\e[0m... ";
186
187         my $v = `pkg-config --modversion $packagename 2>/dev/null`;
188         if (defined $v)
189         {
190                 chomp($v);
191         }
192         if ((defined $v) && ($v ne ""))
193         {
194                 if (!system "pkg-config --atleast-version $version $packagename")
195                 {
196                         print "\e[1;32mYes (version $v)\e[0m\n";
197                         return 1;
198                 }
199                 else
200                 {
201                         print "\e[1;32mNo (version $v)\e[0m\n";
202                         return 0;
203                 }
204         }
205         # If we didnt find it, we  cant definitively say its too old.
206         # Return ok, and let pkgconflibs() or pkgconfincludes() pick up
207         # the missing library later on.
208         print "\e[1;32mNo (not found)\e[0m\n";
209         return 1;
210 }
211
212 sub pkgconfig_get_lib_dirs($$$;$)
213 {
214         my ($packagename, $libname, $defaults, $module) = @_;
215
216         extend_pkg_path();
217
218         print "Locating library directory for package \e[1;32m$packagename\e[0m for module \e[1;32m$module\e[0m... ";
219
220         my $v = `pkg-config --modversion $packagename 2>/dev/null`;
221         my $ret = `pkg-config --libs $packagename 2>/dev/null`;
222
223         my $foo = "";
224         if ((!defined $v) || ($v eq ""))
225         {
226                 my $locbin = $^O eq 'solaris' ? 'slocate' : 'locate';
227                 $foo = `$locbin "$libname" | head -n 1`;
228                 $foo =~ /(.+)\Q$libname\E/;
229                 my $find = $1;
230                 chomp($find);
231                 if ((defined $find) && ($find ne "") && ($find ne $packagename))
232                 {
233                         print "(\e[1;32mFound via search\e[0m) ";
234                         $foo = "-L$1";
235                 }
236                 else
237                 {
238                         $foo = " ";
239                         undef $v;
240                 }
241                 $ret = "$foo";
242         }
243
244         if (($defaults ne "") && (($ret eq "") || (!defined $ret)))
245         {
246                 $ret = "$foo " . $defaults;
247         }
248         chomp($ret);
249         if ((($ret eq " ") || (!defined $ret)) && ((!defined $v) || ($v eq "")))
250         {
251                 my $key = "default_libdir_$packagename";
252                 if (exists $main::config{$key})
253                 {
254                         $ret = $main::config{$key};
255                 }
256                 else
257                 {
258                         $libname =~ s/^\///;
259                         promptstring("path to the directory containing $libname", $key, "/usr/lib",$packagename,"$packagename-libs");
260                         $main::config{$key} = "-L$main::config{$key}" . " $defaults";
261                         $main::config{$key} =~ s/^\s+//g;
262                         $ret = $main::config{$key};
263                         return $ret;
264                 }
265         }
266         else
267         {
268                 chomp($v);
269                 print "\e[1;32m$ret\e[0m (version $v)\n";
270                 my $key = "default_libdir_$packagename";
271                 $main::config{$key} = $ret;
272                 $main::config{$key} =~ s/^\s+//g;
273                 $ret =~ s/^\s+//g;
274         }
275         $ret =~ s/^\s+//g;
276         return $ret;
277 }
278
279 # Translate a $CompileFlags etc line and parse out function calls
280 # to functions within these modules at configure time.
281 sub translate_functions($$)
282 {
283         my ($line,$module) = @_;
284
285         eval
286         {
287                 $module =~ /modules*\/(.+?)$/;
288                 $module = $1;
289
290                 if ($line =~ /ifuname\(\!"(\w+)"\)/)
291                 {
292                         my $uname = $1;
293                         if ($uname eq $^O)
294                         {
295                                 $line = "";
296                                 return "";
297                         }
298
299                         $line =~ s/ifuname\(\!"(.+?)"\)//;
300                 }
301
302                 if ($line =~ /ifuname\("(\w+)"\)/)
303                 {
304                         my $uname = $1;
305                         if ($uname ne $^O)
306                         {
307                                 $line = "";
308                                 return "";
309                         }
310
311                         $line =~ s/ifuname\("(.+?)"\)//;
312                 }
313
314                 if ($line =~ /if\("(\w+)"\)/)
315                 {
316                         if (defined $main::config{$1})
317                         {
318                                 if (($main::config{$1} !~ /y/i) and ($main::config{$1} ne "1"))
319                                 {
320                                         $line = "";
321                                         return "";
322                                 }
323                         }
324
325                         $line =~ s/if\("(.+?)"\)//;
326                 }
327                 if ($line =~ /if\(\!"(\w+)"\)/)
328                 {
329                         if (!exists $main::config{$1})
330                         {
331                                 $line = "";
332                                 return "";
333                         }
334                         else
335                         {
336                                 if (defined $1)
337                                 {
338                                         if (exists ($main::config{$1}) and (($main::config{$1} =~ /y/i) or ($main::config{$1} eq "1")))
339                                         {
340                                                 $line = "";
341                                                 return "";
342                                         }
343                                 }
344                         }
345
346                         $line =~ s/if\(\!"(.+?)"\)//;
347                 }
348                 while ($line =~ /exec\("(.+?)"\)/)
349                 {
350                         print "Executing program for module \e[1;32m$module\e[0m ... \e[1;32m$1\e[0m\n";
351                         my $replace = `$1`;
352                         die $replace if ($replace =~ /Configuration failed/);
353                         chomp($replace);
354                         $line =~ s/exec\("(.+?)"\)/$replace/;
355                 }
356                 while ($line =~ /execruntime\("(.+?)"\)/)
357                 {
358                         $line =~ s/execruntime\("(.+?)"\)/`$1`/;
359                 }
360                 while ($line =~ /eval\("(.+?)"\)/)
361                 {
362                         print "Evaluating perl code for module \e[1;32m$module\e[0m ... ";
363                         my $tmpfile;
364                         do
365                         {
366                                 $tmpfile = tmpnam();
367                         } until sysopen(TF, $tmpfile, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW, 0700);
368                         print "(Created and executed \e[1;32m$tmpfile\e[0m)\n";
369                         print TF $1;
370                         close TF;
371                         my $replace = `perl $tmpfile`;
372                         chomp($replace);
373                         unlink($tmpfile);
374                         $line =~ s/eval\("(.+?)"\)/$replace/;
375                 }
376                 while ($line =~ /pkgconflibs\("(.+?)","(.+?)","(.+?)"\)/)
377                 {
378                         my $replace = pkgconfig_get_lib_dirs($1, $2, $3, $module);
379                         $line =~ s/pkgconflibs\("(.+?)","(.+?)","(.+?)"\)/$replace/;
380                 }
381                 while ($line =~ /pkgconfversion\("(.+?)","(.+?)"\)/)
382                 {
383                         if (pkgconfig_check_version($1, $2, $module) != 1)
384                         {
385                                 die "Version of package $1 is too old. Please upgrade it to version \e[1;32m$2\e[0m or greater and try again.";
386                         }
387                         # This doesnt actually get replaced with anything
388                         $line =~ s/pkgconfversion\("(.+?)","(.+?)"\)//;
389                 }
390                 while ($line =~ /pkgconflibs\("(.+?)","(.+?)",""\)/)
391                 {
392                         my $replace = pkgconfig_get_lib_dirs($1, $2, "", $module);
393                         $line =~ s/pkgconflibs\("(.+?)","(.+?)",""\)/$replace/;
394                 }
395                 while ($line =~ /pkgconfincludes\("(.+?)","(.+?)",""\)/)
396                 {
397                         my $replace = pkgconfig_get_include_dirs($1, $2, "", $module);
398                         $line =~ s/pkgconfincludes\("(.+?)","(.+?)",""\)/$replace/;
399                 }
400                 while ($line =~ /pkgconfincludes\("(.+?)","(.+?)","(.+?)"\)/)
401                 {
402                         my $replace = pkgconfig_get_include_dirs($1, $2, $3, $module);
403                         $line =~ s/pkgconfincludes\("(.+?)","(.+?)","(.+?)"\)/$replace/;
404                 }
405                 while ($line =~ /rpath\("(.+?)"\)/)
406                 {
407                         my $replace = make_rpath($1,$module);
408                         $line =~ s/rpath\("(.+?)"\)/$replace/;
409                 }
410         };
411         if ($@)
412         {
413                 my $err = $@;
414                 #$err =~ s/at .+? line \d+.*//g;
415                 print "\n\nConfiguration failed. The following error occured:\n\n$err\n";
416                 print "\nMake sure you have pkg-config installed\n";
417                 print "\nIn the case of gnutls configuration errors on debian,\n";
418                 print "Ubuntu, etc, you should ensure that you have installed\n";
419                 print "gnutls-bin as well as libgnutls-dev and libgnutls.\n";
420                 exit;
421         }
422         else
423         {
424                 return $line;
425         }
426 }
427
428 1;
429