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