]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - configure
Add $NoPedantic build macro, for m_mysql because mysql AB dont know how to code :p
[user/henk/code/inspircd.git] / configure
1 #!/usr/bin/perl
2 ###################################################
3 # InspIRCd Configuration Script
4 #
5 # Copyright 2002-2007 The InspIRCd Development Team
6 #  http://www.inspircd.org/wiki/index.php/Credits
7 #
8 # Licensed under GPL, please see the COPYING file
9 # for more information
10 #
11 # $Id$
12 #
13 ###################################################
14
15 require 5.8.0;
16 use Socket;
17 use Cwd;
18 use Getopt::Long;
19
20 # Utility functions for our buildsystem
21 use make::utilities;
22 use make::configure;
23 use make::gnutlscert;
24 use make::opensslcert;
25
26 ###############################################################################################
27 #
28 #                                   EDITABLE VARIABLES
29 #
30 ###############################################################################################
31
32 # If you wish to ignore a dependency throughout the entire core, add it here.
33
34 my @ignoredeps = (
35         "inspircd_win32wrapper.h",      # windows has its own configure program
36 );
37
38 # If you wish for all files in the entire core to have a given dependency, insert it here.
39 # You should keep this to an absolute minimum to avoid rebuilds that are not neccessary.
40
41 my @immutabledeps = (
42         "inspircd_config.h",            # auto re-generated by configure
43         "inspircd.h",
44 );
45
46 ###############################################################################################
47 #
48 #                                 NON-EDITABLE VARIABLES
49 #
50 ###############################################################################################
51
52 # List of commands that make up 'make install'
53
54 my $install_list = "";
55
56 # This is a list of all files in the core. Each cpp file is mapped to a shared object file,
57 # whos file extension is omitted (these can vary from system to system). Auto detected by
58 # scanning the src/*.cpp files for files containing /* $Core: */ identifiers.
59
60 my %filelist = ();
61
62 # If you wish for a file to have special dependencies in the makefile, add an entry here.
63 # Auto populated by /* $ExtraDeps: */ instruction
64
65 my %specialdeps = ();
66
67 # If you wish for a file to have extra make lines (in between the compile and link steps)
68 # then insert them here.
69 # Auto populated by /* $ExtraBuild: */ instruction
70         
71 my %extrabuildlines = ();
72
73 # If you wish for a file to be linked against extra objects or arctives, insert them here.
74 # Auto populated by /* $ExtraObjects: */ instruction
75
76 my %extraobjects = ();
77
78 # If you wish to compile extra cpp sources into an object, define them here.
79 # NOTE: Certain cpp files such as the socket engines have a value auto calculated
80 # for this table so that their derived class is built.
81 # Auto populated by /* $ExtraSources: */ instruction
82
83 my %extrasources = ();
84
85
86 GetOptions (
87         'enable-gnutls' => \$opt_use_gnutls,
88         'rebuild' => \$opt_rebuild,
89         'enable-openssl' => \$opt_use_openssl,
90         'disable-interactive' => \$opt_nointeractive,
91         'with-nick-length=i' => \$opt_nick_length,
92         'with-channel-length=i' => \$opt_chan_length,
93         'with-max-clients=i' => \$opt_maxclients,
94         'enable-ports' => \$opt_ports,
95         'enable-epoll' => \$opt_epoll,
96         'enable-kqueue' => \$opt_kqueue,
97         'disable-ports' => \$opt_noports,
98         'disable-epoll' => \$opt_noepoll,
99         'disable-kqueue' => \$opt_nokqueue,
100         'enable-ipv6' => \$opt_ipv6,
101         'enable-remote-ipv6' => \$opt_ipv6links,
102         'disable-remote-ipv6' => \$opt_noipv6links,
103         'with-cc=s' => \$opt_cc,
104         'with-ident-length=i' => \$opt_ident,
105         'with-quit-length=i' => \$opt_quit,
106         'with-topic-length=i' => \$opt_topic,
107         'with-maxbuf=i' => \$opt_maxbuf,
108         'with-kick-length=i' => \$opt_kick,
109         'with-gecos-length=i' => \$opt_gecos,
110         'with-away-length=i' => \$opt_away,
111         'with-max-modes=i' => \$opt_modes,
112         'prefix=s' => \$opt_base_dir,
113         'config-dir=s' => \$opt_config_dir,
114         'module-dir=s' => \$opt_module_dir,
115         'binary-dir=s' => \$opt_binary_dir,
116         'library-dir=s' => \$opt_library_dir,
117         'disable-debuginfo' => sub { $opt_disable_debug = 1 },
118         'help'  => sub { showhelp(); },
119         'modupdate' => sub { modupdate(); },
120         'update' => sub { update(); },
121         'svnupdate' => sub { svnupdate(); },
122         'clean' => sub { clean(); },
123 );
124
125 my $non_interactive = (
126         (defined $opt_library_dir) ||
127         (defined $opt_base_dir) ||
128         (defined $opt_config_dir) ||
129         (defined $opt_module_dir) ||
130         (defined $opt_base_dir) ||
131         (defined $opt_binary_dir) ||
132         (defined $opt_nointeractive) ||
133         (defined $opt_away) ||
134         (defined $opt_gecos) ||
135         (defined $opt_kick) ||
136         (defined $opt_maxclients) ||
137         (defined $opt_modes) ||
138         (defined $opt_topic) ||
139         (defined $opt_quit) ||
140         (defined $opt_ident) ||
141         (defined $opt_cc) ||
142         (defined $opt_ipv6) ||
143         (defined $opt_ipv6links) ||
144         (defined $opt_noipv6links) ||
145         (defined $opt_kqueue) ||
146         (defined $opt_epoll) ||
147         (defined $opt_ports) ||
148         (defined $opt_maxchans) ||
149         (defined $opt_opermaxchans) ||
150         (defined $opt_chan_length) ||
151         (defined $opt_nick_length) ||
152         (defined $opt_use_openssl) ||
153         (defined $opt_nokqueue) ||
154         (defined $opt_noepoll) ||
155         (defined $opt_noports) ||
156         (defined $opt_maxbuf) ||
157         (defined $opt_use_gnutls)
158 );
159 my $interactive = !$non_interactive;
160
161
162 chomp($topdir = getcwd());
163 $this = resolve_directory($topdir);                                             # PWD, Regardless.
164 @modlist = ();                                                                  # Declare for Module List..
165 %config = ();                                                                   # Initiate Configuration Hash..
166 $config{ME}              = resolve_directory($topdir);                          # Present Working Directory
167
168 $config{BASE_DIR}          = $config{ME};
169
170 if (defined $opt_base_dir)
171 {
172         $config{BASE_DIR} = $opt_base_dir;
173 }
174
175 $config{CONFIG_DIR}      = resolve_directory($config{BASE_DIR}."/conf");        # Configuration Directory
176 $config{MODULE_DIR}      = resolve_directory($config{BASE_DIR}."/modules");     # Modules Directory
177 $config{BINARY_DIR}      = resolve_directory($config{BASE_DIR}."/bin");         # Binary Directory
178 $config{LIBRARY_DIR}    = resolve_directory($config{BASE_DIR}."/lib");          # Library Directory
179
180 if (defined $opt_config_dir)
181 {
182         $config{CONFIG_DIR} = $opt_config_dir;
183 }
184 if (defined $opt_module_dir)
185 {
186         $config{MODULE_DIR} = $opt_module_dir;
187 }
188 if (defined $opt_binary_dir)
189 {
190         $config{BINARY_DIR} = $opt_binary_dir;
191 }
192 if (defined $opt_library_dir)
193 {
194         $config{LIBRARY_DIR} = $opt_library_dir;
195 }
196 chomp($config{HAS_GNUTLS}   = `libgnutls-config --version 2>/dev/null | cut -c 1,2,3`); # GNUTLS Version.
197 chomp($config{HAS_OPENSSL}  = `pkg-config --modversion openssl 2>/dev/null`);           # Openssl version
198 chomp($gnutls_ver = $config{HAS_GNUTLS});
199 chomp($openssl_ver = $config{HAS_OPENSSL});
200 $config{USE_GNUTLS}         = "n";
201 if (defined $opt_use_gnutls)
202 {
203         $config{USE_GNUTLS} = "y";                                      # Use gnutls.
204 }
205 $config{USE_OPENSSL}    = "n";                                          # Use openssl.
206 if (defined $opt_use_openssl)
207 {
208         $config{USE_OPENSSL} = "y";
209 }
210
211 # no, let's not change these.
212 $config{OPTIMITEMP}      = "0";                                         # Default Optimisation Value
213 if (!defined $opt_disable_debug)
214 {
215         $config{OPTIMISATI}      = "-g1";                               # Optimisation Flag
216 }
217 else
218 {
219         $config{OPTIMISATI}      = "-O2";                               # DEBUGGING OFF!
220 }
221
222 $config{NICK_LENGT}      = "31";                                        # Default Nick Length
223 if (defined $opt_nick_length)
224 {
225         $config{NICK_LENGT} = $opt_nick_length;
226 }
227 $config{CHAN_LENGT}      = "64";                                        # Default Channel Name Length
228 if (defined $opt_chan_length)
229 {
230         $config{CHAN_LENGT} = $opt_chan_length;
231 }
232 $config{MAXI_MODES}      = "20";                                        # Default Max. Number of Modes set at once.
233 if (defined $opt_modes)
234 {
235         $config{MAXI_MODES} = $opt_modes;
236 }
237 $config{HAS_STRLCPY}    = "false";                                      # strlcpy Check.
238 $config{HAS_STDINT}      = "false";                                     # stdint.h check
239 $config{USE_KQUEUE}      = "y";                                         # kqueue enabled
240 if (defined $opt_kqueue)
241 {
242         $config{USE_KQUEUE} = "y";
243 }
244 if (defined $opt_nokqueue)
245 {
246         $config{USE_KQUEUE} = "n";
247 }
248 $config{USE_EPOLL}        = "y";                                        # epoll enabled
249 if (defined $opt_epoll)
250 {
251         $config{USE_EPOLL} = "y";
252 }
253 if (defined $opt_noepoll)
254 {
255         $config{USE_EPOLL} = "n";
256 }
257 $config{USE_PORTS}        = "y";                                        # epoll enabled
258 if (defined $opt_ports)
259 {
260         $config{USE_PORTS} = "y";
261 }
262 if (defined $opt_noports)
263 {
264         $config{USE_PORTS} = "n";
265 }
266 $config{IPV6}          = "n";                                           # IPv6 support (experimental)
267 if (defined $opt_ipv6)
268 {
269         $config{IPV6} = "y";
270 }
271 $config{SUPPORT_IP6LINKS}   = "y";                                      # IPv4 supporting IPv6 links (experimental)
272 if (defined $opt_ipv6links)
273 {
274         $config{SUPPORT_IP6LINKS} = "y";
275 }
276 if (defined $opt_noipv6links)
277 {
278         $config{SUPPORT_IP6LINKS} = "n";
279 }
280 chomp($config{MAX_CLIENT_T} = `sh -c \"ulimit -n\"`);                   # FD Limit
281 chomp($config{MAX_DESCRIPTORS} = `sh -c \"ulimit -n\"`);                # Hard FD Limit
282 chomp($config{GCCVER}       = `g++ -dumpversion | cut -c 1`);           # Major GCC Version
283 $config{_SOMAXCONN} = SOMAXCONN;                                        # Max connections in accept queue
284 $config{OSNAME}             = $^O;                                      # Operating System Name
285 $config{IS_DARWIN}        = "NO";                                       # Is OSX?
286 $config{STARTSCRIPT}      = "inspircd";                 # start script?
287 $config{DESTINATION}      = "BASE";                             # Is target path.
288 $config{EXTRA_DIR}        = "";                                         # Is empty.
289 if ($config{OSNAME} =~ /darwin/i)
290 {
291         $config{IS_DARWIN} = "YES";
292         $config{STARTSCRIPT}      = "org.inspircd.plist";               # start script for OSX.
293         $config{DESTINATION}      = "LAUNCHDPATH";                              # Is OSX target.
294         $config{EXTRA_DIR}          = " launchd_dir";                           # Is OSX specific path.
295 }
296 $config{CC}                 = "g++";                                            # C++ compiler
297 if (defined $opt_cc)
298 {
299         $config{CC} = $opt_cc;
300 }
301 $exec = $config{CC} . " -dumpversion | cut -c 1";
302 chomp($config{GCCVER}           = `$exec`);                             # Major GCC Version
303 $config{MAKEORDER}              = "ircd mods";                          # build order
304 $config{MAX_IDENT}              = "12";                                 # max ident size
305 $config{MAX_QUIT}               = "255";                                # max quit message size
306 $config{MAX_TOPIC}              = "307";                                # max topic size
307 $config{MAX_KICK}               = "255";                                # max kick message size
308 $config{MAX_GECOS}              = "128";                                # max GECOS size
309 $config{MAX_AWAY}               = "200";                                # max AWAY size
310 $config{MAXBUF}                 = "512";                                # Max buffer size
311 if (defined $opt_ident)
312 {
313         $config{MAX_IDENT} = $opt_ident;
314 }
315 if (defined $opt_quit)
316 {
317         $config{MAX_QUIT} = $opt_quit;
318 }
319 if (defined $opt_topic)
320 {
321         $config{MAX_TOPIC} = $opt_topic;
322 }
323 if (defined $opt_kick)
324 {
325         $config{MAX_KICK} = $opt_kick;
326 }
327 if (defined $opt_gecos)
328 {
329         $config{MAX_GECOS} = $opt_gecos;
330 }
331 if (defined $opt_away)
332 {
333         $config{MAX_AWAY} = $opt_away;
334 }
335
336 $config{HAS_OPENSSL} =~ /^([-[:digit:].]+)([a-z])?(\-[a-z][0-9])?$/;
337 $config{HAS_OPENSSL} = $1;
338
339 if ($config{GCCVER} eq "") {
340         print $config{CC} . " was not found! You require g++ (the GNU C++ compiler, part of GCC) to build InspIRCd!\n";
341         exit;
342 }
343
344 if (!$config{MAX_CLIENT_T}) { 
345         $config{MAX_CLIENT_T} = 1024;                            # Set a reasonable 'Default'
346         $fd_scan_fail = "true";                                # Used Later
347 }
348
349 # Get and Set some important vars..
350 getmodules();
351
352 sub clean
353 {
354         system("rm -rf .config.cache");
355 }
356
357 sub update
358 {
359         eval {
360                 chomp($topdir = getcwd());
361                 $this = resolve_directory($topdir);                                          # PWD, Regardless.
362                 getmodules();
363                 # Does the cache file exist?
364                 if (!getcache()) {
365                         # No, No it doesn't.. *BASH*
366                         print "You have not run ./configure before. Please do this before trying to run the update script.\n";
367                         exit 0;
368                 } else {
369                         # We've Loaded the cache file and all our variables..
370                         print "Updating Files..\n";
371                         getosflags();
372                         if ($opt_disable_debug == 1)
373                         {
374                                 print "Disabling debug information (-g).\n";
375                                 $config{OPTIMISATI} = "";
376                                 getosflags();
377                         }
378                         $has_epoll = $config{HAS_EPOLL};
379                         $has_ports = $config{HAS_PORTS};
380                         $has_kqueue = $config{HAS_KQUEUE};
381                         writefiles(1);
382                         makecache();
383                         print "Complete.\n";
384                         exit;
385                 }
386         };
387         if ($@)
388         {
389                 print "Configure update failed: $@\n";
390         }
391         exit;
392 }
393
394 sub modupdate
395 {
396         eval {
397                 chomp($topdir = getcwd());
398                 $this = resolve_directory($topdir);                                          # PWD, Regardless.
399                 getmodules();
400                 # Does the cache file exist?
401                 if (!getcache()) {
402                         # No, No it doesn't.. *BASH*
403                         print "You have not run ./configure before. Please do this before trying to run the update script.\n";
404                         exit 0;
405                 } else {
406                         # We've Loaded the cache file and all our variables..
407                         print "Updating Files..\n";
408                         getosflags();
409                         $has_epoll = $config{HAS_EPOLL};
410                         $has_ports = $config{HAS_PORTS};
411                         $has_kqueue = $config{HAS_KQUEUE};
412                         writefiles(0);
413                         makecache();
414                         print "Complete.\n";
415                         exit;
416                 }
417         };
418         if ($@)
419         {
420                 print "Module update failed: $@\n";
421         }
422         exit;
423 }
424
425
426
427 sub svnupdate
428 {
429         my $fail = 0;
430         open(FH,"<.svn/entries") or $fail = 1;
431         if ($fail) {
432                 print "This is not an SVN copy of InspIRCd.\n";
433                 exit;
434         }
435         else
436         {
437                 close(FH);
438         }
439         system("svn update");
440         system("perl configure -update");
441         if (defined $opt_rebuild) {
442                 system("make install");
443         }
444         exit;
445 }
446
447 print "Running non-interactive configure...\n" unless $interactive;
448 print "Checking for cache from previous configure... ";
449 print ((!getcache()) ? "not found\n" : "found\n");
450 print "Checking operating system version... ";
451 print getosflags() . "\n";
452
453 if (defined $opt_maxclients)
454 {
455         $config{MAX_CLIENT} = $opt_maxclients;
456 }
457
458 if (!$config{MAX_CLIENT}) { 
459         # If the cache hasn't set the max clients, copy the variable of MAX_CLIENT_T, this
460         # allows us to keep _T for testing purposes. (ie. "Are you sure you want to go
461         # higher than the found value" :))
462         $config{MAX_CLIENT} = $config{MAX_CLIENT_T};
463 }
464
465 printf "Checking if stdint.h exists... ";
466 $config{HAS_STDINT} = "true";
467 my $fail = 0;
468 open(STDINT, "</usr/include/stdint.h") or $config{HAS_STDINT} = "false";
469 if ($config{HAS_STDINT} eq "true") {
470         close(STDINT);
471 }
472 print "yes\n" if $config{HAS_STDINT} eq "true";
473 print "no\n" if $config{HAS_STDINT} eq "false";
474
475
476 printf "Checking if strlcpy exists... ";
477 # Perform the strlcpy() test..
478 $config{HAS_STRLCPY} = "false";
479 my $fail = 0;
480 open(STRLCPY, "</usr/include/string.h") or $fail = 1;
481 if (!$fail) {
482         while (chomp($line = <STRLCPY>)) {
483                 # try and find the delcaration of:
484                 # size_t strlcpy(...)
485                 if ($line =~ /size_t(\0x9|\s)+strlcpy/) {
486                         $config{HAS_STRLCPY} = "true";
487                 }
488         }
489         close(STRLCPY);
490 }
491 print "yes\n" if $config{HAS_STRLCPY} eq "true";
492 print "no\n" if $config{HAS_STRLCPY} eq "false";
493
494
495 printf "Checking if kqueue exists... ";
496 $has_kqueue = 0;
497 $fail = 0;
498 open(KQUEUE, "</usr/include/sys/event.h") or $fail = 1;
499 if (!$fail) {
500         while (chomp($line = <KQUEUE>)) {
501                 # try and find the delcaration of:
502                 # int kqueue(void);
503                 if ($line =~ /int(\0x9|\s)+kqueue/) {
504                         $has_kqueue = 1;
505                 }
506         }
507         close(KQUEUE);
508 }
509 print "yes\n" if $has_kqueue == 1;
510 print "no\n" if $has_kqueue == 0;
511
512 printf "Checking if epoll exists... ";
513 $has_epoll = 0;
514 $fail = 0;
515 open(EPOLL, "</usr/include/sys/epoll.h") or $fail = 1;
516 if (!$fail) {
517         $has_epoll = 1;
518         close(EPOLL);
519 }
520 if ($has_epoll) {
521         my $kernel = `uname -r`;
522         chomp($kernel);
523         if (($kernel =~ /^2\.0\./) || ($kernel =~ /^2\.2\./) || ($kernel =~ /^2\.4\./)) {
524                 $has_epoll = 0;
525         }
526         else
527         {
528                 # Suggestion from nenolod, weed out odd systems which have glibc built
529                 # against 2.4 kernels (ick)
530                 my $kernel_arch = `uname -p`;
531                 chomp($kernel_arch);
532                 $libcv = 0.0;
533                 $kernelv = 0.0;
534                 if ($kernel_arch =~ /x86_64/) {
535                         open (FH,"/lib64/libc.so.6|") or $has_epoll = 0;
536                 }
537                 else {
538                         open (FH,"/lib/libc.so.6|") or $has_epoll = 0;
539                 }
540                 if ($has_epoll)
541                 {
542                         while (chomp($line = <FH>))
543                         {
544                                 if ($line =~ /GNU C Library .* version (.*?) /)
545                                 {
546                                         $libcv = $1;
547                                         $libcv =~  /(\d+\.\d+)/;
548                                         $libcv = $1;
549                                 }
550                                 elsif ($line =~ /Compiled on a Linux (.*?\..*?)\.* system/)
551                                 {
552                                         $kernelv = $1;
553                                         # Fix for some retarded libc builds, strip off >> and << etc.
554                                         $kernelv =~ /(\d+\.\d+)/;
555                                         $kernelv = $1;
556                                 }
557                         }
558                         close FH;
559                         if ($libcv < 2.3)
560                         {
561                                 $has_epoll = 0;
562                                 printf "libc too old: $libcv... ";
563                         }
564                         if ($kernelv < 2.6)
565                         {
566                                 $has_epoll = 0;
567                                 printf "libc built against older kernel $kernelv... ";
568                         }
569                 }
570         }
571 }
572 print "yes\n" if $has_epoll == 1;
573 print "no\n" if $has_epoll == 0;
574
575 printf "Checking if Solaris I/O completion ports are available... ";
576 $has_ports = 0;
577 my $system = `uname -s`;
578 chomp ($system);
579 $has_ports = 1 if ($system eq "SunOS");
580
581 if ($has_ports) {
582         my $kernel = `uname -r`;
583         chomp($kernel);
584         if (($kernel !~ /^5\.1./)) {
585                 $has_ports = 0;
586         }
587 }
588 print "yes\n" if $has_ports == 1;
589 print "no\n" if $has_ports == 0;
590
591 $config{HAS_EPOLL} = $has_epoll;
592 $config{HAS_KQUEUE} = $has_kqueue; 
593
594 printf "Checking for libgnutls... ";
595 if (($config{HAS_GNUTLS}) && (($config{HAS_GNUTLS} >= 1.2) || ($config{HAS_GNUTLS} eq "y"))) {
596         print "yes\n";
597         $config{HAS_GNUTLS} = "y";
598 } else {
599         print "no\n";
600         $config{HAS_GNUTLS} = "n";
601 }
602
603 printf "Checking for openssl... ";
604 if (($config{HAS_OPENSSL}) && (($config{HAS_OPENSSL} >= 0.8) || ($config{HAS_OPENSSL} eq "y"))) {
605         print "yes\n";
606         $config{HAS_OPENSSL} = "y";
607 } else {
608         print "no\n";
609         $config{HAS_OPENSSL} = "n";
610 }
611
612 printf "Checking if you are running an ancient, unsupported OS... ";
613 if ($config{OSNAME} =~ /FreeBSD/i)
614 {
615         $version = `uname -r`;
616         if ($version =~ /^4\./)
617         {
618                 $foundit = `ls -l /usr/local/lib/libgnugetopt* | wc -l`;
619                 if ($foundit > 0)
620                 {
621                         # ICKY ICKY ICK, FREEBSD 4.x! GET AN UPGRADE!
622                         $config{CRAQ} = "-L/usr/local/lib -lgnugetopt -DHAVE_DECL_GETOPT=1";
623                         print "yes\n";
624                 }
625                 else
626                 {
627                         print "\n\nERROR: You require libgnugetopt (from ports or packages) to build InspIRCd on FreeBSD 4.11.\n";
628                 }
629         }
630         else
631         {
632                 $config{CRAQ} = " ";
633                 print "no ($version)\n";
634         }
635 }
636 else
637 {
638         $config{CRAQ} = " ";
639         print "no ($config{OSNAME})\n";
640 }
641
642 ################################################################################
643 #                         BEGIN INTERACTIVE PART                              #
644 ################################################################################
645
646 # Clear the Screen..
647 if ($interactive)
648 {
649         system("clear");
650         $wholeos = $^O;
651
652         my $rev = getrevision();
653         # Display Introduction Message..
654         print "
655 Welcome to the \033[1mInspIRCd\033[0m Configuration program! (\033[1minteractive mode\033[0m)
656 \033[1mPackage maintainers: Type ./configure --help for non-interactive help\033[0m
657
658 *** If you are unsure of any of these values, leave it blank for    ***
659 *** standard settings that will work, and your server will run      ***
660 *** using them. Please consult your IRC network admin if in doubt.  ***
661
662 Press \033[1m<RETURN>\033[0m to accept the default for any option, or enter
663 a new value. Please note: You will \033[1mHAVE\033[0m to read the docs
664 dir, otherwise you won't have a config file!
665
666 Your operating system is: \033[1;32m$config{OSNAME}\033[0m ($wholeos)
667 Maximum file descriptors: \033[1;32m$config{MAX_CLIENT_T}\033[0m
668 Your InspIRCd revision ID is \033[1;32mr$rev\033[0m";
669         if ($rev eq "r0") {
670                 print " (Non-SVN build)";
671         }
672         print ".\n\n";
673
674         $config{CHANGE_COMPILER} = "n";
675         print "I have detected the following compiler: \033[1;32m$config{CC}\033[0m (version \033[1;32m$config{GCCVER}.x\033[0m)\n";
676
677         while (($config{GCCVER} < 3) || ($config{GCCVER} eq "")) {
678                 print "\033[1;32mIMPORTANT!\033[0m A GCC 2.x compiler has been detected, and
679 should NOT be used. You should probably specify a newer compiler.\n\n";
680                 yesno(CHANGE_COMPILER,"Do you want to change the compiler?");
681                 if ($config{CHANGE_COMPILER} =~ /y/i) {
682                         print "What command do you want to use to invoke your compiler?\n";
683                         print "[\033[1;32m$config{CC}\033[0m] -> ";
684                         chomp($config{CC} = <STDIN>);
685                         if ($config{CC} eq "") {
686                                 $config{CC} = "g++";
687                         }
688                         chomp($foo = `$config{CC} -dumpversion | cut -c 1`);
689                         if ($foo ne "") {
690                                 chomp($config{GCCVER}       = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
691                                 print "Queried compiler: \033[1;32m$config{CC}\033[0m (version \033[1;32m$config{GCCVER}.x\033[0m)\n";
692                                 if ($config{GCCVER} < 3) {
693                                         print "\033[1;32mGCC 2.x WILL NOT WORK!\033[0m. Let's try that again, shall we?\n";
694                                 }
695                         }
696                         else {
697                                 print "\033[1;32mWARNING!\033[0m Could not execute the compiler you specified. You may want to try again.\n";
698                         }
699                 }
700         }
701
702         print "\n";
703
704         # Directory Settings..
705         my $tmpbase = $config{BASE_DIR};
706         dir_check("do you wish to install the InspIRCd base", "BASE_DIR");
707         if ($tmpbase ne $config{BASE_DIR}) {
708                 $config{CONFIG_DIR}      = resolve_directory($config{BASE_DIR}."/conf");           # Configuration Dir
709                 $config{MODULE_DIR}      = resolve_directory($config{BASE_DIR}."/modules");     # Modules Directory
710                 $config{BINARY_DIR}      = resolve_directory($config{BASE_DIR}."/bin");     # Binary Directory
711                 $config{LIBRARY_DIR}    = resolve_directory($config{BASE_DIR}."/lib");      # Library Directory
712         }
713
714         dir_check("are the configuration files", "CONFIG_DIR");
715         dir_check("are the modules to be compiled to", "MODULE_DIR");
716         dir_check("is the IRCd binary to be placed", "BINARY_DIR");
717         dir_check("are the IRCd libraries to be placed", "LIBRARY_DIR");
718
719         if ($has_kqueue) {
720                 yesno(USE_KQUEUE,"You are running a BSD operating system, and kqueue\nwas detected. Would you like to enable kqueue support?\nThis is likely to increase performance.\nIf you are unsure, answer yes.\n\nEnable kqueue?");
721                 print "\n";
722         }
723         if ($has_epoll) {
724                 yesno(USE_EPOLL,"You are running a Linux 2.6+ operating system, and epoll\nwas detected. Would you like to enable epoll support?\nThis is likely to increase performance.\nIf you are unsure, answer yes.\n\nEnable epoll?");
725                 print "\n";
726         }
727         if ($has_ports) {
728                 yesno(USE_PORTS,"You are running Solaris 10.\nWould you like to enable I/O completion ports support?\nThis is likely to increase performance.\nIf you are unsure, answer yes.\n\nEnable support for I/O completion ports?");
729                 print "\n";
730         }
731         $chose_hiperf = (($config{USE_EPOLL} eq "y") || ($config{USE_KQUEUE} eq "y") || ($config{USE_PORTS} eq "y"));
732         if (!$chose_hiperf) {
733                 print "No high-performance socket engines are available, or you chose\n";
734                 print "not to enable one. Defaulting to select() engine.\n\n";
735         }
736
737         yesno(IPV6,"Would you like to build InspIRCd with IPv6 support?");
738         print "\n";
739
740         if ($config{IPV6} eq "y") {
741                 print "You have chosen to build an \033[1;32mIPV6-enabled\033[0m server.\nTo accept IPV4 users, you can still use IPV4 addresses\nin your port bindings..\n\n";
742                 $config{SUPPORT_IP6LINKS} = "y";
743         } else {
744                 yesno(SUPPORT_IP6LINKS,"You have chosen to build an \033[1;32mIPV4-only\033[0m server.\nWould you like to enable support for linking to IPV6-enabled\nInspIRCd servers?\nIf you are using a recent operating\nsystem and are unsure, answer yes.\nIf you answer 'no' here, your InspIRCd server will be unable\nto parse IPV6 addresses (e.g. for CIDR bans)");
745                 print "\n";
746         }
747
748         if (($config{HAS_GNUTLS} eq "y") && ($config{HAS_OPENSSL} eq "y")) {
749                 print "I have detected both \033[1;32mGnuTLS\033[0m and \033[1;32mOpenSSL\033[0m on your system.\n";
750                 print "I will default to GnuTLS. If you wish to use OpenSSL\n";
751                 print "instead, you should enable the OpenSSL module yourself\n";
752                 print "by copying it from src/modules/extra to src/modules.\n\n";
753                 print "Detected GnuTLS version: \033[1;32m" . $gnutls_ver . "\033[0m\n";
754                 print "Detected OpenSSL version: \033[1;32m" . $openssl_ver . "\033[0m\n\n";
755         }
756
757         if ($config{HAS_GNUTLS} eq "y") {
758                 yesno(USE_GNUTLS, "Would you like to enable SSL Support?");
759                 if ($config{USE_GNUTLS} eq "y") {
760                         print "\nUsing GnuTLS SSL module.\n";
761                 }
762         } elsif ($config{HAS_OPENSSL} eq "y") {
763                         yesno(USE_OPENSSL, "Would you like to enable SSL Support?");
764         if ($config{USE_OPENSSL} eq "y") {
765                         print "\nUsing OpenSSL SSL module.\nYou will get better performance if you move to GnuTLS in the future.\n";
766                 }
767         }
768         else {
769                 print "\nCould not detect OpenSSL or GnuTLS. Make sure pkg-config is installed if\nyou intend to use OpenSSL, or that GnuTLS is in your path if you intend\nto use GnuTLS.\n\n";
770         }
771
772         print "\nThe following questions will ask you for various figures relating\n";
773         print "To your IRCd install. Please note that these should usually be left\n";
774         print "as defaults unless you have a real reason to change them. If they\n";
775         print "changed, then the values must be identical on all servers on your\n";
776         print "network, or malfunctions and/or crashes may occur, with the exception\n";
777         print "of the 'maximum number of clients' setting which may be different on\n";
778         print "different servers on the network.\n\n";
779
780         # File Descriptor Settings..
781         promptnumeric("number of clients at any one time", "MAX_CLIENT_T");
782         $config{MAX_CLIENT} = $config{MAX_CLIENT_T};
783         $config{MAX_DESCRIPTORS} = $config{MAX_CLIENT_T};
784
785         promptnumeric("length of nicknames", "NICK_LENGT");
786         promptnumeric("length of channel names", "CHAN_LENGT");
787         promptnumeric("number of mode changes in one line", "MAXI_MODES");
788         promptnumeric("length of an ident (username)", "MAX_IDENT");
789         promptnumeric("length of a quit message", "MAX_QUIT");
790         promptnumeric("length of a channel topic", "MAX_TOPIC");
791         promptnumeric("length of a kick message", "MAX_KICK");
792         promptnumeric("length of a GECOS (real name)", "MAX_GECOS");
793         promptnumeric("length of an away message", "MAX_AWAY");
794 }
795
796 dumphash();
797
798 if (($config{USE_GNUTLS} eq "y") && ($config{HAS_GNUTLS} ne "y"))
799 {
800         print "Sorry, but i couldn't detect gnutls. Make sure gnutls-config is in your path.\n";
801         exit(0);
802 }
803 if (($config{USE_OPENSSL} eq "y") && ($config{HAS_OPENSSL} ne "y"))
804 {
805         print "Sorry, but i couldn't detect openssl. Make sure openssl is in your path.\n";
806         exit(0);
807 }
808
809 if ($config{USE_GNUTLS} eq "y") {
810         $failed = 0;
811         open(TMP, "<src/modules/m_ssl_gnutls.cpp") or $failed = 1;
812         close(TMP);
813         if ($failed) {
814                 print "Symlinking src/modules/m_ssl_gnutls.cpp from extra/\n";
815                 chdir("src/modules");
816                 system("ln -s extra/m_ssl_gnutls.cpp");
817                 chdir("../..");
818         }
819         getmodules();
820         if ($interactive)
821         {
822                 $failed = 0;
823                 open(TMP, "<$config{CONFIG_DIR}/key.pem") or $failed = 1;
824                 close(TMP);
825                 open(TMP, "<$config{CONFIG_DIR}/cert.pem") or $failed = 1;
826                 close(TMP);
827                 if ($failed) {
828                         print "SSL Certificates Not found, Generating.. \n\n
829 *************************************************************
830 * Generating the Private Key may take some time, go grab a  *
831 * Coffee. Even better, to generate some more entropy if it  *
832 * is taking a while, open another console and type du / a   *
833 * few times and get that HD going :) Then answer the        *
834 * Questions which follow. If you are unsure, just hit enter *
835 *************************************************************\n\n";
836                         $failed = make_gnutls_cert();
837                         if ($failed) {
838                                 print "\n\033[1;32mCertificate generation failed!\033[0m\n\n";
839                         } else {
840                                 print "\nCertificate generation complete, copying to config directory... ";
841                                 system("mv key.pem $config{CONFIG_DIR}/key.pem");
842                                 system("mv cert.pem $config{CONFIG_DIR}/cert.pem");
843                                 print "Done.\n\n";
844                         }
845                 }
846                 else {
847                         print "SSL Certificates found, skipping.\n\n";
848                 }
849         }
850         else
851         {
852                 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
853         }
854 } elsif ($config{USE_OPENSSL} eq "y") {
855         $failed = 0;
856         open(TMP, "<src/modules/m_ssl_openssl.cpp") or $failed = 1;
857         close(TMP);
858         if ($failed) {
859                 print "Symlinking src/modules/m_ssl_openssl.cpp from extra/\n";
860                 chdir("src/modules");
861                 system("ln -s extra/m_ssl_openssl.cpp");
862                 chdir("../..");
863         }
864         getmodules();
865         $failed = 0;
866         if ($interactive)
867         {
868                 open(TMP, "<$config{CONFIG_DIR}/key.pem") or $failed = 1;
869                 close(TMP);
870                 open(TMP, "<$config{CONFIG_DIR}/cert.pem") or $failed = 1;
871                 close(TMP);
872                 if ($failed) {
873                         print "SSL Certificates Not found, Generating.. \n\n
874 *************************************************************
875 * Generating the certificates may take some time, go grab a *
876 * coffee, or something.                                     *
877 *************************************************************\n\n";
878                         make_openssl_cert();
879                         print "\nCertificate generation complete, copying to config directory... ";
880                         system("mv key.pem $config{CONFIG_DIR}/key.pem");
881                         system("mv cert.pem $config{CONFIG_DIR}/cert.pem");
882                         system("mv dhparams.pem $config{CONFIG_DIR}/dhparams.pem");
883                         print "Done.\n\n";
884                 } else {
885                         print "SSL Certificates found, skipping.\n\n"
886                 }
887         }
888         else
889         {
890                 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
891         }
892 }
893 if (($config{USE_GNUTLS} eq "n") && ($config{USE_OPENSSL} eq "n")) {
894         print "Skipping SSL Certificate generation, SSL support is not available.\n\n";
895 }
896
897 getosflags();
898 writefiles(1);
899 makecache();
900
901 print "\n\n";
902 print "To build your server with these settings, please type '\033[1;32m$config{MAKEPROG}\033[0m' now.\n";
903 if (($config{USE_GNUTLS} eq "y") || ($config{USE_OPENSSL} eq "y")) {
904         print "Please remember that to enable \033[1;32mSSL support\033[0m you must\n";
905         print "load the required modules in your config. This configure process\n";
906         print "has just prepared these modules to be compiled for you, and has not\n";
907         print "configured them to be compiled into the core of the ircd.\n";
908 }
909 print "*** \033[1;32mRemember to edit your configuration files!!!\033[0m ***\n\n\n";
910 if (($config{OSNAME} eq "OpenBSD") && ($config{CC} ne "eg++")) {
911         print "\033[1;32mWARNING!\033[0m You are running OpenBSD but you are using the base gcc package\nrather than eg++. This compile will most likely fail, but i'm letting you\ngo ahead with it anyway, just in case i'm wrong :-)\n";
912 }
913
914 if ($config{GCCVER} < "3") {
915         print <<FOO2;
916 \033[1;32mWARNING!\033[0m You are attempting to compile InspIRCd on GCC 2.x!
917 GCC 2.x series compilers only had partial (read as broken) C++ support, and
918 your compile will most likely fail horribly! If you have any problems, do NOT
919 report them to the bugtracker or forums without first upgrading your compiler
920 to a newer 3.x or 4.x (or whatever is available currently) version.
921 FOO2
922 }
923
924 ################################################################################
925 #                             HELPER FUNCTIONS                          #
926 ################################################################################
927 sub getcache {
928         # Retrieves the .config.cache file, and loads values into the main config hash.
929         open(CACHE, ".config.cache") or return 0;
930         while (<CACHE>) {
931                 chomp;
932                 # Ignore Blank lines, and comments..
933                 next if /^\s*$/;
934                 next if /^\s*#/;
935                 my ($key, $value) = split("=", $_, 2);
936                 $value =~ /^\"(.*)\"$/;
937                 # Do something with data here!
938                 $config{$key} = $1;
939         }
940         close(CONFIG);
941         return 1;
942 }
943
944 sub makecache {
945         # Dump the contents of %config
946         print "Writing \033[1;32mcache file\033[0m for future ./configures ...\n";
947         open(FILEHANDLE, ">.config.cache");
948         foreach $key (keys %config) {
949                 print FILEHANDLE "$key=\"$config{$key}\"\n";
950         }
951         close(FILEHANDLE);
952 }
953
954 sub dir_check {
955         my ($desc, $hash_key) = @_;
956         my $complete = 0;
957         while (!$complete) {
958                 print "In what directory $desc?\n";
959                 print "[\033[1;32m$config{$hash_key}\033[0m] -> ";
960                 chomp($var = <STDIN>);
961                 if ($var eq "") {
962                         $var = $config{$hash_key};
963                 }
964                 if ($var =~ /^\~\/(.+)$/) {
965                         # Convert it to a full path..
966                         $var = resolve_directory($ENV{HOME} . "/" . $1);
967                 }
968                 elsif ((($config{OSNAME} =~ /MINGW32/i) and ($var !~ /^[A-Z]{1}:\\.*/)) and (substr($var,0,1) ne "/"))
969                 {
970                         # Assume relative Path was given.. fill in the rest.
971                         $var = $this . "/$var";
972                 }
973                 
974                 $var = resolve_directory($var); 
975                 if (! -e $var) {
976                         print "$var does not exist. Create it?\n[\033[1;32my\033[0m] ";
977                         chomp($tmp = <STDIN>);
978                         if (($tmp eq "") || ($tmp =~ /^y/i)) {
979                                 # Attempt to Create the Dir..
980                                 
981                                 system("mkdir -p \"$var\" >> /dev/null 2>&1");
982                                 $chk = system("mkdir -p \"$var\" >> /dev/null 2>&1") / 256;
983                                 if ($chk != 0) {
984                                         print "Unable to create directory. ($var)\n\n";
985                                         # Restart Loop..
986                                         next;
987                                 }
988                         } else {
989                                 # They said they don't want to create, and we can't install there.
990                                 print "\n\n";
991                                 next;
992                         }
993                 } else {
994                         if (!is_dir($var)) {
995                                 # Target exists, but is not a directory.
996                                 print "File $var exists, but is not a directory.\n\n";
997                                 next;
998                         }
999                 }
1000                 # Either Dir Exists, or was created fine.
1001                 $config{$hash_key} = $var;
1002                 $complete = 1;
1003                 print "\n";
1004         }
1005 }
1006
1007 sub getosflags {
1008
1009         $config{LDLIBS} = "-lstdc++";
1010         $config{FLAGS}  = "-W -pedantic -fPIC $config{OPTIMISATI}";
1011         $config{DEVELOPER} = "-W -pedantic -fPIC -g";
1012         $SHARED = "-Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared";
1013         $config{MAKEPROG} = "make";
1014
1015         if ($config{OSNAME} =~ /darwin/i) {
1016                 $config{FLAGS}  = "-W -pedantic -DDARWIN -frtti -fPIC $config{OPTIMISATI}";
1017                 $SHARED = "-bundle -twolevel_namespace -undefined dynamic_lookup";
1018                 $config{LDLIBS} = "-ldl -lstdc++";
1019         }
1020
1021         if ($config{OSNAME} =~ /OpenBSD/i) {
1022                 $config{MAKEPROG} = "gmake";
1023                 $config{LDLIBS} = $config{LDLIBS} . " -lunwind";
1024                 chomp($foo = `eg++ -dumpversion | cut -c 1`);
1025                 # theyre running the package version of gcc (eg++)... detect it and set up its version numbers.
1026                 # if theyre not running this, configure lets the build continue but they probably wont manage to
1027                 # compile as this standard version is 2.95.3!
1028                 if ($foo ne "") {
1029                         $config{CC} = "eg++";
1030                         chomp($config{GCCVER}       = `eg++ -dumpversion | cut -c 1`); # we must redo these if we change the compiler path
1031                 }
1032                 return "OpenBSD";
1033         }
1034
1035         if ($config{OSNAME} =~ /Linux/i) {
1036                 $config{LDLIBS} = "-ldl -lstdc++";
1037                 $config{FLAGS}  = "-W -pedantic -fPIC $config{OPTIMISATI}";
1038                 $config{FLAGS}  .= " " . $ENV{CXXFLAGS} if exists($ENV{CXXFLAGS});
1039                 $config{LDLIBS} .= " " . $ENV{LDLIBS} if exists($ENV{LDLIBS});
1040                 $config{MAKEPROG} = "make";
1041         }
1042
1043         if ($config{OSNAME} =~ /FreeBSD/i) {
1044                 $config{FLAGS}  .= " " . $ENV{CXXFLAGS} if exists($ENV{CXXFLAGS});
1045                 $config{LDLIBS} .= " " . $ENV{LDLIBS} if exists($ENV{LDLIBS});
1046         }
1047
1048         if ($config{OSNAME} =~ /SunOS/i or $config{OSNAME} =~ /solaris/i)
1049         {
1050                 # solaris/sunos needs these
1051                 # socket = bsd sockets api
1052                 # nsl = dns stuff
1053                 # rt = POSIX realtime extensions
1054                 # resolv = inet_aton only (why isnt this in nsl?!)
1055                 $config{MAKEPROG} = "gmake";
1056                 $config{LDLIBS} .= " -lsocket -lnsl -lrt -lresolv";
1057                 return "Solaris";
1058         }
1059         
1060         if($config{OSNAME} =~ /MINGW32/i)
1061         {
1062                 # All code is position-independent on windows
1063                 $config{FLAGS} =~ s/-fPIC //;
1064                 return "MinGW";
1065         }
1066
1067         return $config{OSNAME};
1068 }
1069
1070 sub writefiles {
1071         my($writeheader) = @_;
1072         # First File.. inspircd_config.h
1073         chomp(my $incos = `uname -n -s -r`);
1074         chomp($version = `sh src/version.sh`);
1075         chomp(my $revision2 = getrevision());
1076         if ($writeheader == 1)
1077         {
1078                 print "Writing \033[1;32minspircd_config.h\033[0m\n";
1079                 open(FILEHANDLE, ">include/inspircd_config.h");
1080                 my $NL = $config{NICK_LENGT}+1;
1081                 my $CL = $config{CHAN_LENGT}+1;
1082                 print FILEHANDLE <<EOF;
1083 /* Auto generated by configure, do not modify! */
1084 #ifndef __CONFIGURATION_AUTO__
1085 #define __CONFIGURATION_AUTO__
1086
1087 /* this is for windows support. */
1088 #define CoreExport /**/
1089 #define DllExport /**/
1090
1091 #define CONFIG_FILE "$config{CONFIG_DIR}/inspircd.conf"
1092 #define MOD_PATH "$config{MODULE_DIR}"
1093 #define VERSION "$version"
1094 #define REVISION "$revision2"
1095 #define MAXCLIENTS $config{MAX_CLIENT}
1096 #define MAXCLIENTS_S "$config{MAX_CLIENT}"
1097 #define SOMAXCONN_S "$config{_SOMAXCONN}"
1098 #define MAX_DESCRIPTORS $config{MAX_DESCRIPTORS}
1099 #define NICKMAX $NL
1100 #define CHANMAX $CL
1101 #define MAXMODES $config{MAXI_MODES}
1102 #define IDENTMAX $config{MAX_IDENT}
1103 #define MAXQUIT $config{MAX_QUIT}
1104 #define MAXTOPIC $config{MAX_TOPIC}
1105 #define MAXKICK $config{MAX_KICK}
1106 #define MAXGECOS $config{MAX_GECOS}
1107 #define MAXAWAY $config{MAX_AWAY}
1108 #define OPTIMISATION $config{OPTIMITEMP}
1109 #define LIBRARYDIR "$config{LIBRARY_DIR}"
1110 #define SYSTEM "$incos"
1111 EOF
1112 print FILEHANDLE "#define MAXBUF " . ($config{MAXBUF}+2) . "\n";
1113
1114                 if ($config{OSNAME} =~ /SunOS/i) {
1115                         print FILEHANDLE "#define IS_SOLARIS\n";
1116                 }
1117                 if ($config{OSNAME} =~ /MINGW32/i) {
1118                         print FILEHANDLE "#define IS_MINGW\n";
1119                 }
1120                 if ($config{GCCVER} >= 3) {
1121                         print FILEHANDLE "#define GCC3\n";
1122                 }
1123                 if ($config{HAS_STRLCPY} eq "true") {
1124                         print FILEHANDLE "#define HAS_STRLCPY\n";
1125                 }
1126                 if ($config{HAS_STDINT} eq "true") {
1127                         print FILEHANDLE "#define HAS_STDINT\n";
1128                 }
1129                 if ($config{IPV6} =~ /y/i) {
1130                         print FILEHANDLE "#define IPV6\n";
1131                 }
1132                 if ($config{SUPPORT_IP6LINKS} =~ /y/i) {
1133                         print FILEHANDLE "#define SUPPORT_IP6LINKS\n";
1134                 }
1135                 my $use_hiperf = 0;
1136                 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
1137                         print FILEHANDLE "#define USE_KQUEUE\n";
1138                         $se = "socketengine_kqueue";
1139                         $use_hiperf = 1;
1140                 }
1141                 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
1142                         print FILEHANDLE "#define USE_EPOLL\n";
1143                         $se = "socketengine_epoll";
1144                         $use_hiperf = 1;
1145                 }
1146                 if (($has_ports) && ($config{USE_PORTS} eq "y")) {
1147                         print FILEHANDLE "#define USE_PORTS\n";
1148                         $se = "socketengine_ports";
1149                         $use_hiperf = 1;
1150                 }
1151                 # user didn't choose either epoll or select for their OS.
1152                 # default them to USE_SELECT (ewwy puke puke)
1153                 if (!$use_hiperf) {
1154                         print FILEHANDLE "#define USE_SELECT\n";
1155                         $se = "socketengine_select";
1156                 }
1157                 print FILEHANDLE "\n#endif\n";
1158                 close(FILEHANDLE);
1159         }
1160
1161         if ($writeheader)
1162         {
1163                 open(FILEHANDLE, ">include/inspircd_se_config.h");
1164                 print FILEHANDLE <<EOF;
1165 /* Auto generated by configure, do not modify or commit to svn! */
1166 #ifndef __CONFIGURATION_SOCKETENGINE__
1167 #define __CONFIGURATION_SOCKETENGINE__
1168
1169 #include "$se.h"
1170
1171 #endif
1172 EOF
1173                 close(FILEHANDLE);
1174         }
1175
1176
1177         # Create a Modules List..
1178         my $modules = "";
1179         foreach $i (@modlist)
1180         {
1181                 $modules .= "m_".$i.".so ";
1182         }
1183         chomp($modules);   # Remove Redundant whitespace..
1184
1185         opendir(DIRHANDLE, "src/modules");
1186         foreach $name (sort readdir(DIRHANDLE)) {
1187                 if ($name =~ /^m_(.+?)$/) {
1188                         if (opendir(MDIRHANDLE, "src/modules/$name") != 0) {
1189                                 closedir(MDIRHANDLE);
1190                                 $modules .= "$name.so ";
1191                         }
1192                 }
1193         }
1194         closedir(DIRHANDLE);
1195
1196
1197         # Write all .in files.
1198         my $tmp = "";
1199         my $file = "";
1200         my $exe = "inspircd";
1201
1202         # Do this once here, and cache it in the .*.inc files,
1203         # rather than attempting to read src/version.sh from
1204         # compiled code -- we might not have the source to hand.
1205         # Fix for bug#177 by Brain.
1206
1207         chomp(my $version = `sh ./src/version.sh`);
1208         chomp(my $revision = getrevision());
1209         $version = "$version(r$revision)";
1210
1211         # We can actually parse any file starting with . and ending with .inc,
1212         # but right now we only parse .inspircd.inc to form './inspircd'
1213
1214         print "Writing dynamic-build \033[1;32msrc/Makefile\033[0m\n";
1215         write_dynamic_makefile();
1216         write_dynamic_modules_makefile();
1217
1218         opendir(DIRHANDLE, $this);
1219
1220         foreach $name (sort readdir(DIRHANDLE)) {
1221                 if ($name =~ /^\.(.+)\.inc$/) {
1222                         $file = $1;
1223
1224                         # Bug #353, omit this on non-darwin
1225                         next if (($config{OSNAME} !~ /darwin/) && ($file eq "org.inspircd.plist"));
1226
1227                         # All .name.inc files need parsing!
1228                         $tmp = "";
1229                         open(FILEHANDLE, ".$file.inc") or die ("Can't open .$file.inc");
1230                         while (<FILEHANDLE>) {
1231                                 $tmp .= $_;
1232                         }
1233                         close(FILEHANDLE);
1234
1235                         print "Writing \033[1;32m$file\033[0m ...\n";
1236                         $tmp =~ s/\@CC\@/$config{CC}/;
1237                         $tmp =~ s/\@MAKEPROG\@/$config{MAKEPROG}/;
1238                         $tmp =~ s/\@FLAGS\@/$config{FLAGS}/;
1239                         $tmp =~ s/\@DEVELOPER\@/$config{DEVELOPER}/;
1240                         $tmp =~ s/\@LDLIBS\@/$config{LDLIBS}/;
1241                         $tmp =~ s/\@BASE_DIR\@/$config{BASE_DIR}/;
1242                         $tmp =~ s/\@CONFIG_DIR\@/$config{CONFIG_DIR}/;
1243                         $tmp =~ s/\@MODULE_DIR\@/$config{MODULE_DIR}/;
1244                         $tmp =~ s/\@BINARY_DIR\@/$config{BINARY_DIR}/;
1245                         $tmp =~ s/\@LIBRARY_DIR\@/$config{LIBRARY_DIR}/;
1246                         $tmp =~ s/\@MODULES\@/$modules/;
1247                         $tmp =~ s/\@STARTSCRIPT\@/$config{STARTSCRIPT}/;
1248                         $tmp =~ s/\@DESTINATION\@/$config{DESTINATION}/;
1249                         $tmp =~ s/\@EXTRA_DIR\@/$config{EXTRA_DIR}/;
1250                         $tmp =~ s/\@EXECUTABLE\@/$exe/;
1251                         $tmp =~ s/\@MAKEORDER\@/$config{MAKEORDER}/;
1252                         $tmp =~ s/\@VERSION\@/$version/;
1253                         $tmp =~ s/\@INSTALL_LIST\@/$install_list/;
1254
1255                         open(FILEHANDLE, ">$file");
1256                         print FILEHANDLE $tmp;
1257                 }
1258         }
1259         closedir(DIRHANDLE);
1260
1261         # Make inspircd executable!
1262         chmod 0744, 'inspircd';
1263 }
1264
1265 sub write_dynamic_modules_makefile {
1266         # Modules Makefile..
1267         print "Writing \033[1;32msrc/modules/Makefile\033[0m\n";
1268         open(FILEHANDLE, ">src/modules/Makefile");
1269
1270 ###
1271 # Module Makefile Header
1272 ###
1273         print FILEHANDLE <<EOF;
1274 ###################################################
1275 # Copyright 2002-2007 The InspIRCd Development Team
1276 #  http://www.inspircd.org/wiki/index.php/Credits
1277 #
1278 # Thanks to Andrew Church <achurch\@achurch.org>
1279 #   for assisting with making this work right.
1280 #
1281 # Automatically Generated by ./configure to add a
1282 #  modules please run ./configure -modupdate
1283 ###################################################
1284
1285 all: \$(MODULES)
1286
1287 EOF
1288
1289 $nicerflags = $options{FLAGS};
1290 $nicerflags =~ s/\-pedantic//g;
1291
1292 if ($config{OSNAME} =~ /darwin/) {
1293                 print FILEHANDLE <<EOCHEESE;
1294
1295 PICLDFLAGS = -twolevel_namespace -undefined dynamic_lookup \$(FLAGS) -bundle
1296 NICERFLAGS = $nicerflags
1297
1298 EOCHEESE
1299 } else {
1300                 print FILEHANDLE <<EOCHEESE;
1301
1302 PICLDFLAGS = -fPIC -DPIC -shared \$(FLAGS)
1303 NICERFLAGS = $nicerflags
1304
1305 EOCHEESE
1306 }
1307
1308         ###
1309         # End Module Makefile Header
1310         ###
1311
1312         # Create a Modules List..
1313         my $modules = "";
1314         my $cmflags = "";
1315         my $liflags = "";
1316         my $crud = "";
1317
1318         foreach $i (@modlist) {
1319                 ###
1320                 # Write Entry to the MakeFile
1321                 ###
1322                 $cmflags = getcompilerflags("src/modules/m_".$i.".cpp");
1323                 $liflags = getlinkerflags("src/modules/m_".$i.".cpp");
1324                 $deps = getdependencies("src/modules/m_".$i.".cpp");
1325
1326                 if (nopedantic("src/modules/m_".$i.".cpp"))
1327                 {
1328                         $fl = "\$(FLAGS)";
1329                 }
1330                 else
1331                 {
1332                         $fl = "\$(LAMEFLAGS)";
1333                 }
1334         
1335                 #print "file: $i: cmflags=$cmflags; liflags=$liflags; deps=$deps\n";
1336         
1337                 print FILEHANDLE <<EOCHEESE;
1338 m_$i.so: m_$i.cpp ../../include/modules.h ../../include/users.h ../../include/channels.h ../../include/base.h ../../include/inspircd_config.h ../../include/inspircd.h ../../include/configreader.h $deps
1339         \$(CC) -pipe -I../../include $fl $cmflags \$(PICLDFLAGS) $liflags -export-dynamic -o m_$i.so m_$i.cpp
1340 EOCHEESE
1341                 $crud = $crud . "       install -m \$(INSTMODE) m_$i.so \$(MODPATH)\n";
1342 ###
1343                 # End Write Entry to the MakeFile
1344                 ###
1345         }
1346
1347         opendir(DIRHANDLE, "src/modules");
1348         foreach $name (sort readdir(DIRHANDLE)) {
1349                 if ($name =~ /^m_(.+?)$/) {
1350                         $mfrules = "";
1351                         $mobjs = "";
1352                         $mliflags = "";
1353                         $mfcount = 0;
1354                         # A module made of multiple files, in a dir, e.g. src/modules/m_spanningtree/
1355                         if (opendir(MDIRHANDLE, "src/modules/$name") != 0) {
1356                                 read_module_directory("src/modules/$name", $name);
1357                                 print "Composing Makefile rules for directory \033[1;32m$name\033[0m... (\033[1;32m$mfcount files found\033[0m)\n";
1358                                 print FILEHANDLE "$name.so: ../../include/modules.h ../../include/users.h ../../include/channels.h ../../include/base.h ../../include/inspircd_config.h ../../include/inspircd.h ../../include/configreader.h $mobjs\n"; 
1359                                 if ($config{IS_DARWIN} eq "YES") {
1360                                         print FILEHANDLE "      \$(CC) -pipe -twolevel_namespace -undefined dynamic_lookup $fl $mliflags -bundle -o $name.so $mobjs\n"; 
1361                                 } else {
1362                                         print FILEHANDLE "      \$(CC) -pipe $fl -shared $mliflags -o $name.so $mobjs\n";
1363                                 }
1364                                 print FILEHANDLE "\n$mfrules\n";
1365                                 closedir(MDIRHANDLE);
1366                                 $crud = $crud . "       install -m \$(INSTMODE) $name.so \$(MODPATH)\n";
1367                         }
1368                 }
1369         }
1370         closedir(DIRHANDLE);
1371
1372         print FILEHANDLE "modinst:\n    \@echo \"Installing modules...\"\n" . $crud;
1373 }
1374
1375 sub read_module_directory {
1376         my ($dpath, $reldpath) = @_;
1377         
1378         if (opendir(MDIRHANDLE, $dpath) == 0) {
1379                 return;
1380         }
1381         
1382         foreach $fname (sort readdir(MDIRHANDLE)) {
1383                 if ($fname =~ /\.cpp$/) {
1384                         $cmflags = getcompilerflags("$dpath/$fname");
1385                         $mliflags = $mliflags . " " . getlinkerflags("$dpath/$fname");
1386                         $deps = getdependencies("$dpath/$fname");
1387                         $oname = $fname;
1388                         $oname =~ s/\.cpp$/.o/g;
1389                         $mfrules = $mfrules .  "$reldpath/$oname: $reldpath/$fname ../../include/modules.h ../../include/users.h ../../include/channels.h ../../include/base.h ../../include/inspircd_config.h ../../include/inspircd.h ../../include/configreader.h $deps\n";
1390                         $mfrules = $mfrules .  "        \$(CC) -pipe -I../../include -I. \$(FLAGS) $cmflags -export-dynamic -o $reldpath/$oname -c $reldpath/$fname\n\n";
1391                         $mobjs = $mobjs . " $reldpath/$oname";
1392                         $mfcount++;
1393                 }
1394                 elsif ((-d "$dpath/$fname") && !($fname eq ".") && !($fname eq "..")) {
1395                         read_module_directory($dpath."/".$fname, $reldpath."/".$fname);
1396                 }
1397         }
1398 }
1399
1400 sub calcdeps($)
1401 {
1402         # Yes i know we could use gcc -M but it seems to ideneify a lot of 'deep'
1403         # dependencies which are not relevent in C++.
1404
1405         my $file = $_[0];
1406
1407         open (CPP, "<$file") or die("Can't open $file for reading!");
1408
1409         my %dupe = ();
1410         my $retlist = "";
1411
1412         foreach my $d (@ignoredeps)
1413         {
1414                 $dupe{$d} = 1;
1415         }
1416
1417         my $immutable = "";
1418         foreach my $dep (@immutabledeps)
1419         {
1420                 $immutable = $immutable . "../include/$dep ";
1421         }
1422         $immutable =~ s/ $//g;
1423
1424         while (chomp($line = <CPP>))
1425         {
1426                 if ($line =~ /#include "(.+\.h)"/)
1427                 {
1428                         if (!exists($dupe{$1}))
1429                         {
1430                                 $retlist = $retlist . "../include/$1 ";
1431                                 $dupe{$1} = 1;
1432                         }
1433                 }
1434         }
1435         close CPP;
1436         return length($immutable) ? $immutable . " " . $retlist : $retlist;
1437 }
1438
1439 sub write_dynamic_makefile
1440 {
1441         my $i = 0;
1442         my @cmdlist = ();
1443         opendir(DIRHANDLE, "src/commands");
1444         foreach $name (sort readdir(DIRHANDLE))
1445         {
1446                 if ($name =~ /^cmd_(.+)\.cpp$/)
1447                 {
1448                         $cmdlist[$i++] = $1;
1449                         $install_list = $install_list . "       -install -m \$(INSTMODE) src/commands/cmd_" . $1  . ".so \$(LIBPATH)\n";
1450                 }
1451         }
1452         closedir(DIRHANDLE);
1453
1454         if (!$has_epoll)
1455         {
1456                 $config{USE_EPOLL} = 0;
1457         }
1458         if (!$has_kqueue)
1459         {
1460                 $config{USE_KQUEUE} = 0;
1461         }
1462         if (!$has_ports)
1463         {
1464                 $config{USE_PORTS} = 0;
1465         }
1466
1467         print "Scanning src folder for core files";
1468         opendir(DIRHANDLE, "src");
1469         foreach $name (sort readdir(DIRHANDLE))
1470         {
1471                 if ($name =~ /\.cpp$/)
1472                 {
1473                         open (CPP, "<src/$name") or die("Can't open src/$name to scan it! oh bugger");
1474                         while (chomp($line = <CPP>))
1475                         {
1476                                 if ($line =~ /\/\* \$Core: (\w+) \*\//i)
1477                                 {
1478                                         $filelist{$name} = $1;
1479                                         print ".";
1480                                 }
1481                                 elsif ($line =~ /\/\* \$ExtraDeps: (.*?) \*\//i)
1482                                 {
1483                                         $specialdeps{$name} = $1;
1484                                 }
1485                                 elsif ($line =~ /\/\* \$ExtraObjects: (.*?) \*\//i)
1486                                 {
1487                                         $extraobjects{$name} = $1;
1488                                 }
1489                                 elsif ($line =~ /\/\* \$ExtraBuild: (.*?) \*\//i)
1490                                 {
1491                                         $extrabuildlines{$name} = $1;
1492                                 }
1493                                 elsif ($line =~ /\/\* \$ExtraSources: (.*?) \*\//i)
1494                                 {
1495                                         $extrasources{$name} = $1;
1496                                 }
1497                                 elsif ($line =~ /\/\* \$If: (\w+) \*\//i)
1498                                 {
1499                                         if (($config{$1} !~ /y/i) and ($config{$1} ne "1"))
1500                                         {
1501                                                 # Skip to 'endif'
1502                                                 while (chomp($line = <CPP>))
1503                                                 {
1504                                                         die ("\$If buildsystem instruction within another \$If in file src/$name") if ($line =~ /\/\* \$If: (\w+) \*\//i);
1505                                                         last if ($line =~ /\/\* \$EndIf \*\//i);
1506                                                 }
1507                                         }
1508                                 }
1509                         }
1510                         close CPP;
1511                 }
1512         }
1513         closedir(DIRHANDLE);
1514         print " done!\n";
1515
1516         $freebsd4libs = $config{CRAQ};
1517
1518         my $all = "all: ";
1519         $all_libsonly = "";
1520
1521         if ($config{IS_DARWIN} eq "YES")
1522         {
1523                 $libraryext = "dylib";
1524                 $othercrap = "  \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c inspircd.cpp\n   \$(CC) -pipe -dynamic -bind_at_load -L. -o inspircd \$(LDLIBS) inspircd.o "
1525         }
1526         else
1527         {
1528                 $libraryext = "so";
1529                 $othercrap = "  \$(CC) -pipe -I../include -Wl,--rpath -Wl,$config{LIBRARY_DIR} \$(FLAGS) $freebsd4libs -rdynamic -L. inspircd.cpp -o inspircd \$(LDLIBS) ";
1530         }
1531
1532         foreach my $cpp (sort keys %filelist)
1533         {
1534                 $all = $all . $filelist{$cpp} . "." . $libraryext . " ";
1535                 $all_libsonly = $all_libsonly . $filelist{$cpp} . "." . $libraryext . " ";
1536                 $install_list = $install_list . "       -install -m \$(INSTMODE) src/" . $filelist{$cpp} . "." . $libraryext . " \$(LIBPATH)\n";
1537         }
1538         $all = $all . "moo inspircd\n";
1539
1540         $othercrap = $othercrap . " $all_libsonly\n\n";
1541
1542         open(FH,">src/Makefile") or die("Could not write src/Makefile");
1543         print FH <<EOM;
1544
1545 CC = im a cheezeball
1546 CXXFLAGS = -I../include \${FLAGS}
1547 CPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* //' | grep -v svn)
1548 RELCPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* /modes\\//' | grep -v svn)
1549
1550 EOM
1551
1552         print FH "$all\n\n";
1553
1554         $deps = calcdeps("src/inspircd.cpp");
1555         print FH "inspircd: inspircd.cpp $deps $all_libsonly\n";
1556         print FH "$othercrap\n";
1557
1558         foreach my $cpp (sort keys %filelist)
1559         {
1560                 my $thislib = $filelist{$cpp} . "." . $libraryext; 
1561                 my $objs = $cpp;
1562                 my $rawcpp = $cpp;
1563                 $objs =~ s/\.cpp$/.o/;
1564                 if (exists($extraobjects{$cpp}))
1565                 {
1566                         $objs = $objs . " " . $extraobjects{$cpp};
1567                 }
1568                 if (exists($extrasources{$cpp}))
1569                 {
1570                         $rawcpp = $rawcpp . " " . $extrasources{$cpp};
1571                 }
1572                 if ($config{IS_DARWIN} eq "YES")
1573                 {
1574                         $libcrap = "-install_name " . $config{LIBRARY_DIR} . "/" . $thislib . " -dynamiclib -twolevel_namespace -undefined dynamic_lookup";
1575                 }
1576                 else
1577                 {
1578                         $libcrap = "-Wl,--rpath -Wl," . $config{LIBRARY_DIR} . " -shared";
1579                 }
1580                 $deps = calcdeps("src/$cpp");
1581                 if (exists($extrasources{$cpp}))
1582                 {
1583                         foreach my $seperate (sort split(' ',$extrasources{$cpp}))
1584                         {
1585                                 $d = calcdeps("src/$extrasources{$cpp}") . " ";
1586                                 if ($d ne "")
1587                                 {
1588                                         $deps = $deps . $d . " ";
1589                                 }
1590                         }
1591                 }
1592                 print FH $thislib . ": $cpp $deps ". $specialdeps{$cpp} . "\n";
1593                 print FH "      \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c $rawcpp\n";
1594                 if (exists($extrabuildlines{$cpp}))
1595                 {
1596                         print FH "      " . $extrabuildlines{$cpp} . "\n";
1597                 }
1598                 print FH "      \$(CC) -pipe $libcrap -o " . $thislib . " " . $objs . "\n\n";
1599         }
1600
1601         print FH "moo:\n        \${MAKE} -C \"commands\" DIRNAME=\"src/commands\" CC=\"\$(CC)\" \$(MAKEARGS)\n\n";
1602
1603         # close main makefile
1604         close(FH);
1605
1606         # generate a list of .so
1607         foreach my $cmd (@cmdlist) {
1608                 $cmdobjs = $cmdobjs . "cmd_$cmd.so ";
1609         }
1610
1611         # and now reopen the commands makefile
1612         open(FH,">src/commands/Makefile") or die("Could not write src/commands/Makefile");
1613         print FH <<ITEM;
1614 CC = i am cornholio
1615 CXXFLAGS = -I../../include ${FLAGS}
1616
1617 all: $cmdobjs
1618
1619
1620 ITEM
1621
1622         # now print the command file details.
1623         foreach my $cmd (@cmdlist) {
1624                 print FH <<ITEM;
1625 cmd_$cmd.so: cmd_$cmd.cpp ../../include/base.h ../../include/modules.h ../../include/inspircd.h ../../include/channels.h ../../include/users.h ../../include/globals.h ../../include/inspircd_config.h ../../include/commands/cmd_$cmd.h
1626         \$(CC) -pipe -I../../include \$(FLAGS) -export-dynamic -c cmd_$cmd.cpp
1627         \$(CC) -pipe $SHARED -o cmd_$cmd.so cmd_$cmd.o
1628
1629 ITEM
1630         }
1631 #try build a .so, no intermediate .o
1632 #       \$(CC) -pipe -I../../include \$(FLAGS) -export-dynamic $SHARED -o cmd_$cmd.so
1633
1634 #this works for sure
1635 #       \$(CC) -pipe -I../../include \$(FLAGS) -export-dynamic -c cmd_$cmd.cpp
1636 #       \$(CC) -pipe $SHARED -o cmd_$cmd.so cmd_$cmd.o
1637 }
1638