]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - make/configure.pm
Correctly detect the compiler version and whether it is acceptable.
[user/henk/code/inspircd.git] / make / configure.pm
1 #
2 # InspIRCd -- Internet Relay Chat Daemon
3 #
4 #   Copyright (C) 2012 Peter Powell <petpow@saberuk.com>
5 #   Copyright (C) 2008 Robin Burchell <robin+git@viroteck.net>
6 #   Copyright (C) 2007-2008 Craig Edwards <craigedwards@brainbox.cc>
7 #   Copyright (C) 2008 Thomas Stagner <aquanight@inspircd.org>
8 #   Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
9 #
10 # This file is part of InspIRCd.  InspIRCd is free software: you can
11 # redistribute it and/or modify it under the terms of the GNU General Public
12 # License as published by the Free Software Foundation, version 2.
13 #
14 # This program is distributed in the hope that it will be useful, but WITHOUT
15 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
17 # details.
18 #
19 # You should have received a copy of the GNU General Public License
20 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 #
22
23
24 package make::configure;
25
26 require 5.8.0;
27
28 use strict;
29 use warnings FATAL => qw(all);
30
31 use Exporter 'import';
32 use POSIX;
33 use make::utilities;
34 our @EXPORT = qw(get_compiler_info find_compiler test_file test_header promptnumeric dumphash is_dir getmodules getrevision getcompilerflags getlinkerflags getdependencies nopedantic resolve_directory yesno showhelp promptstring_s module_installed);
35
36 my $no_git = 0;
37
38 sub get_compiler_info($) {
39         my %info = (NAME => shift, VERSION => '0.0');
40         my $version = `$info{NAME} -v 2>&1`;
41                 return (ERROR => 1) if $?;
42         if ($version =~ /(?:clang|llvm)\sversion\s(\d+\.\d+)/i) {
43                 $info{NAME} = 'Clang';
44                 $info{VERSION} = $1;
45                 $info{UNSUPPORTED} = $1 lt '3.0';
46                 $info{REASON} = 'Clang 2.9 and older do not have adequate C++ support.';
47         } elsif ($version =~ /gcc\sversion\s(\d+\.\d+)/i) {
48                 $info{NAME} = 'GCC';
49                 $info{VERSION} = $1;
50                 $info{UNSUPPORTED} = $1 lt '4.1';
51                 $info{REASON} = 'GCC 4.0 and older do not have adequate C++ support.';
52         } elsif ($version =~ /(?:icc|icpc)\sversion\s(\d+\.\d+).\d+\s\(gcc\sversion\s(\d+\.\d+).\d+/i) {
53                 $info{NAME} = 'ICC';
54                 $info{VERSION} = $1;
55                 $info{UNSUPPORTED} = $2 lt '4.1';
56                 $info{REASON} = "ICC $1 (GCC $2 compatibility mode) does not have adequate C++ support."
57         }
58         return %info;
59 }  
60
61 sub find_compiler {
62         foreach my $compiler ('c++', 'g++', 'clang++', 'icpc') {
63                 return $compiler unless system "$compiler -v > /dev/null 2>&1";
64                 if ($^O eq 'Darwin') {
65                         return $compiler unless system "xcrun $compiler -v > /dev/null 2>&1";
66                 }
67         }
68         return "";
69 }
70
71 sub test_file($$;$) {
72         my ($cc, $file, $args) = @_;
73         my $status = 0;
74         $args ||= '';
75         $status ||= system "$cc -o __test_$file make/test/$file $args >/dev/null 2>&1";
76         $status ||= system "./__test_$file >/dev/null 2>&1";
77         unlink  "./__test_$file";
78         return !$status;
79 }
80
81 sub test_header($$;$) {
82         my ($cc, $header, $args) = @_;
83         $args ||= '';
84         open(CC, "| $cc -E - $args >/dev/null 2>&1") or return 0;
85         print CC "#include <$header>";
86         close(CC);
87         return !$?;
88 }
89
90 sub yesno {
91         my ($flag,$prompt) = @_;
92         print "$prompt [\e[1;32m$main::config{$flag}\e[0m] -> ";
93         chomp(my $tmp = <STDIN>);
94         if ($tmp eq "") { $tmp = $main::config{$flag} }
95         if (($tmp eq "") || ($tmp =~ /^y/i))
96         {
97                 $main::config{$flag} = "y";
98         }
99         else
100         {
101                 $main::config{$flag} = "n";
102         }
103         return;
104 }
105
106 sub resolve_directory
107 {
108         my $ret = $_[0];
109         eval
110         {
111                 use File::Spec;
112                 $ret = File::Spec->rel2abs($_[0]);
113         };
114         return $ret;
115 }
116
117 sub getrevision {
118         if ($no_git)
119         {
120                 return "0";
121         }
122         my $data = `git describe --tags 2>/dev/null`;
123         if ($data eq "")
124         {
125                 $no_git = 1;
126                 return '0';
127         }
128         chomp $data; # remove \n
129         return $data;
130 }
131
132 sub getcompilerflags {
133         my ($file) = @_;
134         open(FLAGS, $file) or return "";
135         while (<FLAGS>) {
136                 if ($_ =~ /^\/\* \$CompileFlags: (.+) \*\/$/) {
137                         my $x = translate_functions($1, $file);
138                         next if ($x eq "");
139                         close(FLAGS);
140                         return $x;
141                 }
142         }
143         close(FLAGS);
144         return "";
145 }
146
147 sub getlinkerflags {
148         my ($file) = @_;
149         open(FLAGS, $file) or return "";
150         while (<FLAGS>) {
151                 if ($_ =~ /^\/\* \$LinkerFlags: (.+) \*\/$/) {
152                         my $x = translate_functions($1, $file);
153                         next if ($x eq "");
154                         close(FLAGS);
155                         return $x;
156                 }
157         }
158         close(FLAGS);
159         return "";
160 }
161
162 sub getdependencies {
163         my ($file) = @_;
164         open(FLAGS, $file) or return "";
165         while (<FLAGS>) {
166                 if ($_ =~ /^\/\* \$ModDep: (.+) \*\/$/) {
167                         my $x = translate_functions($1, $file);
168                         next if ($x eq "");
169                         close(FLAGS);
170                         return $x;
171                 }
172         }
173         close(FLAGS);
174         return "";
175 }
176
177 sub nopedantic {
178         my ($file) = @_;
179         open(FLAGS, $file) or return "";
180         while (<FLAGS>) {
181                 if ($_ =~ /^\/\* \$NoPedantic \*\/$/) {
182                         my $x = translate_functions($_, $file);
183                         next if ($x eq "");
184                         close(FLAGS);
185                         return 1;
186                 }
187         }
188         close(FLAGS);
189         return 0;
190 }
191
192 sub getmodules
193 {
194         my ($silent) = @_;
195
196         my $i = 0;
197
198         if (!$silent)
199         {
200                 print "Detecting modules ";
201         }
202
203         opendir(DIRHANDLE, "src/modules") or die("WTF, missing src/modules!");
204         foreach my $name (sort readdir(DIRHANDLE))
205         {
206                 if ($name =~ /^m_(.+)\.cpp$/)
207                 {
208                         my $mod = $1;
209                         $main::modlist[$i++] = $mod;
210                         if (!$silent)
211                         {
212                                 print ".";
213                         }
214                 }
215         }
216         closedir(DIRHANDLE);
217
218         if (!$silent)
219         {
220                 print "\nOk, $i modules.\n";
221         }
222 }
223
224 sub promptnumeric($$)
225 {
226         my $continue = 0;
227         my ($prompt, $configitem) = @_;
228         while (!$continue)
229         {
230                 print "Please enter the maximum $prompt?\n";
231                 print "[\e[1;32m$main::config{$configitem}\e[0m] -> ";
232                 chomp(my $var = <STDIN>);
233                 if ($var eq "")
234                 {
235                         $var = $main::config{$configitem};
236                 }
237                 if ($var =~ /^\d+$/) {
238                         # We don't care what the number is, set it and be on our way.
239                         $main::config{$configitem} = $var;
240                         $continue = 1;
241                         print "\n";
242                 } else {
243                         print "You must enter a number in this field. Please try again.\n\n";
244                 }
245         }
246 }
247
248 sub module_installed($)
249 {
250         my $module = shift;
251         eval("use $module;");
252         return !$@;
253 }
254
255 sub promptstring_s($$)
256 {
257         my ($prompt,$default) = @_;
258         my $var;
259         print "$prompt\n";
260         print "[\e[1;32m$default\e[0m] -> ";
261         chomp($var = <STDIN>);
262         $var = $default if $var eq "";
263         print "\n";
264         return $var;
265 }
266
267 sub dumphash()
268 {
269         print "\n\e[1;32mPre-build configuration is complete!\e[0m\n\n";
270         print "\e[0mBase install path:\e[1;32m\t\t$main::config{BASE_DIR}\e[0m\n";
271         print "\e[0mConfig path:\e[1;32m\t\t\t$main::config{CONFIG_DIR}\e[0m\n";
272         print "\e[0mModule path:\e[1;32m\t\t\t$main::config{MODULE_DIR}\e[0m\n";
273         print "\e[0mCompiler:\e[1;32m\t\t\t$main::cxx{NAME} $main::cxx{VERSION}\e[0m\n";
274         print "\e[0mGnuTLS Support:\e[1;32m\t\t\t$main::config{USE_GNUTLS}\e[0m\n";
275         print "\e[0mOpenSSL Support:\e[1;32m\t\t$main::config{USE_OPENSSL}\e[0m\n\n";
276         print "\e[1;32mImportant note: The maximum length values are now configured in the\e[0m\n";
277         print "\e[1;32m                configuration file, not in ./configure! See the <limits>\e[0m\n";
278         print "\e[1;32m                tag in the configuration file for more information.\e[0m\n\n";
279 }
280
281 sub is_dir
282 {
283         my ($path) = @_;
284         if (chdir($path))
285         {
286                 chdir($main::this);
287                 return 1;
288         }
289         else
290         {
291                 # Just in case..
292                 chdir($main::this);
293                 return 0;
294         }
295 }
296
297 sub showhelp
298 {
299         chomp(my $PWD = `pwd`);
300         print <<EOH;
301 Usage: configure [options]
302
303 *** NOTE: NON-INTERACTIVE CONFIGURE IS *NOT* SUPPORTED BY THE ***
304 *** INSPIRCD DEVELOPMENT TEAM. DO NOT ASK FOR HELP REGARDING  ***
305 ***     NON-INTERACTIVE CONFIGURE ON THE FORUMS OR ON IRC!    ***
306
307 Options: [defaults in brackets after descriptions]
308
309 When no options are specified, interactive
310 configuration is started and you must specify
311 any required values manually. If one or more
312 options are specified, non-interactive configuration
313 is started, and any omitted values are defaulted.
314
315 Arguments with a single \"-\" symbol, as in
316 InspIRCd 1.0.x, are also allowed.
317
318   --disable-interactive        Sets no options itself, but
319                                will disable any interactive prompting.
320   --update                     Update makefiles and dependencies
321   --clean                      Remove .config.cache file and go interactive
322   --enable-gnutls              Enable GnuTLS module [no]
323   --enable-openssl             Enable OpenSSL module [no]
324   --enable-epoll               Enable epoll() where supported [set]
325   --enable-kqueue              Enable kqueue() where supported [set]
326   --disable-epoll              Do not enable epoll(), fall back
327                                to select() [not set]
328   --disable-kqueue             Do not enable kqueue(), fall back
329                                to select() [not set]
330   --prefix=[directory]         Base directory to install into (if defined,
331                                can automatically define config, module, bin
332                                and library dirs as subdirectories of prefix)
333                                [$PWD]
334   --config-dir=[directory]     Config file directory for config and SSL certs
335                                [$PWD/conf]
336   --log-dir=[directory]        Log file directory for logs
337                                [$PWD/logs]
338   --data-dir=[directory]       Data directory for variable data, such as the permchannel configuration and the XLine database
339                                [$PWD/data]
340   --module-dir=[directory]     Modules directory for loadable modules
341                                [$PWD/modules]
342   --binary-dir=[directory]     Binaries directory for core binary
343                                [$PWD/bin]
344   --library-dir=[directory]    Library directory for core libraries
345                                [$PWD/lib]
346   --list-extras                Show current status of extra modules
347   --enable-extras=[extras]     Enable the specified list of extras
348   --disable-extras=[extras]    Disable the specified list of extras
349   --help                       Show this help text and exit
350
351 EOH
352         exit(0);
353 }
354
355 1;
356