2 ###################################################
3 # InspIRCd Configuration Script
5 # Copyright 2002-2008 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_ports,
101 $opt_epoll, $opt_kqueue, $opt_noports, $opt_noepoll, $opt_nokqueue,
102 $opt_ipv6, $opt_ipv6links, $opt_noipv6links, $opt_maxbuf, $opt_disable_debug,
105 our ($opt_cc, $opt_base_dir, $opt_config_dir, $opt_module_dir, $opt_binary_dir,
110 sub enable_extras (@);
112 sub disable_extras (@);
114 my @opt_enableextras;
115 my @opt_disableextras;
118 'enable-gnutls' => \$opt_use_gnutls,
119 'rebuild' => \$opt_rebuild,
120 'enable-openssl' => \$opt_use_openssl,
121 'disable-interactive' => \$opt_nointeractive,
122 'enable-ports' => \$opt_ports,
123 'enable-epoll' => \$opt_epoll,
124 'enable-kqueue' => \$opt_kqueue,
125 'disable-ports' => \$opt_noports,
126 'disable-epoll' => \$opt_noepoll,
127 'disable-kqueue' => \$opt_nokqueue,
128 'enable-ipv6' => \$opt_ipv6,
129 'enable-remote-ipv6' => \$opt_ipv6links,
130 'disable-remote-ipv6' => \$opt_noipv6links,
131 'with-cc=s' => \$opt_cc,
132 'with-maxbuf=i' => \$opt_maxbuf,
133 'enable-freebsd-ports-openssl' => \$opt_freebsd_port,
134 'prefix=s' => \$opt_base_dir,
135 'config-dir=s' => \$opt_config_dir,
136 'module-dir=s' => \$opt_module_dir,
137 'binary-dir=s' => \$opt_binary_dir,
138 'library-dir=s' => \$opt_library_dir,
139 'disable-debuginfo' => sub { $opt_disable_debug = 1 },
140 'help' => sub { showhelp(); },
141 'modupdate' => sub { modupdate(); },
142 'update' => sub { update(); },
143 'svnupdate' => sub { svnupdate(); },
144 'clean' => sub { clean(); },
145 'list-extras' => sub { list_extras; exit 0; }, # This, --enable-extras, and --disable-extras are for non-interactive managing.
146 'enable-extras=s@' => \@opt_enableextras, # ^
147 'disable-extras=s@' => \@opt_disableextras, # ^
150 if (scalar(@opt_enableextras) + scalar(@opt_disableextras) > 0) {
151 @opt_enableextras = split /,/, join(',', @opt_enableextras);
152 @opt_disableextras = split /,/, join(',', @opt_disableextras);
153 enable_extras(@opt_enableextras);
154 disable_extras(@opt_disableextras);
156 print "Remember: YOU are responsible for making sure any libraries needed have been installed!\n";
157 print "Run $0 -modupdate after you've done this to update the makefiles.\n";
161 our $non_interactive = (
162 (defined $opt_library_dir) ||
163 (defined $opt_base_dir) ||
164 (defined $opt_config_dir) ||
165 (defined $opt_module_dir) ||
166 (defined $opt_base_dir) ||
167 (defined $opt_binary_dir) ||
168 (defined $opt_nointeractive) ||
170 (defined $opt_ipv6) ||
171 (defined $opt_ipv6links) ||
172 (defined $opt_noipv6links) ||
173 (defined $opt_kqueue) ||
174 (defined $opt_epoll) ||
175 (defined $opt_ports) ||
176 (defined $opt_use_openssl) ||
177 (defined $opt_nokqueue) ||
178 (defined $opt_noepoll) ||
179 (defined $opt_noports) ||
180 (defined $opt_maxbuf) ||
181 (defined $opt_use_gnutls) ||
182 (defined $opt_freebsd_port)
184 our $interactive = !$non_interactive;
186 chomp(our $topdir = getcwd());
187 our $this = resolve_directory($topdir); # PWD, Regardless.
188 our @modlist = (); # Declare for Module List..
189 our %config = (); # Initiate Configuration Hash..
190 $config{ME} = resolve_directory($topdir); # Present Working Directory
192 $config{BASE_DIR} = $config{ME};
194 if (defined $opt_base_dir)
196 $config{BASE_DIR} = $opt_base_dir;
199 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Directory
200 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
201 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
202 $config{LIBRARY_DIR} = resolve_directory($config{BASE_DIR}."/lib"); # Library Directory
204 if (defined $opt_config_dir)
206 $config{CONFIG_DIR} = $opt_config_dir;
208 if (defined $opt_module_dir)
210 $config{MODULE_DIR} = $opt_module_dir;
212 if (defined $opt_binary_dir)
214 $config{BINARY_DIR} = $opt_binary_dir;
216 if (defined $opt_library_dir)
218 $config{LIBRARY_DIR} = $opt_library_dir;
220 chomp($config{HAS_GNUTLS} = `libgnutls-config --version 2>/dev/null | cut -c 1,2,3`); # GNUTLS Version.
222 if (defined $opt_freebsd_port)
224 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`);
225 chomp($config{HAS_OPENSSL_PORT} = `pkg-config --modversion openssl 2>/dev/null`);
226 $config{USE_FREEBSD_BASE_SSL} = "n";
230 if ($^O eq "freebsd")
232 # default: use base ssl
233 chomp($config{HAS_OPENSSL} = `openssl version | cut -d ' ' -f 2`); # OpenSSL version, freebsd specific
234 chomp($config{HAS_OPENSSL_PORT} = `pkg-config --modversion openssl 2>/dev/null`); # Port version, may be different
238 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`); # Openssl version, others
239 $config{HAS_OPENSSL_PORT} = "";
243 chomp(our $gnutls_ver = $config{HAS_GNUTLS});
244 chomp(our $openssl_ver = $config{HAS_OPENSSL});
245 $config{USE_GNUTLS} = "n";
246 if (defined $opt_use_gnutls)
248 $config{USE_GNUTLS} = "y"; # Use gnutls.
250 $config{USE_OPENSSL} = "n"; # Use openssl.
251 if (defined $opt_use_openssl)
253 $config{USE_OPENSSL} = "y";
256 # no, let's not change these.
257 $config{OPTIMITEMP} = "0"; # Default Optimisation Value
258 if (!defined $opt_disable_debug)
260 $config{OPTIMISATI} = "-g1"; # Optimisation Flag
264 $config{OPTIMISATI} = "-O2"; # DEBUGGING OFF!
267 $config{HAS_STRLCPY} = "false"; # strlcpy Check.
268 $config{HAS_STDINT} = "false"; # stdint.h check
269 $config{USE_KQUEUE} = "y"; # kqueue enabled
270 if (defined $opt_kqueue)
272 $config{USE_KQUEUE} = "y";
274 if (defined $opt_nokqueue)
276 $config{USE_KQUEUE} = "n";
278 $config{USE_EPOLL} = "y"; # epoll enabled
279 if (defined $opt_epoll)
281 $config{USE_EPOLL} = "y";
283 if (defined $opt_noepoll)
285 $config{USE_EPOLL} = "n";
287 $config{USE_PORTS} = "y"; # epoll enabled
288 if (defined $opt_ports)
290 $config{USE_PORTS} = "y";
292 if (defined $opt_noports)
294 $config{USE_PORTS} = "n";
296 $config{IPV6} = "n"; # IPv6 support (experimental)
297 if (defined $opt_ipv6)
301 $config{SUPPORT_IP6LINKS} = "y"; # IPv4 supporting IPv6 links (experimental)
302 if (defined $opt_ipv6links)
304 $config{SUPPORT_IP6LINKS} = "y";
306 if (defined $opt_noipv6links)
308 $config{SUPPORT_IP6LINKS} = "n";
310 chomp($config{GCCVER} = `g++ -dumpversion | cut -c 1`); # Major GCC Version
311 chomp($config{GCCMINOR} = `g++ -dumpversion | cut -c 3`);
312 $config{_SOMAXCONN} = SOMAXCONN; # Max connections in accept queue
313 $config{OSNAME} = $^O; # Operating System Name
314 $config{IS_DARWIN} = "NO"; # Is OSX?
315 $config{STARTSCRIPT} = "inspircd"; # start script?
316 $config{DESTINATION} = "BASE"; # Is target path.
317 $config{EXTRA_DIR} = ""; # Is empty.
318 if ($config{OSNAME} =~ /darwin/i)
320 $config{IS_DARWIN} = "YES";
321 $config{STARTSCRIPT} = "org.inspircd.plist"; # start script for OSX.
322 $config{DESTINATION} = "LAUNCHDPATH"; # Is OSX target.
323 $config{EXTRA_DIR} = " launchd_dir"; # Is OSX specific path.
325 $config{CC} = "g++"; # C++ compiler
328 $config{CC} = $opt_cc;
330 our $exec = $config{CC} . " -dumpversion | cut -c 1";
331 chomp($config{GCCVER} = `$exec`); # Major GCC Version
332 $exec = $config{CC} . " -dumpversion | cut -c 3";
333 chomp($config{GCCMINOR} = `$exec`);
334 $config{MAKEORDER} = "ircd mods"; # build order
335 $config{MAXBUF} = "512"; # Max buffer size
337 if ($config{HAS_OPENSSL} =~ /^([-[:digit:].]+)([a-z])?(\-[a-z][0-9])?$/) {
338 $config{HAS_OPENSSL} = $1;
340 $config{HAS_OPENSSL} = "";
343 if (($config{GCCVER} eq "") || ($config{GCCMINOR} eq "")) {
344 print $config{CC} . " was not found! You require g++ (the GNU C++ compiler, part of GCC) to build InspIRCd!\n";
348 # Get and Set some important vars..
353 unlink(".config.cache");
356 our ($has_epoll, $has_ports, $has_kqueue) = (0, 0, 0);
361 chomp($topdir = getcwd());
362 $this = resolve_directory($topdir); # PWD, Regardless.
364 # Does the cache file exist?
366 # No, No it doesn't.. *BASH*
367 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
370 # We've Loaded the cache file and all our variables..
371 print "Updating files...\n";
373 if (defined($opt_disable_debug) && $opt_disable_debug == 1)
375 print "Disabling debug information (-g).\n";
376 $config{OPTIMISATI} = "";
379 $has_epoll = $config{HAS_EPOLL};
380 $has_ports = $config{HAS_PORTS};
381 $has_kqueue = $config{HAS_KQUEUE};
390 print "Configure update failed: $@\n";
398 chomp($topdir = getcwd());
399 $this = resolve_directory($topdir); # PWD, Regardless.
401 # Does the cache file exist?
403 # No, No it doesn't.. *BASH*
404 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
407 # We've Loaded the cache file and all our variables..
408 print "Updating files...\n";
410 $has_epoll = $config{HAS_EPOLL};
411 $has_ports = $config{HAS_PORTS};
412 $has_kqueue = $config{HAS_KQUEUE};
421 print "Module update failed: $@\n";
431 open(FH,"<.svn/entries") or $fail = 1;
433 print "This is not an SVN copy of InspIRCd.\n";
440 open my $fd, "-|", "svn update";
441 my $configurechanged = 0; # Needs ./configure -update
442 my $coredirchanged = 0; # Needs ./configure -update
443 my $moduledirchanged = 0; # Needs ./configure -modupdate
444 my $rootincchanged = 0;
446 while (defined(my $line = <$fd>))
450 $line =~ m/^([ADUCG])\s+(.*)$/ or next;
451 ($action, $file) = ($1, $2);
454 push @conflicted, $file;
455 if ($file eq "configure")
457 $configurechanged = 1;
459 elsif ($file =~ m#^src/modules#)
461 $moduledirchanged = 1;
463 elsif ($file =~ m#^src/#)
467 elsif ($file =~ m/^\..*\.inc$/)
472 elsif ($action eq "U" || $action eq "G")
474 if ($file eq "configure")
476 $configurechanged = 1;
478 elsif ($file =~ m/^\..*\.inc$/)
483 elsif ($action eq "A" || $action eq "D")
485 if ($file =~ m#^src/modules#)
487 $moduledirchanged = 1;
489 elsif ($file =~ m#^src/#)
495 unless (close $fd) # close() waits for exit and returns false if the command failed
499 print STDERR "Problem updating from SVN, please check above for errors\n";
503 print STDERR "Failed to run SVN: $!\n";
507 if (scalar(@conflicted) > 0)
509 print STDERR "\e[0;33;1mERROR:\e[0m You have local modifications which conflicted with the updates from SVN\n";
510 printf STDERR "Configure is not able to complete the update. Please resolve these conflicts, then run ./configure -%supdate\n", (($coredirchanged || $configurechanged) ? "" : "mod");
511 print "Conflicted files: " . join ", ", @conflicted . "\n";
514 if ($configurechanged || $coredirchanged)
516 system("perl configure -update");
518 elsif ($moduledirchanged || $rootincchanged)
520 system("perl configure -modupdate");
524 print "No need to update Makefiles.\n";
526 if (defined $opt_rebuild) {
527 system("make install");
532 print "Running non-interactive configure...\n" unless $interactive;
533 print "Checking for cache from previous configure... ";
534 print ((!getcache()) ? "not found\n" : "found\n");
535 print "Checking operating system version... ";
536 print getosflags() . "\n";
538 printf "Checking if stdint.h exists... ";
539 $config{HAS_STDINT} = "true";
541 open(STDINT, "</usr/include/stdint.h") or $config{HAS_STDINT} = "false";
542 if ($config{HAS_STDINT} eq "true") {
545 print "yes\n" if $config{HAS_STDINT} eq "true";
546 print "no\n" if $config{HAS_STDINT} eq "false";
548 printf "Checking if strlcpy exists... ";
549 # Perform the strlcpy() test..
550 $config{HAS_STRLCPY} = "false";
552 open(STRLCPY, "</usr/include/string.h") or $fail = 1;
554 while (defined(my $line = <STRLCPY>)) {
556 # try and find the delcaration of:
557 # size_t strlcpy(...)
558 if ($line =~ /size_t(\0x9|\s)+strlcpy/) {
559 $config{HAS_STRLCPY} = "true";
564 print "yes\n" if $config{HAS_STRLCPY} eq "true";
565 print "no\n" if $config{HAS_STRLCPY} eq "false";
567 printf "Checking if kqueue exists... ";
570 open(KQUEUE, "</usr/include/sys/event.h") or $fail = 1;
572 while (defined(my $line = <KQUEUE>)) {
574 # try and find the delcaration of:
576 if ($line =~ /int(\0x9|\s)+kqueue/) {
582 print "yes\n" if $has_kqueue == 1;
583 print "no\n" if $has_kqueue == 0;
585 printf "Checking if epoll exists... ";
588 open(EPOLL, "</usr/include/sys/epoll.h") or $fail = 1;
594 my $kernel = `uname -r`;
596 if (($kernel =~ /^2\.0\./) || ($kernel =~ /^2\.2\./) || ($kernel =~ /^2\.4\./)) {
601 # Suggestion from nenolod, weed out odd systems which have glibc built
602 # against 2.4 kernels (ick)
603 my $kernel_arch = `uname -p`;
607 if ($kernel_arch =~ /x86_64/) {
608 open (FH,"/lib64/libc.so.6|") or $has_epoll = 0;
611 open (FH,"/lib/libc.so.6|") or $has_epoll = 0;
615 while (defined(my $line = <FH>))
618 if ($line =~ /GNU C Library .* version (.*?) /)
621 $libcv =~ /(\d+\.\d+)/;
624 elsif ($line =~ /Compiled on a Linux (.*?\..*?)\.* system/)
627 # Fix for some retarded libc builds, strip off >> and << etc.
628 $kernelv =~ /(\d+\.\d+)/;
636 printf "libc too old: $libcv... ";
641 printf "libc built against older kernel $kernelv... ";
646 print "yes\n" if $has_epoll == 1;
647 print "no\n" if $has_epoll == 0;
649 printf "Checking if Solaris I/O completion ports are available... ";
651 our $system = `uname -s`;
653 $has_ports = 1 if ($system eq "SunOS");
656 my $kernel = `uname -r`;
658 if (($kernel !~ /^5\.1./)) {
662 print "yes\n" if $has_ports == 1;
663 print "no\n" if $has_ports == 0;
665 $config{HAS_EPOLL} = $has_epoll;
666 $config{HAS_KQUEUE} = $has_kqueue;
668 printf "Checking for libgnutls... ";
669 if (defined($config{HAS_GNUTLS}) && (($config{HAS_GNUTLS}) || ($config{HAS_GNUTLS} eq "y"))) {
670 if (defined($gnutls_ver) && ($gnutls_ver ne "")) {
672 $config{HAS_GNUTLS} = "y";
675 $config{HAS_GNUTLS} = "n";
679 $config{HAS_GNUTLS} = "n";
682 printf "Checking for openssl... ";
683 if (defined($config{HAS_OPENSSL}) && (($config{HAS_OPENSSL}) || ($config{HAS_OPENSSL} eq "y"))) {
684 if (defined($openssl_ver) && ($openssl_ver ne "")) {
686 $config{HAS_OPENSSL} = "y";
689 $config{HAS_OPENSSL} = "n";
693 $config{HAS_OPENSSL} = "n";
696 printf "Checking if you are running an ancient, unsupported OS... ";
697 if ($config{OSNAME} =~ /FreeBSD/i)
699 my $version = `uname -r`;
700 if ($version =~ /^4\./)
702 my $foundit = `ls -l /usr/local/lib/libgnugetopt* | wc -l`;
705 # ICKY ICKY ICK, FREEBSD 4.x! GET AN UPGRADE!
706 $config{CRAQ} = "-L/usr/local/lib -lgnugetopt -DHAVE_DECL_GETOPT=1";
711 print "\n\nERROR: You require libgnugetopt (from ports or packages) to build InspIRCd on FreeBSD 4.11.\n";
717 print "no ($version)\n";
723 print "no ($config{OSNAME})\n";
726 ################################################################################
727 # BEGIN INTERACTIVE PART #
728 ################################################################################
733 print "\e[2J\e[0G\e[0d"; # J = Erase in Display, 2 = Entire Screen, (G, d) = Move cursor to (..,..)
736 my $rev = getrevision();
737 # Display Introduction Message..
739 Welcome to the \e[1mInspIRCd\e[0m Configuration program! (\e[1minteractive mode\e[0m)
740 \e[1mPackage maintainers: Type ./configure --help for non-interactive help\e[0m
742 *** If you are unsure of any of these values, leave it blank for ***
743 *** standard settings that will work, and your server will run ***
744 *** using them. Please consult your IRC network admin if in doubt. ***
746 Press \e[1m<RETURN>\e[0m to accept the default for any option, or enter
747 a new value. Please note: You will \e[1mHAVE\e[0m to read the docs
748 dir, otherwise you won't have a config file!
750 Your operating system is: \e[1;32m$config{OSNAME}\e[0m ($wholeos)
751 Your InspIRCd revision ID is \e[1;32mr$rev\e[0m
754 print " (Non-SVN build)";
758 $config{CHANGE_COMPILER} = "n";
759 print "I have detected the following compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.$config{GCCMINOR}\e[0m)\n";
761 while (($config{GCCVER} < 3) || ($config{GCCVER} eq "")) {
762 print "\e[1;32mIMPORTANT!\e[0m A GCC 2.x compiler has been detected, and
763 should NOT be used. You should probably specify a newer compiler.\n\n";
764 yesno('CHANGE_COMPILER',"Do you want to change the compiler?");
765 if ($config{CHANGE_COMPILER} =~ /y/i) {
766 print "What command do you want to use to invoke your compiler?\n";
767 print "[\e[1;32m$config{CC}\e[0m] -> ";
768 chomp($config{CC} = <STDIN>);
769 if ($config{CC} eq "") {
772 chomp(my $foo = `$config{CC} -dumpversion | cut -c 1`);
774 chomp($config{GCCVER} = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
775 chomp($config{GCCMINOR} = `$config{CC} -dumpversion | cut -c 3`);
776 print "Queried compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.$config{GCCMINOR}\e[0m)\n";
777 if ($config{GCCVER} < 3) {
778 print "\e[1;32mGCC 2.x WILL NOT WORK!\e[0m. Let's try that again, shall we?\n";
782 print "\e[1;32mWARNING!\e[0m Could not execute the compiler you specified. You may want to try again.\n";
789 # Directory Settings..
790 my $tmpbase = $config{BASE_DIR};
791 dir_check("do you wish to install the InspIRCd base", "BASE_DIR");
792 if ($tmpbase ne $config{BASE_DIR}) {
793 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Dir
794 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
795 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
796 $config{LIBRARY_DIR} = resolve_directory($config{BASE_DIR}."/lib"); # Library Directory
799 dir_check("are the configuration files", "CONFIG_DIR");
800 dir_check("are the modules to be compiled to", "MODULE_DIR");
801 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
802 dir_check("are the IRCd libraries to be placed", "LIBRARY_DIR");
805 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?");
809 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?");
813 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?");
816 my $chose_hiperf = (($config{USE_EPOLL} eq "y") || ($config{USE_KQUEUE} eq "y") || ($config{USE_PORTS} eq "y"));
817 if (!$chose_hiperf) {
818 print "No high-performance socket engines are available, or you chose\n";
819 print "not to enable one. Defaulting to select() engine.\n\n";
822 yesno('IPV6',"Would you like to build InspIRCd with IPv6 support?");
825 if ($config{IPV6} eq "y") {
826 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";
827 $config{SUPPORT_IP6LINKS} = "y";
829 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? If you are using a recent operating system and are\nunsure, answer yes. If you answer 'no' here, your InspIRCd server will\nbe unable to parse IPV6 addresses (e.g. for CIDR bans)\n\nEnable linking to servers which have IPV6 enabled?");
833 $config{USE_FREEBSD_BASE_SSL} = "n";
834 $config{USE_FREEBSD_PORTS_SSL} = "n";
835 if ($config{HAS_OPENSSL_PORT} ne "")
837 $config{USE_FREEBSD_PORTS_SSL} = "y";
838 print "I have detected the OpenSSL FreeBSD port installed on your system,\n";
839 print "version \e[1;32m".$config{HAS_OPENSSL_PORT}."\e[0m. Your base system OpenSSL is version \e[1;32m".$openssl_ver."\e[0m.\n\n";
840 yesno('USE_FREEBSD_PORTS_SSL', "Do you want to use the FreeBSD ports version?");
842 $config{USE_FREEBSD_BASE_SSL} = "y" if ($config{USE_FREEBSD_PORTS_SSL} eq "n");
844 if ($config{USE_FREEBSD_BASE_SSL} eq "n")
846 # update to port version
847 $openssl_ver = $config{HAS_OPENSSL_PORT};
852 $config{USE_FREEBSD_BASE_SSL} = "y" if ($^O eq "freebsd");
855 if (($config{HAS_GNUTLS} eq "y") && ($config{HAS_OPENSSL} eq "y")) {
856 print "I have detected both \e[1;32mGnuTLS\e[0m and \e[1;32mOpenSSL\e[0m on your system.\n";
857 print "I will default to GnuTLS. If you wish to use OpenSSL\n";
858 print "instead, you should enable the OpenSSL module yourself\n";
859 print "by copying it from src/modules/extra to src/modules.\n\n";
860 print "Detected GnuTLS version: \e[1;32m" . $gnutls_ver . "\e[0m\n";
861 print "Detected OpenSSL version: \e[1;32m" . $openssl_ver . "\e[0m\n\n";
864 if ($config{HAS_GNUTLS} eq "y") {
865 yesno('USE_GNUTLS', "Would you like to enable SSL Support?");
866 if ($config{USE_GNUTLS} eq "y") {
867 print "\nUsing GnuTLS SSL module.\n";
869 } elsif ($config{HAS_OPENSSL} eq "y") {
870 yesno('USE_OPENSSL', "Would you like to enable SSL Support?");
871 if ($config{USE_OPENSSL} eq "y") {
872 print "\nUsing OpenSSL SSL module.\nYou will get better performance if you move to GnuTLS in the future.\n";
876 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";
882 if (($config{USE_GNUTLS} eq "y") && ($config{HAS_GNUTLS} ne "y"))
884 print "Sorry, but i couldn't detect gnutls. Make sure gnutls-config is in your path.\n";
887 if (($config{USE_OPENSSL} eq "y") && ($config{HAS_OPENSSL} ne "y"))
889 print "Sorry, but i couldn't detect openssl. Make sure openssl is in your path.\n";
894 if ($config{USE_GNUTLS} eq "y") {
895 unless (-r "src/modules/m_ssl_gnutls.cpp") {
896 print "Symlinking src/modules/m_ssl_gnutls.cpp from extra/\n";
897 symlink "extra/m_ssl_gnutls.cpp", "src/modules/m_ssl_gnutls.cpp" or print STDERR "Symlink failed: $!";
902 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
903 print "SSL Certificates Not found, Generating.. \n\n
904 *************************************************************
905 * Generating the Private Key may take some time, go grab a *
906 * Coffee. Even better, to generate some more entropy if it *
907 * is taking a while, open another console and type du / a *
908 * few times and get that HD going :) Then answer the *
909 * Questions which follow. If you are unsure, just hit enter *
910 *************************************************************\n\n";
911 $failed = make_gnutls_cert();
913 print "\n\e[1;32mCertificate generation failed!\e[0m\n\n";
915 print "\nCertificate generation complete, copying to config directory... ";
916 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
917 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
922 print "SSL Certificates found, skipping.\n\n";
927 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
929 } elsif ($config{USE_OPENSSL} eq "y") {
930 unless (-r "src/modules/m_ssl_openssl.cpp") {
931 print "Symlinking src/modules/m_ssl_openssl.cpp from extra/\n";
932 symlink "extra/m_ssl_openssl.cpp", "src/modules/m_ssl_openssl.cpp" or print STDERR "Symlink failed: $!";
938 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
939 print "SSL Certificates Not found, Generating.. \n\n
940 *************************************************************
941 * Generating the certificates may take some time, go grab a *
942 * coffee, or something. *
943 *************************************************************\n\n";
945 print "\nCertificate generation complete, copying to config directory... ";
946 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
947 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
948 File::Copy::move("dhparams.pem", "$config{CONFIG_DIR}/dhparams.pem") or print STDERR "Could not copy dhparams.pem!\n";
951 print "SSL Certificates found, skipping.\n\n"
956 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
959 if (($config{USE_GNUTLS} eq "n") && ($config{USE_OPENSSL} eq "n")) {
960 print "Skipping SSL Certificate generation, SSL support is not available.\n\n";
968 print "To build your server with these settings, please type '\e[1;32m$config{MAKEPROG}\e[0m' now.\n";
969 if (($config{USE_GNUTLS} eq "y") || ($config{USE_OPENSSL} eq "y")) {
970 print "Please note: for \e[1;32mSSL support\e[0m you will need to load required\n";
971 print "modules in your config. This configure script has added those modules to the\n";
972 print "build process. For more info please refer to:\n";
973 print "\e[1;32mhttp://www.inspircd.org/wiki/Installation_From_Tarball\e[0m\n";
975 print "*** \e[1;32mRemember to edit your configuration files!!!\e[0m ***\n\n\n";
976 if (($config{OSNAME} eq "OpenBSD") && ($config{CC} ne "eg++")) {
977 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";
980 if ($config{GCCVER} < "3") {
982 \e[1;32mWARNING!\e[0m You are attempting to compile InspIRCd on GCC 2.x!
983 GCC 2.x series compilers only had partial (read as broken) C++ support, and
984 your compile will most likely fail horribly! If you have any problems, do NOT
985 report them to the bugtracker or forums without first upgrading your compiler
986 to a newer 3.x or 4.x (or whatever is available currently) version.
990 ################################################################################
992 ################################################################################
994 # Retrieves the .config.cache file, and loads values into the main config hash.
995 open(CACHE, ".config.cache") or return 0;
998 # Ignore Blank lines, and comments..
1001 my ($key, $value) = split("=", $_, 2);
1002 $value =~ /^\"(.*)\"$/;
1003 # Do something with data here!
1011 # Dump the contents of %config
1012 print "Writing \e[1;32mcache file\e[0m for future ./configures ...\n";
1013 open(FILEHANDLE, ">.config.cache");
1014 foreach my $key (keys %config) {
1015 print FILEHANDLE "$key=\"$config{$key}\"\n";
1021 my ($desc, $hash_key) = @_;
1023 while (!$complete) {
1024 print "In what directory $desc?\n";
1025 print "[\e[1;32m$config{$hash_key}\e[0m] -> ";
1026 chomp(my $var = <STDIN>);
1028 $var = $config{$hash_key};
1030 if ($var =~ /^\~\/(.+)$/) {
1031 # Convert it to a full path..
1032 $var = resolve_directory($ENV{HOME} . "/" . $1);
1034 elsif ((($config{OSNAME} =~ /MINGW32/i) and ($var !~ /^[A-Z]{1}:\\.*/)) and (substr($var,0,1) ne "/"))
1036 # Assume relative Path was given.. fill in the rest.
1037 $var = $this . "/$var";
1040 $var = resolve_directory($var);
1042 print "$var does not exist. Create it?\n[\e[1;32my\e[0m] ";
1043 chomp(my $tmp = <STDIN>);
1044 if (($tmp eq "") || ($tmp =~ /^y/i)) {
1045 # Attempt to Create the Dir..
1048 File::Path::mkpath($var, 0, 0777);
1051 unless (defined($chk) && -d $var) {
1052 print "Unable to create directory. ($var)\n\n";
1057 # They said they don't want to create, and we can't install there.
1062 if (!is_dir($var)) {
1063 # Target exists, but is not a directory.
1064 print "File $var exists, but is not a directory.\n\n";
1068 # Either Dir Exists, or was created fine.
1069 $config{$hash_key} = $var;
1079 # Beware: Linux sets it's own cflags below for some retarded reason
1080 $config{LDLIBS} = "-pthread -lstdc++";
1081 $config{FLAGS} = "-fPIC -Woverloaded-virtual -Wshadow -Wformat=2 -Wmissing-format-attribute -Wall $config{OPTIMISATI}";
1082 $config{DEVELOPER} = "-fPIC -Woverloaded-virtual -Wshadow -Wall -Wformat=2 -Wmissing-format-attribute -g";
1083 $SHARED = "-shared";
1084 $config{MAKEPROG} = "make";
1086 if ($config{OSNAME} =~ /darwin/i) {
1087 $config{FLAGS} = "-DDARWIN -frtti -fPIC -Wall $config{OPTIMISATI}";
1088 $SHARED = "-bundle -twolevel_namespace -undefined dynamic_lookup";
1089 $config{LDLIBS} = "-ldl -pthread -lstdc++";
1092 if ($config{OSNAME} =~ /OpenBSD/i) {
1093 $config{MAKEPROG} = "gmake";
1094 $config{LDLIBS} = $config{LDLIBS} . " -lunwind";
1095 chomp(my $foo = `eg++ -dumpversion | cut -c 1`);
1096 # theyre running the package version of gcc (eg++)... detect it and set up its version numbers.
1097 # if theyre not running this, configure lets the build continue but they probably wont manage to
1098 # compile as this standard version is 2.95.3!
1100 $config{CC} = "eg++";
1101 chomp($config{GCCVER} = `eg++ -dumpversion | cut -c 1`); # we must redo these if we change the compiler path
1102 chomp($config{GCCMINOR} = `eg++ -dumpversion | cut -c 3`);
1107 if ($config{OSNAME} =~ /Linux/i) {
1108 $config{LDLIBS} = "-ldl -lstdc++ -pthread";
1109 # $config{FLAGS} = "-fPIC -Woverloaded-virtual -Wshadow -Wall $config{OPTIMISATI}";
1110 $config{FLAGS} .= " " . $ENV{CXXFLAGS} if exists($ENV{CXXFLAGS});
1111 $config{LDLIBS} .= " " . $ENV{LDLIBS} if exists($ENV{LDLIBS});
1112 $config{MAKEPROG} = "make";
1115 if ($config{OSNAME} =~ /FreeBSD/i) {
1116 $config{FLAGS} .= " " . $ENV{CXXFLAGS} if exists($ENV{CXXFLAGS});
1117 $config{LDLIBS} .= " " . $ENV{LDLIBS} if exists($ENV{LDLIBS});
1120 if ($config{OSNAME} =~ /SunOS/i or $config{OSNAME} =~ /solaris/i)
1122 # solaris/sunos needs these
1123 # socket = bsd sockets api
1125 # rt = POSIX realtime extensions
1126 # resolv = inet_aton only (why isnt this in nsl?!)
1127 $config{MAKEPROG} = "gmake";
1128 $config{LDLIBS} .= " -lsocket -lnsl -lrt -lresolv -pthread";
1132 if($config{OSNAME} =~ /MINGW32/i)
1134 # All code is position-independent on windows
1135 $config{FLAGS} =~ s/-fPIC //;
1139 return $config{OSNAME};
1142 my ($mliflags, $mfrules, $mobjs, $mfcount) = ("", "", "", 0);
1145 my($writeheader) = @_;
1147 # First File.. inspircd_config.h
1148 chomp(my $incos = `uname -n -s -r`);
1149 chomp(my $version = `sh src/version.sh`);
1150 chomp(my $revision2 = getrevision());
1151 if ($writeheader == 1)
1153 print "Writing \e[1;32minspircd_config.h\e[0m\n";
1154 open(FILEHANDLE, ">include/inspircd_config.h");
1155 print FILEHANDLE <<EOF;
1156 /* Auto generated by configure, do not modify! */
1157 #ifndef __CONFIGURATION_AUTO__
1158 #define __CONFIGURATION_AUTO__
1160 /* this is for windows support. */
1161 #define CoreExport /**/
1162 #define DllExport /**/
1164 #define CONFIG_FILE "$config{CONFIG_DIR}/inspircd.conf"
1165 #define MOD_PATH "$config{MODULE_DIR}"
1166 #define VERSION "$version"
1167 #define REVISION "$revision2"
1168 #define SOMAXCONN_S "$config{_SOMAXCONN}"
1169 #define OPTIMISATION $config{OPTIMITEMP}
1170 #define LIBRARYDIR "$config{LIBRARY_DIR}"
1171 #define SYSTEM "$incos"
1172 #define ENTRYPOINT int main(int argc, char** argv)
1175 print FILEHANDLE "#define MAXBUF " . ($config{MAXBUF}+2) . "\n";
1177 if ($config{OSNAME} =~ /SunOS/i) {
1178 print FILEHANDLE "#define IS_SOLARIS\n";
1180 if ($config{OSNAME} =~ /MINGW32/i) {
1181 print FILEHANDLE "#define IS_MINGW\n";
1183 if ($config{GCCVER} >= 3) {
1184 print FILEHANDLE "#define GCC3\n";
1187 (($config{GCCVER} == 4) && ($config{GCCMINOR} >= 3))
1189 ($config{GCCVER} > 4)
1191 print FILEHANDLE "#define HASHMAP_DEPRECATED\n";
1193 if ($config{HAS_STRLCPY} eq "true") {
1194 print FILEHANDLE "#define HAS_STRLCPY\n";
1196 if ($config{HAS_STDINT} eq "true") {
1197 print FILEHANDLE "#define HAS_STDINT\n";
1199 if ($config{IPV6} =~ /y/i) {
1200 print FILEHANDLE "#define IPV6\n";
1202 if ($config{SUPPORT_IP6LINKS} =~ /y/i) {
1203 print FILEHANDLE "#define SUPPORT_IP6LINKS\n";
1206 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
1207 print FILEHANDLE "#define USE_KQUEUE\n";
1208 $se = "socketengine_kqueue";
1211 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
1212 print FILEHANDLE "#define USE_EPOLL\n";
1213 $se = "socketengine_epoll";
1216 if (($has_ports) && ($config{USE_PORTS} eq "y")) {
1217 print FILEHANDLE "#define USE_PORTS\n";
1218 $se = "socketengine_ports";
1221 # user didn't choose either epoll or select for their OS.
1222 # default them to USE_SELECT (ewwy puke puke)
1224 print FILEHANDLE "#define USE_SELECT\n";
1225 $se = "socketengine_select";
1227 print FILEHANDLE "\n#include \"threadengines/threadengine_pthread.h\"\n\n#endif\n";
1233 open(FILEHANDLE, ">include/inspircd_se_config.h");
1234 print FILEHANDLE <<EOF;
1235 /* Auto generated by configure, do not modify or commit to svn! */
1236 #ifndef __CONFIGURATION_SOCKETENGINE__
1237 #define __CONFIGURATION_SOCKETENGINE__
1239 #include "socketengines/$se.h"
1247 # Create a Modules List..
1249 foreach my $i (@modlist)
1251 $modules .= "m_".$i.".so ";
1253 chomp($modules); # Remove Redundant whitespace..
1255 opendir(DIRHANDLE, "src/modules");
1256 foreach my $name2 (sort readdir(DIRHANDLE)) {
1257 if ($name2 =~ /^m_(.+?)$/) {
1258 if (defined(opendir(MDIRHANDLE, "src/modules/$name2"))) {
1259 closedir(MDIRHANDLE);
1260 $modules .= "$name2.so ";
1261 $uninstall_list = $uninstall_list . " -rm \$(MODULES)/$name2.so\n";
1265 closedir(DIRHANDLE);
1268 # Write all .in files.
1271 my $exe = "inspircd";
1273 # Do this once here, and cache it in the .*.inc files,
1274 # rather than attempting to read src/version.sh from
1275 # compiled code -- we might not have the source to hand.
1276 # Fix for bug#177 by Brain.
1278 chomp($version = `sh ./src/version.sh`);
1279 chomp(my $revision = getrevision());
1280 $version = "$version(r$revision)";
1282 # We can actually parse any file starting with . and ending with .inc,
1283 # but right now we only parse .inspircd.inc to form './inspircd'
1285 print "Writing \e[1;32mMakefiles\e[0m\n";
1286 write_dynamic_modules_makefile();
1287 write_dynamic_makefile();
1289 opendir(DIRHANDLE, $this);
1291 foreach my $name (sort readdir(DIRHANDLE)) {
1292 if ($name =~ /^\.(.+)\.inc$/) {
1295 # Bug #353, omit this on non-darwin
1296 next if (($config{OSNAME} !~ /darwin/) && ($file eq "org.inspircd.plist"));
1298 # All .name.inc files need parsing!
1300 open(FILEHANDLE, ".$file.inc") or die ("Can't open .$file.inc");
1301 while (<FILEHANDLE>) {
1306 print "Writing \e[1;32m$file\e[0m ...\n";
1307 $tmp =~ s/\@CC\@/$config{CC}/ if defined $config{CC};
1308 $tmp =~ s/\@MAKEPROG\@/$config{MAKEPROG}/ if defined $config{MAKEPROG};
1309 $tmp =~ s/\@FLAGS\@/$config{FLAGS}/ if defined $config{FLAGS};
1310 $tmp =~ s/\@DEVELOPER\@/$config{DEVELOPER}/ if defined $config{DEVELOPER};
1311 $tmp =~ s/\@LDLIBS\@/$config{LDLIBS}/ if defined $config{LDLIBS};
1312 $tmp =~ s/\@BASE_DIR\@/$config{BASE_DIR}/ if defined $config{BASE_DIR};
1313 $tmp =~ s/\@CONFIG_DIR\@/$config{CONFIG_DIR}/ if defined $config{CONFIG_DIR};
1314 $tmp =~ s/\@MODULE_DIR\@/$config{MODULE_DIR}/ if defined $config{MODULE_DIR};
1315 $tmp =~ s/\@BINARY_DIR\@/$config{BINARY_DIR}/ if defined $config{BINARY_DIR};
1316 $tmp =~ s/\@LIBRARY_DIR\@/$config{LIBRARY_DIR}/ if defined $config{LIBRARY_DIR};
1317 $tmp =~ s/\@MODULES\@/$modules/ if defined $modules;
1318 $tmp =~ s/\@STARTSCRIPT\@/$config{STARTSCRIPT}/ if defined $config{STARTSCRIPT};
1319 $tmp =~ s/\@DESTINATION\@/$config{DESTINATION}/ if defined $config{DESTINATION};
1320 $tmp =~ s/\@EXTRA_DIR\@/$config{EXTRA_DIR}/ if defined $config{EXTRA_DIR};
1321 $tmp =~ s/\@EXECUTABLE\@/$exe/ if defined $exe;
1322 $tmp =~ s/\@MAKEORDER\@/$config{MAKEORDER}/ if defined $config{MAKEORDER};
1323 $tmp =~ s/\@VERSION\@/$version/ if defined $version;
1324 $tmp =~ s/\@INSTALL_LIST\@/$install_list/ if defined $install_list;
1325 $tmp =~ s/\@UNINSTALL_LIST\@/$uninstall_list/ if defined $uninstall_list;
1327 open(FILEHANDLE, ">$file");
1328 print FILEHANDLE $tmp;
1331 closedir(DIRHANDLE);
1333 # Make inspircd executable!
1334 chmod 0744, 'inspircd';
1337 sub write_dynamic_modules_makefile {
1338 # Modules Makefile..
1339 print "Writing \e[1;32msrc/modules/Makefile\e[0m\n";
1340 open(FILEHANDLE, ">src/modules/Makefile");
1343 # Module Makefile Header
1345 print FILEHANDLE <<EOF;
1346 ###################################################
1347 # Copyright 2002-2007 The InspIRCd Development Team
1348 # http://www.inspircd.org/wiki/index.php/Credits
1350 # Thanks to Andrew Church <achurch\@achurch.org>
1351 # for assisting with making this work right.
1353 # Automatically Generated by ./configure to add a
1354 # modules please run ./configure -modupdate
1355 ###################################################
1361 if ($config{OSNAME} =~ /darwin/) {
1362 print FILEHANDLE <<EOCHEESE;
1364 PICLDFLAGS = -twolevel_namespace -undefined dynamic_lookup -bundle
1368 print FILEHANDLE <<EOCHEESE;
1370 PICLDFLAGS = -fPIC -DPIC -shared
1376 # End Module Makefile Header
1379 # Create a Modules List..
1383 foreach my $i (@modlist) {
1385 # Write Entry to the MakeFile
1387 $cmflags = getcompilerflags("src/modules/m_".$i.".cpp");
1388 $liflags = getlinkerflags("src/modules/m_".$i.".cpp");
1389 my $deps = getdependencies("src/modules/m_".$i.".cpp");
1391 #print "file: $i: cmflags=$cmflags; liflags=$liflags; deps=$deps\n";
1394 if (nopedantic("src/modules/m_".$i.".cpp"))
1397 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
1398 \@../../make/run-cc.pl \$(CC) -pipe -I../../include \$(NICEFLAGS) $cmflags \$(PICLDFLAGS) $liflags -export-dynamic -o m_$i.so m_$i.cpp
1404 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
1405 \@../../make/run-cc.pl \$(CC) -pipe -I../../include \$(FLAGS) $cmflags \$(PICLDFLAGS) $liflags -export-dynamic -o m_$i.so m_$i.cpp
1408 $install_list = $install_list . " install -m \$(INSTMODE) src/modules/m_$i.so \$(MODPATH)\n";
1409 $uninstall_list = $uninstall_list . " -rm \$(MODULES)/m_$i.so\n";
1411 # End Write Entry to the MakeFile
1415 opendir(DIRHANDLE, "src/modules");
1416 foreach my $name (sort readdir(DIRHANDLE)) {
1417 if ($name =~ /^m_(.+?)$/) {
1422 # A module made of multiple files, in a dir, e.g. src/modules/m_spanningtree/
1423 if (defined(opendir(MDIRHANDLE, "src/modules/$name"))) {
1424 read_module_directory("src/modules/$name", $name);
1425 print "Composing Makefile rules for directory \e[1;32m$name\e[0m... (\e[1;32m$mfcount files found\e[0m)\n";
1426 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";
1427 if ($config{IS_DARWIN} eq "YES") {
1428 print FILEHANDLE " \@../../make/run-cc.pl \$(CC) -pipe -twolevel_namespace -undefined dynamic_lookup \$(FLAGS) $mliflags -bundle -o $name.so $mobjs\n";
1430 print FILEHANDLE " \@../../make/run-cc.pl \$(CC) -pipe \$(FLAGS) -shared $mliflags -o $name.so $mobjs\n";
1432 print FILEHANDLE "\n$mfrules\n";
1433 closedir(MDIRHANDLE);
1434 $install_list = $install_list . " install -m \$(INSTMODE) src/modules/$name.so \$(MODPATH)\n";
1438 closedir(DIRHANDLE);
1441 sub read_module_directory {
1442 my ($dpath, $reldpath) = @_;
1444 if (opendir(MDIRHANDLE, $dpath) == 0) {
1448 foreach my $fname (sort readdir(MDIRHANDLE)) {
1449 if ($fname =~ /\.cpp$/) {
1450 my $cmflags = getcompilerflags("$dpath/$fname");
1451 $mliflags = $mliflags . " " . getlinkerflags("$dpath/$fname");
1452 my $deps = getdependencies("$dpath/$fname");
1454 $oname =~ s/\.cpp$/.o/g;
1455 $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";
1456 $mfrules = $mfrules . " \@../../make/run-cc.pl \$(CC) -pipe -I../../include -I. \$(FLAGS) $cmflags -export-dynamic -o $reldpath/$oname -c $reldpath/$fname\n\n";
1457 $mobjs = $mobjs . " $reldpath/$oname";
1460 elsif ((-d "$dpath/$fname") && !($fname eq ".") && !($fname eq "..")) {
1461 read_module_directory($dpath."/".$fname, $reldpath."/".$fname);
1468 # Yes i know we could use gcc -M but it seems to ideneify a lot of 'deep'
1469 # dependencies which are not relevent in C++.
1473 open (CPP, "<$file") or die("Can't open $file for reading!");
1478 foreach my $d (@ignoredeps)
1484 foreach my $dep (@immutabledeps)
1486 $immutable = $immutable . "../include/$dep ";
1488 $immutable =~ s/ $//g;
1490 while (defined(my $line = <CPP>))
1493 if ($line =~ /#include "(.+\.h)"/)
1495 if (!exists($dupe{$1}))
1497 $retlist = $retlist . "../include/$1 ";
1503 return length($immutable) ? $immutable . " " . $retlist : $retlist;
1506 sub write_dynamic_makefile
1510 my %existing_install_list = ();
1511 my %core_files_list = ();
1513 opendir(DIRHANDLE, "src/commands");
1514 foreach my $name (sort readdir(DIRHANDLE))
1516 if ($name =~ /^cmd_(.+)\.cpp$/)
1518 $cmdlist[$i++] = $1;
1519 $install_list = $install_list . " -install -m \$(INSTMODE) src/commands/cmd_" . $1 . ".so \$(LIBPATH)\n";
1520 $uninstall_list = $uninstall_list . " -rm \$(LIBPATH)/cmd_$1.so\n";
1523 closedir(DIRHANDLE);
1527 $config{USE_EPOLL} = 0;
1531 $config{USE_KQUEUE} = 0;
1535 $config{USE_PORTS} = 0;
1538 # formerly generated below this foreach, now it's not! magic.
1541 foreach my $dir (("src","src/commands","src/modes","src/socketengines","src/modules"))
1543 print "Scanning \e[1;32m$dir\e[0m for core files ";
1544 opendir(DIRHANDLE, $dir);
1545 foreach my $name (sort readdir(DIRHANDLE))
1547 if ($name =~ /\.cpp$/)
1549 open (CPP, "<$dir/$name") or die("Can't open $dir/$name to scan it! oh bugger");
1551 while (defined(my $line = <CPP>))
1554 if ($line =~ /\/\* \$Core \*\//i)
1557 $sname =~ s/\.cpp$/.o/;
1559 # append it to list to be built
1560 $all_core = $all_core . $sname . " ";
1561 $filelist{$name} = $sname;
1563 # mark it as a core file, so it won't get shared object cflags
1564 if (!exists($core_files_list{$name}))
1566 $core_files_list{$name} = 1;
1569 elsif ($line =~ /\/\* \$ExtraDeps: (.*?) \*\//i)
1571 $specialdeps{$name} = $1;
1573 elsif ($line =~ /\/\* \$ExtraObjects: (.*?) \*\//i)
1575 $extraobjects{$name} = $1;
1577 elsif ($line =~ /\/\* \$ExtraBuild: (.*?) \*\//i)
1579 $extrabuildlines{$name} = $1;
1581 elsif ($line =~ /\/\* \$ExtraSources: (.*?) \*\//i)
1583 $extrasources{$name} = $1;
1585 elsif ($line =~ /\/\* \$If: (\w+) \*\//i)
1587 if (defined $config{$1})
1589 if (($config{$1} !~ /y/i) and ($config{$1} ne "1"))
1592 while (defined($line = <CPP>))
1595 die ("\$If buildsystem instruction within another \$If in file $dir/$name") if ($line =~ /\/\* \$If: (\w+) \*\//i);
1596 last if ($line =~ /\/\* \$EndIf \*\//i);
1601 elsif ($line =~ /\/\* \$Install: (.*?) \*\//i)
1603 if (!exists($existing_install_list{$1}))
1605 $existing_install_list{$1} = 1;
1606 my $idir = (split(' ',$1))[1];
1607 my $ifile = (split(' ',$1))[0];
1608 $install_list = $install_list . " -install -m \$(INSTMODE) $1\n";
1609 $ifile =~ s/.*\///g;
1610 $uninstall_list = $uninstall_list . " -rm $idir/$ifile\n";
1613 elsif ($line =~ /\/\* \$CopyInstall: (.*?) \*\//i)
1615 if (!exists($existing_install_list{$1}))
1617 $existing_install_list{$1} = 1;
1618 my $idir = (split(' ',$1))[1];
1619 my $ifile = (split(' ',$1))[0];
1620 $install_list = $install_list . " -cp $1\n";
1621 $ifile =~ s/.*\///g;
1622 $uninstall_list = $uninstall_list . " -rm $idir/$ifile\n";
1629 closedir(DIRHANDLE);
1633 # modes need to be compiled in too
1634 $all_core = $all_core . "modes/modeclasses.a";
1636 my $freebsd4libs = (defined $config{CRAQ} ? $config{CRAQ} : "");
1638 my $libraryext = "";
1639 my $binary_rule = "";
1641 if ($config{IS_DARWIN} eq "YES")
1643 $libraryext = "dylib";
1644 $binary_rule = " \@../make/run-cc.pl \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c inspircd.cpp\n \@../make/run-cc.pl \$(CC) -pipe -dynamic -bind_at_load -L. -o inspircd \$(LDLIBS) inspircd.o "
1649 $binary_rule = " \@../make/run-cc.pl \$(CC) -pipe -I../include \$(FLAGS) $freebsd4libs -rdynamic -L. inspircd.cpp -o inspircd \$(LDLIBS) ";
1652 open(FH,">src/Makefile") or die("Could not write src/Makefile");
1655 CC = im a cheezeball
1656 CXXFLAGS = -I../include \${FLAGS}
1657 CPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* //' | grep -v svn)
1658 RELCPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* /modes\\//' | grep -v svn)
1662 my $buildstring = "";
1665 foreach my $cpp (sort keys %filelist)
1669 $objs =~ s/\.cpp$/.o/;
1670 if (exists($extraobjects{$cpp}))
1672 $objs = $objs . " " . $extraobjects{$cpp};
1673 $all_core = $all_core . " " . $extraobjects{$cpp};
1675 if (exists($extrasources{$cpp}))
1677 $rawcpp = $rawcpp . " " . $extrasources{$cpp};
1680 $deps = calcdeps("src/$cpp");
1681 if (exists($extrasources{$cpp}))
1683 foreach my $seperate (sort split(' ',$extrasources{$cpp}))
1685 my $d = calcdeps("src/$extrasources{$cpp}") . " ";
1688 $deps = $deps . $d . " ";
1692 $buildstring = $buildstring . $objs . ": $cpp $deps ". (defined($specialdeps{$cpp}) ? $specialdeps{$cpp} : "") . "\n";
1694 if (exists($core_files_list{$cpp}))
1696 # core files are statically linked into the binary and do not require -export-dynamic
1697 $buildstring = $buildstring . " \@../make/run-cc.pl \$(CC) -pipe -I../include \$(FLAGS) -c $rawcpp\n";
1701 $buildstring = $buildstring . " \@../make/run-cc.pl \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c $rawcpp\n";
1704 if (exists($extrabuildlines{$cpp}))
1706 $buildstring = $buildstring . " " . $extrabuildlines{$cpp} . "\n";
1710 print FH "all: inspircd moo\n\n\n";
1712 $deps = calcdeps("src/inspircd.cpp");
1713 print FH "inspircd: inspircd.cpp $deps $all_core\n";
1714 print FH "$binary_rule $all_core\n\n";
1716 print FH $buildstring;
1717 print FH "moo:\n \@\${MAKE} -C \"commands\" DIRNAME=\"src/commands\" CC=\"\$(CC)\" \$(MAKEARGS)\n\n";
1719 # close main makefile
1723 # generate a list of .so
1724 foreach my $cmd (@cmdlist) {
1725 $cmdobjs = $cmdobjs . "cmd_$cmd.so ";
1728 # and now reopen the commands makefile
1729 open(FH,">src/commands/Makefile") or die("Could not write src/commands/Makefile");
1732 CXXFLAGS = -I../../include \${FLAGS}
1739 # now print the command file details.
1740 foreach my $cmd (@cmdlist) {
1742 cmd_$cmd.so: cmd_$cmd.cpp ../../include/base.h ../../include/modules.h ../../include/inspircd.h ../../include/channels.h ../../include/users.h ../../include/inspircd_config.h ../../include/commands/cmd_$cmd.h
1743 \@../../make/run-cc.pl \$(CC) -pipe -I../../include \$(FLAGS) -export-dynamic $SHARED -o cmd_$cmd.so cmd_$cmd.cpp
1749 # Routine to list out the extra/ modules that have been enabled.
1750 # Note: when getting any filenames out and comparing, it's important to lc it if the
1751 # file system is not case-sensitive (== Epoc, MacOS, OS/2 (incl DOS/DJGPP), VMS, Win32
1752 # (incl NetWare, Symbian)). Cygwin may or may not be case-sensitive, depending on
1753 # configuration, however, File::Spec does not currently tell us (it assumes Unix behavior).
1754 sub list_extras () {
1757 my $srcdir = File::Spec->catdir("src", "modules");
1758 my $abs_srcdir = File::Spec->rel2abs($srcdir);
1761 opendir $dd, File::Spec->catdir($abs_srcdir, "extra") or die (File::Spec->catdir($abs_srcdir, "extra") . ": $!\n");
1762 my @extras = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1765 opendir $dd, $abs_srcdir or die "$abs_srcdir: $!\n";
1766 my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1769 my $maxlen = (sort { $b <=> $a } (map {length($_)} (@extras)))[0];
1771 EXTRA: for my $extra (@extras) {
1772 next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra);
1773 next if ($extra eq '.svn');
1774 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1775 my $abs_source = File::Spec->catfile($abs_srcdir, $extra);
1776 next unless ($extra =~ m/\.(cpp|h)$/ || (-d $abs_extra)); # C++ Source/Header, or directory
1777 if (-l $abs_source) {
1778 # Symlink, is it in the right place?
1779 my $targ = readlink($abs_source);
1780 my $abs_targ = File::Spec->rel2abs($targ, $abs_srcdir);
1781 if ($abs_targ eq $abs_extra) {
1782 $extras{$extra} = "\e[32;1menabled\e[0m";
1784 $extras{$extra} = sprintf("\e[31;1mwrong symlink target (%s)\e[0m", $abs_targ);
1786 } elsif (-e $abs_source) {
1787 my ($devext, $inoext) = stat($abs_extra);
1788 my ($devsrc, $inosrc, undef, $lnksrc) = stat($abs_source);
1790 if ($devsrc == $devext && $inosrc == $inoext) {
1791 $extras{$extra} = "\e[32;1menabled\e[0m";
1793 $extras{$extra} = sprintf("\e[31;1mwrong hardlink target (%d:%d)\e[0m", $devsrc, $inosrc);
1796 open my $extfd, "<", $abs_extra;
1797 open my $srcfd, "<", $abs_source;
1799 if (scalar(<$extfd>) eq scalar(<$srcfd>)) {
1800 $extras{$extra} = "\e[32;1menabled\e[0m";
1802 $extras{$extra} = sprintf("\e[31;1mout of synch (re-copy)\e[0m");
1806 $extras{$extra} = "\e[33;1mdisabled\e[0m";
1809 # Now let's add dependency info
1810 for my $extra (keys(%extras)) {
1811 next unless $extras{$extra} =~ m/enabled/; # only process enabled extras.
1812 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1813 my @deps = split / +/, getdependencies($abs_extra);
1814 for my $dep (@deps) {
1815 if (exists($extras{$dep})) {
1816 my $ref = \$extras{$dep}; # Take reference.
1817 if ($$ref !~ m/needed by/) {
1818 # First dependency found.
1819 if ($$ref =~ m/enabled/) {
1820 $$ref .= " (needed by \e[32;1m$extra\e[0m";
1822 $$ref =~ s/\e\[.*?m//g; # Strip out previous coloring. Will be set in bold+red+blink later.
1823 $$ref .= " (needed by \e[0;32;1;5m$extra\e[0;31;1;5m";
1826 if ($$ref =~ m/enabled/) {
1827 $$ref .= ", \e[32;1m$extra\e[0m";
1829 $$ref .= ", \e[0;32;1;5m$extra\e[0;31;1;5m";
1835 for my $extra (sort {$a cmp $b} keys(%extras)) {
1836 my $text = $extras{$extra};
1837 if ($text =~ m/needed by/ && $text !~ m/enabled/) {
1838 printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? ")" : "");
1840 printf "%-*s = %s%s\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? "\e[0m)" : "");
1843 return keys(%extras) if wantarray; # Can be used by manage_extras.
1846 sub enable_extras (@) {
1848 for my $extra (@extras) {
1849 my $extrapath = "src/modules/extra/$extra";
1850 if (!-e $extrapath) {
1851 print STDERR "Cannot enable \e[32;1m$extra\e[0m : No such file or directory in src/modules/extra\n";
1854 my $source = "src/modules/$extra";
1856 print STDERR "Cannot enable \e[32;1m$extra\e[0m : destination in src/modules exists (might already be enabled?)\n";
1859 # Get dependencies, and add them to be processed.
1860 my @deps = split / +/, getdependencies($extrapath);
1861 for my $dep (@deps) {
1862 next if scalar(grep { $_ eq $dep } (@extras)) > 0; # Skip if we're going to be enabling it anyway.
1863 if (!-e "src/modules/$dep") {
1864 if (-e "src/modules/extra/$dep") {
1865 print STDERR "Will also enable extra \e[32;1m$dep\e[0m (needed by \e[32;1m$extra\e[0m)\n";
1868 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";
1872 print "Enabling $extra ... \n";
1873 symlink "extra/$extra", $source or print STDERR "$source: Cannot link to 'extra/$extra': $!\n";
1877 sub disable_extras (@)
1879 opendir my $dd, "src/modules/extra/";
1880 my @files = readdir($dd);
1883 EXTRA: for my $extra (@extras) {
1884 my $extrapath = "src/modules/extra/$extra";
1885 my $source = "src/modules/$extra";
1886 if (!-e $extrapath) {
1887 print STDERR "Cannot disable \e[32;1m$extra\e[0m : Is not an extra\n";
1890 if ((! -l $source) || readlink($source) ne "extra/$extra") {
1891 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";
1894 # Check if anything needs this.
1895 for my $file (@files) {
1896 my @deps = split / +/, getdependencies("src/modules/extra/$file");
1897 # File depends on this extra...
1898 if (scalar(grep { $_ eq $extra } @deps) > 0) {
1899 # And is both enabled and not about to be disabled.
1900 if (-e "src/modules/$file" && scalar(grep { $_ eq $file } @extras) < 1) {
1901 print STDERR "Cannot disable \e[32;1m$extra\e[0m : is needed by \e[32;1m$file\e[0m\n";
1907 print "Disabling $extra ... \n";
1908 unlink "src/modules/$extra" or print STDERR "Cannot disable \e[32;1m$extra\e[0m : $!\n";