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