2 ###################################################
3 # InspIRCd Configuration Script
5 # Copyright 2002-2007 The InspIRCd Development Team
6 # http://www.inspircd.org/wiki/index.php/Credits
8 # Licensed under GPL, please see the COPYING file
13 ###################################################
20 use warnings FATAL => qw(all);
24 $Data::Dumper::Sortkeys = 1;
25 $Data::Dumper::Useqq = 1;
34 # Utility functions for our buildsystem
38 use make::opensslcert;
40 ###############################################################################################
44 ###############################################################################################
46 # If you wish to ignore a dependency throughout the entire core, add it here.
49 "inspircd_win32wrapper.h", # windows has its own configure program
52 # If you wish for all files in the entire core to have a given dependency, insert it here.
53 # You should keep this to an absolute minimum to avoid rebuilds that are not neccessary.
55 our @immutabledeps = (
56 "inspircd_config.h", # auto re-generated by configure
60 ###############################################################################################
62 # NON-EDITABLE VARIABLES
64 ###############################################################################################
66 # List of commands that make up 'make install' and 'make deinstall'
68 our $install_list = "";
69 our $uninstall_list = "";
71 # This is a list of all files in the core. Each cpp file is mapped to a shared object file,
72 # whos file extension is omitted (these can vary from system to system). Auto detected by
73 # scanning the src/*.cpp files for files containing /* $Core: */ identifiers.
77 # If you wish for a file to have special dependencies in the makefile, add an entry here.
78 # Auto populated by /* $ExtraDeps: */ instruction
80 our %specialdeps = ();
82 # If you wish for a file to have extra make lines (in between the compile and link steps)
83 # then insert them here.
84 # Auto populated by /* $ExtraBuild: */ instruction
86 our %extrabuildlines = ();
88 # If you wish for a file to be linked against extra objects or arctives, insert them here.
89 # Auto populated by /* $ExtraObjects: */ instruction
91 our %extraobjects = ();
93 # If you wish to compile extra cpp sources into an object, define them here.
94 # NOTE: Certain cpp files such as the socket engines have a value auto calculated
95 # for this table so that their derived class is built.
96 # Auto populated by /* $ExtraSources: */ instruction
98 our %extrasources = ();
100 our ($opt_use_gnutls, $opt_rebuild, $opt_use_openssl, $opt_nointeractive, $opt_nick_length,
101 $opt_chan_length, $opt_maxclients, $opt_ports, $opt_epoll, $opt_kqueue, $opt_noports,
102 $opt_noepoll, $opt_nokqueue, $opt_disablerpath, $opt_ipv6, $opt_ipv6links,
103 $opt_noipv6links, $opt_ident, $opt_quit, $opt_topic, $opt_maxbuf, $opt_kick,
104 $opt_gecos, $opt_away, $opt_modes, $opt_disable_debug, $opt_maxchans,
107 our ($opt_cc, $opt_base_dir, $opt_config_dir, $opt_module_dir, $opt_binary_dir,
112 sub enable_extras (@);
114 sub disable_extras (@);
116 my @opt_enableextras;
117 my @opt_disableextras;
120 'enable-gnutls' => \$opt_use_gnutls,
121 'rebuild' => \$opt_rebuild,
122 'enable-openssl' => \$opt_use_openssl,
123 'disable-interactive' => \$opt_nointeractive,
124 'with-nick-length=i' => \$opt_nick_length,
125 'with-channel-length=i' => \$opt_chan_length,
126 'with-max-clients=i' => \$opt_maxclients,
127 'enable-ports' => \$opt_ports,
128 'enable-epoll' => \$opt_epoll,
129 'enable-kqueue' => \$opt_kqueue,
130 'disable-ports' => \$opt_noports,
131 'disable-epoll' => \$opt_noepoll,
132 'disable-kqueue' => \$opt_nokqueue,
133 'disable-rpath' => \$opt_disablerpath,
134 'enable-ipv6' => \$opt_ipv6,
135 'enable-remote-ipv6' => \$opt_ipv6links,
136 'disable-remote-ipv6' => \$opt_noipv6links,
137 'with-cc=s' => \$opt_cc,
138 'with-ident-length=i' => \$opt_ident,
139 'with-quit-length=i' => \$opt_quit,
140 'with-topic-length=i' => \$opt_topic,
141 'with-maxbuf=i' => \$opt_maxbuf,
142 'with-kick-length=i' => \$opt_kick,
143 'with-gecos-length=i' => \$opt_gecos,
144 'with-away-length=i' => \$opt_away,
145 'with-max-modes=i' => \$opt_modes,
146 'prefix=s' => \$opt_base_dir,
147 'config-dir=s' => \$opt_config_dir,
148 'module-dir=s' => \$opt_module_dir,
149 'binary-dir=s' => \$opt_binary_dir,
150 'library-dir=s' => \$opt_library_dir,
151 'disable-debuginfo' => sub { $opt_disable_debug = 1 },
152 'help' => sub { showhelp(); },
153 'modupdate' => sub { modupdate(); },
154 'update' => sub { update(); },
155 'svnupdate' => sub { svnupdate(); },
156 'clean' => sub { clean(); },
157 'list-extras' => sub { list_extras; exit 0; }, # This, --enable-extras, and --disable-extras are for non-interactive managing.
158 'enable-extras=s@' => \@opt_enableextras, # ^
159 'disable-extras=s@' => \@opt_disableextras, # ^
162 if (scalar(@opt_enableextras) + scalar(@opt_disableextras) > 0) {
163 @opt_enableextras = split /,/, join(',', @opt_enableextras);
164 @opt_disableextras = split /,/, join(',', @opt_disableextras);
165 enable_extras(@opt_enableextras);
166 disable_extras(@opt_disableextras);
168 print "Remember: YOU are responsible for making sure any libraries needed have been installed!\n";
169 print "Run $0 -modupdate after you've done this to update the makefiles.\n";
173 our $non_interactive = (
174 (defined $opt_library_dir) ||
175 (defined $opt_base_dir) ||
176 (defined $opt_config_dir) ||
177 (defined $opt_module_dir) ||
178 (defined $opt_base_dir) ||
179 (defined $opt_binary_dir) ||
180 (defined $opt_nointeractive) ||
181 (defined $opt_away) ||
182 (defined $opt_gecos) ||
183 (defined $opt_kick) ||
184 (defined $opt_maxclients) ||
185 (defined $opt_modes) ||
186 (defined $opt_topic) ||
187 (defined $opt_quit) ||
188 (defined $opt_ident) ||
190 (defined $opt_ipv6) ||
191 (defined $opt_ipv6links) ||
192 (defined $opt_noipv6links) ||
193 (defined $opt_kqueue) ||
194 (defined $opt_epoll) ||
195 (defined $opt_ports) ||
196 (defined $opt_maxchans) ||
197 (defined $opt_opermaxchans) ||
198 (defined $opt_chan_length) ||
199 (defined $opt_nick_length) ||
200 (defined $opt_use_openssl) ||
201 (defined $opt_nokqueue) ||
202 (defined $opt_noepoll) ||
203 (defined $opt_noports) ||
204 (defined $opt_maxbuf) ||
205 (defined $opt_use_gnutls)
207 our $interactive = !$non_interactive;
209 chomp(our $topdir = getcwd());
210 our $this = resolve_directory($topdir); # PWD, Regardless.
211 our @modlist = (); # Declare for Module List..
212 our %config = (); # Initiate Configuration Hash..
213 $config{ME} = resolve_directory($topdir); # Present Working Directory
215 $config{BASE_DIR} = $config{ME};
217 if (defined $opt_base_dir)
219 $config{BASE_DIR} = $opt_base_dir;
222 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Directory
223 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
224 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
225 $config{LIBRARY_DIR} = resolve_directory($config{BASE_DIR}."/lib"); # Library Directory
227 if (defined $opt_config_dir)
229 $config{CONFIG_DIR} = $opt_config_dir;
231 if (defined $opt_module_dir)
233 $config{MODULE_DIR} = $opt_module_dir;
235 if (defined $opt_binary_dir)
237 $config{BINARY_DIR} = $opt_binary_dir;
239 if (defined $opt_library_dir)
241 $config{LIBRARY_DIR} = $opt_library_dir;
243 chomp($config{HAS_GNUTLS} = `libgnutls-config --version 2>/dev/null | cut -c 1,2,3`); # GNUTLS Version.
244 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`); # Openssl version
245 chomp(our $gnutls_ver = $config{HAS_GNUTLS});
246 chomp(our $openssl_ver = $config{HAS_OPENSSL});
247 $config{USE_GNUTLS} = "n";
248 if (defined $opt_use_gnutls)
250 $config{USE_GNUTLS} = "y"; # Use gnutls.
252 $config{USE_OPENSSL} = "n"; # Use openssl.
253 if (defined $opt_use_openssl)
255 $config{USE_OPENSSL} = "y";
258 # no, let's not change these.
259 $config{OPTIMITEMP} = "0"; # Default Optimisation Value
260 if (!defined $opt_disable_debug)
262 $config{OPTIMISATI} = "-g1"; # Optimisation Flag
266 $config{OPTIMISATI} = "-O2"; # DEBUGGING OFF!
269 $config{NICK_LENGT} = "31"; # Default Nick Length
270 if (defined $opt_nick_length)
272 $config{NICK_LENGT} = $opt_nick_length;
274 $config{CHAN_LENGT} = "64"; # Default Channel Name Length
275 if (defined $opt_chan_length)
277 $config{CHAN_LENGT} = $opt_chan_length;
279 $config{MAXI_MODES} = "20"; # Default Max. Number of Modes set at once.
280 if (defined $opt_modes)
282 $config{MAXI_MODES} = $opt_modes;
284 $config{HAS_STRLCPY} = "false"; # strlcpy Check.
285 $config{HAS_STDINT} = "false"; # stdint.h check
286 $config{USE_KQUEUE} = "y"; # kqueue enabled
287 if (defined $opt_kqueue)
289 $config{USE_KQUEUE} = "y";
291 if (defined $opt_nokqueue)
293 $config{USE_KQUEUE} = "n";
295 $config{USE_EPOLL} = "y"; # epoll enabled
296 if (defined $opt_epoll)
298 $config{USE_EPOLL} = "y";
300 if (defined $opt_noepoll)
302 $config{USE_EPOLL} = "n";
304 $config{USE_PORTS} = "y"; # epoll enabled
305 if (defined $opt_ports)
307 $config{USE_PORTS} = "y";
309 if (defined $opt_noports)
311 $config{USE_PORTS} = "n";
313 $config{IPV6} = "n"; # IPv6 support (experimental)
314 if (defined $opt_ipv6)
318 $config{SUPPORT_IP6LINKS} = "y"; # IPv4 supporting IPv6 links (experimental)
319 if (defined $opt_ipv6links)
321 $config{SUPPORT_IP6LINKS} = "y";
323 if (defined $opt_noipv6links)
325 $config{SUPPORT_IP6LINKS} = "n";
327 chomp($config{MAX_CLIENT_T} = `sh -c \"ulimit -n\"`); # FD Limit
328 chomp($config{MAX_DESCRIPTORS} = `sh -c \"ulimit -n\"`); # Hard FD Limit
329 chomp($config{GCCVER} = `g++ -dumpversion | cut -c 1`); # Major GCC Version
330 $config{_SOMAXCONN} = SOMAXCONN; # Max connections in accept queue
331 $config{OSNAME} = $^O; # Operating System Name
332 $config{IS_DARWIN} = "NO"; # Is OSX?
333 $config{STARTSCRIPT} = "inspircd"; # start script?
334 $config{DESTINATION} = "BASE"; # Is target path.
335 $config{EXTRA_DIR} = ""; # Is empty.
336 if ($config{OSNAME} =~ /darwin/i)
338 $config{IS_DARWIN} = "YES";
339 $config{STARTSCRIPT} = "org.inspircd.plist"; # start script for OSX.
340 $config{DESTINATION} = "LAUNCHDPATH"; # Is OSX target.
341 $config{EXTRA_DIR} = " launchd_dir"; # Is OSX specific path.
343 $config{CC} = "g++"; # C++ compiler
346 $config{CC} = $opt_cc;
348 our $exec = $config{CC} . " -dumpversion | cut -c 1";
349 chomp($config{GCCVER} = `$exec`); # Major GCC Version
350 $config{MAKEORDER} = "ircd mods"; # build order
351 $config{MAX_IDENT} = "12"; # max ident size
352 $config{MAX_QUIT} = "255"; # max quit message size
353 $config{MAX_TOPIC} = "307"; # max topic size
354 $config{MAX_KICK} = "255"; # max kick message size
355 $config{MAX_GECOS} = "128"; # max GECOS size
356 $config{MAX_AWAY} = "200"; # max AWAY size
357 $config{MAXBUF} = "512"; # Max buffer size
358 if (defined $opt_ident)
360 $config{MAX_IDENT} = $opt_ident;
362 if (defined $opt_quit)
364 $config{MAX_QUIT} = $opt_quit;
366 if (defined $opt_topic)
368 $config{MAX_TOPIC} = $opt_topic;
370 if (defined $opt_kick)
372 $config{MAX_KICK} = $opt_kick;
374 if (defined $opt_gecos)
376 $config{MAX_GECOS} = $opt_gecos;
378 if (defined $opt_away)
380 $config{MAX_AWAY} = $opt_away;
383 $config{HAS_OPENSSL} =~ /^([-[:digit:].]+)([a-z])?(\-[a-z][0-9])?$/;
384 $config{HAS_OPENSSL} = $1;
386 if ($config{GCCVER} eq "") {
387 print $config{CC} . " was not found! You require g++ (the GNU C++ compiler, part of GCC) to build InspIRCd!\n";
391 our $fd_scan_fail = "";
392 if (!$config{MAX_CLIENT_T}) {
393 $config{MAX_CLIENT_T} = 1024; # Set a reasonable 'Default'
394 $fd_scan_fail = "true"; # Used Later
397 # Get and Set some important vars..
402 unlink(".config.cache");
405 our ($has_epoll, $has_ports, $has_kqueue) = (0, 0, 0);
410 chomp($topdir = getcwd());
411 $this = resolve_directory($topdir); # PWD, Regardless.
413 # Does the cache file exist?
415 # No, No it doesn't.. *BASH*
416 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
419 # We've Loaded the cache file and all our variables..
420 print "Updating files...\n";
422 if (defined($opt_disable_debug) && $opt_disable_debug == 1)
424 print "Disabling debug information (-g).\n";
425 $config{OPTIMISATI} = "";
428 $has_epoll = $config{HAS_EPOLL};
429 $has_ports = $config{HAS_PORTS};
430 $has_kqueue = $config{HAS_KQUEUE};
439 print "Configure update failed: $@\n";
447 chomp($topdir = getcwd());
448 $this = resolve_directory($topdir); # PWD, Regardless.
450 # Does the cache file exist?
452 # No, No it doesn't.. *BASH*
453 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
456 # We've Loaded the cache file and all our variables..
457 print "Updating files...\n";
459 $has_epoll = $config{HAS_EPOLL};
460 $has_ports = $config{HAS_PORTS};
461 $has_kqueue = $config{HAS_KQUEUE};
470 print "Module update failed: $@\n";
480 open(FH,"<.svn/entries") or $fail = 1;
482 print "This is not an SVN copy of InspIRCd.\n";
489 system("svn update");
490 system("perl configure -update");
491 if (defined $opt_rebuild) {
492 system("make install");
497 print "Running non-interactive configure...\n" unless $interactive;
498 print "Checking for cache from previous configure... ";
499 print ((!getcache()) ? "not found\n" : "found\n");
500 print "Checking operating system version... ";
501 print getosflags() . "\n";
503 if (defined $opt_maxclients)
505 $config{MAX_CLIENT} = $opt_maxclients;
508 if (!$config{MAX_CLIENT}) {
509 # If the cache hasn't set the max clients, copy the variable of MAX_CLIENT_T, this
510 # allows us to keep _T for testing purposes. (ie. "Are you sure you want to go
511 # higher than the found value" :))
512 $config{MAX_CLIENT} = $config{MAX_CLIENT_T};
515 printf "Checking if stdint.h exists... ";
516 $config{HAS_STDINT} = "true";
518 open(STDINT, "</usr/include/stdint.h") or $config{HAS_STDINT} = "false";
519 if ($config{HAS_STDINT} eq "true") {
522 print "yes\n" if $config{HAS_STDINT} eq "true";
523 print "no\n" if $config{HAS_STDINT} eq "false";
525 printf "Checking if strlcpy exists... ";
526 # Perform the strlcpy() test..
527 $config{HAS_STRLCPY} = "false";
529 open(STRLCPY, "</usr/include/string.h") or $fail = 1;
531 while (defined(my $line = <STRLCPY>)) {
533 # try and find the delcaration of:
534 # size_t strlcpy(...)
535 if ($line =~ /size_t(\0x9|\s)+strlcpy/) {
536 $config{HAS_STRLCPY} = "true";
541 print "yes\n" if $config{HAS_STRLCPY} eq "true";
542 print "no\n" if $config{HAS_STRLCPY} eq "false";
544 printf "Checking if kqueue exists... ";
547 open(KQUEUE, "</usr/include/sys/event.h") or $fail = 1;
549 while (defiined(my $line = <KQUEUE>)) {
551 # try and find the delcaration of:
553 if ($line =~ /int(\0x9|\s)+kqueue/) {
559 print "yes\n" if $has_kqueue == 1;
560 print "no\n" if $has_kqueue == 0;
562 printf "Checking if epoll exists... ";
565 open(EPOLL, "</usr/include/sys/epoll.h") or $fail = 1;
571 my $kernel = `uname -r`;
573 if (($kernel =~ /^2\.0\./) || ($kernel =~ /^2\.2\./) || ($kernel =~ /^2\.4\./)) {
578 # Suggestion from nenolod, weed out odd systems which have glibc built
579 # against 2.4 kernels (ick)
580 my $kernel_arch = `uname -p`;
584 if ($kernel_arch =~ /x86_64/) {
585 open (FH,"/lib64/libc.so.6|") or $has_epoll = 0;
588 open (FH,"/lib/libc.so.6|") or $has_epoll = 0;
592 while (defined(my $line = <FH>))
595 if ($line =~ /GNU C Library .* version (.*?) /)
598 $libcv =~ /(\d+\.\d+)/;
601 elsif ($line =~ /Compiled on a Linux (.*?\..*?)\.* system/)
604 # Fix for some retarded libc builds, strip off >> and << etc.
605 $kernelv =~ /(\d+\.\d+)/;
613 printf "libc too old: $libcv... ";
618 printf "libc built against older kernel $kernelv... ";
623 print "yes\n" if $has_epoll == 1;
624 print "no\n" if $has_epoll == 0;
626 printf "Checking if Solaris I/O completion ports are available... ";
628 our $system = `uname -s`;
630 $has_ports = 1 if ($system eq "SunOS");
633 my $kernel = `uname -r`;
635 if (($kernel !~ /^5\.1./)) {
639 print "yes\n" if $has_ports == 1;
640 print "no\n" if $has_ports == 0;
642 $config{HAS_EPOLL} = $has_epoll;
643 $config{HAS_KQUEUE} = $has_kqueue;
645 printf "Checking for libgnutls... ";
646 if (($config{HAS_GNUTLS}) || ($config{HAS_GNUTLS} eq "y")) {
648 $config{HAS_GNUTLS} = "y";
651 $config{HAS_GNUTLS} = "n";
654 printf "Checking for openssl... ";
655 if (($config{HAS_OPENSSL}) || ($config{HAS_OPENSSL} eq "y")) {
657 $config{HAS_OPENSSL} = "y";
660 $config{HAS_OPENSSL} = "n";
663 printf "Checking if you are running an ancient, unsupported OS... ";
664 if ($config{OSNAME} =~ /FreeBSD/i)
666 my $version = `uname -r`;
667 if ($version =~ /^4\./)
669 my $foundit = `ls -l /usr/local/lib/libgnugetopt* | wc -l`;
672 # ICKY ICKY ICK, FREEBSD 4.x! GET AN UPGRADE!
673 $config{CRAQ} = "-L/usr/local/lib -lgnugetopt -DHAVE_DECL_GETOPT=1";
678 print "\n\nERROR: You require libgnugetopt (from ports or packages) to build InspIRCd on FreeBSD 4.11.\n";
684 print "no ($version)\n";
690 print "no ($config{OSNAME})\n";
693 ################################################################################
694 # BEGIN INTERACTIVE PART #
695 ################################################################################
700 print "\e[2J\e[0G\e[0d"; # J = Erase in Display, 2 = Entire Screen, (G, d) = Move cursor to (..,..)
703 my $rev = getrevision();
704 # Display Introduction Message..
706 Welcome to the \e[1mInspIRCd\e[0m Configuration program! (\e[1minteractive mode\e[0m)
707 \e[1mPackage maintainers: Type ./configure --help for non-interactive help\e[0m
709 *** If you are unsure of any of these values, leave it blank for ***
710 *** standard settings that will work, and your server will run ***
711 *** using them. Please consult your IRC network admin if in doubt. ***
713 Press \e[1m<RETURN>\e[0m to accept the default for any option, or enter
714 a new value. Please note: You will \e[1mHAVE\e[0m to read the docs
715 dir, otherwise you won't have a config file!
717 Your operating system is: \e[1;32m$config{OSNAME}\e[0m ($wholeos)
718 Maximum file descriptors: \e[1;32m$config{MAX_CLIENT_T}\e[0m
719 Your InspIRCd revision ID is \e[1;32mr$rev\e[0m
722 print " (Non-SVN build)";
726 $config{CHANGE_COMPILER} = "n";
727 print "I have detected the following compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.x\e[0m)\n";
729 while (($config{GCCVER} < 3) || ($config{GCCVER} eq "")) {
730 print "\e[1;32mIMPORTANT!\e[0m A GCC 2.x compiler has been detected, and
731 should NOT be used. You should probably specify a newer compiler.\n\n";
732 yesno('CHANGE_COMPILER',"Do you want to change the compiler?");
733 if ($config{CHANGE_COMPILER} =~ /y/i) {
734 print "What command do you want to use to invoke your compiler?\n";
735 print "[\e[1;32m$config{CC}\e[0m] -> ";
736 chomp($config{CC} = <STDIN>);
737 if ($config{CC} eq "") {
740 chomp(my $foo = `$config{CC} -dumpversion | cut -c 1`);
742 chomp($config{GCCVER} = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
743 print "Queried compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.x\e[0m)\n";
744 if ($config{GCCVER} < 3) {
745 print "\e[1;32mGCC 2.x WILL NOT WORK!\e[0m. Let's try that again, shall we?\n";
749 print "\e[1;32mWARNING!\e[0m Could not execute the compiler you specified. You may want to try again.\n";
756 # Directory Settings..
757 my $tmpbase = $config{BASE_DIR};
758 dir_check("do you wish to install the InspIRCd base", "BASE_DIR");
759 if ($tmpbase ne $config{BASE_DIR}) {
760 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Dir
761 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
762 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
763 $config{LIBRARY_DIR} = resolve_directory($config{BASE_DIR}."/lib"); # Library Directory
766 dir_check("are the configuration files", "CONFIG_DIR");
767 dir_check("are the modules to be compiled to", "MODULE_DIR");
768 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
769 dir_check("are the IRCd libraries to be placed", "LIBRARY_DIR");
772 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?");
776 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?");
780 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?");
783 my $chose_hiperf = (($config{USE_EPOLL} eq "y") || ($config{USE_KQUEUE} eq "y") || ($config{USE_PORTS} eq "y"));
784 if (!$chose_hiperf) {
785 print "No high-performance socket engines are available, or you chose\n";
786 print "not to enable one. Defaulting to select() engine.\n\n";
789 yesno('IPV6',"Would you like to build InspIRCd with IPv6 support?");
792 if ($config{IPV6} eq "y") {
793 print "You have chosen to build an \e[1;32mIPV6-enabled\e[0m server.\nTo accept IPV4 users, you can still use IPV4 addresses\nin your port bindings..\n\n";
794 $config{SUPPORT_IP6LINKS} = "y";
796 yesno('SUPPORT_IP6LINKS',"You have chosen to build an \e[1;32mIPV4-only\e[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)");
800 if (($config{HAS_GNUTLS} eq "y") && ($config{HAS_OPENSSL} eq "y")) {
801 print "I have detected both \e[1;32mGnuTLS\e[0m and \e[1;32mOpenSSL\e[0m on your system.\n";
802 print "I will default to GnuTLS. If you wish to use OpenSSL\n";
803 print "instead, you should enable the OpenSSL module yourself\n";
804 print "by copying it from src/modules/extra to src/modules.\n\n";
805 print "Detected GnuTLS version: \e[1;32m" . $gnutls_ver . "\e[0m\n";
806 print "Detected OpenSSL version: \e[1;32m" . $openssl_ver . "\e[0m\n\n";
809 if ($config{HAS_GNUTLS} eq "y") {
810 yesno('USE_GNUTLS', "Would you like to enable SSL Support?");
811 if ($config{USE_GNUTLS} eq "y") {
812 print "\nUsing GnuTLS SSL module.\n";
814 } elsif ($config{HAS_OPENSSL} eq "y") {
815 yesno('USE_OPENSSL', "Would you like to enable SSL Support?");
816 if ($config{USE_OPENSSL} eq "y") {
817 print "\nUsing OpenSSL SSL module.\nYou will get better performance if you move to GnuTLS in the future.\n";
821 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";
824 print "\nThe following questions will ask you for various figures relating\n";
825 print "To your IRCd install. Please note that these should usually be left\n";
826 print "as defaults unless you have a real reason to change them. If they\n";
827 print "changed, then the values must be identical on all servers on your\n";
828 print "network, or malfunctions and/or crashes may occur, with the exception\n";
829 print "of the 'maximum number of clients' setting which may be different on\n";
830 print "different servers on the network.\n\n";
832 # File Descriptor Settings..
833 promptnumeric("number of clients at any one time", "MAX_CLIENT_T");
834 $config{MAX_CLIENT} = $config{MAX_CLIENT_T};
835 $config{MAX_DESCRIPTORS} = $config{MAX_CLIENT_T};
837 promptnumeric("length of nicknames", "NICK_LENGT");
838 promptnumeric("length of channel names", "CHAN_LENGT");
839 promptnumeric("number of mode changes in one line", "MAXI_MODES");
840 promptnumeric("length of an ident (username)", "MAX_IDENT");
841 promptnumeric("length of a quit message", "MAX_QUIT");
842 promptnumeric("length of a channel topic", "MAX_TOPIC");
843 promptnumeric("length of a kick message", "MAX_KICK");
844 promptnumeric("length of a GECOS (real name)", "MAX_GECOS");
845 promptnumeric("length of an away message", "MAX_AWAY");
850 if (($config{USE_GNUTLS} eq "y") && ($config{HAS_GNUTLS} ne "y"))
852 print "Sorry, but i couldn't detect gnutls. Make sure gnutls-config is in your path.\n";
855 if (($config{USE_OPENSSL} eq "y") && ($config{HAS_OPENSSL} ne "y"))
857 print "Sorry, but i couldn't detect openssl. Make sure openssl is in your path.\n";
862 if ($config{USE_GNUTLS} eq "y") {
863 unless (-r "src/modules/m_ssl_gnutls.cpp") {
864 print "Symlinking src/modules/m_ssl_gnutls.cpp from extra/\n";
865 symlink "extra/m_ssl_gnutls.cpp", "src/modules/m_ssl_gnutls.cpp" or print STDERR "Symlink failed: $!";
870 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
871 print "SSL Certificates Not found, Generating.. \n\n
872 *************************************************************
873 * Generating the Private Key may take some time, go grab a *
874 * Coffee. Even better, to generate some more entropy if it *
875 * is taking a while, open another console and type du / a *
876 * few times and get that HD going :) Then answer the *
877 * Questions which follow. If you are unsure, just hit enter *
878 *************************************************************\n\n";
879 $failed = make_gnutls_cert();
881 print "\n\e[1;32mCertificate generation failed!\e[0m\n\n";
883 print "\nCertificate generation complete, copying to config directory... ";
884 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
885 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
890 print "SSL Certificates found, skipping.\n\n";
895 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
897 } elsif ($config{USE_OPENSSL} eq "y") {
898 unless (-r "src/modules/m_ssl_openssl.cpp") {
899 print "Symlinking src/modules/m_ssl_openssl.cpp from extra/\n";
900 symlink "extra/m_ssl_openssl.cpp", "src/modules/m_ssl_openssl.cpp" or print STDERR "Symlink failed: $!";
906 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
907 print "SSL Certificates Not found, Generating.. \n\n
908 *************************************************************
909 * Generating the certificates may take some time, go grab a *
910 * coffee, or something. *
911 *************************************************************\n\n";
913 print "\nCertificate generation complete, copying to config directory... ";
914 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
915 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
916 File::Copy::move("dhparams.pem", "$config{CONFIG_DIR}/dhparams.pem") or print STDERR "Could not copy dhparams.pem!\n";
919 print "SSL Certificates found, skipping.\n\n"
924 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
927 if (($config{USE_GNUTLS} eq "n") && ($config{USE_OPENSSL} eq "n")) {
928 print "Skipping SSL Certificate generation, SSL support is not available.\n\n";
936 print "To build your server with these settings, please type '\e[1;32m$config{MAKEPROG}\e[0m' now.\n";
937 if (($config{USE_GNUTLS} eq "y") || ($config{USE_OPENSSL} eq "y")) {
938 print "Please remember that to enable \e[1;32mSSL support\e[0m you must\n";
939 print "load the required modules in your config. This configure process\n";
940 print "has just prepared these modules to be compiled for you, and has not\n";
941 print "configured them to be compiled into the core of the ircd.\n";
943 print "*** \e[1;32mRemember to edit your configuration files!!!\e[0m ***\n\n\n";
944 if (($config{OSNAME} eq "OpenBSD") && ($config{CC} ne "eg++")) {
945 print "\e[1;32mWARNING!\e[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";
948 if ($config{GCCVER} < "3") {
950 \e[1;32mWARNING!\e[0m You are attempting to compile InspIRCd on GCC 2.x!
951 GCC 2.x series compilers only had partial (read as broken) C++ support, and
952 your compile will most likely fail horribly! If you have any problems, do NOT
953 report them to the bugtracker or forums without first upgrading your compiler
954 to a newer 3.x or 4.x (or whatever is available currently) version.
958 ################################################################################
960 ################################################################################
962 # Retrieves the .config.cache file, and loads values into the main config hash.
963 open(CACHE, ".config.cache") or return 0;
966 # Ignore Blank lines, and comments..
969 my ($key, $value) = split("=", $_, 2);
970 $value =~ /^\"(.*)\"$/;
971 # Do something with data here!
979 # Dump the contents of %config
980 print "Writing \e[1;32mcache file\e[0m for future ./configures ...\n";
981 open(FILEHANDLE, ">.config.cache");
982 foreach my $key (keys %config) {
983 print FILEHANDLE "$key=\"$config{$key}\"\n";
989 my ($desc, $hash_key) = @_;
992 print "In what directory $desc?\n";
993 print "[\e[1;32m$config{$hash_key}\e[0m] -> ";
994 chomp(my $var = <STDIN>);
996 $var = $config{$hash_key};
998 if ($var =~ /^\~\/(.+)$/) {
999 # Convert it to a full path..
1000 $var = resolve_directory($ENV{HOME} . "/" . $1);
1002 elsif ((($config{OSNAME} =~ /MINGW32/i) and ($var !~ /^[A-Z]{1}:\\.*/)) and (substr($var,0,1) ne "/"))
1004 # Assume relative Path was given.. fill in the rest.
1005 $var = $this . "/$var";
1008 $var = resolve_directory($var);
1010 print "$var does not exist. Create it?\n[\e[1;32my\e[0m] ";
1011 chomp(my $tmp = <STDIN>);
1012 if (($tmp eq "") || ($tmp =~ /^y/i)) {
1013 # Attempt to Create the Dir..
1016 File::Path::mkpath($var, 0, 0777);
1019 unless (defined($chk) && -d $var) {
1020 print "Unable to create directory. ($var)\n\n";
1025 # They said they don't want to create, and we can't install there.
1030 if (!is_dir($var)) {
1031 # Target exists, but is not a directory.
1032 print "File $var exists, but is not a directory.\n\n";
1036 # Either Dir Exists, or was created fine.
1037 $config{$hash_key} = $var;
1047 $config{LDLIBS} = "-lstdc++";
1048 $config{FLAGS} = "-fPIC -Wall $config{OPTIMISATI}";
1049 $config{DEVELOPER} = "-fPIC -Wall -g";
1050 $SHARED = "-Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared" unless defined $opt_disablerpath;
1051 $config{MAKEPROG} = "make";
1053 if ($config{OSNAME} =~ /darwin/i) {
1054 $config{FLAGS} = "-DDARWIN -frtti -fPIC -Wall $config{OPTIMISATI}";
1055 $SHARED = "-bundle -twolevel_namespace -undefined dynamic_lookup";
1056 $config{LDLIBS} = "-ldl -lstdc++";
1059 if ($config{OSNAME} =~ /OpenBSD/i) {
1060 $config{MAKEPROG} = "gmake";
1061 $config{LDLIBS} = $config{LDLIBS} . " -lunwind";
1062 chomp(my $foo = `eg++ -dumpversion | cut -c 1`);
1063 # theyre running the package version of gcc (eg++)... detect it and set up its version numbers.
1064 # if theyre not running this, configure lets the build continue but they probably wont manage to
1065 # compile as this standard version is 2.95.3!
1067 $config{CC} = "eg++";
1068 chomp($config{GCCVER} = `eg++ -dumpversion | cut -c 1`); # we must redo these if we change the compiler path
1073 if ($config{OSNAME} =~ /Linux/i) {
1074 $config{LDLIBS} = "-ldl -lstdc++";
1075 $config{FLAGS} = "-fPIC -Wall $config{OPTIMISATI}";
1076 $config{FLAGS} .= " " . $ENV{CXXFLAGS} if exists($ENV{CXXFLAGS});
1077 $config{LDLIBS} .= " " . $ENV{LDLIBS} if exists($ENV{LDLIBS});
1078 $config{MAKEPROG} = "make";
1081 if ($config{OSNAME} =~ /FreeBSD/i) {
1082 $config{FLAGS} .= " " . $ENV{CXXFLAGS} if exists($ENV{CXXFLAGS});
1083 $config{LDLIBS} .= " " . $ENV{LDLIBS} if exists($ENV{LDLIBS});
1086 if ($config{OSNAME} =~ /SunOS/i or $config{OSNAME} =~ /solaris/i)
1088 # solaris/sunos needs these
1089 # socket = bsd sockets api
1091 # rt = POSIX realtime extensions
1092 # resolv = inet_aton only (why isnt this in nsl?!)
1093 $config{MAKEPROG} = "gmake";
1094 $config{LDLIBS} .= " -lsocket -lnsl -lrt -lresolv";
1098 if($config{OSNAME} =~ /MINGW32/i)
1100 # All code is position-independent on windows
1101 $config{FLAGS} =~ s/-fPIC //;
1105 return $config{OSNAME};
1108 my ($mliflags, $mfrules, $mobjs, $mfcount) = ("", "", "", 0);
1111 my($writeheader) = @_;
1113 # First File.. inspircd_config.h
1114 chomp(my $incos = `uname -n -s -r`);
1115 chomp(my $version = `sh src/version.sh`);
1116 chomp(my $revision2 = getrevision());
1117 if ($writeheader == 1)
1119 print "Writing \e[1;32minspircd_config.h\e[0m\n";
1120 open(FILEHANDLE, ">include/inspircd_config.h");
1121 my $NL = $config{NICK_LENGT}+1;
1122 my $CL = $config{CHAN_LENGT}+1;
1123 print FILEHANDLE <<EOF;
1124 /* Auto generated by configure, do not modify! */
1125 #ifndef __CONFIGURATION_AUTO__
1126 #define __CONFIGURATION_AUTO__
1128 /* this is for windows support. */
1129 #define CoreExport /**/
1130 #define DllExport /**/
1132 #define CONFIG_FILE "$config{CONFIG_DIR}/inspircd.conf"
1133 #define MOD_PATH "$config{MODULE_DIR}"
1134 #define VERSION "$version"
1135 #define REVISION "$revision2"
1136 #define MAXCLIENTS $config{MAX_CLIENT}
1137 #define MAXCLIENTS_S "$config{MAX_CLIENT}"
1138 #define SOMAXCONN_S "$config{_SOMAXCONN}"
1139 #define MAX_DESCRIPTORS $config{MAX_DESCRIPTORS}
1142 #define MAXMODES $config{MAXI_MODES}
1143 #define IDENTMAX $config{MAX_IDENT}
1144 #define MAXQUIT $config{MAX_QUIT}
1145 #define MAXTOPIC $config{MAX_TOPIC}
1146 #define MAXKICK $config{MAX_KICK}
1147 #define MAXGECOS $config{MAX_GECOS}
1148 #define MAXAWAY $config{MAX_AWAY}
1149 #define OPTIMISATION $config{OPTIMITEMP}
1150 #define LIBRARYDIR "$config{LIBRARY_DIR}"
1151 #define SYSTEM "$incos"
1153 print FILEHANDLE "#define MAXBUF " . ($config{MAXBUF}+2) . "\n";
1155 if ($config{OSNAME} =~ /SunOS/i) {
1156 print FILEHANDLE "#define IS_SOLARIS\n";
1158 if ($config{OSNAME} =~ /MINGW32/i) {
1159 print FILEHANDLE "#define IS_MINGW\n";
1161 if ($config{GCCVER} >= 3) {
1162 print FILEHANDLE "#define GCC3\n";
1164 if ($config{HAS_STRLCPY} eq "true") {
1165 print FILEHANDLE "#define HAS_STRLCPY\n";
1167 if ($config{HAS_STDINT} eq "true") {
1168 print FILEHANDLE "#define HAS_STDINT\n";
1170 if ($config{IPV6} =~ /y/i) {
1171 print FILEHANDLE "#define IPV6\n";
1173 if ($config{SUPPORT_IP6LINKS} =~ /y/i) {
1174 print FILEHANDLE "#define SUPPORT_IP6LINKS\n";
1177 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
1178 print FILEHANDLE "#define USE_KQUEUE\n";
1179 $se = "socketengine_kqueue";
1182 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
1183 print FILEHANDLE "#define USE_EPOLL\n";
1184 $se = "socketengine_epoll";
1187 if (($has_ports) && ($config{USE_PORTS} eq "y")) {
1188 print FILEHANDLE "#define USE_PORTS\n";
1189 $se = "socketengine_ports";
1192 # user didn't choose either epoll or select for their OS.
1193 # default them to USE_SELECT (ewwy puke puke)
1195 print FILEHANDLE "#define USE_SELECT\n";
1196 $se = "socketengine_select";
1198 print FILEHANDLE "\n#endif\n";
1204 open(FILEHANDLE, ">include/inspircd_se_config.h");
1205 print FILEHANDLE <<EOF;
1206 /* Auto generated by configure, do not modify or commit to svn! */
1207 #ifndef __CONFIGURATION_SOCKETENGINE__
1208 #define __CONFIGURATION_SOCKETENGINE__
1210 #include "socketengines/$se.h"
1218 # Create a Modules List..
1220 foreach my $i (@modlist)
1222 $modules .= "m_".$i.".so ";
1224 chomp($modules); # Remove Redundant whitespace..
1226 opendir(DIRHANDLE, "src/modules");
1227 foreach my $name (sort readdir(DIRHANDLE)) {
1228 if ($name =~ /^m_(.+?)$/) {
1229 if (defined(opendir(MDIRHANDLE, "src/modules/$name"))) {
1230 closedir(MDIRHANDLE);
1231 $modules .= "$name.so ";
1232 $uninstall_list = $uninstall_list . " -rm \$(MODULES)/$name.so\n";
1236 closedir(DIRHANDLE);
1239 # Write all .in files.
1242 my $exe = "inspircd";
1244 # Do this once here, and cache it in the .*.inc files,
1245 # rather than attempting to read src/version.sh from
1246 # compiled code -- we might not have the source to hand.
1247 # Fix for bug#177 by Brain.
1249 chomp($version = `sh ./src/version.sh`);
1250 chomp(my $revision = getrevision());
1251 $version = "$version(r$revision)";
1253 # We can actually parse any file starting with . and ending with .inc,
1254 # but right now we only parse .inspircd.inc to form './inspircd'
1256 print "Writing \e[1;32mMakefiles\e[0m\n";
1257 write_dynamic_modules_makefile();
1258 write_dynamic_makefile();
1260 opendir(DIRHANDLE, $this);
1262 foreach my $name (sort readdir(DIRHANDLE)) {
1263 if ($name =~ /^\.(.+)\.inc$/) {
1266 # Bug #353, omit this on non-darwin
1267 next if (($config{OSNAME} !~ /darwin/) && ($file eq "org.inspircd.plist"));
1269 # All .name.inc files need parsing!
1271 open(FILEHANDLE, ".$file.inc") or die ("Can't open .$file.inc");
1272 while (<FILEHANDLE>) {
1277 print "Writing \e[1;32m$file\e[0m ...\n";
1278 $tmp =~ s/\@CC\@/$config{CC}/ if defined $config{CC};
1279 $tmp =~ s/\@MAKEPROG\@/$config{MAKEPROG}/ if defined $config{MAKEPROG};
1280 $tmp =~ s/\@FLAGS\@/$config{FLAGS}/ if defined $config{FLAGS};
1281 $tmp =~ s/\@DEVELOPER\@/$config{DEVELOPER}/ if defined $config{DEVELOPER};
1282 $tmp =~ s/\@LDLIBS\@/$config{LDLIBS}/ if defined $config{LDLIBS};
1283 $tmp =~ s/\@BASE_DIR\@/$config{BASE_DIR}/ if defined $config{BASE_DIR};
1284 $tmp =~ s/\@CONFIG_DIR\@/$config{CONFIG_DIR}/ if defined $config{CONFIG_DIR};
1285 $tmp =~ s/\@MODULE_DIR\@/$config{MODULE_DIR}/ if defined $config{MODULE_DIR};
1286 $tmp =~ s/\@BINARY_DIR\@/$config{BINARY_DIR}/ if defined $config{BINARY_DIR};
1287 $tmp =~ s/\@LIBRARY_DIR\@/$config{LIBRARY_DIR}/ if defined $config{LIBRARY_DIR};
1288 $tmp =~ s/\@MODULES\@/$modules/ if defined $modules;
1289 $tmp =~ s/\@STARTSCRIPT\@/$config{STARTSCRIPT}/ if defined $config{STARTSCRIPT};
1290 $tmp =~ s/\@DESTINATION\@/$config{DESTINATION}/ if defined $config{DESTINATION};
1291 $tmp =~ s/\@EXTRA_DIR\@/$config{EXTRA_DIR}/ if defined $config{EXTRA_DIR};
1292 $tmp =~ s/\@EXECUTABLE\@/$exe/ if defined $exe;
1293 $tmp =~ s/\@MAKEORDER\@/$config{MAKEORDER}/ if defined $config{MAKEORDER};
1294 $tmp =~ s/\@VERSION\@/$version/ if defined $version;
1295 $tmp =~ s/\@INSTALL_LIST\@/$install_list/ if defined $install_list;
1296 $tmp =~ s/\@UNINSTALL_LIST\@/$uninstall_list/ if defined $uninstall_list;
1298 open(FILEHANDLE, ">$file");
1299 print FILEHANDLE $tmp;
1302 closedir(DIRHANDLE);
1304 # Make inspircd executable!
1305 chmod 0744, 'inspircd';
1308 sub write_dynamic_modules_makefile {
1309 # Modules Makefile..
1310 print "Writing \e[1;32msrc/modules/Makefile\e[0m\n";
1311 open(FILEHANDLE, ">src/modules/Makefile");
1314 # Module Makefile Header
1316 print FILEHANDLE <<EOF;
1317 ###################################################
1318 # Copyright 2002-2007 The InspIRCd Development Team
1319 # http://www.inspircd.org/wiki/index.php/Credits
1321 # Thanks to Andrew Church <achurch\@achurch.org>
1322 # for assisting with making this work right.
1324 # Automatically Generated by ./configure to add a
1325 # modules please run ./configure -modupdate
1326 ###################################################
1332 if ($config{OSNAME} =~ /darwin/) {
1333 print FILEHANDLE <<EOCHEESE;
1335 PICLDFLAGS = -twolevel_namespace -undefined dynamic_lookup -bundle
1339 print FILEHANDLE <<EOCHEESE;
1341 PICLDFLAGS = -fPIC -DPIC -shared
1347 # End Module Makefile Header
1350 # Create a Modules List..
1354 foreach my $i (@modlist) {
1356 # Write Entry to the MakeFile
1358 $cmflags = getcompilerflags("src/modules/m_".$i.".cpp");
1359 $liflags = getlinkerflags("src/modules/m_".$i.".cpp");
1360 my $deps = getdependencies("src/modules/m_".$i.".cpp");
1362 #print "file: $i: cmflags=$cmflags; liflags=$liflags; deps=$deps\n";
1365 if (nopedantic("src/modules/m_".$i.".cpp"))
1368 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
1369 \$(CC) -pipe -I../../include \$(NICEFLAGS) $cmflags \$(PICLDFLAGS) $liflags -export-dynamic -o m_$i.so m_$i.cpp
1375 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
1376 \$(CC) -pipe -I../../include \$(FLAGS) $cmflags \$(PICLDFLAGS) $liflags -export-dynamic -o m_$i.so m_$i.cpp
1379 $install_list = $install_list . " install -m \$(INSTMODE) src/modules/m_$i.so \$(MODPATH)\n";
1380 $uninstall_list = $uninstall_list . " -rm \$(MODULES)/m_$i.so\n";
1382 # End Write Entry to the MakeFile
1386 opendir(DIRHANDLE, "src/modules");
1387 foreach my $name (sort readdir(DIRHANDLE)) {
1388 if ($name =~ /^m_(.+?)$/) {
1393 # A module made of multiple files, in a dir, e.g. src/modules/m_spanningtree/
1394 if (defined(opendir(MDIRHANDLE, "src/modules/$name"))) {
1395 read_module_directory("src/modules/$name", $name);
1396 print "Composing Makefile rules for directory \e[1;32m$name\e[0m... (\e[1;32m$mfcount files found\e[0m)\n";
1397 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";
1398 if ($config{IS_DARWIN} eq "YES") {
1399 print FILEHANDLE " \$(CC) -pipe -twolevel_namespace -undefined dynamic_lookup \$(FLAGS) $mliflags -bundle -o $name.so $mobjs\n";
1401 print FILEHANDLE " \$(CC) -pipe \$(FLAGS) -shared $mliflags -o $name.so $mobjs\n";
1403 print FILEHANDLE "\n$mfrules\n";
1404 closedir(MDIRHANDLE);
1405 $install_list = $install_list . " install -m \$(INSTMODE) src/modules/$name.so \$(MODPATH)\n";
1409 closedir(DIRHANDLE);
1412 sub read_module_directory {
1413 my ($dpath, $reldpath) = @_;
1415 if (opendir(MDIRHANDLE, $dpath) == 0) {
1419 foreach my $fname (sort readdir(MDIRHANDLE)) {
1420 if ($fname =~ /\.cpp$/) {
1421 my $cmflags = getcompilerflags("$dpath/$fname");
1422 $mliflags = $mliflags . " " . getlinkerflags("$dpath/$fname");
1423 my $deps = getdependencies("$dpath/$fname");
1425 $oname =~ s/\.cpp$/.o/g;
1426 $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";
1427 $mfrules = $mfrules . " \$(CC) -pipe -I../../include -I. \$(FLAGS) $cmflags -export-dynamic -o $reldpath/$oname -c $reldpath/$fname\n\n";
1428 $mobjs = $mobjs . " $reldpath/$oname";
1431 elsif ((-d "$dpath/$fname") && !($fname eq ".") && !($fname eq "..")) {
1432 read_module_directory($dpath."/".$fname, $reldpath."/".$fname);
1439 # Yes i know we could use gcc -M but it seems to ideneify a lot of 'deep'
1440 # dependencies which are not relevent in C++.
1444 open (CPP, "<$file") or die("Can't open $file for reading!");
1449 foreach my $d (@ignoredeps)
1455 foreach my $dep (@immutabledeps)
1457 $immutable = $immutable . "../include/$dep ";
1459 $immutable =~ s/ $//g;
1461 while (defined(my $line = <CPP>))
1464 if ($line =~ /#include "(.+\.h)"/)
1466 if (!exists($dupe{$1}))
1468 $retlist = $retlist . "../include/$1 ";
1474 return length($immutable) ? $immutable . " " . $retlist : $retlist;
1477 sub write_dynamic_makefile
1481 my %existing_install_list = ();
1482 opendir(DIRHANDLE, "src/commands");
1483 foreach my $name (sort readdir(DIRHANDLE))
1485 if ($name =~ /^cmd_(.+)\.cpp$/)
1487 $cmdlist[$i++] = $1;
1488 $install_list = $install_list . " -install -m \$(INSTMODE) src/commands/cmd_" . $1 . ".so \$(LIBPATH)\n";
1489 $uninstall_list = $uninstall_list . " -rm \$(LIBPATH)/cmd_$1.so\n";
1492 closedir(DIRHANDLE);
1496 $config{USE_EPOLL} = 0;
1500 $config{USE_KQUEUE} = 0;
1504 $config{USE_PORTS} = 0;
1507 foreach my $dir (("src","src/commands","src/modes","src/socketengines","src/modules"))
1509 print "Scanning \e[1;32m$dir\e[0m for core files ";
1510 opendir(DIRHANDLE, $dir);
1511 foreach my $name (sort readdir(DIRHANDLE))
1513 if ($name =~ /\.cpp$/)
1515 open (CPP, "<$dir/$name") or die("Can't open $dir/$name to scan it! oh bugger");
1517 while (defined(my $line = <CPP>))
1520 if ($line =~ /\/\* \$Core: (\w+) \*\//i)
1522 $filelist{$name} = $1;
1524 elsif ($line =~ /\/\* \$ExtraDeps: (.*?) \*\//i)
1526 $specialdeps{$name} = $1;
1528 elsif ($line =~ /\/\* \$ExtraObjects: (.*?) \*\//i)
1530 $extraobjects{$name} = $1;
1532 elsif ($line =~ /\/\* \$ExtraBuild: (.*?) \*\//i)
1534 $extrabuildlines{$name} = $1;
1536 elsif ($line =~ /\/\* \$ExtraSources: (.*?) \*\//i)
1538 $extrasources{$name} = $1;
1540 elsif ($line =~ /\/\* \$If: (\w+) \*\//i)
1542 if (($config{$1} !~ /y/i) and ($config{$1} ne "1"))
1545 while (defined($line = <CPP>))
1548 die ("\$If buildsystem instruction within another \$If in file $dir/$name") if ($line =~ /\/\* \$If: (\w+) \*\//i);
1549 last if ($line =~ /\/\* \$EndIf \*\//i);
1553 elsif ($line =~ /\/\* \$Install: (.*?) \*\//i)
1555 if (!exists($existing_install_list{$1}))
1557 $existing_install_list{$1} = 1;
1558 my $idir = (split(' ',$1))[1];
1559 my $ifile = (split(' ',$1))[0];
1560 $install_list = $install_list . " -install -m \$(INSTMODE) $1\n";
1561 $ifile =~ s/.*\///g;
1562 $uninstall_list = $uninstall_list . " -rm $idir/$ifile\n";
1565 elsif ($line =~ /\/\* \$CopyInstall: (.*?) \*\//i)
1567 if (!exists($existing_install_list{$1}))
1569 $existing_install_list{$1} = 1;
1570 my $idir = (split(' ',$1))[1];
1571 my $ifile = (split(' ',$1))[0];
1572 $install_list = $install_list . " -cp $1\n";
1573 $ifile =~ s/.*\///g;
1574 $uninstall_list = $uninstall_list . " -rm $idir/$ifile\n";
1581 closedir(DIRHANDLE);
1585 my $freebsd4libs = (defined $config{CRAQ} ? $config{CRAQ} : "");
1588 my $all_libsonly = "";
1590 my $libraryext = "";
1594 if ($config{IS_DARWIN} eq "YES")
1596 $libraryext = "dylib";
1597 $othercrap = " \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c inspircd.cpp\n \$(CC) -pipe -dynamic -bind_at_load -L. -o inspircd \$(LDLIBS) inspircd.o "
1602 $RPATH = "-Wl,--rpath -Wl,$config{LIBRARY_DIR}" unless defined $opt_disablerpath;
1603 $othercrap = " \$(CC) -pipe -I../include $RPATH \$(FLAGS) $freebsd4libs -rdynamic -L. inspircd.cpp -o inspircd \$(LDLIBS) ";
1606 foreach my $cpp (sort keys %filelist)
1608 $all = $all . $filelist{$cpp} . "." . $libraryext . " ";
1609 $all_libsonly = $all_libsonly . $filelist{$cpp} . "." . $libraryext . " ";
1610 $install_list = $install_list . " -install -m \$(INSTMODE) src/" . $filelist{$cpp} . "." . $libraryext . " \$(LIBPATH)\n";
1611 $uninstall_list = $uninstall_list . " -rm \$(LIBPATH)/" . $filelist{$cpp} . "." . $libraryext . "\n";
1613 $all = $all . "moo inspircd\n";
1615 $othercrap = $othercrap . " $all_libsonly\n\n";
1617 open(FH,">src/Makefile") or die("Could not write src/Makefile");
1620 CC = im a cheezeball
1621 CXXFLAGS = -I../include \${FLAGS}
1622 CPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* //' | grep -v svn)
1623 RELCPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* /modes\\//' | grep -v svn)
1627 print FH "$all\n\n";
1629 my $deps = calcdeps("src/inspircd.cpp");
1630 print FH "inspircd: inspircd.cpp $deps $all_libsonly\n";
1631 print FH "$othercrap\n";
1633 foreach my $cpp (sort keys %filelist)
1635 my $thislib = $filelist{$cpp} . "." . $libraryext;
1639 $objs =~ s/\.cpp$/.o/;
1640 if (exists($extraobjects{$cpp}))
1642 $objs = $objs . " " . $extraobjects{$cpp};
1644 if (exists($extrasources{$cpp}))
1646 $rawcpp = $rawcpp . " " . $extrasources{$cpp};
1648 if ($config{IS_DARWIN} eq "YES")
1650 $libcrap = "-install_name " . $config{LIBRARY_DIR} . "/" . $thislib . " -dynamiclib -twolevel_namespace -undefined dynamic_lookup";
1654 if (defined $opt_disablerpath)
1656 $libcrap = " -shared";
1660 $libcrap = "-Wl,--rpath -Wl," . $config{LIBRARY_DIR} . " -shared";
1663 $deps = calcdeps("src/$cpp");
1664 if (exists($extrasources{$cpp}))
1666 foreach my $seperate (sort split(' ',$extrasources{$cpp}))
1668 my $d = calcdeps("src/$extrasources{$cpp}") . " ";
1671 $deps = $deps . $d . " ";
1675 print FH $thislib . ": $cpp $deps ". (defined($specialdeps{$cpp}) ? $specialdeps{$cpp} : "") . "\n";
1676 print FH " \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c $rawcpp\n";
1677 if (exists($extrabuildlines{$cpp}))
1679 print FH " " . $extrabuildlines{$cpp} . "\n";
1681 print FH " \$(CC) -pipe $libcrap -o " . $thislib . " " . $objs . "\n\n";
1684 print FH "moo:\n \${MAKE} -C \"commands\" DIRNAME=\"src/commands\" CC=\"\$(CC)\" \$(MAKEARGS)\n\n";
1686 # close main makefile
1690 # generate a list of .so
1691 foreach my $cmd (@cmdlist) {
1692 $cmdobjs = $cmdobjs . "cmd_$cmd.so ";
1695 # and now reopen the commands makefile
1696 open(FH,">src/commands/Makefile") or die("Could not write src/commands/Makefile");
1699 CXXFLAGS = -I../../include \${FLAGS}
1706 # now print the command file details.
1707 foreach my $cmd (@cmdlist) {
1709 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
1710 \$(CC) -pipe -I../../include \$(FLAGS) -export-dynamic -c cmd_$cmd.cpp
1711 \$(CC) -pipe $SHARED -o cmd_$cmd.so cmd_$cmd.o
1715 #try build a .so, no intermediate .o
1716 # \$(CC) -pipe -I../../include \$(FLAGS) -export-dynamic $SHARED -o cmd_$cmd.so
1718 #this works for sure
1719 # \$(CC) -pipe -I../../include \$(FLAGS) -export-dynamic -c cmd_$cmd.cpp
1720 # \$(CC) -pipe $SHARED -o cmd_$cmd.so cmd_$cmd.o
1723 # Routine to list out the extra/ modules that have been enabled.
1724 # Note: when getting any filenames out and comparing, it's important to lc it if the
1725 # file system is not case-sensitive (== Epoc, MacOS, OS/2 (incl DOS/DJGPP), VMS, Win32
1726 # (incl NetWare, Symbian)). Cygwin may or may not be case-sensitive, depending on
1727 # configuration, however, File::Spec does not currently tell us (it assumes Unix behavior).
1728 sub list_extras () {
1731 my $srcdir = File::Spec->catdir("src", "modules");
1732 my $abs_srcdir = File::Spec->rel2abs($srcdir);
1735 opendir $dd, File::Spec->catdir($abs_srcdir, "extra") or die (File::Spec->catdir($abs_srcdir, "extra") . ": $!\n");
1736 my @extras = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1739 opendir $dd, $abs_srcdir or die "$abs_srcdir: $!\n";
1740 my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1743 my $maxlen = (sort { $b <=> $a } (map {length($_)} (@extras)))[0];
1745 EXTRA: for my $extra (@extras) {
1746 next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra);
1747 next if ($extra eq '.svn');
1748 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1749 my $abs_source = File::Spec->catfile($abs_srcdir, $extra);
1750 next unless ($extra =~ m/\.(cpp|h)$/ || (-d $abs_extra)); # C++ Source/Header, or directory
1751 if (-l $abs_source) {
1752 # Symlink, is it in the right place?
1753 my $targ = readlink($abs_source);
1754 my $abs_targ = File::Spec->rel2abs($targ, $abs_srcdir);
1755 if ($abs_targ eq $abs_extra) {
1756 $extras{$extra} = "\e[32;1menabled\e[0m";
1758 $extras{$extra} = sprintf("\e[31;1mwrong symlink target (%s)\e[0m", $abs_targ);
1760 } elsif (-e $abs_source) {
1761 my ($devext, $inoext) = stat($abs_extra);
1762 my ($devsrc, $inosrc, undef, $lnksrc) = stat($abs_source);
1764 if ($devsrc == $devext && $inosrc == $inoext) {
1765 $extras{$extra} = "\e[32;1menabled\e[0m";
1767 $extras{$extra} = sprintf("\e[31;1mwrong hardlink target (%d:%d)\e[0m", $devsrc, $inosrc);
1770 open my $extfd, "<", $abs_extra;
1771 open my $srcfd, "<", $abs_source;
1773 if (scalar(<$extfd>) eq scalar(<$srcfd>)) {
1774 $extras{$extra} = "\e[32;1menabled\e[0m";
1776 $extras{$extra} = sprintf("\e[31;1mout of synch (re-copy)\e[0m");
1780 $extras{$extra} = "\e[33;1mdisabled\e[0m";
1783 # Now let's add dependency info
1784 for my $extra (keys(%extras)) {
1785 next unless $extras{$extra} =~ m/enabled/; # only process enabled extras.
1786 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1787 my @deps = split / +/, getdependencies($abs_extra);
1788 for my $dep (@deps) {
1789 if (exists($extras{$dep})) {
1790 my $ref = \$extras{$dep}; # Take reference.
1791 if ($$ref !~ m/needed by/) {
1792 # First dependency found.
1793 if ($$ref =~ m/enabled/) {
1794 $$ref .= " (needed by \e[32;1m$extra\e[0m";
1796 $$ref =~ s/\e\[.*?m//g; # Strip out previous coloring. Will be set in bold+red+blink later.
1797 $$ref .= " (needed by \e[0;32;1;5m$extra\e[0;31;1;5m";
1800 if ($$ref =~ m/enabled/) {
1801 $$ref .= ", \e[32;1m$extra\e[0m";
1803 $$ref .= ", \e[0;32;1;5m$extra\e[0;31;1;5m";
1809 for my $extra (sort {$a cmp $b} keys(%extras)) {
1810 my $text = $extras{$extra};
1811 if ($text =~ m/needed by/ && $text !~ m/enabled/) {
1812 printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? ")" : "");
1814 printf "%-*s = %s%s\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? "\e[0m)" : "");
1817 return keys(%extras) if wantarray; # Can be used by manage_extras.
1820 sub enable_extras (@) {
1822 for my $extra (@extras) {
1823 my $extrapath = "src/modules/extra/$extra";
1824 if (!-e $extrapath) {
1825 print STDERR "Cannot enable \e[32;1m$extra\e[0m : No such file or directory in src/modules/extra\n";
1828 my $source = "src/modules/$extra";
1830 print STDERR "Cannot enable \e[32;1m$extra\e[0m : destination in src/modules exists (might already be enabled?)\n";
1833 # Get dependencies, and add them to be processed.
1834 my @deps = split / +/, getdependencies($extrapath);
1835 for my $dep (@deps) {
1836 next if scalar(grep { $_ eq $dep } (@extras)) > 0; # Skip if we're going to be enabling it anyway.
1837 if (!-e "src/modules/$dep") {
1838 if (-e "src/modules/extra/$dep") {
1839 print STDERR "Will also enable extra \e[32;1m$dep\e[0m (needed by \e[32;1m$extra\e[0m)\n";
1842 print STDERR "\e[33;1mWARNING:\e[0m module \e[32;1m$extra\e[0m might be missing dependency \e[32;1m$dep\e[0m - YOU are responsible for satisfying it!\n";
1846 print "Enabling $extra ... \n";
1847 symlink "extra/$extra", $source or print STDERR "$source: Cannot link to 'extra/$extra': $!\n";
1851 sub disable_extras (@)
1853 opendir my $dd, "src/modules/extra/";
1854 my @files = readdir($dd);
1857 EXTRA: for my $extra (@extras) {
1858 my $extrapath = "src/modules/extra/$extra";
1859 my $source = "src/modules/$extra";
1860 if (!-e $extrapath) {
1861 print STDERR "Cannot disable \e[32;1m$extra\e[0m : Is not an extra\n";
1864 if ((! -l $source) || readlink($source) ne "extra/$extra") {
1865 print STDERR "Cannot disable \e[32;1m$extra\e[0m : Source is not a link or doesn't refer to the right file. Remove manually if this is in error.\n";
1868 # Check if anything needs this.
1869 for my $file (@files) {
1870 my @deps = split / +/, getdependencies("src/modules/extra/$file");
1871 # File depends on this extra...
1872 if (scalar(grep { $_ eq $extra } @deps) > 0) {
1873 # And is both enabled and not about to be disabled.
1874 if (-e "src/modules/$file" && scalar(grep { $_ eq $file } @extras) < 1) {
1875 print STDERR "Cannot disable \e[32;1m$extra\e[0m : is needed by \e[32;1m$file\e[0m\n";
1881 print "Disabling $extra ... \n";
1882 unlink "src/modules/$extra" or print STDERR "Cannot disable \e[32;1m$extra\e[0m : $!\n";