2 ###################################################
3 # InspIRCd Configuration Script
5 # Copyright 2002-2009 The InspIRCd Development Team
6 # http://wiki.inspircd.org/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;
33 # Utility functions for our buildsystem
37 use make::opensslcert;
39 ###############################################################################################
43 ###############################################################################################
45 # If you wish to ignore a dependency throughout the entire core, add it here.
48 "inspircd_win32wrapper.h", # windows has its own configure program
51 # If you wish for all files in the entire core to have a given dependency, insert it here.
52 # You should keep this to an absolute minimum to avoid rebuilds that are not neccessary.
54 our @immutabledeps = (
55 "inspircd_config.h", # auto re-generated by configure
59 ###############################################################################################
61 # NON-EDITABLE VARIABLES
63 ###############################################################################################
65 # List of commands that make up 'make install' and 'make deinstall'
67 our $install_list = "";
68 our $uninstall_list = "";
70 # This is a list of all files in the core. Each cpp file is mapped to a shared object file,
71 # whos file extension is omitted (these can vary from system to system). Auto detected by
72 # scanning the src/*.cpp files for files containing /* $Core */ identifiers.
76 # If you wish for a file to have special dependencies in the makefile, add an entry here.
77 # Auto populated by /* $ExtraDeps: */ instruction
79 our %specialdeps = ();
81 # If you wish for a file to have extra make lines (in between the compile and link steps)
82 # then insert them here.
83 # Auto populated by /* $ExtraBuild: */ instruction
85 our %extrabuildlines = ();
87 # If you wish for a file to be linked against extra objects or arctives, insert them here.
88 # Auto populated by /* $ExtraObjects: */ instruction
90 our %extraobjects = ();
92 # If you wish to compile extra cpp sources into an object, define them here.
93 # NOTE: Certain cpp files such as the socket engines have a value auto calculated
94 # for this table so that their derived class is built.
95 # Auto populated by /* $ExtraSources: */ instruction
97 our %extrasources = ();
99 our ($opt_use_gnutls, $opt_rebuild, $opt_use_openssl, $opt_nointeractive, $opt_ports,
100 $opt_epoll, $opt_kqueue, $opt_noports, $opt_noepoll, $opt_nokqueue,
101 $opt_ipv6, $opt_ipv6links, $opt_noipv6links, $opt_maxbuf, $opt_disable_debug,
104 our ($opt_cc, $opt_base_dir, $opt_config_dir, $opt_module_dir, $opt_binary_dir,
109 sub enable_extras (@);
111 sub disable_extras (@);
113 my @opt_enableextras;
114 my @opt_disableextras;
117 'enable-gnutls' => \$opt_use_gnutls,
118 'rebuild' => \$opt_rebuild,
119 'enable-openssl' => \$opt_use_openssl,
120 'disable-interactive' => \$opt_nointeractive,
121 'enable-ports' => \$opt_ports,
122 'enable-epoll' => \$opt_epoll,
123 'enable-kqueue' => \$opt_kqueue,
124 'disable-ports' => \$opt_noports,
125 'disable-epoll' => \$opt_noepoll,
126 'disable-kqueue' => \$opt_nokqueue,
127 'enable-ipv6' => \$opt_ipv6,
128 'enable-remote-ipv6' => \$opt_ipv6links,
129 'disable-remote-ipv6' => \$opt_noipv6links,
130 'with-cc=s' => \$opt_cc,
131 'with-maxbuf=i' => \$opt_maxbuf,
132 'enable-freebsd-ports-openssl' => \$opt_freebsd_port,
133 'prefix=s' => \$opt_base_dir,
134 'config-dir=s' => \$opt_config_dir,
135 'module-dir=s' => \$opt_module_dir,
136 'binary-dir=s' => \$opt_binary_dir,
137 'library-dir=s' => \$opt_library_dir,
138 'disable-debuginfo' => sub { $opt_disable_debug = 1 },
139 'help' => sub { showhelp(); },
140 'modupdate' => sub { modupdate(); },
141 'update' => sub { update(); },
142 'svnupdate' => sub { svnupdate(); },
143 'clean' => sub { clean(); },
144 'list-extras' => sub { list_extras; exit 0; }, # This, --enable-extras, and --disable-extras are for non-interactive managing.
145 'enable-extras=s@' => \@opt_enableextras, # ^
146 'disable-extras=s@' => \@opt_disableextras, # ^
147 'generate-openssl-cert' => sub { make_openssl_cert(); exit(0); },
148 'generate-gnutls-cert' => sub { make_gnutls_cert(); exit(0); }
151 if (scalar(@opt_enableextras) + scalar(@opt_disableextras) > 0) {
152 @opt_enableextras = split /,/, join(',', @opt_enableextras);
153 @opt_disableextras = split /,/, join(',', @opt_disableextras);
154 enable_extras(@opt_enableextras);
155 disable_extras(@opt_disableextras);
157 print "Remember: YOU are responsible for making sure any libraries needed have been installed!\n";
158 print "Run $0 -modupdate after you've done this to update the makefiles.\n";
162 our $non_interactive = (
163 (defined $opt_library_dir) ||
164 (defined $opt_base_dir) ||
165 (defined $opt_config_dir) ||
166 (defined $opt_module_dir) ||
167 (defined $opt_base_dir) ||
168 (defined $opt_binary_dir) ||
169 (defined $opt_nointeractive) ||
171 (defined $opt_ipv6) ||
172 (defined $opt_ipv6links) ||
173 (defined $opt_noipv6links) ||
174 (defined $opt_kqueue) ||
175 (defined $opt_epoll) ||
176 (defined $opt_ports) ||
177 (defined $opt_use_openssl) ||
178 (defined $opt_nokqueue) ||
179 (defined $opt_noepoll) ||
180 (defined $opt_noports) ||
181 (defined $opt_maxbuf) ||
182 (defined $opt_use_gnutls) ||
183 (defined $opt_freebsd_port)
185 our $interactive = !$non_interactive;
187 chomp(our $topdir = getcwd());
188 our $this = resolve_directory($topdir); # PWD, Regardless.
189 our @modlist = (); # Declare for Module List..
190 our %config = (); # Initiate Configuration Hash..
191 $config{ME} = resolve_directory($topdir); # Present Working Directory
193 $config{BASE_DIR} = $config{ME};
195 if (defined $opt_base_dir)
197 $config{BASE_DIR} = $opt_base_dir;
200 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Directory
201 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
202 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
203 $config{LIBRARY_DIR} = resolve_directory($config{BASE_DIR}."/lib"); # Library Directory
205 if (defined $opt_config_dir)
207 $config{CONFIG_DIR} = $opt_config_dir;
209 if (defined $opt_module_dir)
211 $config{MODULE_DIR} = $opt_module_dir;
213 if (defined $opt_binary_dir)
215 $config{BINARY_DIR} = $opt_binary_dir;
217 if (defined $opt_library_dir)
219 $config{LIBRARY_DIR} = $opt_library_dir;
221 chomp($config{HAS_GNUTLS} = `libgnutls-config --version 2>/dev/null | cut -c 1,2,3`); # GNUTLS Version.
223 if (defined $opt_freebsd_port)
225 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`);
226 chomp($config{HAS_OPENSSL_PORT} = `pkg-config --modversion openssl 2>/dev/null`);
227 $config{USE_FREEBSD_BASE_SSL} = "n";
231 if ($^O eq "freebsd")
233 # default: use base ssl
234 chomp($config{HAS_OPENSSL} = `openssl version | cut -d ' ' -f 2`); # OpenSSL version, freebsd specific
235 chomp($config{HAS_OPENSSL_PORT} = `pkg-config --modversion openssl 2>/dev/null`); # Port version, may be different
239 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`); # Openssl version, others
240 $config{HAS_OPENSSL_PORT} = "";
244 chomp(our $gnutls_ver = $config{HAS_GNUTLS});
245 chomp(our $openssl_ver = $config{HAS_OPENSSL});
246 $config{USE_GNUTLS} = "n";
247 if (defined $opt_use_gnutls)
249 $config{USE_GNUTLS} = "y"; # Use gnutls.
251 $config{USE_OPENSSL} = "n"; # Use openssl.
252 if (defined $opt_use_openssl)
254 $config{USE_OPENSSL} = "y";
257 # no, let's not change these.
258 $config{OPTIMITEMP} = "0"; # Default Optimisation Value
259 if (!defined $opt_disable_debug)
261 $config{OPTIMISATI} = "-g1"; # Optimisation Flag
265 $config{OPTIMISATI} = "-O2"; # DEBUGGING OFF!
268 $config{HAS_STRLCPY} = "false"; # strlcpy Check.
269 $config{HAS_STDINT} = "false"; # stdint.h check
270 $config{USE_KQUEUE} = "y"; # kqueue enabled
271 if (defined $opt_kqueue)
273 $config{USE_KQUEUE} = "y";
275 if (defined $opt_nokqueue)
277 $config{USE_KQUEUE} = "n";
279 $config{USE_POLL} = "y"; # poll enabled
280 $config{USE_EPOLL} = "y"; # epoll enabled
281 if (defined $opt_epoll)
283 $config{USE_EPOLL} = "y";
285 if (defined $opt_noepoll)
287 $config{USE_EPOLL} = "n";
289 $config{USE_PORTS} = "y"; # epoll enabled
290 if (defined $opt_ports)
292 $config{USE_PORTS} = "y";
294 if (defined $opt_noports)
296 $config{USE_PORTS} = "n";
298 $config{IPV6} = "n"; # IPv6 support (experimental)
299 if (defined $opt_ipv6)
303 $config{SUPPORT_IP6LINKS} = "y"; # IPv4 supporting IPv6 links (experimental)
304 if (defined $opt_ipv6links)
306 $config{SUPPORT_IP6LINKS} = "y";
308 if (defined $opt_noipv6links)
310 $config{SUPPORT_IP6LINKS} = "n";
312 chomp($config{GCCVER} = `g++ -dumpversion | cut -c 1`); # Major GCC Version
313 chomp($config{GCCMINOR} = `g++ -dumpversion | cut -c 3`);
314 $config{_SOMAXCONN} = SOMAXCONN; # Max connections in accept queue
315 $config{OSNAME} = $^O; # Operating System Name
316 $config{IS_DARWIN} = "NO"; # Is OSX?
317 $config{STARTSCRIPT} = "inspircd"; # start script?
318 $config{DESTINATION} = "BASE"; # Is target path.
319 $config{EXTRA_DIR} = ""; # Is empty.
320 if ($config{OSNAME} =~ /darwin/i)
322 $config{IS_DARWIN} = "YES";
323 $config{STARTSCRIPT} = "org.inspircd.plist"; # start script for OSX.
324 $config{DESTINATION} = "LAUNCHDPATH"; # Is OSX target.
325 $config{EXTRA_DIR} = " launchd_dir"; # Is OSX specific path.
327 $config{CC} = "g++"; # C++ compiler
330 $config{CC} = $opt_cc;
332 our $exec = $config{CC} . " -dumpversion | cut -c 1";
333 chomp($config{GCCVER} = `$exec`); # Major GCC Version
334 $exec = $config{CC} . " -dumpversion | cut -c 3";
335 chomp($config{GCCMINOR} = `$exec`);
336 $config{MAKEORDER} = "ircd mods"; # build order
337 $config{MAXBUF} = "512"; # Max buffer size
339 if ($config{HAS_OPENSSL} =~ /^([-[:digit:].]+)([a-z])?(\-[a-z][0-9])?$/) {
340 $config{HAS_OPENSSL} = $1;
342 $config{HAS_OPENSSL} = "";
345 if (($config{GCCVER} eq "") || ($config{GCCMINOR} eq "")) {
346 print $config{CC} . " was not found! You require g++ (the GNU C++ compiler, part of GCC) to build InspIRCd!\n";
350 # Get and Set some important vars..
355 unlink(".config.cache");
358 our ($has_epoll, $has_ports, $has_kqueue) = (0, 0, 0);
363 chomp($topdir = getcwd());
364 $this = resolve_directory($topdir); # PWD, Regardless.
366 # Does the cache file exist?
368 # No, No it doesn't.. *BASH*
369 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
372 # We've Loaded the cache file and all our variables..
373 print "Updating files...\n";
375 if (defined($opt_disable_debug) && $opt_disable_debug == 1)
377 print "Disabling debug information (-g).\n";
378 $config{OPTIMISATI} = "";
381 $has_epoll = $config{HAS_EPOLL};
382 $has_ports = $config{HAS_PORTS};
383 $has_kqueue = $config{HAS_KQUEUE};
392 print "Configure update failed: $@\n";
400 chomp($topdir = getcwd());
401 $this = resolve_directory($topdir); # PWD, Regardless.
403 # Does the cache file exist?
405 # No, No it doesn't.. *BASH*
406 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
409 # We've Loaded the cache file and all our variables..
410 print "Updating files...\n";
412 $has_epoll = $config{HAS_EPOLL};
413 $has_ports = $config{HAS_PORTS};
414 $has_kqueue = $config{HAS_KQUEUE};
423 print "Module update failed: $@\n";
433 open(FH,"<.svn/entries") or $fail = 1;
435 print "This is not an SVN copy of InspIRCd.\n";
442 open my $fd, "-|", "svn update";
443 my $configurechanged = 0; # Needs ./configure -update
444 my $coredirchanged = 0; # Needs ./configure -update
445 my $moduledirchanged = 0; # Needs ./configure -modupdate
446 my $rootincchanged = 0;
448 while (defined(my $line = <$fd>))
452 $line =~ m/^([ADUCG])\s+(.*)$/ or next;
453 ($action, $file) = ($1, $2);
456 push @conflicted, $file;
457 if ($file eq "configure")
459 $configurechanged = 1;
461 elsif ($file =~ m#^src/modules#)
463 $moduledirchanged = 1;
465 elsif ($file =~ m#^src/#)
469 elsif ($file =~ m/^\..*\.inc$/)
474 elsif ($action eq "U" || $action eq "G")
476 if ($file eq "configure")
478 $configurechanged = 1;
480 elsif ($file =~ m/^\..*\.inc$/)
485 elsif ($action eq "A" || $action eq "D")
487 if ($file =~ m#^src/modules#)
489 $moduledirchanged = 1;
491 elsif ($file =~ m#^src/#)
497 unless (close $fd) # close() waits for exit and returns false if the command failed
501 print STDERR "Problem updating from SVN, please check above for errors\n";
505 print STDERR "Failed to run SVN: $!\n";
509 if (scalar(@conflicted) > 0)
511 print STDERR "\e[0;33;1mERROR:\e[0m You have local modifications which conflicted with the updates from SVN\n";
512 printf STDERR "Configure is not able to complete the update. Please resolve these conflicts, then run ./configure -%supdate\n", (($coredirchanged || $configurechanged) ? "" : "mod");
513 print "Conflicted files: " . join ", ", @conflicted . "\n";
516 if ($configurechanged || $coredirchanged)
518 system("perl configure -update");
520 elsif ($moduledirchanged || $rootincchanged)
522 system("perl configure -modupdate");
526 print "No need to update Makefiles.\n";
528 if (defined $opt_rebuild) {
529 system("make install");
537 $fail ||= system "$config{CC} -o test_$feature make/check_$feature.cpp >/dev/null 2>&1";
538 $fail ||= system "./test_$feature";
539 unlink "test_$feature";
543 print "Running non-interactive configure...\n" unless $interactive;
544 print "Checking for cache from previous configure... ";
545 print ((!getcache()) ? "not found\n" : "found\n");
546 print "Checking operating system version... ";
547 print getosflags() . "\n";
549 printf "Checking if stdint.h exists... ";
550 $config{HAS_STDINT} = "true";
552 open(STDINT, "</usr/include/stdint.h") or $config{HAS_STDINT} = "false";
553 if ($config{HAS_STDINT} eq "true") {
556 print "yes\n" if $config{HAS_STDINT} eq "true";
557 print "no\n" if $config{HAS_STDINT} eq "false";
559 printf "Checking if strlcpy exists... ";
560 # Perform the strlcpy() test..
561 $config{HAS_STRLCPY} = "false";
563 open(STRLCPY, "</usr/include/string.h") or $fail = 1;
565 while (defined(my $line = <STRLCPY>)) {
567 # try and find the delcaration of:
568 # size_t strlcpy(...)
569 if ($line =~ /size_t(\0x9|\s)+strlcpy/) {
570 $config{HAS_STRLCPY} = "true";
575 print "yes\n" if $config{HAS_STRLCPY} eq "true";
576 print "no\n" if $config{HAS_STRLCPY} eq "false";
578 printf "Checking if kqueue exists... ";
581 open(KQUEUE, "</usr/include/sys/event.h") or $fail = 1;
583 while (defined(my $line = <KQUEUE>)) {
585 # try and find the delcaration of:
587 if ($line =~ /int(\0x9|\s)+kqueue/) {
593 print "yes\n" if $has_kqueue == 1;
594 print "no\n" if $has_kqueue == 0;
596 printf "Checking for epoll support... ";
597 $has_epoll = test_compile('epoll');
598 print $has_epoll ? "yes\n" : "no\n";
600 printf "Checking for eventfd support... ";
601 $config{HAS_EVENTFD} = test_compile('eventfd') ? 'true' : 'false';
602 print $config{HAS_EVENTFD} eq 'true' ? "yes\n" : "no\n";
604 printf "Checking if Solaris I/O completion ports are available... ";
606 our $system = `uname -s`;
608 $has_ports = 1 if ($system eq "SunOS");
611 my $kernel = `uname -r`;
613 if (($kernel !~ /^5\.1./)) {
617 print "yes\n" if $has_ports == 1;
618 print "no\n" if $has_ports == 0;
620 $config{HAS_EPOLL} = $has_epoll;
621 $config{HAS_KQUEUE} = $has_kqueue;
623 printf "Checking for libgnutls... ";
624 if (defined($config{HAS_GNUTLS}) && (($config{HAS_GNUTLS}) || ($config{HAS_GNUTLS} eq "y"))) {
625 if (defined($gnutls_ver) && ($gnutls_ver ne "")) {
627 $config{HAS_GNUTLS} = "y";
630 $config{HAS_GNUTLS} = "n";
634 $config{HAS_GNUTLS} = "n";
637 printf "Checking for openssl... ";
638 if (defined($config{HAS_OPENSSL}) && (($config{HAS_OPENSSL}) || ($config{HAS_OPENSSL} eq "y"))) {
639 if (defined($openssl_ver) && ($openssl_ver ne "")) {
641 $config{HAS_OPENSSL} = "y";
644 $config{HAS_OPENSSL} = "n";
648 $config{HAS_OPENSSL} = "n";
651 printf "Checking if you are running an ancient, unsupported OS... ";
652 if ($config{OSNAME} =~ /FreeBSD/i)
654 my $version = `uname -r`;
655 if ($version =~ /^4\./)
657 my $foundit = `ls -l /usr/local/lib/libgnugetopt* | wc -l`;
660 # ICKY ICKY ICK, FREEBSD 4.x! GET AN UPGRADE!
661 $config{CRAQ} = "-L/usr/local/lib -lgnugetopt -DHAVE_DECL_GETOPT=1";
662 print "yes (upgrade ffs, freebsd 4 is *way* out of date)\n";
666 print "\n\nERROR: You require libgnugetopt (from ports or packages) to build InspIRCd on FreeBSD 4.11.\n";
672 print "no ($version)\n";
678 print "no ($config{OSNAME})\n";
681 ################################################################################
682 # BEGIN INTERACTIVE PART #
683 ################################################################################
688 print "\e[2J\e[0G\e[0d"; # J = Erase in Display, 2 = Entire Screen, (G, d) = Move cursor to (..,..)
691 my $rev = getrevision();
692 # Display Introduction Message..
694 Welcome to the \e[1mInspIRCd\e[0m Configuration program! (\e[1minteractive mode\e[0m)
695 \e[1mPackage maintainers: Type ./configure --help for non-interactive help\e[0m
697 *** If you are unsure of any of these values, leave it blank for ***
698 *** standard settings that will work, and your server will run ***
699 *** using them. Please consult your IRC network admin if in doubt. ***
701 Press \e[1m<RETURN>\e[0m to accept the default for any option, or enter
702 a new value. Please note: You will \e[1mHAVE\e[0m to read the docs
703 dir, otherwise you won't have a config file!
705 Your operating system is: \e[1;32m$config{OSNAME}\e[0m ($wholeos)
706 Your InspIRCd revision ID is \e[1;32mr$rev\e[0m
709 print " (Non-SVN build)";
713 $config{CHANGE_COMPILER} = "n";
714 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";
716 while (($config{GCCVER} < 3) || ($config{GCCVER} eq "")) {
717 print "\e[1;32mIMPORTANT!\e[0m A GCC 2.x compiler has been detected, and
718 should NOT be used. You should probably specify a newer compiler.\n\n";
719 yesno('CHANGE_COMPILER',"Do you want to change the compiler?");
720 if ($config{CHANGE_COMPILER} =~ /y/i) {
721 print "What command do you want to use to invoke your compiler?\n";
722 print "[\e[1;32m$config{CC}\e[0m] -> ";
723 chomp($config{CC} = <STDIN>);
724 if ($config{CC} eq "") {
727 chomp(my $foo = `$config{CC} -dumpversion | cut -c 1`);
729 chomp($config{GCCVER} = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
730 chomp($config{GCCMINOR} = `$config{CC} -dumpversion | cut -c 3`);
731 print "Queried compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.$config{GCCMINOR}\e[0m)\n";
732 if ($config{GCCVER} < 3) {
733 print "\e[1;32mGCC 2.x WILL NOT WORK!\e[0m. Let's try that again, shall we?\n";
737 print "\e[1;32mWARNING!\e[0m Could not execute the compiler you specified. You may want to try again.\n";
744 # Directory Settings..
745 my $tmpbase = $config{BASE_DIR};
746 dir_check("do you wish to install the InspIRCd base", "BASE_DIR");
747 if ($tmpbase ne $config{BASE_DIR}) {
748 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Dir
749 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
750 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
751 $config{LIBRARY_DIR} = resolve_directory($config{BASE_DIR}."/lib"); # Library Directory
754 dir_check("are the configuration files", "CONFIG_DIR");
755 dir_check("are the modules to be compiled to", "MODULE_DIR");
756 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
757 dir_check("are the IRCd libraries to be placed", "LIBRARY_DIR");
759 my $chose_hiperf = 0;
761 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?");
763 if ($config{USE_KQUEUE} eq "y") {
768 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?");
770 if ($config{USE_EPOLL} eq "y") {
775 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?");
777 if ($config{USE_PORTS} eq "y") {
782 if (!$chose_hiperf) {
783 yesno('USE_POLL', "Would you like to use poll?\n This is likely to increase performance.\nIf you are unsure, answer yes.\n\nEnable poll?\n");
784 if ($config{USE_POLL} ne "y")
786 print "No high-performance socket engines are available, or you chose\n";
787 print "not to enable one. Defaulting to select() engine.\n\n";
791 yesno('IPV6',"Would you like to build InspIRCd with IPv6 support?");
794 if ($config{IPV6} eq "y") {
795 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";
796 $config{SUPPORT_IP6LINKS} = "y";
798 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?");
802 $config{USE_FREEBSD_BASE_SSL} = "n";
803 $config{USE_FREEBSD_PORTS_SSL} = "n";
804 if ($config{HAS_OPENSSL_PORT} ne "")
806 $config{USE_FREEBSD_PORTS_SSL} = "y";
807 print "I have detected the OpenSSL FreeBSD port installed on your system,\n";
808 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";
809 yesno('USE_FREEBSD_PORTS_SSL', "Do you want to use the FreeBSD ports version?");
811 $config{USE_FREEBSD_BASE_SSL} = "y" if ($config{USE_FREEBSD_PORTS_SSL} eq "n");
813 if ($config{USE_FREEBSD_BASE_SSL} eq "n")
815 # update to port version
816 $openssl_ver = $config{HAS_OPENSSL_PORT};
821 $config{USE_FREEBSD_BASE_SSL} = "y" if ($^O eq "freebsd");
824 $config{USE_SSL} = "n";
826 if ($config{HAS_GNUTLS} eq "y" || $config{HAS_OPENSSL} eq "y")
828 print "Detected GnuTLS version: \e[1;32m" . $gnutls_ver . "\e[0m\n";
829 print "Detected OpenSSL version: \e[1;32m" . $openssl_ver . "\e[0m\n\n";
831 yesno('USE_SSL', "One or more SSL libraries detected. Would you like to enable SSL support?");
832 if ($config{USE_SSL} eq "y")
834 if ($config{HAS_GNUTLS} eq "y")
836 yesno('USE_GNUTLS',"Would you like to enable SSL with m_ssl_gnutls? (recommended)");
837 if ($config{USE_GNUTLS} eq "y")
839 print "\nUsing GnuTLS SSL module.\n";
843 if ($config{HAS_OPENSSL} eq "y")
845 yesno('USE_OPENSSL', "Would you like to enable SSL with m_ssl_openssl?");
846 if ($config{USE_OPENSSL} eq "y")
848 print "\nUsing OpenSSL SSL module.\nYou will get better performance if you move to GnuTLS in the future.\n";
855 print "\nCould not detect OpenSSL or GnuTLS. Make sure pkg-config is installed if\n";
856 print "you intend to use OpenSSL, or that GnuTLS is in your path if you intend\nto use GnuTLS.\n\n";
862 if (($config{USE_GNUTLS} eq "y") && ($config{HAS_GNUTLS} ne "y"))
864 print "Sorry, but i couldn't detect gnutls. Make sure gnutls-config is in your path.\n";
867 if (($config{USE_OPENSSL} eq "y") && ($config{HAS_OPENSSL} ne "y"))
869 print "Sorry, but i couldn't detect openssl. Make sure openssl is in your path.\n";
874 if ($config{USE_GNUTLS} eq "y") {
875 unless (-r "src/modules/m_ssl_gnutls.cpp") {
876 print "Symlinking src/modules/m_ssl_gnutls.cpp from extra/\n";
877 symlink "extra/m_ssl_gnutls.cpp", "src/modules/m_ssl_gnutls.cpp" or print STDERR "Symlink failed: $!";
882 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
883 print "SSL Certificates Not found, Generating.. \n\n
884 *************************************************************
885 * Generating the Private Key may take some time, go grab a *
886 * Coffee. Even better, to generate some more entropy if it *
887 * is taking a while, open another console and type du / a *
888 * few times and get that HD going :) Then answer the *
889 * Questions which follow. If you are unsure, just hit enter *
890 *************************************************************\n\n";
891 $failed = make_gnutls_cert();
893 print "\n\e[1;32mCertificate generation failed!\e[0m\n\n";
895 print "\nCertificate generation complete, copying to config directory... ";
896 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
897 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
902 print "SSL Certificates found, skipping.\n\n";
907 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
909 } elsif ($config{USE_OPENSSL} eq "y") {
910 unless (-r "src/modules/m_ssl_openssl.cpp") {
911 print "Symlinking src/modules/m_ssl_openssl.cpp from extra/\n";
912 symlink "extra/m_ssl_openssl.cpp", "src/modules/m_ssl_openssl.cpp" or print STDERR "Symlink failed: $!";
918 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
919 print "SSL Certificates Not found, Generating.. \n\n
920 *************************************************************
921 * Generating the certificates may take some time, go grab a *
922 * coffee, or something. *
923 *************************************************************\n\n";
925 print "\nCertificate generation complete, copying to config directory... ";
926 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
927 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
928 File::Copy::move("dhparams.pem", "$config{CONFIG_DIR}/dhparams.pem") or print STDERR "Could not copy dhparams.pem!\n";
931 print "SSL Certificates found, skipping.\n\n"
936 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
939 if (($config{USE_GNUTLS} eq "n") && ($config{USE_OPENSSL} eq "n")) {
940 print "Skipping SSL Certificate generation, SSL support is not available.\n\n";
948 print "To build your server with these settings, please type '\e[1;32m$config{MAKEPROG}\e[0m' now.\n";
949 if (($config{USE_GNUTLS} eq "y") || ($config{USE_OPENSSL} eq "y")) {
950 print "Please note: for \e[1;32mSSL support\e[0m you will need to load required\n";
951 print "modules in your config. This configure script has added those modules to the\n";
952 print "build process. For more info please refer to:\n";
953 print "\e[1;32mhttp://wiki.inspircd.org/Installation_From_Tarball\e[0m\n";
955 print "*** \e[1;32mRemember to edit your configuration files!!!\e[0m ***\n\n\n";
956 if (($config{OSNAME} eq "OpenBSD") && ($config{CC} ne "eg++")) {
957 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";
960 if ($config{GCCVER} < "3") {
962 \e[1;32mWARNING!\e[0m You are attempting to compile InspIRCd on GCC 2.x!
963 GCC 2.x series compilers only had partial (read as broken) C++ support, and
964 your compile will most likely fail horribly! If you have any problems, do NOT
965 report them to the bugtracker or forums without first upgrading your compiler
966 to a newer 3.x or 4.x (or whatever is available currently) version.
970 ################################################################################
972 ################################################################################
974 # Retrieves the .config.cache file, and loads values into the main config hash.
975 open(CACHE, ".config.cache") or return 0;
978 # Ignore Blank lines, and comments..
981 my ($key, $value) = split("=", $_, 2);
982 $value =~ /^\"(.*)\"$/;
983 # Do something with data here!
991 # Dump the contents of %config
992 print "Writing \e[1;32mcache file\e[0m for future ./configures ...\n";
993 open(FILEHANDLE, ">.config.cache");
994 foreach my $key (keys %config) {
995 print FILEHANDLE "$key=\"$config{$key}\"\n";
1001 my ($desc, $hash_key) = @_;
1003 while (!$complete) {
1004 print "In what directory $desc?\n";
1005 print "[\e[1;32m$config{$hash_key}\e[0m] -> ";
1006 chomp(my $var = <STDIN>);
1008 $var = $config{$hash_key};
1010 if ($var =~ /^\~\/(.+)$/) {
1011 # Convert it to a full path..
1012 $var = resolve_directory($ENV{HOME} . "/" . $1);
1014 elsif ((($config{OSNAME} =~ /MINGW32/i) and ($var !~ /^[A-Z]{1}:\\.*/)) and (substr($var,0,1) ne "/"))
1016 # Assume relative Path was given.. fill in the rest.
1017 $var = $this . "/$var";
1020 $var = resolve_directory($var);
1022 print "$var does not exist. Create it?\n[\e[1;32my\e[0m] ";
1023 chomp(my $tmp = <STDIN>);
1024 if (($tmp eq "") || ($tmp =~ /^y/i)) {
1025 # Attempt to Create the Dir..
1028 File::Path::mkpath($var, 0, 0777);
1031 unless (defined($chk) && -d $var) {
1032 print "Unable to create directory. ($var)\n\n";
1037 # They said they don't want to create, and we can't install there.
1042 if (!is_dir($var)) {
1043 # Target exists, but is not a directory.
1044 print "File $var exists, but is not a directory.\n\n";
1048 # Either Dir Exists, or was created fine.
1049 $config{$hash_key} = $var;
1059 # Beware: Linux sets it's own cflags below for some retarded reason
1060 $config{LDLIBS} = "-pthread -lstdc++";
1061 $config{FLAGS} = "-fPIC -Woverloaded-virtual -Wshadow -Wformat=2 -Wmissing-format-attribute -Wall $config{OPTIMISATI}";
1062 $config{DEVELOPER} = "-fPIC -Woverloaded-virtual -Wshadow -Wall -Wformat=2 -Wmissing-format-attribute -g";
1063 $SHARED = "-shared -export-dynamic";
1064 $config{MAKEPROG} = "make";
1066 if ($config{OSNAME} =~ /darwin/i) {
1067 $config{FLAGS} = "-DDARWIN -frtti -fPIC -Wall $config{OPTIMISATI}";
1068 $SHARED = "-bundle -twolevel_namespace -undefined dynamic_lookup";
1069 $config{LDLIBS} = "-ldl -pthread -lstdc++";
1072 if ($config{OSNAME} =~ /OpenBSD/i) {
1073 $config{MAKEPROG} = "gmake";
1074 # apparantly (Dagonet says) that this causes problems, so let's try without it.
1075 # $config{LDLIBS} = $config{LDLIBS} . " -lunwind";
1076 chomp(my $foo = `eg++ -dumpversion | cut -c 1`);
1077 # theyre running the package version of gcc (eg++)... detect it and set up its version numbers.
1078 # if theyre not running this, configure lets the build continue but they probably wont manage to
1079 # compile as this standard version is 2.95.3!
1081 $config{CC} = "eg++";
1082 chomp($config{GCCVER} = `eg++ -dumpversion | cut -c 1`); # we must redo these if we change the compiler path
1083 chomp($config{GCCMINOR} = `eg++ -dumpversion | cut -c 3`);
1088 if ($config{OSNAME} =~ /Linux/i) {
1089 $config{LDLIBS} = "-ldl -lstdc++ -pthread";
1090 # $config{FLAGS} = "-fPIC -Woverloaded-virtual -Wshadow -Wall $config{OPTIMISATI}";
1091 $config{FLAGS} .= " " . $ENV{CXXFLAGS} if exists($ENV{CXXFLAGS});
1092 $config{LDLIBS} .= " " . $ENV{LDLIBS} if exists($ENV{LDLIBS});
1093 $config{MAKEPROG} = "make";
1096 if ($config{OSNAME} =~ /FreeBSD/i) {
1097 $config{FLAGS} .= " " . $ENV{CXXFLAGS} if exists($ENV{CXXFLAGS});
1098 $config{LDLIBS} .= " " . $ENV{LDLIBS} if exists($ENV{LDLIBS});
1101 if ($config{OSNAME} =~ /SunOS/i or $config{OSNAME} =~ /solaris/i)
1103 # solaris/sunos needs these
1104 # socket = bsd sockets api
1106 # rt = POSIX realtime extensions
1107 # resolv = inet_aton only (why isnt this in nsl?!)
1108 $config{MAKEPROG} = "gmake";
1109 $config{LDLIBS} .= " -lsocket -lnsl -lrt -lresolv -pthread";
1113 if($config{OSNAME} =~ /MINGW32/i)
1115 # All code is position-independent on windows
1116 $config{FLAGS} =~ s/-fPIC //;
1120 return $config{OSNAME};
1123 my ($mliflags, $mfrules, $mobjs, $mfcount) = ("", "", "", 0);
1126 my($writeheader) = @_;
1128 # First File.. inspircd_config.h
1129 chomp(my $incos = `uname -n -s -r`);
1130 chomp(my $version = `sh src/version.sh`);
1131 chomp(my $revision2 = getrevision());
1132 if ($writeheader == 1)
1134 print "Writing \e[1;32minspircd_config.h\e[0m\n";
1135 open(FILEHANDLE, ">include/inspircd_config.h");
1136 print FILEHANDLE <<EOF;
1137 /* Auto generated by configure, do not modify! */
1138 #ifndef __CONFIGURATION_AUTO__
1139 #define __CONFIGURATION_AUTO__
1141 /* this is for windows support. */
1142 #define CoreExport /**/
1143 #define DllExport /**/
1145 #define CONFIG_FILE "$config{CONFIG_DIR}/inspircd.conf"
1146 #define MOD_PATH "$config{MODULE_DIR}"
1147 #define VERSION "$version"
1148 #define REVISION "$revision2"
1149 #define SOMAXCONN_S "$config{_SOMAXCONN}"
1150 #define OPTIMISATION $config{OPTIMITEMP}
1151 #define LIBRARYDIR "$config{LIBRARY_DIR}"
1152 #define SYSTEM "$incos"
1153 #define ENTRYPOINT int main(int argc, char** argv)
1156 print FILEHANDLE "#define MAXBUF " . ($config{MAXBUF}+2) . "\n";
1158 if ($config{OSNAME} =~ /SunOS/i) {
1159 print FILEHANDLE "#define IS_SOLARIS\n";
1161 if ($config{OSNAME} =~ /MINGW32/i) {
1162 print FILEHANDLE "#define IS_MINGW\n";
1164 if ($config{GCCVER} >= 3) {
1165 print FILEHANDLE "#define GCC3\n";
1168 (($config{GCCVER} == 4) && ($config{GCCMINOR} >= 3))
1170 ($config{GCCVER} > 4)
1172 print FILEHANDLE "#define HASHMAP_DEPRECATED\n";
1174 if ($config{HAS_STRLCPY} eq "true") {
1175 print FILEHANDLE "#define HAS_STRLCPY\n";
1177 if ($config{HAS_STDINT} eq "true") {
1178 print FILEHANDLE "#define HAS_STDINT\n";
1180 if ($config{IPV6} =~ /y/i) {
1181 print FILEHANDLE "#define IPV6\n";
1183 if ($config{SUPPORT_IP6LINKS} =~ /y/i) {
1184 print FILEHANDLE "#define SUPPORT_IP6LINKS\n";
1186 if ($config{HAS_EVENTFD} eq 'true') {
1187 print FILEHANDLE "#define HAS_EVENTFD\n";
1190 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
1191 print FILEHANDLE "#define USE_KQUEUE\n";
1192 $se = "socketengine_kqueue";
1195 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
1196 print FILEHANDLE "#define USE_EPOLL\n";
1197 $se = "socketengine_epoll";
1200 if (($has_ports) && ($config{USE_PORTS} eq "y")) {
1201 print FILEHANDLE "#define USE_PORTS\n";
1202 $se = "socketengine_ports";
1205 # user didn't choose either epoll or select for their OS.
1206 # default them to USE_SELECT (ewwy puke puke)
1208 print "no hi-perf, " . $config{USE_POLL};
1209 if ($config{USE_POLL} eq "y")
1211 print FILEHANDLE "#define USE_POLL\n";
1212 $se = "socketengine_poll";
1216 print FILEHANDLE "#define USE_SELECT\n";
1217 $se = "socketengine_select";
1220 print FILEHANDLE "\n#include \"threadengines/threadengine_pthread.h\"\n\n#endif\n";
1226 open(FILEHANDLE, ">include/inspircd_se_config.h");
1227 print FILEHANDLE <<EOF;
1228 /* Auto generated by configure, do not modify or commit to svn! */
1229 #ifndef __CONFIGURATION_SOCKETENGINE__
1230 #define __CONFIGURATION_SOCKETENGINE__
1232 #include "socketengines/$se.h"
1240 # Create a Modules List..
1242 foreach my $i (@modlist)
1244 $modules .= "m_".$i.".so ";
1246 chomp($modules); # Remove Redundant whitespace..
1248 opendir(DIRHANDLE, "src/modules");
1249 foreach my $name2 (sort readdir(DIRHANDLE)) {
1250 if ($name2 =~ /^m_(.+?)$/) {
1251 if (defined(opendir(MDIRHANDLE, "src/modules/$name2"))) {
1252 closedir(MDIRHANDLE);
1253 $modules .= "$name2.so ";
1254 $uninstall_list = $uninstall_list . " -rm \$(MODULES)/$name2.so\n";
1258 closedir(DIRHANDLE);
1261 # Write all .in files.
1264 my $exe = "inspircd";
1266 # Do this once here, and cache it in the .*.inc files,
1267 # rather than attempting to read src/version.sh from
1268 # compiled code -- we might not have the source to hand.
1269 # Fix for bug#177 by Brain.
1271 chomp($version = `sh ./src/version.sh`);
1272 chomp(my $revision = getrevision());
1273 $version = "$version(r$revision)";
1275 # We can actually parse any file starting with . and ending with .inc,
1276 # but right now we only parse .inspircd.inc to form './inspircd'
1278 print "Writing \e[1;32mMakefiles\e[0m\n";
1279 write_dynamic_modules_makefile();
1280 write_dynamic_makefile();
1282 opendir(DIRHANDLE, $this);
1284 foreach my $name (sort readdir(DIRHANDLE)) {
1285 if ($name =~ /^\.(.+)\.inc$/) {
1288 # Bug #353, omit this on non-darwin
1289 next if (($config{OSNAME} !~ /darwin/) && ($file eq "org.inspircd.plist"));
1291 # All .name.inc files need parsing!
1293 open(FILEHANDLE, ".$file.inc") or die ("Can't open .$file.inc");
1294 while (<FILEHANDLE>) {
1299 print "Writing \e[1;32m$file\e[0m ...\n";
1300 $tmp =~ s/\@CC\@/$config{CC}/ if defined $config{CC};
1301 $tmp =~ s/\@MAKEPROG\@/$config{MAKEPROG}/ if defined $config{MAKEPROG};
1302 $tmp =~ s/\@FLAGS\@/$config{FLAGS}/ if defined $config{FLAGS};
1303 $tmp =~ s/\@DEVELOPER\@/$config{DEVELOPER}/ if defined $config{DEVELOPER};
1304 $tmp =~ s/\@LDLIBS\@/$config{LDLIBS}/ if defined $config{LDLIBS};
1305 $tmp =~ s/\@BASE_DIR\@/$config{BASE_DIR}/ if defined $config{BASE_DIR};
1306 $tmp =~ s/\@CONFIG_DIR\@/$config{CONFIG_DIR}/ if defined $config{CONFIG_DIR};
1307 $tmp =~ s/\@MODULE_DIR\@/$config{MODULE_DIR}/ if defined $config{MODULE_DIR};
1308 $tmp =~ s/\@BINARY_DIR\@/$config{BINARY_DIR}/ if defined $config{BINARY_DIR};
1309 $tmp =~ s/\@LIBRARY_DIR\@/$config{LIBRARY_DIR}/ if defined $config{LIBRARY_DIR};
1310 $tmp =~ s/\@MODULES\@/$modules/ if defined $modules;
1311 $tmp =~ s/\@STARTSCRIPT\@/$config{STARTSCRIPT}/ if defined $config{STARTSCRIPT};
1312 $tmp =~ s/\@DESTINATION\@/$config{DESTINATION}/ if defined $config{DESTINATION};
1313 $tmp =~ s/\@EXTRA_DIR\@/$config{EXTRA_DIR}/ if defined $config{EXTRA_DIR};
1314 $tmp =~ s/\@EXECUTABLE\@/$exe/ if defined $exe;
1315 $tmp =~ s/\@MAKEORDER\@/$config{MAKEORDER}/ if defined $config{MAKEORDER};
1316 $tmp =~ s/\@VERSION\@/$version/ if defined $version;
1317 $tmp =~ s/\@INSTALL_LIST\@/$install_list/ if defined $install_list;
1318 $tmp =~ s/\@UNINSTALL_LIST\@/$uninstall_list/ if defined $uninstall_list;
1320 open(FILEHANDLE, ">$file") or die("Can't write to $file: $!\n");
1321 print FILEHANDLE $tmp;
1324 closedir(DIRHANDLE);
1326 # Make inspircd executable!
1327 chmod 0744, 'inspircd';
1330 sub write_dynamic_modules_makefile {
1331 # Modules Makefile..
1332 print "Writing \e[1;32msrc/modules/Makefile\e[0m\n";
1333 open(FILEHANDLE, ">src/modules/Makefile");
1336 # Module Makefile Header
1338 print FILEHANDLE <<EOF;
1339 ###################################################
1340 # Copyright 2002-2009 The InspIRCd Development Team
1341 # http://wiki.inspircd.org/Credits
1343 # Thanks to Andrew Church <achurch\@achurch.org>
1344 # for assisting with making this work right.
1346 # Automatically Generated by ./configure to add a
1347 # modules please run ./configure -modupdate
1348 ###################################################
1354 if ($config{OSNAME} =~ /darwin/) {
1355 print FILEHANDLE <<EOCHEESE;
1357 PICLDFLAGS = -twolevel_namespace -undefined dynamic_lookup -bundle
1361 print FILEHANDLE <<EOCHEESE;
1363 PICLDFLAGS = -fPIC -DPIC -shared
1369 # End Module Makefile Header
1372 # Create a Modules List..
1376 foreach my $i (@modlist) {
1378 # Write Entry to the MakeFile
1380 $cmflags = getcompilerflags("src/modules/m_".$i.".cpp");
1381 $liflags = getlinkerflags("src/modules/m_".$i.".cpp");
1382 my $deps = getdependencies("src/modules/m_".$i.".cpp");
1384 #print "file: $i: cmflags=$cmflags; liflags=$liflags; deps=$deps\n";
1387 if (nopedantic("src/modules/m_".$i.".cpp"))
1390 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
1391 \@../../make/run-cc.pl \$(CC) -pipe -I../../include \$(NICEFLAGS) $cmflags \$(PICLDFLAGS) $liflags $SHARED -o m_$i.so 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 \$(FLAGS) $cmflags \$(PICLDFLAGS) $liflags $SHARED -o m_$i.so m_$i.cpp
1401 $install_list = $install_list . " install -m \$(INSTMODE) src/modules/m_$i.so \$(MODPATH)\n";
1402 $uninstall_list = $uninstall_list . " -rm \$(MODULES)/m_$i.so\n";
1404 # End Write Entry to the MakeFile
1408 opendir(DIRHANDLE, "src/modules");
1409 foreach my $name (sort readdir(DIRHANDLE)) {
1410 if ($name =~ /^m_(.+?)$/) {
1415 # A module made of multiple files, in a dir, e.g. src/modules/m_spanningtree/
1416 if (defined(opendir(MDIRHANDLE, "src/modules/$name"))) {
1417 read_module_directory("src/modules/$name", $name);
1418 print "Composing Makefile rules for directory \e[1;32m$name\e[0m... (\e[1;32m$mfcount files found\e[0m)\n";
1419 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";
1420 print FILEHANDLE " \@../../make/run-cc.pl \$(CC) -pipe \$(FLAGS) $SHARED $mliflags -o $name.so $mobjs\n";
1421 print FILEHANDLE "\n$mfrules\n";
1422 closedir(MDIRHANDLE);
1423 $install_list = $install_list . " install -m \$(INSTMODE) src/modules/$name.so \$(MODPATH)\n";
1427 closedir(DIRHANDLE);
1430 sub read_module_directory {
1431 my ($dpath, $reldpath) = @_;
1433 if (opendir(MDIRHANDLE, $dpath) == 0) {
1437 foreach my $fname (sort readdir(MDIRHANDLE)) {
1438 if ($fname =~ /\.cpp$/) {
1439 my $cmflags = getcompilerflags("$dpath/$fname");
1440 $mliflags = $mliflags . " " . getlinkerflags("$dpath/$fname");
1441 my $deps = getdependencies("$dpath/$fname");
1443 $oname =~ s/\.cpp$/.o/g;
1444 $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";
1445 $mfrules = $mfrules . " \@../../make/run-cc.pl \$(CC) -pipe -I../../include -I. \$(FLAGS) $cmflags $SHARED -o $reldpath/$oname -c $reldpath/$fname\n\n";
1446 $mobjs = $mobjs . " $reldpath/$oname";
1449 elsif ((-d "$dpath/$fname") && !($fname eq ".") && !($fname eq "..")) {
1450 read_module_directory($dpath."/".$fname, $reldpath."/".$fname);
1457 # Yes i know we could use gcc -M but it seems to ideneify a lot of 'deep'
1458 # dependencies which are not relevent in C++.
1462 open (CPP, "<$file") or die("Can't open $file for reading!");
1467 foreach my $d (@ignoredeps)
1473 foreach my $dep (@immutabledeps)
1475 $immutable = $immutable . "../include/$dep ";
1477 $immutable =~ s/ $//g;
1479 while (defined(my $line = <CPP>))
1482 if ($line =~ /#include "(.+\.h)"/)
1484 if (!exists($dupe{$1}))
1486 $retlist = $retlist . "../include/$1 ";
1492 return length($immutable) ? $immutable . " " . $retlist : $retlist;
1495 sub write_dynamic_makefile
1499 my %existing_install_list = ();
1500 my %core_files_list = ();
1502 opendir(DIRHANDLE, "src/commands");
1503 foreach my $name (sort readdir(DIRHANDLE))
1505 if ($name =~ /^cmd_(.+)\.cpp$/)
1507 $cmdlist[$i++] = $1;
1508 $install_list = $install_list . " -install -m \$(INSTMODE) src/commands/cmd_" . $1 . ".so \$(LIBPATH)\n";
1509 $uninstall_list = $uninstall_list . " -rm \$(LIBPATH)/cmd_$1.so\n";
1512 closedir(DIRHANDLE);
1516 $config{USE_EPOLL} = 0;
1520 $config{USE_KQUEUE} = 0;
1524 $config{USE_PORTS} = 0;
1527 # formerly generated below this foreach, now it's not! magic.
1530 foreach my $dir (("src","src/commands","src/modes","src/socketengines","src/modules"))
1532 print "Scanning \e[1;32m$dir\e[0m for core files ";
1533 opendir(DIRHANDLE, $dir);
1534 foreach my $name (sort readdir(DIRHANDLE))
1536 if ($name =~ /\.cpp$/)
1538 open (CPP, "<$dir/$name") or die("Can't open $dir/$name to scan it! oh bugger");
1540 while (defined(my $line = <CPP>))
1543 if ($line =~ /\/\* \$Core \*\//i)
1546 $sname =~ s/\.cpp$/.o/;
1548 # append it to list to be built
1549 $all_core = $all_core . $sname . " ";
1550 $filelist{$name} = $sname;
1552 # mark it as a core file, so it won't get shared object cflags
1553 if (!exists($core_files_list{$name}))
1555 $core_files_list{$name} = 1;
1558 elsif ($line =~ /\/\* \$ExtraDeps: (.*?) \*\//i)
1560 $specialdeps{$name} = $1;
1562 elsif ($line =~ /\/\* \$ExtraObjects: (.*?) \*\//i)
1564 $extraobjects{$name} = $1;
1566 elsif ($line =~ /\/\* \$ExtraBuild: (.*?) \*\//i)
1568 $extrabuildlines{$name} = $1;
1570 elsif ($line =~ /\/\* \$ExtraSources: (.*?) \*\//i)
1572 $extrasources{$name} = $1;
1574 elsif ($line =~ /\/\* \$If: (\w+) \*\//i)
1576 if (defined $config{$1})
1578 if (($config{$1} !~ /y/i) and ($config{$1} ne "1"))
1581 while (defined($line = <CPP>))
1584 die ("\$If buildsystem instruction within another \$If in file $dir/$name") if ($line =~ /\/\* \$If: (\w+) \*\//i);
1585 last if ($line =~ /\/\* \$EndIf \*\//i);
1590 elsif ($line =~ /\/\* \$Install: (.*?) \*\//i)
1592 if (!exists($existing_install_list{$1}))
1594 $existing_install_list{$1} = 1;
1595 my $idir = (split(' ',$1))[1];
1596 my $ifile = (split(' ',$1))[0];
1597 $install_list = $install_list . " -install -m \$(INSTMODE) $1\n";
1598 $ifile =~ s/.*\///g;
1599 $uninstall_list = $uninstall_list . " -rm $idir/$ifile\n";
1602 elsif ($line =~ /\/\* \$CopyInstall: (.*?) \*\//i)
1604 if (!exists($existing_install_list{$1}))
1606 $existing_install_list{$1} = 1;
1607 my $idir = (split(' ',$1))[1];
1608 my $ifile = (split(' ',$1))[0];
1609 $install_list = $install_list . " -cp $1\n";
1610 $ifile =~ s/.*\///g;
1611 $uninstall_list = $uninstall_list . " -rm $idir/$ifile\n";
1618 closedir(DIRHANDLE);
1622 # modes need to be compiled in too
1623 $all_core = $all_core . "modes/modeclasses.a";
1625 my $freebsd4libs = (defined $config{CRAQ} ? $config{CRAQ} : "");
1627 my $libraryext = "";
1628 my $binary_rule = "";
1630 if ($config{IS_DARWIN} eq "YES")
1632 $libraryext = "dylib";
1633 $binary_rule = " \@../make/run-cc.pl \$(CC) -pipe -I../include \$(FLAGS) -c inspircd.cpp\n \@../make/run-cc.pl \$(CC) -pipe -dynamic -bind_at_load -L. -o inspircd \$(LDLIBS) inspircd.o "
1638 $binary_rule = " \@../make/run-cc.pl \$(CC) -pipe -I../include \$(FLAGS) $freebsd4libs -rdynamic -L. inspircd.cpp -o inspircd \$(LDLIBS) ";
1641 open(FH,">src/Makefile") or die("Could not write src/Makefile");
1644 CC = im a cheezeball
1645 CXXFLAGS = -I../include \${FLAGS}
1646 CPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* //' | grep -v svn)
1647 RELCPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* /modes\\//' | grep -v svn)
1651 my $buildstring = "";
1654 foreach my $cpp (sort keys %filelist)
1658 $objs =~ s/\.cpp$/.o/;
1659 if (exists($extraobjects{$cpp}))
1661 $objs = $objs . " " . $extraobjects{$cpp};
1662 $all_core = $all_core . " " . $extraobjects{$cpp};
1664 if (exists($extrasources{$cpp}))
1666 $rawcpp = $rawcpp . " " . $extrasources{$cpp};
1669 $deps = calcdeps("src/$cpp");
1670 if (exists($extrasources{$cpp}))
1672 foreach my $seperate (sort split(' ',$extrasources{$cpp}))
1674 my $d = calcdeps("src/$extrasources{$cpp}") . " ";
1677 $deps = $deps . $d . " ";
1681 $buildstring = $buildstring . $objs . ": $cpp $deps ". (defined($specialdeps{$cpp}) ? $specialdeps{$cpp} : "") . "\n";
1683 if (exists($core_files_list{$cpp}))
1685 # core files are statically linked into the binary and do not require $SHARED shared libs switches
1686 $buildstring = $buildstring . " \@../make/run-cc.pl \$(CC) -pipe -I../include \$(FLAGS) -c $rawcpp\n";
1690 $buildstring = $buildstring . " \@../make/run-cc.pl \$(CC) -pipe -I../include \$(FLAGS) $SHARED -c $rawcpp\n";
1693 if (exists($extrabuildlines{$cpp}))
1695 $buildstring = $buildstring . " " . $extrabuildlines{$cpp} . "\n";
1699 print FH "all: inspircd moo\n\n\n";
1701 $deps = calcdeps("src/inspircd.cpp");
1702 print FH "inspircd: inspircd.cpp $deps $all_core\n";
1703 print FH "$binary_rule $all_core\n\n";
1705 print FH $buildstring;
1706 print FH "moo:\n \@\${MAKE} -C \"commands\" DIRNAME=\"src/commands\" CC=\"\$(CC)\" \$(MAKEARGS)\n\n";
1708 # close main makefile
1712 # generate a list of .so
1713 foreach my $cmd (@cmdlist) {
1714 $cmdobjs = $cmdobjs . "cmd_$cmd.so ";
1717 # and now reopen the commands makefile
1718 open(FH,">src/commands/Makefile") or die("Could not write src/commands/Makefile");
1721 CXXFLAGS = -I../../include \${FLAGS}
1728 # now print the command file detail
1729 foreach my $cmd (@cmdlist) {
1731 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
1732 \@../../make/run-cc.pl \$(CC) -pipe -I../../include \$(FLAGS) $SHARED -o cmd_$cmd.so cmd_$cmd.cpp
1738 # Routine to list out the extra/ modules that have been enabled.
1739 # Note: when getting any filenames out and comparing, it's important to lc it if the
1740 # file system is not case-sensitive (== Epoc, MacOS, OS/2 (incl DOS/DJGPP), VMS, Win32
1741 # (incl NetWare, Symbian)). Cygwin may or may not be case-sensitive, depending on
1742 # configuration, however, File::Spec does not currently tell us (it assumes Unix behavior).
1743 sub list_extras () {
1746 my $srcdir = File::Spec->catdir("src", "modules");
1747 my $abs_srcdir = File::Spec->rel2abs($srcdir);
1750 opendir $dd, File::Spec->catdir($abs_srcdir, "extra") or die (File::Spec->catdir($abs_srcdir, "extra") . ": $!\n");
1751 my @extras = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1754 opendir $dd, $abs_srcdir or die "$abs_srcdir: $!\n";
1755 my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1758 my $maxlen = (sort { $b <=> $a } (map {length($_)} (@extras)))[0];
1760 EXTRA: for my $extra (@extras) {
1761 next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra);
1762 next if ($extra eq '.svn');
1763 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1764 my $abs_source = File::Spec->catfile($abs_srcdir, $extra);
1765 next unless ($extra =~ m/\.(cpp|h)$/ || (-d $abs_extra)); # C++ Source/Header, or directory
1766 if (-l $abs_source) {
1767 # Symlink, is it in the right place?
1768 my $targ = readlink($abs_source);
1769 my $abs_targ = File::Spec->rel2abs($targ, $abs_srcdir);
1770 if ($abs_targ eq $abs_extra) {
1771 $extras{$extra} = "\e[32;1menabled\e[0m";
1773 $extras{$extra} = sprintf("\e[31;1mwrong symlink target (%s)\e[0m", $abs_targ);
1775 } elsif (-e $abs_source) {
1776 my ($devext, $inoext) = stat($abs_extra);
1777 my ($devsrc, $inosrc, undef, $lnksrc) = stat($abs_source);
1779 if ($devsrc == $devext && $inosrc == $inoext) {
1780 $extras{$extra} = "\e[32;1menabled\e[0m";
1782 $extras{$extra} = sprintf("\e[31;1mwrong hardlink target (%d:%d)\e[0m", $devsrc, $inosrc);
1785 open my $extfd, "<", $abs_extra;
1786 open my $srcfd, "<", $abs_source;
1788 if (scalar(<$extfd>) eq scalar(<$srcfd>)) {
1789 $extras{$extra} = "\e[32;1menabled\e[0m";
1791 $extras{$extra} = sprintf("\e[31;1mout of synch (re-copy)\e[0m");
1795 $extras{$extra} = "\e[33;1mdisabled\e[0m";
1798 # Now let's add dependency info
1799 for my $extra (keys(%extras)) {
1800 next unless $extras{$extra} =~ m/enabled/; # only process enabled extras.
1801 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1802 my @deps = split / +/, getdependencies($abs_extra);
1803 for my $dep (@deps) {
1804 if (exists($extras{$dep})) {
1805 my $ref = \$extras{$dep}; # Take reference.
1806 if ($$ref !~ m/needed by/) {
1807 # First dependency found.
1808 if ($$ref =~ m/enabled/) {
1809 $$ref .= " (needed by \e[32;1m$extra\e[0m";
1811 $$ref =~ s/\e\[.*?m//g; # Strip out previous coloring. Will be set in bold+red+blink later.
1812 $$ref .= " (needed by \e[0;32;1;5m$extra\e[0;31;1;5m";
1815 if ($$ref =~ m/enabled/) {
1816 $$ref .= ", \e[32;1m$extra\e[0m";
1818 $$ref .= ", \e[0;32;1;5m$extra\e[0;31;1;5m";
1824 for my $extra (sort {$a cmp $b} keys(%extras)) {
1825 my $text = $extras{$extra};
1826 if ($text =~ m/needed by/ && $text !~ m/enabled/) {
1827 printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? ")" : "");
1829 printf "%-*s = %s%s\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? "\e[0m)" : "");
1832 return keys(%extras) if wantarray; # Can be used by manage_extras.
1835 sub enable_extras (@) {
1837 for my $extra (@extras) {
1838 my $extrapath = "src/modules/extra/$extra";
1839 if (!-e $extrapath) {
1840 print STDERR "Cannot enable \e[32;1m$extra\e[0m : No such file or directory in src/modules/extra\n";
1843 my $source = "src/modules/$extra";
1845 print STDERR "Cannot enable \e[32;1m$extra\e[0m : destination in src/modules exists (might already be enabled?)\n";
1848 # Get dependencies, and add them to be processed.
1849 my @deps = split / +/, getdependencies($extrapath);
1850 for my $dep (@deps) {
1851 next if scalar(grep { $_ eq $dep } (@extras)) > 0; # Skip if we're going to be enabling it anyway.
1852 if (!-e "src/modules/$dep") {
1853 if (-e "src/modules/extra/$dep") {
1854 print STDERR "Will also enable extra \e[32;1m$dep\e[0m (needed by \e[32;1m$extra\e[0m)\n";
1857 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";
1861 print "Enabling $extra ... \n";
1862 symlink "extra/$extra", $source or print STDERR "$source: Cannot link to 'extra/$extra': $!\n";
1866 sub disable_extras (@)
1868 opendir my $dd, "src/modules/extra/";
1869 my @files = readdir($dd);
1872 EXTRA: for my $extra (@extras) {
1873 my $extrapath = "src/modules/extra/$extra";
1874 my $source = "src/modules/$extra";
1875 if (!-e $extrapath) {
1876 print STDERR "Cannot disable \e[32;1m$extra\e[0m : Is not an extra\n";
1879 if ((! -l $source) || readlink($source) ne "extra/$extra") {
1880 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";
1883 # Check if anything needs this.
1884 for my $file (@files) {
1885 my @deps = split / +/, getdependencies("src/modules/extra/$file");
1886 # File depends on this extra...
1887 if (scalar(grep { $_ eq $extra } @deps) > 0) {
1888 # And is both enabled and not about to be disabled.
1889 if (-e "src/modules/$file" && scalar(grep { $_ eq $file } @extras) < 1) {
1890 print STDERR "Cannot disable \e[32;1m$extra\e[0m : is needed by \e[32;1m$file\e[0m\n";
1896 print "Disabling $extra ... \n";
1897 unlink "src/modules/$extra" or print STDERR "Cannot disable \e[32;1m$extra\e[0m : $!\n";