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"))) {
671 $config{HAS_GNUTLS} = "y";
674 $config{HAS_GNUTLS} = "n";
677 printf "Checking for openssl... ";
678 if (defined($config{HAS_OPENSSL}) && (($config{HAS_OPENSSL}) || ($config{HAS_OPENSSL} eq "y"))) {
680 $config{HAS_OPENSSL} = "y";
683 $config{HAS_OPENSSL} = "n";
686 printf "Checking if you are running an ancient, unsupported OS... ";
687 if ($config{OSNAME} =~ /FreeBSD/i)
689 my $version = `uname -r`;
690 if ($version =~ /^4\./)
692 my $foundit = `ls -l /usr/local/lib/libgnugetopt* | wc -l`;
695 # ICKY ICKY ICK, FREEBSD 4.x! GET AN UPGRADE!
696 $config{CRAQ} = "-L/usr/local/lib -lgnugetopt -DHAVE_DECL_GETOPT=1";
701 print "\n\nERROR: You require libgnugetopt (from ports or packages) to build InspIRCd on FreeBSD 4.11.\n";
707 print "no ($version)\n";
713 print "no ($config{OSNAME})\n";
716 ################################################################################
717 # BEGIN INTERACTIVE PART #
718 ################################################################################
723 print "\e[2J\e[0G\e[0d"; # J = Erase in Display, 2 = Entire Screen, (G, d) = Move cursor to (..,..)
726 my $rev = getrevision();
727 # Display Introduction Message..
729 Welcome to the \e[1mInspIRCd\e[0m Configuration program! (\e[1minteractive mode\e[0m)
730 \e[1mPackage maintainers: Type ./configure --help for non-interactive help\e[0m
732 *** If you are unsure of any of these values, leave it blank for ***
733 *** standard settings that will work, and your server will run ***
734 *** using them. Please consult your IRC network admin if in doubt. ***
736 Press \e[1m<RETURN>\e[0m to accept the default for any option, or enter
737 a new value. Please note: You will \e[1mHAVE\e[0m to read the docs
738 dir, otherwise you won't have a config file!
740 Your operating system is: \e[1;32m$config{OSNAME}\e[0m ($wholeos)
741 Your InspIRCd revision ID is \e[1;32mr$rev\e[0m
744 print " (Non-SVN build)";
748 $config{CHANGE_COMPILER} = "n";
749 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";
751 while (($config{GCCVER} < 3) || ($config{GCCVER} eq "")) {
752 print "\e[1;32mIMPORTANT!\e[0m A GCC 2.x compiler has been detected, and
753 should NOT be used. You should probably specify a newer compiler.\n\n";
754 yesno('CHANGE_COMPILER',"Do you want to change the compiler?");
755 if ($config{CHANGE_COMPILER} =~ /y/i) {
756 print "What command do you want to use to invoke your compiler?\n";
757 print "[\e[1;32m$config{CC}\e[0m] -> ";
758 chomp($config{CC} = <STDIN>);
759 if ($config{CC} eq "") {
762 chomp(my $foo = `$config{CC} -dumpversion | cut -c 1`);
764 chomp($config{GCCVER} = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
765 chomp($config{GCCMINOR} = `$config{CC} -dumpversion | cut -c 3`);
766 print "Queried compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.$config{GCCMINOR}\e[0m)\n";
767 if ($config{GCCVER} < 3) {
768 print "\e[1;32mGCC 2.x WILL NOT WORK!\e[0m. Let's try that again, shall we?\n";
772 print "\e[1;32mWARNING!\e[0m Could not execute the compiler you specified. You may want to try again.\n";
779 # Directory Settings..
780 my $tmpbase = $config{BASE_DIR};
781 dir_check("do you wish to install the InspIRCd base", "BASE_DIR");
782 if ($tmpbase ne $config{BASE_DIR}) {
783 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Dir
784 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
785 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
786 $config{LIBRARY_DIR} = resolve_directory($config{BASE_DIR}."/lib"); # Library Directory
789 dir_check("are the configuration files", "CONFIG_DIR");
790 dir_check("are the modules to be compiled to", "MODULE_DIR");
791 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
792 dir_check("are the IRCd libraries to be placed", "LIBRARY_DIR");
795 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?");
799 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?");
803 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?");
806 my $chose_hiperf = (($config{USE_EPOLL} eq "y") || ($config{USE_KQUEUE} eq "y") || ($config{USE_PORTS} eq "y"));
807 if (!$chose_hiperf) {
808 print "No high-performance socket engines are available, or you chose\n";
809 print "not to enable one. Defaulting to select() engine.\n\n";
812 yesno('IPV6',"Would you like to build InspIRCd with IPv6 support?");
815 if ($config{IPV6} eq "y") {
816 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";
817 $config{SUPPORT_IP6LINKS} = "y";
819 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?");
823 $config{USE_FREEBSD_BASE_SSL} = "n";
824 $config{USE_FREEBSD_PORTS_SSL} = "n";
825 if ($config{HAS_OPENSSL_PORT} ne "")
827 $config{USE_FREEBSD_PORTS_SSL} = "y";
828 print "I have detected the OpenSSL FreeBSD port installed on your system,\n";
829 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";
830 yesno('USE_FREEBSD_PORTS_SSL', "Do you want to use the FreeBSD ports version?");
832 $config{USE_FREEBSD_BASE_SSL} = "y" if ($config{USE_FREEBSD_PORTS_SSL} eq "n");
834 if ($config{USE_FREEBSD_BASE_SSL} eq "n")
836 # update to port version
837 $openssl_ver = $config{HAS_OPENSSL_PORT};
842 $config{USE_FREEBSD_BASE_SSL} = "y" if ($^O eq "freebsd");
845 if (($config{HAS_GNUTLS} eq "y") && ($config{HAS_OPENSSL} eq "y")) {
846 print "I have detected both \e[1;32mGnuTLS\e[0m and \e[1;32mOpenSSL\e[0m on your system.\n";
847 print "I will default to GnuTLS. If you wish to use OpenSSL\n";
848 print "instead, you should enable the OpenSSL module yourself\n";
849 print "by copying it from src/modules/extra to src/modules.\n\n";
850 print "Detected GnuTLS version: \e[1;32m" . $gnutls_ver . "\e[0m\n";
851 print "Detected OpenSSL version: \e[1;32m" . $openssl_ver . "\e[0m\n\n";
854 if ($config{HAS_GNUTLS} eq "y") {
855 yesno('USE_GNUTLS', "Would you like to enable SSL Support?");
856 if ($config{USE_GNUTLS} eq "y") {
857 print "\nUsing GnuTLS SSL module.\n";
859 } elsif ($config{HAS_OPENSSL} eq "y") {
860 yesno('USE_OPENSSL', "Would you like to enable SSL Support?");
861 if ($config{USE_OPENSSL} eq "y") {
862 print "\nUsing OpenSSL SSL module.\nYou will get better performance if you move to GnuTLS in the future.\n";
866 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";
872 if (($config{USE_GNUTLS} eq "y") && ($config{HAS_GNUTLS} ne "y"))
874 print "Sorry, but i couldn't detect gnutls. Make sure gnutls-config is in your path.\n";
877 if (($config{USE_OPENSSL} eq "y") && ($config{HAS_OPENSSL} ne "y"))
879 print "Sorry, but i couldn't detect openssl. Make sure openssl is in your path.\n";
884 if ($config{USE_GNUTLS} eq "y") {
885 unless (-r "src/modules/m_ssl_gnutls.cpp") {
886 print "Symlinking src/modules/m_ssl_gnutls.cpp from extra/\n";
887 symlink "extra/m_ssl_gnutls.cpp", "src/modules/m_ssl_gnutls.cpp" or print STDERR "Symlink failed: $!";
892 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
893 print "SSL Certificates Not found, Generating.. \n\n
894 *************************************************************
895 * Generating the Private Key may take some time, go grab a *
896 * Coffee. Even better, to generate some more entropy if it *
897 * is taking a while, open another console and type du / a *
898 * few times and get that HD going :) Then answer the *
899 * Questions which follow. If you are unsure, just hit enter *
900 *************************************************************\n\n";
901 $failed = make_gnutls_cert();
903 print "\n\e[1;32mCertificate generation failed!\e[0m\n\n";
905 print "\nCertificate generation complete, copying to config directory... ";
906 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
907 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
912 print "SSL Certificates found, skipping.\n\n";
917 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
919 } elsif ($config{USE_OPENSSL} eq "y") {
920 unless (-r "src/modules/m_ssl_openssl.cpp") {
921 print "Symlinking src/modules/m_ssl_openssl.cpp from extra/\n";
922 symlink "extra/m_ssl_openssl.cpp", "src/modules/m_ssl_openssl.cpp" or print STDERR "Symlink failed: $!";
928 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
929 print "SSL Certificates Not found, Generating.. \n\n
930 *************************************************************
931 * Generating the certificates may take some time, go grab a *
932 * coffee, or something. *
933 *************************************************************\n\n";
935 print "\nCertificate generation complete, copying to config directory... ";
936 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
937 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
938 File::Copy::move("dhparams.pem", "$config{CONFIG_DIR}/dhparams.pem") or print STDERR "Could not copy dhparams.pem!\n";
941 print "SSL Certificates found, skipping.\n\n"
946 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
949 if (($config{USE_GNUTLS} eq "n") && ($config{USE_OPENSSL} eq "n")) {
950 print "Skipping SSL Certificate generation, SSL support is not available.\n\n";
958 print "To build your server with these settings, please type '\e[1;32m$config{MAKEPROG}\e[0m' now.\n";
959 if (($config{USE_GNUTLS} eq "y") || ($config{USE_OPENSSL} eq "y")) {
960 print "Please note: for \e[1;32mSSL support\e[0m you will need to load required\n";
961 print "modules in your config. This configure script has added those modules to the\n";
962 print "build process. For more info please refer to:\n";
963 print "\e[1;32mhttp://www.inspircd.org/wiki/Installation_From_Tarball\e[0m\n";
965 print "*** \e[1;32mRemember to edit your configuration files!!!\e[0m ***\n\n\n";
966 if (($config{OSNAME} eq "OpenBSD") && ($config{CC} ne "eg++")) {
967 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";
970 if ($config{GCCVER} < "3") {
972 \e[1;32mWARNING!\e[0m You are attempting to compile InspIRCd on GCC 2.x!
973 GCC 2.x series compilers only had partial (read as broken) C++ support, and
974 your compile will most likely fail horribly! If you have any problems, do NOT
975 report them to the bugtracker or forums without first upgrading your compiler
976 to a newer 3.x or 4.x (or whatever is available currently) version.
980 ################################################################################
982 ################################################################################
984 # Retrieves the .config.cache file, and loads values into the main config hash.
985 open(CACHE, ".config.cache") or return 0;
988 # Ignore Blank lines, and comments..
991 my ($key, $value) = split("=", $_, 2);
992 $value =~ /^\"(.*)\"$/;
993 # Do something with data here!
1001 # Dump the contents of %config
1002 print "Writing \e[1;32mcache file\e[0m for future ./configures ...\n";
1003 open(FILEHANDLE, ">.config.cache");
1004 foreach my $key (keys %config) {
1005 print FILEHANDLE "$key=\"$config{$key}\"\n";
1011 my ($desc, $hash_key) = @_;
1013 while (!$complete) {
1014 print "In what directory $desc?\n";
1015 print "[\e[1;32m$config{$hash_key}\e[0m] -> ";
1016 chomp(my $var = <STDIN>);
1018 $var = $config{$hash_key};
1020 if ($var =~ /^\~\/(.+)$/) {
1021 # Convert it to a full path..
1022 $var = resolve_directory($ENV{HOME} . "/" . $1);
1024 elsif ((($config{OSNAME} =~ /MINGW32/i) and ($var !~ /^[A-Z]{1}:\\.*/)) and (substr($var,0,1) ne "/"))
1026 # Assume relative Path was given.. fill in the rest.
1027 $var = $this . "/$var";
1030 $var = resolve_directory($var);
1032 print "$var does not exist. Create it?\n[\e[1;32my\e[0m] ";
1033 chomp(my $tmp = <STDIN>);
1034 if (($tmp eq "") || ($tmp =~ /^y/i)) {
1035 # Attempt to Create the Dir..
1038 File::Path::mkpath($var, 0, 0777);
1041 unless (defined($chk) && -d $var) {
1042 print "Unable to create directory. ($var)\n\n";
1047 # They said they don't want to create, and we can't install there.
1052 if (!is_dir($var)) {
1053 # Target exists, but is not a directory.
1054 print "File $var exists, but is not a directory.\n\n";
1058 # Either Dir Exists, or was created fine.
1059 $config{$hash_key} = $var;
1069 # Beware: Linux sets it's own cflags below for some retarded reason
1070 $config{LDLIBS} = "-pthread -lstdc++";
1071 $config{FLAGS} = "-fPIC -Woverloaded-virtual -Wshadow -Wformat=2 -Wmissing-format-attribute -Wall $config{OPTIMISATI}";
1072 $config{DEVELOPER} = "-fPIC -Woverloaded-virtual -Wshadow -Wall -Wformat=2 -Wmissing-format-attribute -g";
1073 $SHARED = "-shared";
1074 $config{MAKEPROG} = "make";
1076 if ($config{OSNAME} =~ /darwin/i) {
1077 $config{FLAGS} = "-DDARWIN -frtti -fPIC -Wall $config{OPTIMISATI}";
1078 $SHARED = "-bundle -twolevel_namespace -undefined dynamic_lookup";
1079 $config{LDLIBS} = "-ldl -pthread -lstdc++";
1082 if ($config{OSNAME} =~ /OpenBSD/i) {
1083 $config{MAKEPROG} = "gmake";
1084 $config{LDLIBS} = $config{LDLIBS} . " -lunwind";
1085 chomp(my $foo = `eg++ -dumpversion | cut -c 1`);
1086 # theyre running the package version of gcc (eg++)... detect it and set up its version numbers.
1087 # if theyre not running this, configure lets the build continue but they probably wont manage to
1088 # compile as this standard version is 2.95.3!
1090 $config{CC} = "eg++";
1091 chomp($config{GCCVER} = `eg++ -dumpversion | cut -c 1`); # we must redo these if we change the compiler path
1092 chomp($config{GCCMINOR} = `eg++ -dumpversion | cut -c 3`);
1097 if ($config{OSNAME} =~ /Linux/i) {
1098 $config{LDLIBS} = "-ldl -lstdc++ -pthread";
1099 # $config{FLAGS} = "-fPIC -Woverloaded-virtual -Wshadow -Wall $config{OPTIMISATI}";
1100 $config{FLAGS} .= " " . $ENV{CXXFLAGS} if exists($ENV{CXXFLAGS});
1101 $config{LDLIBS} .= " " . $ENV{LDLIBS} if exists($ENV{LDLIBS});
1102 $config{MAKEPROG} = "make";
1105 if ($config{OSNAME} =~ /FreeBSD/i) {
1106 $config{FLAGS} .= " " . $ENV{CXXFLAGS} if exists($ENV{CXXFLAGS});
1107 $config{LDLIBS} .= " " . $ENV{LDLIBS} if exists($ENV{LDLIBS});
1110 if ($config{OSNAME} =~ /SunOS/i or $config{OSNAME} =~ /solaris/i)
1112 # solaris/sunos needs these
1113 # socket = bsd sockets api
1115 # rt = POSIX realtime extensions
1116 # resolv = inet_aton only (why isnt this in nsl?!)
1117 $config{MAKEPROG} = "gmake";
1118 $config{LDLIBS} .= " -lsocket -lnsl -lrt -lresolv -pthread";
1122 if($config{OSNAME} =~ /MINGW32/i)
1124 # All code is position-independent on windows
1125 $config{FLAGS} =~ s/-fPIC //;
1129 return $config{OSNAME};
1132 my ($mliflags, $mfrules, $mobjs, $mfcount) = ("", "", "", 0);
1135 my($writeheader) = @_;
1137 # First File.. inspircd_config.h
1138 chomp(my $incos = `uname -n -s -r`);
1139 chomp(my $version = `sh src/version.sh`);
1140 chomp(my $revision2 = getrevision());
1141 if ($writeheader == 1)
1143 print "Writing \e[1;32minspircd_config.h\e[0m\n";
1144 open(FILEHANDLE, ">include/inspircd_config.h");
1145 print FILEHANDLE <<EOF;
1146 /* Auto generated by configure, do not modify! */
1147 #ifndef __CONFIGURATION_AUTO__
1148 #define __CONFIGURATION_AUTO__
1150 /* this is for windows support. */
1151 #define CoreExport /**/
1152 #define DllExport /**/
1154 #define CONFIG_FILE "$config{CONFIG_DIR}/inspircd.conf"
1155 #define MOD_PATH "$config{MODULE_DIR}"
1156 #define VERSION "$version"
1157 #define REVISION "$revision2"
1158 #define SOMAXCONN_S "$config{_SOMAXCONN}"
1159 #define OPTIMISATION $config{OPTIMITEMP}
1160 #define LIBRARYDIR "$config{LIBRARY_DIR}"
1161 #define SYSTEM "$incos"
1162 #define ENTRYPOINT int main(int argc, char** argv)
1165 print FILEHANDLE "#define MAXBUF " . ($config{MAXBUF}+2) . "\n";
1167 if ($config{OSNAME} =~ /SunOS/i) {
1168 print FILEHANDLE "#define IS_SOLARIS\n";
1170 if ($config{OSNAME} =~ /MINGW32/i) {
1171 print FILEHANDLE "#define IS_MINGW\n";
1173 if ($config{GCCVER} >= 3) {
1174 print FILEHANDLE "#define GCC3\n";
1177 (($config{GCCVER} == 4) && ($config{GCCMINOR} >= 3))
1179 ($config{GCCVER} > 4)
1181 print FILEHANDLE "#define HASHMAP_DEPRECATED\n";
1183 if ($config{HAS_STRLCPY} eq "true") {
1184 print FILEHANDLE "#define HAS_STRLCPY\n";
1186 if ($config{HAS_STDINT} eq "true") {
1187 print FILEHANDLE "#define HAS_STDINT\n";
1189 if ($config{IPV6} =~ /y/i) {
1190 print FILEHANDLE "#define IPV6\n";
1192 if ($config{SUPPORT_IP6LINKS} =~ /y/i) {
1193 print FILEHANDLE "#define SUPPORT_IP6LINKS\n";
1196 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
1197 print FILEHANDLE "#define USE_KQUEUE\n";
1198 $se = "socketengine_kqueue";
1201 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
1202 print FILEHANDLE "#define USE_EPOLL\n";
1203 $se = "socketengine_epoll";
1206 if (($has_ports) && ($config{USE_PORTS} eq "y")) {
1207 print FILEHANDLE "#define USE_PORTS\n";
1208 $se = "socketengine_ports";
1211 # user didn't choose either epoll or select for their OS.
1212 # default them to USE_SELECT (ewwy puke puke)
1214 print FILEHANDLE "#define USE_SELECT\n";
1215 $se = "socketengine_select";
1217 print FILEHANDLE "\n#include \"threadengines/threadengine_pthread.h\"\n\n#endif\n";
1223 open(FILEHANDLE, ">include/inspircd_se_config.h");
1224 print FILEHANDLE <<EOF;
1225 /* Auto generated by configure, do not modify or commit to svn! */
1226 #ifndef __CONFIGURATION_SOCKETENGINE__
1227 #define __CONFIGURATION_SOCKETENGINE__
1229 #include "socketengines/$se.h"
1237 # Create a Modules List..
1239 foreach my $i (@modlist)
1241 $modules .= "m_".$i.".so ";
1243 chomp($modules); # Remove Redundant whitespace..
1245 opendir(DIRHANDLE, "src/modules");
1246 foreach my $name2 (sort readdir(DIRHANDLE)) {
1247 if ($name2 =~ /^m_(.+?)$/) {
1248 if (defined(opendir(MDIRHANDLE, "src/modules/$name2"))) {
1249 closedir(MDIRHANDLE);
1250 $modules .= "$name2.so ";
1251 $uninstall_list = $uninstall_list . " -rm \$(MODULES)/$name2.so\n";
1255 closedir(DIRHANDLE);
1258 # Write all .in files.
1261 my $exe = "inspircd";
1263 # Do this once here, and cache it in the .*.inc files,
1264 # rather than attempting to read src/version.sh from
1265 # compiled code -- we might not have the source to hand.
1266 # Fix for bug#177 by Brain.
1268 chomp($version = `sh ./src/version.sh`);
1269 chomp(my $revision = getrevision());
1270 $version = "$version(r$revision)";
1272 # We can actually parse any file starting with . and ending with .inc,
1273 # but right now we only parse .inspircd.inc to form './inspircd'
1275 print "Writing \e[1;32mMakefiles\e[0m\n";
1276 write_dynamic_modules_makefile();
1277 write_dynamic_makefile();
1279 opendir(DIRHANDLE, $this);
1281 foreach my $name (sort readdir(DIRHANDLE)) {
1282 if ($name =~ /^\.(.+)\.inc$/) {
1285 # Bug #353, omit this on non-darwin
1286 next if (($config{OSNAME} !~ /darwin/) && ($file eq "org.inspircd.plist"));
1288 # All .name.inc files need parsing!
1290 open(FILEHANDLE, ".$file.inc") or die ("Can't open .$file.inc");
1291 while (<FILEHANDLE>) {
1296 print "Writing \e[1;32m$file\e[0m ...\n";
1297 $tmp =~ s/\@CC\@/$config{CC}/ if defined $config{CC};
1298 $tmp =~ s/\@MAKEPROG\@/$config{MAKEPROG}/ if defined $config{MAKEPROG};
1299 $tmp =~ s/\@FLAGS\@/$config{FLAGS}/ if defined $config{FLAGS};
1300 $tmp =~ s/\@DEVELOPER\@/$config{DEVELOPER}/ if defined $config{DEVELOPER};
1301 $tmp =~ s/\@LDLIBS\@/$config{LDLIBS}/ if defined $config{LDLIBS};
1302 $tmp =~ s/\@BASE_DIR\@/$config{BASE_DIR}/ if defined $config{BASE_DIR};
1303 $tmp =~ s/\@CONFIG_DIR\@/$config{CONFIG_DIR}/ if defined $config{CONFIG_DIR};
1304 $tmp =~ s/\@MODULE_DIR\@/$config{MODULE_DIR}/ if defined $config{MODULE_DIR};
1305 $tmp =~ s/\@BINARY_DIR\@/$config{BINARY_DIR}/ if defined $config{BINARY_DIR};
1306 $tmp =~ s/\@LIBRARY_DIR\@/$config{LIBRARY_DIR}/ if defined $config{LIBRARY_DIR};
1307 $tmp =~ s/\@MODULES\@/$modules/ if defined $modules;
1308 $tmp =~ s/\@STARTSCRIPT\@/$config{STARTSCRIPT}/ if defined $config{STARTSCRIPT};
1309 $tmp =~ s/\@DESTINATION\@/$config{DESTINATION}/ if defined $config{DESTINATION};
1310 $tmp =~ s/\@EXTRA_DIR\@/$config{EXTRA_DIR}/ if defined $config{EXTRA_DIR};
1311 $tmp =~ s/\@EXECUTABLE\@/$exe/ if defined $exe;
1312 $tmp =~ s/\@MAKEORDER\@/$config{MAKEORDER}/ if defined $config{MAKEORDER};
1313 $tmp =~ s/\@VERSION\@/$version/ if defined $version;
1314 $tmp =~ s/\@INSTALL_LIST\@/$install_list/ if defined $install_list;
1315 $tmp =~ s/\@UNINSTALL_LIST\@/$uninstall_list/ if defined $uninstall_list;
1317 open(FILEHANDLE, ">$file");
1318 print FILEHANDLE $tmp;
1321 closedir(DIRHANDLE);
1323 # Make inspircd executable!
1324 chmod 0744, 'inspircd';
1327 sub write_dynamic_modules_makefile {
1328 # Modules Makefile..
1329 print "Writing \e[1;32msrc/modules/Makefile\e[0m\n";
1330 open(FILEHANDLE, ">src/modules/Makefile");
1333 # Module Makefile Header
1335 print FILEHANDLE <<EOF;
1336 ###################################################
1337 # Copyright 2002-2007 The InspIRCd Development Team
1338 # http://www.inspircd.org/wiki/index.php/Credits
1340 # Thanks to Andrew Church <achurch\@achurch.org>
1341 # for assisting with making this work right.
1343 # Automatically Generated by ./configure to add a
1344 # modules please run ./configure -modupdate
1345 ###################################################
1351 if ($config{OSNAME} =~ /darwin/) {
1352 print FILEHANDLE <<EOCHEESE;
1354 PICLDFLAGS = -twolevel_namespace -undefined dynamic_lookup -bundle
1358 print FILEHANDLE <<EOCHEESE;
1360 PICLDFLAGS = -fPIC -DPIC -shared
1366 # End Module Makefile Header
1369 # Create a Modules List..
1373 foreach my $i (@modlist) {
1375 # Write Entry to the MakeFile
1377 $cmflags = getcompilerflags("src/modules/m_".$i.".cpp");
1378 $liflags = getlinkerflags("src/modules/m_".$i.".cpp");
1379 my $deps = getdependencies("src/modules/m_".$i.".cpp");
1381 #print "file: $i: cmflags=$cmflags; liflags=$liflags; deps=$deps\n";
1384 if (nopedantic("src/modules/m_".$i.".cpp"))
1387 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
1388 \@../../make/run-cc.pl \$(CC) -pipe -I../../include \$(NICEFLAGS) $cmflags \$(PICLDFLAGS) $liflags -export-dynamic -o m_$i.so m_$i.cpp
1394 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
1395 \@../../make/run-cc.pl \$(CC) -pipe -I../../include \$(FLAGS) $cmflags \$(PICLDFLAGS) $liflags -export-dynamic -o m_$i.so m_$i.cpp
1398 $install_list = $install_list . " install -m \$(INSTMODE) src/modules/m_$i.so \$(MODPATH)\n";
1399 $uninstall_list = $uninstall_list . " -rm \$(MODULES)/m_$i.so\n";
1401 # End Write Entry to the MakeFile
1405 opendir(DIRHANDLE, "src/modules");
1406 foreach my $name (sort readdir(DIRHANDLE)) {
1407 if ($name =~ /^m_(.+?)$/) {
1412 # A module made of multiple files, in a dir, e.g. src/modules/m_spanningtree/
1413 if (defined(opendir(MDIRHANDLE, "src/modules/$name"))) {
1414 read_module_directory("src/modules/$name", $name);
1415 print "Composing Makefile rules for directory \e[1;32m$name\e[0m... (\e[1;32m$mfcount files found\e[0m)\n";
1416 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";
1417 if ($config{IS_DARWIN} eq "YES") {
1418 print FILEHANDLE " \@../../make/run-cc.pl \$(CC) -pipe -twolevel_namespace -undefined dynamic_lookup \$(FLAGS) $mliflags -bundle -o $name.so $mobjs\n";
1420 print FILEHANDLE " \@../../make/run-cc.pl \$(CC) -pipe \$(FLAGS) -shared $mliflags -o $name.so $mobjs\n";
1422 print FILEHANDLE "\n$mfrules\n";
1423 closedir(MDIRHANDLE);
1424 $install_list = $install_list . " install -m \$(INSTMODE) src/modules/$name.so \$(MODPATH)\n";
1428 closedir(DIRHANDLE);
1431 sub read_module_directory {
1432 my ($dpath, $reldpath) = @_;
1434 if (opendir(MDIRHANDLE, $dpath) == 0) {
1438 foreach my $fname (sort readdir(MDIRHANDLE)) {
1439 if ($fname =~ /\.cpp$/) {
1440 my $cmflags = getcompilerflags("$dpath/$fname");
1441 $mliflags = $mliflags . " " . getlinkerflags("$dpath/$fname");
1442 my $deps = getdependencies("$dpath/$fname");
1444 $oname =~ s/\.cpp$/.o/g;
1445 $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";
1446 $mfrules = $mfrules . " \@../../make/run-cc.pl \$(CC) -pipe -I../../include -I. \$(FLAGS) $cmflags -export-dynamic -o $reldpath/$oname -c $reldpath/$fname\n\n";
1447 $mobjs = $mobjs . " $reldpath/$oname";
1450 elsif ((-d "$dpath/$fname") && !($fname eq ".") && !($fname eq "..")) {
1451 read_module_directory($dpath."/".$fname, $reldpath."/".$fname);
1458 # Yes i know we could use gcc -M but it seems to ideneify a lot of 'deep'
1459 # dependencies which are not relevent in C++.
1463 open (CPP, "<$file") or die("Can't open $file for reading!");
1468 foreach my $d (@ignoredeps)
1474 foreach my $dep (@immutabledeps)
1476 $immutable = $immutable . "../include/$dep ";
1478 $immutable =~ s/ $//g;
1480 while (defined(my $line = <CPP>))
1483 if ($line =~ /#include "(.+\.h)"/)
1485 if (!exists($dupe{$1}))
1487 $retlist = $retlist . "../include/$1 ";
1493 return length($immutable) ? $immutable . " " . $retlist : $retlist;
1496 sub write_dynamic_makefile
1500 my %existing_install_list = ();
1501 my %core_files_list = ();
1503 opendir(DIRHANDLE, "src/commands");
1504 foreach my $name (sort readdir(DIRHANDLE))
1506 if ($name =~ /^cmd_(.+)\.cpp$/)
1508 $cmdlist[$i++] = $1;
1509 $install_list = $install_list . " -install -m \$(INSTMODE) src/commands/cmd_" . $1 . ".so \$(LIBPATH)\n";
1510 $uninstall_list = $uninstall_list . " -rm \$(LIBPATH)/cmd_$1.so\n";
1513 closedir(DIRHANDLE);
1517 $config{USE_EPOLL} = 0;
1521 $config{USE_KQUEUE} = 0;
1525 $config{USE_PORTS} = 0;
1528 # formerly generated below this foreach, now it's not! magic.
1531 foreach my $dir (("src","src/commands","src/modes","src/socketengines","src/modules"))
1533 print "Scanning \e[1;32m$dir\e[0m for core files ";
1534 opendir(DIRHANDLE, $dir);
1535 foreach my $name (sort readdir(DIRHANDLE))
1537 if ($name =~ /\.cpp$/)
1539 open (CPP, "<$dir/$name") or die("Can't open $dir/$name to scan it! oh bugger");
1541 while (defined(my $line = <CPP>))
1544 if ($line =~ /\/\* \$Core \*\//i)
1547 $sname =~ s/\.cpp$/.o/;
1549 # append it to list to be built
1550 $all_core = $all_core . $sname . " ";
1551 $filelist{$name} = $sname;
1553 # mark it as a core file, so it won't get shared object cflags
1554 if (!exists($core_files_list{$name}))
1556 $core_files_list{$name} = 1;
1559 elsif ($line =~ /\/\* \$ExtraDeps: (.*?) \*\//i)
1561 $specialdeps{$name} = $1;
1563 elsif ($line =~ /\/\* \$ExtraObjects: (.*?) \*\//i)
1565 $extraobjects{$name} = $1;
1567 elsif ($line =~ /\/\* \$ExtraBuild: (.*?) \*\//i)
1569 $extrabuildlines{$name} = $1;
1571 elsif ($line =~ /\/\* \$ExtraSources: (.*?) \*\//i)
1573 $extrasources{$name} = $1;
1575 elsif ($line =~ /\/\* \$If: (\w+) \*\//i)
1577 if (defined $config{$1})
1579 if (($config{$1} !~ /y/i) and ($config{$1} ne "1"))
1582 while (defined($line = <CPP>))
1585 die ("\$If buildsystem instruction within another \$If in file $dir/$name") if ($line =~ /\/\* \$If: (\w+) \*\//i);
1586 last if ($line =~ /\/\* \$EndIf \*\//i);
1591 elsif ($line =~ /\/\* \$Install: (.*?) \*\//i)
1593 if (!exists($existing_install_list{$1}))
1595 $existing_install_list{$1} = 1;
1596 my $idir = (split(' ',$1))[1];
1597 my $ifile = (split(' ',$1))[0];
1598 $install_list = $install_list . " -install -m \$(INSTMODE) $1\n";
1599 $ifile =~ s/.*\///g;
1600 $uninstall_list = $uninstall_list . " -rm $idir/$ifile\n";
1603 elsif ($line =~ /\/\* \$CopyInstall: (.*?) \*\//i)
1605 if (!exists($existing_install_list{$1}))
1607 $existing_install_list{$1} = 1;
1608 my $idir = (split(' ',$1))[1];
1609 my $ifile = (split(' ',$1))[0];
1610 $install_list = $install_list . " -cp $1\n";
1611 $ifile =~ s/.*\///g;
1612 $uninstall_list = $uninstall_list . " -rm $idir/$ifile\n";
1619 closedir(DIRHANDLE);
1623 # modes need to be compiled in too
1624 $all_core = $all_core . "modes/modeclasses.a";
1626 my $freebsd4libs = (defined $config{CRAQ} ? $config{CRAQ} : "");
1628 my $libraryext = "";
1629 my $binary_rule = "";
1631 if ($config{IS_DARWIN} eq "YES")
1633 $libraryext = "dylib";
1634 $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 "
1639 $binary_rule = " \@../make/run-cc.pl \$(CC) -pipe -I../include \$(FLAGS) $freebsd4libs -rdynamic -L. inspircd.cpp -o inspircd \$(LDLIBS) ";
1642 open(FH,">src/Makefile") or die("Could not write src/Makefile");
1645 CC = im a cheezeball
1646 CXXFLAGS = -I../include \${FLAGS}
1647 CPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* //' | grep -v svn)
1648 RELCPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* /modes\\//' | grep -v svn)
1652 my $buildstring = "";
1655 foreach my $cpp (sort keys %filelist)
1659 $objs =~ s/\.cpp$/.o/;
1660 if (exists($extraobjects{$cpp}))
1662 $objs = $objs . " " . $extraobjects{$cpp};
1663 $all_core = $all_core . " " . $extraobjects{$cpp};
1665 if (exists($extrasources{$cpp}))
1667 $rawcpp = $rawcpp . " " . $extrasources{$cpp};
1670 $deps = calcdeps("src/$cpp");
1671 if (exists($extrasources{$cpp}))
1673 foreach my $seperate (sort split(' ',$extrasources{$cpp}))
1675 my $d = calcdeps("src/$extrasources{$cpp}") . " ";
1678 $deps = $deps . $d . " ";
1682 $buildstring = $buildstring . $objs . ": $cpp $deps ". (defined($specialdeps{$cpp}) ? $specialdeps{$cpp} : "") . "\n";
1684 if (exists($core_files_list{$cpp}))
1686 # core files are statically linked into the binary and do not require -export-dynamic
1687 $buildstring = $buildstring . " \@../make/run-cc.pl \$(CC) -pipe -I../include \$(FLAGS) -c $rawcpp\n";
1691 $buildstring = $buildstring . " \@../make/run-cc.pl \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c $rawcpp\n";
1694 if (exists($extrabuildlines{$cpp}))
1696 $buildstring = $buildstring . " " . $extrabuildlines{$cpp} . "\n";
1700 print FH "all: inspircd moo\n\n\n";
1702 $deps = calcdeps("src/inspircd.cpp");
1703 print FH "inspircd: inspircd.cpp $deps $all_core\n";
1704 print FH "$binary_rule $all_core\n\n";
1706 print FH $buildstring;
1707 print FH "moo:\n \@\${MAKE} -C \"commands\" DIRNAME=\"src/commands\" CC=\"\$(CC)\" \$(MAKEARGS)\n\n";
1709 # close main makefile
1713 # generate a list of .so
1714 foreach my $cmd (@cmdlist) {
1715 $cmdobjs = $cmdobjs . "cmd_$cmd.so ";
1718 # and now reopen the commands makefile
1719 open(FH,">src/commands/Makefile") or die("Could not write src/commands/Makefile");
1722 CXXFLAGS = -I../../include \${FLAGS}
1729 # now print the command file details.
1730 foreach my $cmd (@cmdlist) {
1732 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
1733 \@../../make/run-cc.pl \$(CC) -pipe -I../../include \$(FLAGS) -export-dynamic $SHARED -o cmd_$cmd.so cmd_$cmd.cpp
1739 # Routine to list out the extra/ modules that have been enabled.
1740 # Note: when getting any filenames out and comparing, it's important to lc it if the
1741 # file system is not case-sensitive (== Epoc, MacOS, OS/2 (incl DOS/DJGPP), VMS, Win32
1742 # (incl NetWare, Symbian)). Cygwin may or may not be case-sensitive, depending on
1743 # configuration, however, File::Spec does not currently tell us (it assumes Unix behavior).
1744 sub list_extras () {
1747 my $srcdir = File::Spec->catdir("src", "modules");
1748 my $abs_srcdir = File::Spec->rel2abs($srcdir);
1751 opendir $dd, File::Spec->catdir($abs_srcdir, "extra") or die (File::Spec->catdir($abs_srcdir, "extra") . ": $!\n");
1752 my @extras = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1755 opendir $dd, $abs_srcdir or die "$abs_srcdir: $!\n";
1756 my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1759 my $maxlen = (sort { $b <=> $a } (map {length($_)} (@extras)))[0];
1761 EXTRA: for my $extra (@extras) {
1762 next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra);
1763 next if ($extra eq '.svn');
1764 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1765 my $abs_source = File::Spec->catfile($abs_srcdir, $extra);
1766 next unless ($extra =~ m/\.(cpp|h)$/ || (-d $abs_extra)); # C++ Source/Header, or directory
1767 if (-l $abs_source) {
1768 # Symlink, is it in the right place?
1769 my $targ = readlink($abs_source);
1770 my $abs_targ = File::Spec->rel2abs($targ, $abs_srcdir);
1771 if ($abs_targ eq $abs_extra) {
1772 $extras{$extra} = "\e[32;1menabled\e[0m";
1774 $extras{$extra} = sprintf("\e[31;1mwrong symlink target (%s)\e[0m", $abs_targ);
1776 } elsif (-e $abs_source) {
1777 my ($devext, $inoext) = stat($abs_extra);
1778 my ($devsrc, $inosrc, undef, $lnksrc) = stat($abs_source);
1780 if ($devsrc == $devext && $inosrc == $inoext) {
1781 $extras{$extra} = "\e[32;1menabled\e[0m";
1783 $extras{$extra} = sprintf("\e[31;1mwrong hardlink target (%d:%d)\e[0m", $devsrc, $inosrc);
1786 open my $extfd, "<", $abs_extra;
1787 open my $srcfd, "<", $abs_source;
1789 if (scalar(<$extfd>) eq scalar(<$srcfd>)) {
1790 $extras{$extra} = "\e[32;1menabled\e[0m";
1792 $extras{$extra} = sprintf("\e[31;1mout of synch (re-copy)\e[0m");
1796 $extras{$extra} = "\e[33;1mdisabled\e[0m";
1799 # Now let's add dependency info
1800 for my $extra (keys(%extras)) {
1801 next unless $extras{$extra} =~ m/enabled/; # only process enabled extras.
1802 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1803 my @deps = split / +/, getdependencies($abs_extra);
1804 for my $dep (@deps) {
1805 if (exists($extras{$dep})) {
1806 my $ref = \$extras{$dep}; # Take reference.
1807 if ($$ref !~ m/needed by/) {
1808 # First dependency found.
1809 if ($$ref =~ m/enabled/) {
1810 $$ref .= " (needed by \e[32;1m$extra\e[0m";
1812 $$ref =~ s/\e\[.*?m//g; # Strip out previous coloring. Will be set in bold+red+blink later.
1813 $$ref .= " (needed by \e[0;32;1;5m$extra\e[0;31;1;5m";
1816 if ($$ref =~ m/enabled/) {
1817 $$ref .= ", \e[32;1m$extra\e[0m";
1819 $$ref .= ", \e[0;32;1;5m$extra\e[0;31;1;5m";
1825 for my $extra (sort {$a cmp $b} keys(%extras)) {
1826 my $text = $extras{$extra};
1827 if ($text =~ m/needed by/ && $text !~ m/enabled/) {
1828 printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? ")" : "");
1830 printf "%-*s = %s%s\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? "\e[0m)" : "");
1833 return keys(%extras) if wantarray; # Can be used by manage_extras.
1836 sub enable_extras (@) {
1838 for my $extra (@extras) {
1839 my $extrapath = "src/modules/extra/$extra";
1840 if (!-e $extrapath) {
1841 print STDERR "Cannot enable \e[32;1m$extra\e[0m : No such file or directory in src/modules/extra\n";
1844 my $source = "src/modules/$extra";
1846 print STDERR "Cannot enable \e[32;1m$extra\e[0m : destination in src/modules exists (might already be enabled?)\n";
1849 # Get dependencies, and add them to be processed.
1850 my @deps = split / +/, getdependencies($extrapath);
1851 for my $dep (@deps) {
1852 next if scalar(grep { $_ eq $dep } (@extras)) > 0; # Skip if we're going to be enabling it anyway.
1853 if (!-e "src/modules/$dep") {
1854 if (-e "src/modules/extra/$dep") {
1855 print STDERR "Will also enable extra \e[32;1m$dep\e[0m (needed by \e[32;1m$extra\e[0m)\n";
1858 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";
1862 print "Enabling $extra ... \n";
1863 symlink "extra/$extra", $source or print STDERR "$source: Cannot link to 'extra/$extra': $!\n";
1867 sub disable_extras (@)
1869 opendir my $dd, "src/modules/extra/";
1870 my @files = readdir($dd);
1873 EXTRA: for my $extra (@extras) {
1874 my $extrapath = "src/modules/extra/$extra";
1875 my $source = "src/modules/$extra";
1876 if (!-e $extrapath) {
1877 print STDERR "Cannot disable \e[32;1m$extra\e[0m : Is not an extra\n";
1880 if ((! -l $source) || readlink($source) ne "extra/$extra") {
1881 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";
1884 # Check if anything needs this.
1885 for my $file (@files) {
1886 my @deps = split / +/, getdependencies("src/modules/extra/$file");
1887 # File depends on this extra...
1888 if (scalar(grep { $_ eq $extra } @deps) > 0) {
1889 # And is both enabled and not about to be disabled.
1890 if (-e "src/modules/$file" && scalar(grep { $_ eq $file } @extras) < 1) {
1891 print STDERR "Cannot disable \e[32;1m$extra\e[0m : is needed by \e[32;1m$file\e[0m\n";
1897 print "Disabling $extra ... \n";
1898 unlink "src/modules/$extra" or print STDERR "Cannot disable \e[32;1m$extra\e[0m : $!\n";