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_nick_length,
101 $opt_chan_length, $opt_ports, $opt_epoll, $opt_kqueue, $opt_noports,
102 $opt_noepoll, $opt_nokqueue, $opt_disablerpath, $opt_ipv6, $opt_ipv6links,
103 $opt_noipv6links, $opt_ident, $opt_quit, $opt_topic, $opt_maxbuf, $opt_kick,
104 $opt_gecos, $opt_away, $opt_modes, $opt_disable_debug, $opt_maxchans,
107 our ($opt_cc, $opt_base_dir, $opt_config_dir, $opt_module_dir, $opt_binary_dir,
112 sub enable_extras (@);
114 sub disable_extras (@);
116 my @opt_enableextras;
117 my @opt_disableextras;
120 'enable-gnutls' => \$opt_use_gnutls,
121 'rebuild' => \$opt_rebuild,
122 'enable-openssl' => \$opt_use_openssl,
123 'disable-interactive' => \$opt_nointeractive,
124 'with-nick-length=i' => \$opt_nick_length,
125 'with-channel-length=i' => \$opt_chan_length,
126 'enable-ports' => \$opt_ports,
127 'enable-epoll' => \$opt_epoll,
128 'enable-kqueue' => \$opt_kqueue,
129 'disable-ports' => \$opt_noports,
130 'disable-epoll' => \$opt_noepoll,
131 'disable-kqueue' => \$opt_nokqueue,
132 'disable-rpath' => \$opt_disablerpath,
133 'enable-ipv6' => \$opt_ipv6,
134 'enable-remote-ipv6' => \$opt_ipv6links,
135 'disable-remote-ipv6' => \$opt_noipv6links,
136 'with-cc=s' => \$opt_cc,
137 'with-ident-length=i' => \$opt_ident,
138 'with-quit-length=i' => \$opt_quit,
139 'with-topic-length=i' => \$opt_topic,
140 'with-maxbuf=i' => \$opt_maxbuf,
141 'with-kick-length=i' => \$opt_kick,
142 'with-gecos-length=i' => \$opt_gecos,
143 'with-away-length=i' => \$opt_away,
144 'with-max-modes=i' => \$opt_modes,
145 'prefix=s' => \$opt_base_dir,
146 'config-dir=s' => \$opt_config_dir,
147 'module-dir=s' => \$opt_module_dir,
148 'binary-dir=s' => \$opt_binary_dir,
149 'library-dir=s' => \$opt_library_dir,
150 'disable-debuginfo' => sub { $opt_disable_debug = 1 },
151 'help' => sub { showhelp(); },
152 'modupdate' => sub { modupdate(); },
153 'update' => sub { update(); },
154 'svnupdate' => sub { svnupdate(); },
155 'clean' => sub { clean(); },
156 'list-extras' => sub { list_extras; exit 0; }, # This, --enable-extras, and --disable-extras are for non-interactive managing.
157 'enable-extras=s@' => \@opt_enableextras, # ^
158 'disable-extras=s@' => \@opt_disableextras, # ^
161 if (scalar(@opt_enableextras) + scalar(@opt_disableextras) > 0) {
162 @opt_enableextras = split /,/, join(',', @opt_enableextras);
163 @opt_disableextras = split /,/, join(',', @opt_disableextras);
164 enable_extras(@opt_enableextras);
165 disable_extras(@opt_disableextras);
167 print "Remember: YOU are responsible for making sure any libraries needed have been installed!\n";
168 print "Run $0 -modupdate after you've done this to update the makefiles.\n";
172 our $non_interactive = (
173 (defined $opt_library_dir) ||
174 (defined $opt_base_dir) ||
175 (defined $opt_config_dir) ||
176 (defined $opt_module_dir) ||
177 (defined $opt_base_dir) ||
178 (defined $opt_binary_dir) ||
179 (defined $opt_nointeractive) ||
180 (defined $opt_away) ||
181 (defined $opt_gecos) ||
182 (defined $opt_kick) ||
183 (defined $opt_modes) ||
184 (defined $opt_topic) ||
185 (defined $opt_quit) ||
186 (defined $opt_ident) ||
188 (defined $opt_ipv6) ||
189 (defined $opt_ipv6links) ||
190 (defined $opt_noipv6links) ||
191 (defined $opt_kqueue) ||
192 (defined $opt_epoll) ||
193 (defined $opt_ports) ||
194 (defined $opt_maxchans) ||
195 (defined $opt_opermaxchans) ||
196 (defined $opt_chan_length) ||
197 (defined $opt_nick_length) ||
198 (defined $opt_use_openssl) ||
199 (defined $opt_nokqueue) ||
200 (defined $opt_noepoll) ||
201 (defined $opt_noports) ||
202 (defined $opt_maxbuf) ||
203 (defined $opt_use_gnutls)
205 our $interactive = !$non_interactive;
207 chomp(our $topdir = getcwd());
208 our $this = resolve_directory($topdir); # PWD, Regardless.
209 our @modlist = (); # Declare for Module List..
210 our %config = (); # Initiate Configuration Hash..
211 $config{ME} = resolve_directory($topdir); # Present Working Directory
213 $config{BASE_DIR} = $config{ME};
215 if (defined $opt_base_dir)
217 $config{BASE_DIR} = $opt_base_dir;
220 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Directory
221 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
222 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
223 $config{LIBRARY_DIR} = resolve_directory($config{BASE_DIR}."/lib"); # Library Directory
225 if (defined $opt_config_dir)
227 $config{CONFIG_DIR} = $opt_config_dir;
229 if (defined $opt_module_dir)
231 $config{MODULE_DIR} = $opt_module_dir;
233 if (defined $opt_binary_dir)
235 $config{BINARY_DIR} = $opt_binary_dir;
237 if (defined $opt_library_dir)
239 $config{LIBRARY_DIR} = $opt_library_dir;
241 chomp($config{HAS_GNUTLS} = `libgnutls-config --version 2>/dev/null | cut -c 1,2,3`); # GNUTLS Version.
243 if ($^O eq "freebsd")
245 chomp($config{HAS_OPENSSL} = `openssl version | cut -d ' ' -f 2`); # OpenSSL version, freebsd specific
249 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`); # Openssl version, others
252 chomp(our $gnutls_ver = $config{HAS_GNUTLS});
253 chomp(our $openssl_ver = $config{HAS_OPENSSL});
254 $config{USE_GNUTLS} = "n";
255 if (defined $opt_use_gnutls)
257 $config{USE_GNUTLS} = "y"; # Use gnutls.
259 $config{USE_OPENSSL} = "n"; # Use openssl.
260 if (defined $opt_use_openssl)
262 $config{USE_OPENSSL} = "y";
265 # no, let's not change these.
266 $config{OPTIMITEMP} = "0"; # Default Optimisation Value
267 if (!defined $opt_disable_debug)
269 $config{OPTIMISATI} = "-g1"; # Optimisation Flag
273 $config{OPTIMISATI} = "-O2"; # DEBUGGING OFF!
276 $config{NICK_LENGT} = "31"; # Default Nick Length
277 if (defined $opt_nick_length)
279 $config{NICK_LENGT} = $opt_nick_length;
281 $config{CHAN_LENGT} = "64"; # Default Channel Name Length
282 if (defined $opt_chan_length)
284 $config{CHAN_LENGT} = $opt_chan_length;
286 $config{MAXI_MODES} = "20"; # Default Max. Number of Modes set at once.
287 if (defined $opt_modes)
289 $config{MAXI_MODES} = $opt_modes;
291 $config{HAS_STRLCPY} = "false"; # strlcpy Check.
292 $config{HAS_STDINT} = "false"; # stdint.h check
293 $config{USE_KQUEUE} = "y"; # kqueue enabled
294 if (defined $opt_kqueue)
296 $config{USE_KQUEUE} = "y";
298 if (defined $opt_nokqueue)
300 $config{USE_KQUEUE} = "n";
302 $config{USE_EPOLL} = "y"; # epoll enabled
303 if (defined $opt_epoll)
305 $config{USE_EPOLL} = "y";
307 if (defined $opt_noepoll)
309 $config{USE_EPOLL} = "n";
311 $config{USE_PORTS} = "y"; # epoll enabled
312 if (defined $opt_ports)
314 $config{USE_PORTS} = "y";
316 if (defined $opt_noports)
318 $config{USE_PORTS} = "n";
320 $config{IPV6} = "n"; # IPv6 support (experimental)
321 if (defined $opt_ipv6)
325 $config{SUPPORT_IP6LINKS} = "y"; # IPv4 supporting IPv6 links (experimental)
326 if (defined $opt_ipv6links)
328 $config{SUPPORT_IP6LINKS} = "y";
330 if (defined $opt_noipv6links)
332 $config{SUPPORT_IP6LINKS} = "n";
334 chomp($config{GCCVER} = `g++ -dumpversion | cut -c 1`); # Major GCC Version
335 $config{_SOMAXCONN} = SOMAXCONN; # Max connections in accept queue
336 $config{OSNAME} = $^O; # Operating System Name
337 $config{IS_DARWIN} = "NO"; # Is OSX?
338 $config{STARTSCRIPT} = "inspircd"; # start script?
339 $config{DESTINATION} = "BASE"; # Is target path.
340 $config{EXTRA_DIR} = ""; # Is empty.
341 if ($config{OSNAME} =~ /darwin/i)
343 $config{IS_DARWIN} = "YES";
344 $config{STARTSCRIPT} = "org.inspircd.plist"; # start script for OSX.
345 $config{DESTINATION} = "LAUNCHDPATH"; # Is OSX target.
346 $config{EXTRA_DIR} = " launchd_dir"; # Is OSX specific path.
348 $config{CC} = "g++"; # C++ compiler
351 $config{CC} = $opt_cc;
353 our $exec = $config{CC} . " -dumpversion | cut -c 1";
354 chomp($config{GCCVER} = `$exec`); # Major GCC Version
355 $config{MAKEORDER} = "ircd mods"; # build order
356 $config{MAX_IDENT} = "12"; # max ident size
357 $config{MAX_QUIT} = "255"; # max quit message size
358 $config{MAX_TOPIC} = "307"; # max topic size
359 $config{MAX_KICK} = "255"; # max kick message size
360 $config{MAX_GECOS} = "128"; # max GECOS size
361 $config{MAX_AWAY} = "200"; # max AWAY size
362 $config{MAXBUF} = "512"; # Max buffer size
363 if (defined $opt_ident)
365 $config{MAX_IDENT} = $opt_ident;
367 if (defined $opt_quit)
369 $config{MAX_QUIT} = $opt_quit;
371 if (defined $opt_topic)
373 $config{MAX_TOPIC} = $opt_topic;
375 if (defined $opt_kick)
377 $config{MAX_KICK} = $opt_kick;
379 if (defined $opt_gecos)
381 $config{MAX_GECOS} = $opt_gecos;
383 if (defined $opt_away)
385 $config{MAX_AWAY} = $opt_away;
388 if ($config{HAS_OPENSSL} =~ /^([-[:digit:].]+)([a-z])?(\-[a-z][0-9])?$/) {
389 $config{HAS_OPENSSL} = $1;
391 $config{HAS_OPENSSL} = "";
394 if ($config{GCCVER} eq "") {
395 print $config{CC} . " was not found! You require g++ (the GNU C++ compiler, part of GCC) to build InspIRCd!\n";
399 # Get and Set some important vars..
404 unlink(".config.cache");
407 our ($has_epoll, $has_ports, $has_kqueue) = (0, 0, 0);
412 chomp($topdir = getcwd());
413 $this = resolve_directory($topdir); # PWD, Regardless.
415 # Does the cache file exist?
417 # No, No it doesn't.. *BASH*
418 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
421 # We've Loaded the cache file and all our variables..
422 print "Updating files...\n";
424 if (defined($opt_disable_debug) && $opt_disable_debug == 1)
426 print "Disabling debug information (-g).\n";
427 $config{OPTIMISATI} = "";
430 $has_epoll = $config{HAS_EPOLL};
431 $has_ports = $config{HAS_PORTS};
432 $has_kqueue = $config{HAS_KQUEUE};
441 print "Configure update failed: $@\n";
449 chomp($topdir = getcwd());
450 $this = resolve_directory($topdir); # PWD, Regardless.
452 # Does the cache file exist?
454 # No, No it doesn't.. *BASH*
455 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
458 # We've Loaded the cache file and all our variables..
459 print "Updating files...\n";
461 $has_epoll = $config{HAS_EPOLL};
462 $has_ports = $config{HAS_PORTS};
463 $has_kqueue = $config{HAS_KQUEUE};
472 print "Module update failed: $@\n";
482 open(FH,"<.svn/entries") or $fail = 1;
484 print "This is not an SVN copy of InspIRCd.\n";
491 open my $fd, "-|", "svn update";
492 my $configurechanged = 0; # Needs ./configure -update
493 my $coredirchanged = 0; # Needs ./configure -update
494 my $moduledirchanged = 0; # Needs ./configure -modupdate
495 my $rootincchanged = 0;
497 while (defined(my $line = <$fd>))
501 $line =~ m/^([ADUCG])\s+(.*)$/ or next;
502 ($action, $file) = ($1, $2);
505 push @conflicted, $file;
506 if ($file eq "configure")
508 $configurechanged = 1;
510 elsif ($file =~ m#^src/modules#)
512 $moduledirchanged = 1;
514 elsif ($file =~ m#^src/#)
518 elsif ($file =~ m/^\..*\.inc$/)
523 elsif ($action eq "U" || $action eq "G")
525 if ($file eq "configure")
527 $configurechanged = 1;
529 elsif ($file =~ m/^\..*\.inc$/)
534 elsif ($action eq "A" || $action eq "D")
536 if ($file =~ m#^src/modules#)
538 $moduledirchanged = 1;
540 elsif ($file =~ m#^src/#)
546 unless (close $fd) # close() waits for exit and returns false if the command failed
550 print STDERR "Problem updating from SVN, please check above for errors\n";
554 print STDERR "Failed to run SVN: $!\n";
558 if (scalar(@conflicted) > 0)
560 print STDERR "\e[0;33;1mERROR:\e[0m You have local modifications which conflicted with the updates from SVN\n";
561 printf STDERR "Configure is not able to complete the update. Please resolve these conflicts, then run ./configure -%supdate\n", (($coredirchanged || $configurechanged) ? "" : "mod");
562 print "Conflicted files: " . join ", ", @conflicted . "\n";
565 if ($configurechanged || $coredirchanged)
567 system("perl configure -update");
569 elsif ($moduledirchanged || $rootincchanged)
571 system("perl configure -modupdate");
575 print "No need to update Makefiles.\n";
577 if (defined $opt_rebuild) {
578 system("make install");
583 print "Running non-interactive configure...\n" unless $interactive;
584 print "Checking for cache from previous configure... ";
585 print ((!getcache()) ? "not found\n" : "found\n");
586 print "Checking operating system version... ";
587 print getosflags() . "\n";
589 printf "Checking if stdint.h exists... ";
590 $config{HAS_STDINT} = "true";
592 open(STDINT, "</usr/include/stdint.h") or $config{HAS_STDINT} = "false";
593 if ($config{HAS_STDINT} eq "true") {
596 print "yes\n" if $config{HAS_STDINT} eq "true";
597 print "no\n" if $config{HAS_STDINT} eq "false";
599 printf "Checking if strlcpy exists... ";
600 # Perform the strlcpy() test..
601 $config{HAS_STRLCPY} = "false";
603 open(STRLCPY, "</usr/include/string.h") or $fail = 1;
605 while (defined(my $line = <STRLCPY>)) {
607 # try and find the delcaration of:
608 # size_t strlcpy(...)
609 if ($line =~ /size_t(\0x9|\s)+strlcpy/) {
610 $config{HAS_STRLCPY} = "true";
615 print "yes\n" if $config{HAS_STRLCPY} eq "true";
616 print "no\n" if $config{HAS_STRLCPY} eq "false";
618 printf "Checking if kqueue exists... ";
621 open(KQUEUE, "</usr/include/sys/event.h") or $fail = 1;
623 while (defined(my $line = <KQUEUE>)) {
625 # try and find the delcaration of:
627 if ($line =~ /int(\0x9|\s)+kqueue/) {
633 print "yes\n" if $has_kqueue == 1;
634 print "no\n" if $has_kqueue == 0;
636 printf "Checking if epoll exists... ";
639 open(EPOLL, "</usr/include/sys/epoll.h") or $fail = 1;
645 my $kernel = `uname -r`;
647 if (($kernel =~ /^2\.0\./) || ($kernel =~ /^2\.2\./) || ($kernel =~ /^2\.4\./)) {
652 # Suggestion from nenolod, weed out odd systems which have glibc built
653 # against 2.4 kernels (ick)
654 my $kernel_arch = `uname -p`;
658 if ($kernel_arch =~ /x86_64/) {
659 open (FH,"/lib64/libc.so.6|") or $has_epoll = 0;
662 open (FH,"/lib/libc.so.6|") or $has_epoll = 0;
666 while (defined(my $line = <FH>))
669 if ($line =~ /GNU C Library .* version (.*?) /)
672 $libcv =~ /(\d+\.\d+)/;
675 elsif ($line =~ /Compiled on a Linux (.*?\..*?)\.* system/)
678 # Fix for some retarded libc builds, strip off >> and << etc.
679 $kernelv =~ /(\d+\.\d+)/;
687 printf "libc too old: $libcv... ";
692 printf "libc built against older kernel $kernelv... ";
697 print "yes\n" if $has_epoll == 1;
698 print "no\n" if $has_epoll == 0;
700 printf "Checking if Solaris I/O completion ports are available... ";
702 our $system = `uname -s`;
704 $has_ports = 1 if ($system eq "SunOS");
707 my $kernel = `uname -r`;
709 if (($kernel !~ /^5\.1./)) {
713 print "yes\n" if $has_ports == 1;
714 print "no\n" if $has_ports == 0;
716 $config{HAS_EPOLL} = $has_epoll;
717 $config{HAS_KQUEUE} = $has_kqueue;
719 printf "Checking for libgnutls... ";
720 if (defined($config{HAS_GNUTLS}) && (($config{HAS_GNUTLS}) || ($config{HAS_GNUTLS} eq "y"))) {
722 $config{HAS_GNUTLS} = "y";
725 $config{HAS_GNUTLS} = "n";
728 printf "Checking for openssl... ";
729 if (defined($config{HAS_OPENSSL}) && (($config{HAS_OPENSSL}) || ($config{HAS_OPENSSL} eq "y"))) {
731 $config{HAS_OPENSSL} = "y";
734 $config{HAS_OPENSSL} = "n";
737 printf "Checking if you are running an ancient, unsupported OS... ";
738 if ($config{OSNAME} =~ /FreeBSD/i)
740 my $version = `uname -r`;
741 if ($version =~ /^4\./)
743 my $foundit = `ls -l /usr/local/lib/libgnugetopt* | wc -l`;
746 # ICKY ICKY ICK, FREEBSD 4.x! GET AN UPGRADE!
747 $config{CRAQ} = "-L/usr/local/lib -lgnugetopt -DHAVE_DECL_GETOPT=1";
752 print "\n\nERROR: You require libgnugetopt (from ports or packages) to build InspIRCd on FreeBSD 4.11.\n";
758 print "no ($version)\n";
764 print "no ($config{OSNAME})\n";
767 ################################################################################
768 # BEGIN INTERACTIVE PART #
769 ################################################################################
774 print "\e[2J\e[0G\e[0d"; # J = Erase in Display, 2 = Entire Screen, (G, d) = Move cursor to (..,..)
777 my $rev = getrevision();
778 # Display Introduction Message..
780 Welcome to the \e[1mInspIRCd\e[0m Configuration program! (\e[1minteractive mode\e[0m)
781 \e[1mPackage maintainers: Type ./configure --help for non-interactive help\e[0m
783 *** If you are unsure of any of these values, leave it blank for ***
784 *** standard settings that will work, and your server will run ***
785 *** using them. Please consult your IRC network admin if in doubt. ***
787 Press \e[1m<RETURN>\e[0m to accept the default for any option, or enter
788 a new value. Please note: You will \e[1mHAVE\e[0m to read the docs
789 dir, otherwise you won't have a config file!
791 Your operating system is: \e[1;32m$config{OSNAME}\e[0m ($wholeos)
792 Your InspIRCd revision ID is \e[1;32mr$rev\e[0m
795 print " (Non-SVN build)";
799 $config{CHANGE_COMPILER} = "n";
800 print "I have detected the following compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.x\e[0m)\n";
802 while (($config{GCCVER} < 3) || ($config{GCCVER} eq "")) {
803 print "\e[1;32mIMPORTANT!\e[0m A GCC 2.x compiler has been detected, and
804 should NOT be used. You should probably specify a newer compiler.\n\n";
805 yesno('CHANGE_COMPILER',"Do you want to change the compiler?");
806 if ($config{CHANGE_COMPILER} =~ /y/i) {
807 print "What command do you want to use to invoke your compiler?\n";
808 print "[\e[1;32m$config{CC}\e[0m] -> ";
809 chomp($config{CC} = <STDIN>);
810 if ($config{CC} eq "") {
813 chomp(my $foo = `$config{CC} -dumpversion | cut -c 1`);
815 chomp($config{GCCVER} = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
816 print "Queried compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.x\e[0m)\n";
817 if ($config{GCCVER} < 3) {
818 print "\e[1;32mGCC 2.x WILL NOT WORK!\e[0m. Let's try that again, shall we?\n";
822 print "\e[1;32mWARNING!\e[0m Could not execute the compiler you specified. You may want to try again.\n";
829 # Directory Settings..
830 my $tmpbase = $config{BASE_DIR};
831 dir_check("do you wish to install the InspIRCd base", "BASE_DIR");
832 if ($tmpbase ne $config{BASE_DIR}) {
833 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Dir
834 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
835 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
836 $config{LIBRARY_DIR} = resolve_directory($config{BASE_DIR}."/lib"); # Library Directory
839 dir_check("are the configuration files", "CONFIG_DIR");
840 dir_check("are the modules to be compiled to", "MODULE_DIR");
841 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
842 dir_check("are the IRCd libraries to be placed", "LIBRARY_DIR");
845 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?");
849 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?");
853 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?");
856 my $chose_hiperf = (($config{USE_EPOLL} eq "y") || ($config{USE_KQUEUE} eq "y") || ($config{USE_PORTS} eq "y"));
857 if (!$chose_hiperf) {
858 print "No high-performance socket engines are available, or you chose\n";
859 print "not to enable one. Defaulting to select() engine.\n\n";
862 yesno('IPV6',"Would you like to build InspIRCd with IPv6 support?");
865 if ($config{IPV6} eq "y") {
866 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";
867 $config{SUPPORT_IP6LINKS} = "y";
869 yesno('SUPPORT_IP6LINKS',"You have chosen to build an \e[1;32mIPV4-only\e[0m server.\nWould you like to enable support for linking to IPV6-enabled\nInspIRCd servers?\nIf you are using a recent operating\nsystem and are unsure, answer yes.\nIf you answer 'no' here, your InspIRCd server will be unable\nto parse IPV6 addresses (e.g. for CIDR bans)");
873 if (($config{HAS_GNUTLS} eq "y") && ($config{HAS_OPENSSL} eq "y")) {
874 print "I have detected both \e[1;32mGnuTLS\e[0m and \e[1;32mOpenSSL\e[0m on your system.\n";
875 print "I will default to GnuTLS. If you wish to use OpenSSL\n";
876 print "instead, you should enable the OpenSSL module yourself\n";
877 print "by copying it from src/modules/extra to src/modules.\n\n";
878 print "Detected GnuTLS version: \e[1;32m" . $gnutls_ver . "\e[0m\n";
879 print "Detected OpenSSL version: \e[1;32m" . $openssl_ver . "\e[0m\n\n";
882 if ($config{HAS_GNUTLS} eq "y") {
883 yesno('USE_GNUTLS', "Would you like to enable SSL Support?");
884 if ($config{USE_GNUTLS} eq "y") {
885 print "\nUsing GnuTLS SSL module.\n";
887 } elsif ($config{HAS_OPENSSL} eq "y") {
888 yesno('USE_OPENSSL', "Would you like to enable SSL Support?");
889 if ($config{USE_OPENSSL} eq "y") {
890 print "\nUsing OpenSSL SSL module.\nYou will get better performance if you move to GnuTLS in the future.\n";
894 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";
897 print "\nThe following questions will ask you for various figures relating\n";
898 print "To your IRCd install. Please note that these should usually be left\n";
899 print "as defaults unless you have a real reason to change them. If they\n";
900 print "changed, then the values must be identical on all servers on your\n";
901 print "network, or malfunctions and/or crashes may occur, with the exception\n";
902 print "of the 'maximum number of clients' setting which may be different on\n";
903 print "different servers on the network.\n\n";
905 promptnumeric("length of nicknames", "NICK_LENGT");
906 promptnumeric("length of channel names", "CHAN_LENGT");
907 promptnumeric("number of mode changes in one line", "MAXI_MODES");
908 promptnumeric("length of an ident (username)", "MAX_IDENT");
909 promptnumeric("length of a quit message", "MAX_QUIT");
910 promptnumeric("length of a channel topic", "MAX_TOPIC");
911 promptnumeric("length of a kick message", "MAX_KICK");
912 promptnumeric("length of a GECOS (real name)", "MAX_GECOS");
913 promptnumeric("length of an away message", "MAX_AWAY");
918 if (($config{USE_GNUTLS} eq "y") && ($config{HAS_GNUTLS} ne "y"))
920 print "Sorry, but i couldn't detect gnutls. Make sure gnutls-config is in your path.\n";
923 if (($config{USE_OPENSSL} eq "y") && ($config{HAS_OPENSSL} ne "y"))
925 print "Sorry, but i couldn't detect openssl. Make sure openssl is in your path.\n";
930 if ($config{USE_GNUTLS} eq "y") {
931 unless (-r "src/modules/m_ssl_gnutls.cpp") {
932 print "Symlinking src/modules/m_ssl_gnutls.cpp from extra/\n";
933 symlink "extra/m_ssl_gnutls.cpp", "src/modules/m_ssl_gnutls.cpp" or print STDERR "Symlink failed: $!";
938 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
939 print "SSL Certificates Not found, Generating.. \n\n
940 *************************************************************
941 * Generating the Private Key may take some time, go grab a *
942 * Coffee. Even better, to generate some more entropy if it *
943 * is taking a while, open another console and type du / a *
944 * few times and get that HD going :) Then answer the *
945 * Questions which follow. If you are unsure, just hit enter *
946 *************************************************************\n\n";
947 $failed = make_gnutls_cert();
949 print "\n\e[1;32mCertificate generation failed!\e[0m\n\n";
951 print "\nCertificate generation complete, copying to config directory... ";
952 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
953 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
958 print "SSL Certificates found, skipping.\n\n";
963 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
965 } elsif ($config{USE_OPENSSL} eq "y") {
966 unless (-r "src/modules/m_ssl_openssl.cpp") {
967 print "Symlinking src/modules/m_ssl_openssl.cpp from extra/\n";
968 symlink "extra/m_ssl_openssl.cpp", "src/modules/m_ssl_openssl.cpp" or print STDERR "Symlink failed: $!";
974 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
975 print "SSL Certificates Not found, Generating.. \n\n
976 *************************************************************
977 * Generating the certificates may take some time, go grab a *
978 * coffee, or something. *
979 *************************************************************\n\n";
981 print "\nCertificate generation complete, copying to config directory... ";
982 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
983 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
984 File::Copy::move("dhparams.pem", "$config{CONFIG_DIR}/dhparams.pem") or print STDERR "Could not copy dhparams.pem!\n";
987 print "SSL Certificates found, skipping.\n\n"
992 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
995 if (($config{USE_GNUTLS} eq "n") && ($config{USE_OPENSSL} eq "n")) {
996 print "Skipping SSL Certificate generation, SSL support is not available.\n\n";
1004 print "To build your server with these settings, please type '\e[1;32m$config{MAKEPROG}\e[0m' now.\n";
1005 if (($config{USE_GNUTLS} eq "y") || ($config{USE_OPENSSL} eq "y")) {
1006 print "Please note: for \e[1;32mSSL support\e[0m you will need to load required\n";
1007 print "modules in your config. This configure script has added those modules to the\n";
1008 print "build process. For more info please refer to:\n";
1009 print "\e[1;32mhttp://www.inspircd.org/wiki/Installation_From_Tarball\e[0m\n";
1011 print "*** \e[1;32mRemember to edit your configuration files!!!\e[0m ***\n\n\n";
1012 if (($config{OSNAME} eq "OpenBSD") && ($config{CC} ne "eg++")) {
1013 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";
1016 if ($config{GCCVER} < "3") {
1018 \e[1;32mWARNING!\e[0m You are attempting to compile InspIRCd on GCC 2.x!
1019 GCC 2.x series compilers only had partial (read as broken) C++ support, and
1020 your compile will most likely fail horribly! If you have any problems, do NOT
1021 report them to the bugtracker or forums without first upgrading your compiler
1022 to a newer 3.x or 4.x (or whatever is available currently) version.
1026 ################################################################################
1027 # HELPER FUNCTIONS #
1028 ################################################################################
1030 # Retrieves the .config.cache file, and loads values into the main config hash.
1031 open(CACHE, ".config.cache") or return 0;
1034 # Ignore Blank lines, and comments..
1037 my ($key, $value) = split("=", $_, 2);
1038 $value =~ /^\"(.*)\"$/;
1039 # Do something with data here!
1047 # Dump the contents of %config
1048 print "Writing \e[1;32mcache file\e[0m for future ./configures ...\n";
1049 open(FILEHANDLE, ">.config.cache");
1050 foreach my $key (keys %config) {
1051 print FILEHANDLE "$key=\"$config{$key}\"\n";
1057 my ($desc, $hash_key) = @_;
1059 while (!$complete) {
1060 print "In what directory $desc?\n";
1061 print "[\e[1;32m$config{$hash_key}\e[0m] -> ";
1062 chomp(my $var = <STDIN>);
1064 $var = $config{$hash_key};
1066 if ($var =~ /^\~\/(.+)$/) {
1067 # Convert it to a full path..
1068 $var = resolve_directory($ENV{HOME} . "/" . $1);
1070 elsif ((($config{OSNAME} =~ /MINGW32/i) and ($var !~ /^[A-Z]{1}:\\.*/)) and (substr($var,0,1) ne "/"))
1072 # Assume relative Path was given.. fill in the rest.
1073 $var = $this . "/$var";
1076 $var = resolve_directory($var);
1078 print "$var does not exist. Create it?\n[\e[1;32my\e[0m] ";
1079 chomp(my $tmp = <STDIN>);
1080 if (($tmp eq "") || ($tmp =~ /^y/i)) {
1081 # Attempt to Create the Dir..
1084 File::Path::mkpath($var, 0, 0777);
1087 unless (defined($chk) && -d $var) {
1088 print "Unable to create directory. ($var)\n\n";
1093 # They said they don't want to create, and we can't install there.
1098 if (!is_dir($var)) {
1099 # Target exists, but is not a directory.
1100 print "File $var exists, but is not a directory.\n\n";
1104 # Either Dir Exists, or was created fine.
1105 $config{$hash_key} = $var;
1115 # Beware: Linux sets it's own cflags below for some retarded reason
1116 $config{LDLIBS} = "-pthread -lstdc++";
1117 $config{FLAGS} = "-fPIC -Woverloaded-virtual -Wshadow -Wformat=2 -Wmissing-format-attribute -Wall $config{OPTIMISATI}";
1118 $config{DEVELOPER} = "-fPIC -Woverloaded-virtual -Wshadow -Wall -Wformat=2 -Wmissing-format-attribute -g";
1119 $SHARED = "-Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared" unless defined $opt_disablerpath;
1120 $config{MAKEPROG} = "make";
1122 if ($config{OSNAME} =~ /darwin/i) {
1123 $config{FLAGS} = "-DDARWIN -frtti -fPIC -Wall $config{OPTIMISATI}";
1124 $SHARED = "-bundle -twolevel_namespace -undefined dynamic_lookup";
1125 $config{LDLIBS} = "-ldl -pthread -lstdc++";
1128 if ($config{OSNAME} =~ /OpenBSD/i) {
1129 $config{MAKEPROG} = "gmake";
1130 $config{LDLIBS} = $config{LDLIBS} . " -lunwind";
1131 chomp(my $foo = `eg++ -dumpversion | cut -c 1`);
1132 # theyre running the package version of gcc (eg++)... detect it and set up its version numbers.
1133 # if theyre not running this, configure lets the build continue but they probably wont manage to
1134 # compile as this standard version is 2.95.3!
1136 $config{CC} = "eg++";
1137 chomp($config{GCCVER} = `eg++ -dumpversion | cut -c 1`); # we must redo these if we change the compiler path
1142 if ($config{OSNAME} =~ /Linux/i) {
1143 $config{LDLIBS} = "-ldl -lstdc++ -pthread";
1144 # $config{FLAGS} = "-fPIC -Woverloaded-virtual -Wshadow -Wall $config{OPTIMISATI}";
1145 $config{FLAGS} .= " " . $ENV{CXXFLAGS} if exists($ENV{CXXFLAGS});
1146 $config{LDLIBS} .= " " . $ENV{LDLIBS} if exists($ENV{LDLIBS});
1147 $config{MAKEPROG} = "make";
1150 if ($config{OSNAME} =~ /FreeBSD/i) {
1151 $config{FLAGS} .= " " . $ENV{CXXFLAGS} if exists($ENV{CXXFLAGS});
1152 $config{LDLIBS} .= " " . $ENV{LDLIBS} if exists($ENV{LDLIBS});
1155 if ($config{OSNAME} =~ /SunOS/i or $config{OSNAME} =~ /solaris/i)
1157 # solaris/sunos needs these
1158 # socket = bsd sockets api
1160 # rt = POSIX realtime extensions
1161 # resolv = inet_aton only (why isnt this in nsl?!)
1162 $config{MAKEPROG} = "gmake";
1163 $config{LDLIBS} .= " -lsocket -lnsl -lrt -lresolv -pthread";
1167 if($config{OSNAME} =~ /MINGW32/i)
1169 # All code is position-independent on windows
1170 $config{FLAGS} =~ s/-fPIC //;
1174 return $config{OSNAME};
1177 my ($mliflags, $mfrules, $mobjs, $mfcount) = ("", "", "", 0);
1180 my($writeheader) = @_;
1182 # First File.. inspircd_config.h
1183 chomp(my $incos = `uname -n -s -r`);
1184 chomp(my $version = `sh src/version.sh`);
1185 chomp(my $revision2 = getrevision());
1186 if ($writeheader == 1)
1188 print "Writing \e[1;32minspircd_config.h\e[0m\n";
1189 open(FILEHANDLE, ">include/inspircd_config.h");
1190 my $NL = $config{NICK_LENGT}+1;
1191 my $CL = $config{CHAN_LENGT}+1;
1192 print FILEHANDLE <<EOF;
1193 /* Auto generated by configure, do not modify! */
1194 #ifndef __CONFIGURATION_AUTO__
1195 #define __CONFIGURATION_AUTO__
1197 /* this is for windows support. */
1198 #define CoreExport /**/
1199 #define DllExport /**/
1201 #define CONFIG_FILE "$config{CONFIG_DIR}/inspircd.conf"
1202 #define MOD_PATH "$config{MODULE_DIR}"
1203 #define VERSION "$version"
1204 #define REVISION "$revision2"
1205 #define SOMAXCONN_S "$config{_SOMAXCONN}"
1208 #define MAXMODES $config{MAXI_MODES}
1209 #define IDENTMAX $config{MAX_IDENT}
1210 #define MAXQUIT $config{MAX_QUIT}
1211 #define MAXTOPIC $config{MAX_TOPIC}
1212 #define MAXKICK $config{MAX_KICK}
1213 #define MAXGECOS $config{MAX_GECOS}
1214 #define MAXAWAY $config{MAX_AWAY}
1215 #define OPTIMISATION $config{OPTIMITEMP}
1216 #define LIBRARYDIR "$config{LIBRARY_DIR}"
1217 #define SYSTEM "$incos"
1220 print FILEHANDLE "#define MAXBUF " . ($config{MAXBUF}+2) . "\n";
1222 if ($config{OSNAME} =~ /SunOS/i) {
1223 print FILEHANDLE "#define IS_SOLARIS\n";
1225 if ($config{OSNAME} =~ /MINGW32/i) {
1226 print FILEHANDLE "#define IS_MINGW\n";
1228 if ($config{GCCVER} >= 3) {
1229 print FILEHANDLE "#define GCC3\n";
1231 if ($config{HAS_STRLCPY} eq "true") {
1232 print FILEHANDLE "#define HAS_STRLCPY\n";
1234 if ($config{HAS_STDINT} eq "true") {
1235 print FILEHANDLE "#define HAS_STDINT\n";
1237 if ($config{IPV6} =~ /y/i) {
1238 print FILEHANDLE "#define IPV6\n";
1240 if ($config{SUPPORT_IP6LINKS} =~ /y/i) {
1241 print FILEHANDLE "#define SUPPORT_IP6LINKS\n";
1244 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
1245 print FILEHANDLE "#define USE_KQUEUE\n";
1246 $se = "socketengine_kqueue";
1249 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
1250 print FILEHANDLE "#define USE_EPOLL\n";
1251 $se = "socketengine_epoll";
1254 if (($has_ports) && ($config{USE_PORTS} eq "y")) {
1255 print FILEHANDLE "#define USE_PORTS\n";
1256 $se = "socketengine_ports";
1259 # user didn't choose either epoll or select for their OS.
1260 # default them to USE_SELECT (ewwy puke puke)
1262 print FILEHANDLE "#define USE_SELECT\n";
1263 $se = "socketengine_select";
1265 print FILEHANDLE "\n#include \"threadengines/threadengine_pthread.h\"\n\n#endif\n";
1271 open(FILEHANDLE, ">include/inspircd_se_config.h");
1272 print FILEHANDLE <<EOF;
1273 /* Auto generated by configure, do not modify or commit to svn! */
1274 #ifndef __CONFIGURATION_SOCKETENGINE__
1275 #define __CONFIGURATION_SOCKETENGINE__
1277 #include "socketengines/$se.h"
1285 # Create a Modules List..
1287 foreach my $i (@modlist)
1289 $modules .= "m_".$i.".so ";
1291 chomp($modules); # Remove Redundant whitespace..
1293 opendir(DIRHANDLE, "src/modules");
1294 foreach my $name (sort readdir(DIRHANDLE)) {
1295 if ($name =~ /^m_(.+?)$/) {
1296 if (defined(opendir(MDIRHANDLE, "src/modules/$name"))) {
1297 closedir(MDIRHANDLE);
1298 $modules .= "$name.so ";
1299 $uninstall_list = $uninstall_list . " -rm \$(MODULES)/$name.so\n";
1303 closedir(DIRHANDLE);
1306 # Write all .in files.
1309 my $exe = "inspircd";
1311 # Do this once here, and cache it in the .*.inc files,
1312 # rather than attempting to read src/version.sh from
1313 # compiled code -- we might not have the source to hand.
1314 # Fix for bug#177 by Brain.
1316 chomp($version = `sh ./src/version.sh`);
1317 chomp(my $revision = getrevision());
1318 $version = "$version(r$revision)";
1320 # We can actually parse any file starting with . and ending with .inc,
1321 # but right now we only parse .inspircd.inc to form './inspircd'
1323 print "Writing \e[1;32mMakefiles\e[0m\n";
1324 write_dynamic_modules_makefile();
1325 write_dynamic_makefile();
1327 opendir(DIRHANDLE, $this);
1329 foreach my $name (sort readdir(DIRHANDLE)) {
1330 if ($name =~ /^\.(.+)\.inc$/) {
1333 # Bug #353, omit this on non-darwin
1334 next if (($config{OSNAME} !~ /darwin/) && ($file eq "org.inspircd.plist"));
1336 # All .name.inc files need parsing!
1338 open(FILEHANDLE, ".$file.inc") or die ("Can't open .$file.inc");
1339 while (<FILEHANDLE>) {
1344 print "Writing \e[1;32m$file\e[0m ...\n";
1345 $tmp =~ s/\@CC\@/$config{CC}/ if defined $config{CC};
1346 $tmp =~ s/\@MAKEPROG\@/$config{MAKEPROG}/ if defined $config{MAKEPROG};
1347 $tmp =~ s/\@FLAGS\@/$config{FLAGS}/ if defined $config{FLAGS};
1348 $tmp =~ s/\@DEVELOPER\@/$config{DEVELOPER}/ if defined $config{DEVELOPER};
1349 $tmp =~ s/\@LDLIBS\@/$config{LDLIBS}/ if defined $config{LDLIBS};
1350 $tmp =~ s/\@BASE_DIR\@/$config{BASE_DIR}/ if defined $config{BASE_DIR};
1351 $tmp =~ s/\@CONFIG_DIR\@/$config{CONFIG_DIR}/ if defined $config{CONFIG_DIR};
1352 $tmp =~ s/\@MODULE_DIR\@/$config{MODULE_DIR}/ if defined $config{MODULE_DIR};
1353 $tmp =~ s/\@BINARY_DIR\@/$config{BINARY_DIR}/ if defined $config{BINARY_DIR};
1354 $tmp =~ s/\@LIBRARY_DIR\@/$config{LIBRARY_DIR}/ if defined $config{LIBRARY_DIR};
1355 $tmp =~ s/\@MODULES\@/$modules/ if defined $modules;
1356 $tmp =~ s/\@STARTSCRIPT\@/$config{STARTSCRIPT}/ if defined $config{STARTSCRIPT};
1357 $tmp =~ s/\@DESTINATION\@/$config{DESTINATION}/ if defined $config{DESTINATION};
1358 $tmp =~ s/\@EXTRA_DIR\@/$config{EXTRA_DIR}/ if defined $config{EXTRA_DIR};
1359 $tmp =~ s/\@EXECUTABLE\@/$exe/ if defined $exe;
1360 $tmp =~ s/\@MAKEORDER\@/$config{MAKEORDER}/ if defined $config{MAKEORDER};
1361 $tmp =~ s/\@VERSION\@/$version/ if defined $version;
1362 $tmp =~ s/\@INSTALL_LIST\@/$install_list/ if defined $install_list;
1363 $tmp =~ s/\@UNINSTALL_LIST\@/$uninstall_list/ if defined $uninstall_list;
1365 open(FILEHANDLE, ">$file");
1366 print FILEHANDLE $tmp;
1369 closedir(DIRHANDLE);
1371 # Make inspircd executable!
1372 chmod 0744, 'inspircd';
1375 sub write_dynamic_modules_makefile {
1376 # Modules Makefile..
1377 print "Writing \e[1;32msrc/modules/Makefile\e[0m\n";
1378 open(FILEHANDLE, ">src/modules/Makefile");
1381 # Module Makefile Header
1383 print FILEHANDLE <<EOF;
1384 ###################################################
1385 # Copyright 2002-2007 The InspIRCd Development Team
1386 # http://www.inspircd.org/wiki/index.php/Credits
1388 # Thanks to Andrew Church <achurch\@achurch.org>
1389 # for assisting with making this work right.
1391 # Automatically Generated by ./configure to add a
1392 # modules please run ./configure -modupdate
1393 ###################################################
1399 if ($config{OSNAME} =~ /darwin/) {
1400 print FILEHANDLE <<EOCHEESE;
1402 PICLDFLAGS = -twolevel_namespace -undefined dynamic_lookup -bundle
1406 print FILEHANDLE <<EOCHEESE;
1408 PICLDFLAGS = -fPIC -DPIC -shared
1414 # End Module Makefile Header
1417 # Create a Modules List..
1421 foreach my $i (@modlist) {
1423 # Write Entry to the MakeFile
1425 $cmflags = getcompilerflags("src/modules/m_".$i.".cpp");
1426 $liflags = getlinkerflags("src/modules/m_".$i.".cpp");
1427 my $deps = getdependencies("src/modules/m_".$i.".cpp");
1429 #print "file: $i: cmflags=$cmflags; liflags=$liflags; deps=$deps\n";
1432 if (nopedantic("src/modules/m_".$i.".cpp"))
1435 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
1436 \@../../make/run-cc.pl \$(CC) -pipe -I../../include \$(NICEFLAGS) $cmflags \$(PICLDFLAGS) $liflags -export-dynamic -o m_$i.so m_$i.cpp
1442 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
1443 \@../../make/run-cc.pl \$(CC) -pipe -I../../include \$(FLAGS) $cmflags \$(PICLDFLAGS) $liflags -export-dynamic -o m_$i.so m_$i.cpp
1446 $install_list = $install_list . " install -m \$(INSTMODE) src/modules/m_$i.so \$(MODPATH)\n";
1447 $uninstall_list = $uninstall_list . " -rm \$(MODULES)/m_$i.so\n";
1449 # End Write Entry to the MakeFile
1453 opendir(DIRHANDLE, "src/modules");
1454 foreach my $name (sort readdir(DIRHANDLE)) {
1455 if ($name =~ /^m_(.+?)$/) {
1460 # A module made of multiple files, in a dir, e.g. src/modules/m_spanningtree/
1461 if (defined(opendir(MDIRHANDLE, "src/modules/$name"))) {
1462 read_module_directory("src/modules/$name", $name);
1463 print "Composing Makefile rules for directory \e[1;32m$name\e[0m... (\e[1;32m$mfcount files found\e[0m)\n";
1464 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";
1465 if ($config{IS_DARWIN} eq "YES") {
1466 print FILEHANDLE " \@../../make/run-cc.pl \$(CC) -pipe -twolevel_namespace -undefined dynamic_lookup \$(FLAGS) $mliflags -bundle -o $name.so $mobjs\n";
1468 print FILEHANDLE " \@../../make/run-cc.pl \$(CC) -pipe \$(FLAGS) -shared $mliflags -o $name.so $mobjs\n";
1470 print FILEHANDLE "\n$mfrules\n";
1471 closedir(MDIRHANDLE);
1472 $install_list = $install_list . " install -m \$(INSTMODE) src/modules/$name.so \$(MODPATH)\n";
1476 closedir(DIRHANDLE);
1479 sub read_module_directory {
1480 my ($dpath, $reldpath) = @_;
1482 if (opendir(MDIRHANDLE, $dpath) == 0) {
1486 foreach my $fname (sort readdir(MDIRHANDLE)) {
1487 if ($fname =~ /\.cpp$/) {
1488 my $cmflags = getcompilerflags("$dpath/$fname");
1489 $mliflags = $mliflags . " " . getlinkerflags("$dpath/$fname");
1490 my $deps = getdependencies("$dpath/$fname");
1492 $oname =~ s/\.cpp$/.o/g;
1493 $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";
1494 $mfrules = $mfrules . " \@../../make/run-cc.pl \$(CC) -pipe -I../../include -I. \$(FLAGS) $cmflags -export-dynamic -o $reldpath/$oname -c $reldpath/$fname\n\n";
1495 $mobjs = $mobjs . " $reldpath/$oname";
1498 elsif ((-d "$dpath/$fname") && !($fname eq ".") && !($fname eq "..")) {
1499 read_module_directory($dpath."/".$fname, $reldpath."/".$fname);
1506 # Yes i know we could use gcc -M but it seems to ideneify a lot of 'deep'
1507 # dependencies which are not relevent in C++.
1511 open (CPP, "<$file") or die("Can't open $file for reading!");
1516 foreach my $d (@ignoredeps)
1522 foreach my $dep (@immutabledeps)
1524 $immutable = $immutable . "../include/$dep ";
1526 $immutable =~ s/ $//g;
1528 while (defined(my $line = <CPP>))
1531 if ($line =~ /#include "(.+\.h)"/)
1533 if (!exists($dupe{$1}))
1535 $retlist = $retlist . "../include/$1 ";
1541 return length($immutable) ? $immutable . " " . $retlist : $retlist;
1544 sub write_dynamic_makefile
1548 my %existing_install_list = ();
1549 opendir(DIRHANDLE, "src/commands");
1550 foreach my $name (sort readdir(DIRHANDLE))
1552 if ($name =~ /^cmd_(.+)\.cpp$/)
1554 $cmdlist[$i++] = $1;
1555 $install_list = $install_list . " -install -m \$(INSTMODE) src/commands/cmd_" . $1 . ".so \$(LIBPATH)\n";
1556 $uninstall_list = $uninstall_list . " -rm \$(LIBPATH)/cmd_$1.so\n";
1559 closedir(DIRHANDLE);
1563 $config{USE_EPOLL} = 0;
1567 $config{USE_KQUEUE} = 0;
1571 $config{USE_PORTS} = 0;
1574 foreach my $dir (("src","src/commands","src/modes","src/socketengines","src/modules"))
1576 print "Scanning \e[1;32m$dir\e[0m for core files ";
1577 opendir(DIRHANDLE, $dir);
1578 foreach my $name (sort readdir(DIRHANDLE))
1580 if ($name =~ /\.cpp$/)
1582 open (CPP, "<$dir/$name") or die("Can't open $dir/$name to scan it! oh bugger");
1584 while (defined(my $line = <CPP>))
1587 if ($line =~ /\/\* \$Core: (\w+) \*\//i)
1589 $filelist{$name} = $1;
1591 elsif ($line =~ /\/\* \$ExtraDeps: (.*?) \*\//i)
1593 $specialdeps{$name} = $1;
1595 elsif ($line =~ /\/\* \$ExtraObjects: (.*?) \*\//i)
1597 $extraobjects{$name} = $1;
1599 elsif ($line =~ /\/\* \$ExtraBuild: (.*?) \*\//i)
1601 $extrabuildlines{$name} = $1;
1603 elsif ($line =~ /\/\* \$ExtraSources: (.*?) \*\//i)
1605 $extrasources{$name} = $1;
1607 elsif ($line =~ /\/\* \$If: (\w+) \*\//i)
1609 if (defined $config{$1})
1611 if (($config{$1} !~ /y/i) and ($config{$1} ne "1"))
1614 while (defined($line = <CPP>))
1617 die ("\$If buildsystem instruction within another \$If in file $dir/$name") if ($line =~ /\/\* \$If: (\w+) \*\//i);
1618 last if ($line =~ /\/\* \$EndIf \*\//i);
1623 elsif ($line =~ /\/\* \$Install: (.*?) \*\//i)
1625 if (!exists($existing_install_list{$1}))
1627 $existing_install_list{$1} = 1;
1628 my $idir = (split(' ',$1))[1];
1629 my $ifile = (split(' ',$1))[0];
1630 $install_list = $install_list . " -install -m \$(INSTMODE) $1\n";
1631 $ifile =~ s/.*\///g;
1632 $uninstall_list = $uninstall_list . " -rm $idir/$ifile\n";
1635 elsif ($line =~ /\/\* \$CopyInstall: (.*?) \*\//i)
1637 if (!exists($existing_install_list{$1}))
1639 $existing_install_list{$1} = 1;
1640 my $idir = (split(' ',$1))[1];
1641 my $ifile = (split(' ',$1))[0];
1642 $install_list = $install_list . " -cp $1\n";
1643 $ifile =~ s/.*\///g;
1644 $uninstall_list = $uninstall_list . " -rm $idir/$ifile\n";
1651 closedir(DIRHANDLE);
1655 my $freebsd4libs = (defined $config{CRAQ} ? $config{CRAQ} : "");
1658 my $all_libsonly = "";
1659 my $libraryext = "";
1663 if ($config{IS_DARWIN} eq "YES")
1665 $libraryext = "dylib";
1666 $othercrap = " \@../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 "
1671 $RPATH = "-Wl,--rpath -Wl,$config{LIBRARY_DIR}" unless defined $opt_disablerpath;
1672 $othercrap = " \@../make/run-cc.pl \$(CC) -pipe -I../include $RPATH \$(FLAGS) $freebsd4libs -rdynamic -L. inspircd.cpp -o inspircd \$(LDLIBS) ";
1675 foreach my $cpp (sort keys %filelist)
1677 $all = $all . $filelist{$cpp} . "." . $libraryext . " ";
1678 $all_libsonly = $all_libsonly . $filelist{$cpp} . "." . $libraryext . " ";
1679 $install_list = $install_list . " -install -m \$(INSTMODE) src/" . $filelist{$cpp} . "." . $libraryext . " \$(LIBPATH)\n";
1680 $uninstall_list = $uninstall_list . " -rm \$(LIBPATH)/" . $filelist{$cpp} . "." . $libraryext . "\n";
1682 $all = $all . "moo inspircd\n";
1684 $othercrap = $othercrap . " $all_libsonly\n\n";
1686 open(FH,">src/Makefile") or die("Could not write src/Makefile");
1689 CC = im a cheezeball
1690 CXXFLAGS = -I../include \${FLAGS}
1691 CPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* //' | grep -v svn)
1692 RELCPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* /modes\\//' | grep -v svn)
1696 print FH "$all\n\n";
1698 my $deps = calcdeps("src/inspircd.cpp");
1699 print FH "inspircd: inspircd.cpp $deps $all_libsonly\n";
1700 print FH "$othercrap\n";
1702 foreach my $cpp (sort keys %filelist)
1704 my $thislib = $filelist{$cpp} . "." . $libraryext;
1708 $objs =~ s/\.cpp$/.o/;
1709 if (exists($extraobjects{$cpp}))
1711 $objs = $objs . " " . $extraobjects{$cpp};
1713 if (exists($extrasources{$cpp}))
1715 $rawcpp = $rawcpp . " " . $extrasources{$cpp};
1717 if ($config{IS_DARWIN} eq "YES")
1719 $libcrap = "-install_name " . $config{LIBRARY_DIR} . "/" . $thislib . " -dynamiclib -twolevel_namespace -undefined dynamic_lookup";
1723 if (defined $opt_disablerpath)
1725 $libcrap = " -shared";
1729 $libcrap = "-Wl,--rpath -Wl," . $config{LIBRARY_DIR} . " -shared";
1732 $deps = calcdeps("src/$cpp");
1733 if (exists($extrasources{$cpp}))
1735 foreach my $seperate (sort split(' ',$extrasources{$cpp}))
1737 my $d = calcdeps("src/$extrasources{$cpp}") . " ";
1740 $deps = $deps . $d . " ";
1744 print FH $thislib . ": $cpp $deps ". (defined($specialdeps{$cpp}) ? $specialdeps{$cpp} : "") . "\n";
1745 print FH " \@../make/run-cc.pl \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c $rawcpp\n";
1746 if (exists($extrabuildlines{$cpp}))
1748 print FH " " . $extrabuildlines{$cpp} . "\n";
1750 print FH " \@../make/run-cc.pl \$(CC) -pipe $libcrap -o " . $thislib . " " . $objs . "\n\n";
1753 print FH "moo:\n \@\${MAKE} -C \"commands\" DIRNAME=\"src/commands\" CC=\"\$(CC)\" \$(MAKEARGS)\n\n";
1755 # close main makefile
1759 # generate a list of .so
1760 foreach my $cmd (@cmdlist) {
1761 $cmdobjs = $cmdobjs . "cmd_$cmd.so ";
1764 # and now reopen the commands makefile
1765 open(FH,">src/commands/Makefile") or die("Could not write src/commands/Makefile");
1768 CXXFLAGS = -I../../include \${FLAGS}
1775 # now print the command file details.
1776 foreach my $cmd (@cmdlist) {
1778 cmd_$cmd.so: cmd_$cmd.cpp ../../include/base.h ../../include/modules.h ../../include/inspircd.h ../../include/channels.h ../../include/users.h ../../include/globals.h ../../include/inspircd_config.h ../../include/commands/cmd_$cmd.h
1779 \@../../make/run-cc.pl \$(CC) -pipe -I../../include \$(FLAGS) -export-dynamic $SHARED -o cmd_$cmd.so cmd_$cmd.cpp
1785 # Routine to list out the extra/ modules that have been enabled.
1786 # Note: when getting any filenames out and comparing, it's important to lc it if the
1787 # file system is not case-sensitive (== Epoc, MacOS, OS/2 (incl DOS/DJGPP), VMS, Win32
1788 # (incl NetWare, Symbian)). Cygwin may or may not be case-sensitive, depending on
1789 # configuration, however, File::Spec does not currently tell us (it assumes Unix behavior).
1790 sub list_extras () {
1793 my $srcdir = File::Spec->catdir("src", "modules");
1794 my $abs_srcdir = File::Spec->rel2abs($srcdir);
1797 opendir $dd, File::Spec->catdir($abs_srcdir, "extra") or die (File::Spec->catdir($abs_srcdir, "extra") . ": $!\n");
1798 my @extras = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1801 opendir $dd, $abs_srcdir or die "$abs_srcdir: $!\n";
1802 my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1805 my $maxlen = (sort { $b <=> $a } (map {length($_)} (@extras)))[0];
1807 EXTRA: for my $extra (@extras) {
1808 next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra);
1809 next if ($extra eq '.svn');
1810 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1811 my $abs_source = File::Spec->catfile($abs_srcdir, $extra);
1812 next unless ($extra =~ m/\.(cpp|h)$/ || (-d $abs_extra)); # C++ Source/Header, or directory
1813 if (-l $abs_source) {
1814 # Symlink, is it in the right place?
1815 my $targ = readlink($abs_source);
1816 my $abs_targ = File::Spec->rel2abs($targ, $abs_srcdir);
1817 if ($abs_targ eq $abs_extra) {
1818 $extras{$extra} = "\e[32;1menabled\e[0m";
1820 $extras{$extra} = sprintf("\e[31;1mwrong symlink target (%s)\e[0m", $abs_targ);
1822 } elsif (-e $abs_source) {
1823 my ($devext, $inoext) = stat($abs_extra);
1824 my ($devsrc, $inosrc, undef, $lnksrc) = stat($abs_source);
1826 if ($devsrc == $devext && $inosrc == $inoext) {
1827 $extras{$extra} = "\e[32;1menabled\e[0m";
1829 $extras{$extra} = sprintf("\e[31;1mwrong hardlink target (%d:%d)\e[0m", $devsrc, $inosrc);
1832 open my $extfd, "<", $abs_extra;
1833 open my $srcfd, "<", $abs_source;
1835 if (scalar(<$extfd>) eq scalar(<$srcfd>)) {
1836 $extras{$extra} = "\e[32;1menabled\e[0m";
1838 $extras{$extra} = sprintf("\e[31;1mout of synch (re-copy)\e[0m");
1842 $extras{$extra} = "\e[33;1mdisabled\e[0m";
1845 # Now let's add dependency info
1846 for my $extra (keys(%extras)) {
1847 next unless $extras{$extra} =~ m/enabled/; # only process enabled extras.
1848 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1849 my @deps = split / +/, getdependencies($abs_extra);
1850 for my $dep (@deps) {
1851 if (exists($extras{$dep})) {
1852 my $ref = \$extras{$dep}; # Take reference.
1853 if ($$ref !~ m/needed by/) {
1854 # First dependency found.
1855 if ($$ref =~ m/enabled/) {
1856 $$ref .= " (needed by \e[32;1m$extra\e[0m";
1858 $$ref =~ s/\e\[.*?m//g; # Strip out previous coloring. Will be set in bold+red+blink later.
1859 $$ref .= " (needed by \e[0;32;1;5m$extra\e[0;31;1;5m";
1862 if ($$ref =~ m/enabled/) {
1863 $$ref .= ", \e[32;1m$extra\e[0m";
1865 $$ref .= ", \e[0;32;1;5m$extra\e[0;31;1;5m";
1871 for my $extra (sort {$a cmp $b} keys(%extras)) {
1872 my $text = $extras{$extra};
1873 if ($text =~ m/needed by/ && $text !~ m/enabled/) {
1874 printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? ")" : "");
1876 printf "%-*s = %s%s\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? "\e[0m)" : "");
1879 return keys(%extras) if wantarray; # Can be used by manage_extras.
1882 sub enable_extras (@) {
1884 for my $extra (@extras) {
1885 my $extrapath = "src/modules/extra/$extra";
1886 if (!-e $extrapath) {
1887 print STDERR "Cannot enable \e[32;1m$extra\e[0m : No such file or directory in src/modules/extra\n";
1890 my $source = "src/modules/$extra";
1892 print STDERR "Cannot enable \e[32;1m$extra\e[0m : destination in src/modules exists (might already be enabled?)\n";
1895 # Get dependencies, and add them to be processed.
1896 my @deps = split / +/, getdependencies($extrapath);
1897 for my $dep (@deps) {
1898 next if scalar(grep { $_ eq $dep } (@extras)) > 0; # Skip if we're going to be enabling it anyway.
1899 if (!-e "src/modules/$dep") {
1900 if (-e "src/modules/extra/$dep") {
1901 print STDERR "Will also enable extra \e[32;1m$dep\e[0m (needed by \e[32;1m$extra\e[0m)\n";
1904 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";
1908 print "Enabling $extra ... \n";
1909 symlink "extra/$extra", $source or print STDERR "$source: Cannot link to 'extra/$extra': $!\n";
1913 sub disable_extras (@)
1915 opendir my $dd, "src/modules/extra/";
1916 my @files = readdir($dd);
1919 EXTRA: for my $extra (@extras) {
1920 my $extrapath = "src/modules/extra/$extra";
1921 my $source = "src/modules/$extra";
1922 if (!-e $extrapath) {
1923 print STDERR "Cannot disable \e[32;1m$extra\e[0m : Is not an extra\n";
1926 if ((! -l $source) || readlink($source) ne "extra/$extra") {
1927 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";
1930 # Check if anything needs this.
1931 for my $file (@files) {
1932 my @deps = split / +/, getdependencies("src/modules/extra/$file");
1933 # File depends on this extra...
1934 if (scalar(grep { $_ eq $extra } @deps) > 0) {
1935 # And is both enabled and not about to be disabled.
1936 if (-e "src/modules/$file" && scalar(grep { $_ eq $file } @extras) < 1) {
1937 print STDERR "Cannot disable \e[32;1m$extra\e[0m : is needed by \e[32;1m$file\e[0m\n";
1943 print "Disabling $extra ... \n";
1944 unlink "src/modules/$extra" or print STDERR "Cannot disable \e[32;1m$extra\e[0m : $!\n";