2 ###################################################
3 # InspIRCd Configuration Script
5 # Copyright 2002-2007 The InspIRCd Development Team
6 # http://www.inspircd.org/wiki/index.php/Credits
8 # Licensed under GPL, please see the COPYING file
13 ###################################################
20 use warnings FATAL => qw(all);
24 $Data::Dumper::Sortkeys = 1;
25 $Data::Dumper::Useqq = 1;
34 # Utility functions for our buildsystem
38 use make::opensslcert;
40 ###############################################################################################
44 ###############################################################################################
46 # If you wish to ignore a dependency throughout the entire core, add it here.
49 "inspircd_win32wrapper.h", # windows has its own configure program
52 # If you wish for all files in the entire core to have a given dependency, insert it here.
53 # You should keep this to an absolute minimum to avoid rebuilds that are not neccessary.
55 our @immutabledeps = (
56 "inspircd_config.h", # auto re-generated by configure
60 ###############################################################################################
62 # NON-EDITABLE VARIABLES
64 ###############################################################################################
66 # List of commands that make up 'make install' and 'make deinstall'
68 our $install_list = "";
69 our $uninstall_list = "";
71 # This is a list of all files in the core. Each cpp file is mapped to a shared object file,
72 # whos file extension is omitted (these can vary from system to system). Auto detected by
73 # scanning the src/*.cpp files for files containing /* $Core: */ identifiers.
77 # If you wish for a file to have special dependencies in the makefile, add an entry here.
78 # Auto populated by /* $ExtraDeps: */ instruction
80 our %specialdeps = ();
82 # If you wish for a file to have extra make lines (in between the compile and link steps)
83 # then insert them here.
84 # Auto populated by /* $ExtraBuild: */ instruction
86 our %extrabuildlines = ();
88 # If you wish for a file to be linked against extra objects or arctives, insert them here.
89 # Auto populated by /* $ExtraObjects: */ instruction
91 our %extraobjects = ();
93 # If you wish to compile extra cpp sources into an object, define them here.
94 # NOTE: Certain cpp files such as the socket engines have a value auto calculated
95 # for this table so that their derived class is built.
96 # Auto populated by /* $ExtraSources: */ instruction
98 our %extrasources = ();
100 our ($opt_use_gnutls, $opt_rebuild, $opt_use_openssl, $opt_nointeractive, $opt_nick_length,
101 $opt_chan_length, $opt_maxclients, $opt_ports, $opt_epoll, $opt_kqueue, $opt_noports,
102 $opt_noepoll, $opt_nokqueue, $opt_disablerpath, $opt_ipv6, $opt_ipv6links,
103 $opt_noipv6links, $opt_ident, $opt_quit, $opt_topic, $opt_maxbuf, $opt_kick,
104 $opt_gecos, $opt_away, $opt_modes, $opt_disable_debug, $opt_maxchans,
107 our ($opt_cc, $opt_base_dir, $opt_config_dir, $opt_module_dir, $opt_binary_dir,
112 sub enable_extras (@);
114 sub disable_extras (@);
116 my @opt_enableextras;
117 my @opt_disableextras;
120 'enable-gnutls' => \$opt_use_gnutls,
121 'rebuild' => \$opt_rebuild,
122 'enable-openssl' => \$opt_use_openssl,
123 'disable-interactive' => \$opt_nointeractive,
124 'with-nick-length=i' => \$opt_nick_length,
125 'with-channel-length=i' => \$opt_chan_length,
126 'with-max-clients=i' => \$opt_maxclients,
127 'enable-ports' => \$opt_ports,
128 'enable-epoll' => \$opt_epoll,
129 'enable-kqueue' => \$opt_kqueue,
130 'disable-ports' => \$opt_noports,
131 'disable-epoll' => \$opt_noepoll,
132 'disable-kqueue' => \$opt_nokqueue,
133 'disable-rpath' => \$opt_disablerpath,
134 'enable-ipv6' => \$opt_ipv6,
135 'enable-remote-ipv6' => \$opt_ipv6links,
136 'disable-remote-ipv6' => \$opt_noipv6links,
137 'with-cc=s' => \$opt_cc,
138 'with-ident-length=i' => \$opt_ident,
139 'with-quit-length=i' => \$opt_quit,
140 'with-topic-length=i' => \$opt_topic,
141 'with-maxbuf=i' => \$opt_maxbuf,
142 'with-kick-length=i' => \$opt_kick,
143 'with-gecos-length=i' => \$opt_gecos,
144 'with-away-length=i' => \$opt_away,
145 'with-max-modes=i' => \$opt_modes,
146 'prefix=s' => \$opt_base_dir,
147 'config-dir=s' => \$opt_config_dir,
148 'module-dir=s' => \$opt_module_dir,
149 'binary-dir=s' => \$opt_binary_dir,
150 'library-dir=s' => \$opt_library_dir,
151 'disable-debuginfo' => sub { $opt_disable_debug = 1 },
152 'help' => sub { showhelp(); },
153 'modupdate' => sub { modupdate(); },
154 'update' => sub { update(); },
155 'svnupdate' => sub { svnupdate(); },
156 'clean' => sub { clean(); },
157 'update-root' => sub { update_root() },
158 'list-extras' => sub { list_extras; exit 0; }, # This, --enable-extras, and --disable-extras are for non-interactive managing.
159 'enable-extras=s@' => \@opt_enableextras, # ^
160 'disable-extras=s@' => \@opt_disableextras, # ^
163 if (scalar(@opt_enableextras) + scalar(@opt_disableextras) > 0) {
164 @opt_enableextras = split /,/, join(',', @opt_enableextras);
165 @opt_disableextras = split /,/, join(',', @opt_disableextras);
166 enable_extras(@opt_enableextras);
167 disable_extras(@opt_disableextras);
169 print "Remember: YOU are responsible for making sure any libraries needed have been installed!\n";
170 print "Run $0 -modupdate after you've done this to update the makefiles.\n";
174 our $non_interactive = (
175 (defined $opt_library_dir) ||
176 (defined $opt_base_dir) ||
177 (defined $opt_config_dir) ||
178 (defined $opt_module_dir) ||
179 (defined $opt_base_dir) ||
180 (defined $opt_binary_dir) ||
181 (defined $opt_nointeractive) ||
182 (defined $opt_away) ||
183 (defined $opt_gecos) ||
184 (defined $opt_kick) ||
185 (defined $opt_maxclients) ||
186 (defined $opt_modes) ||
187 (defined $opt_topic) ||
188 (defined $opt_quit) ||
189 (defined $opt_ident) ||
191 (defined $opt_ipv6) ||
192 (defined $opt_ipv6links) ||
193 (defined $opt_noipv6links) ||
194 (defined $opt_kqueue) ||
195 (defined $opt_epoll) ||
196 (defined $opt_ports) ||
197 (defined $opt_maxchans) ||
198 (defined $opt_opermaxchans) ||
199 (defined $opt_chan_length) ||
200 (defined $opt_nick_length) ||
201 (defined $opt_use_openssl) ||
202 (defined $opt_nokqueue) ||
203 (defined $opt_noepoll) ||
204 (defined $opt_noports) ||
205 (defined $opt_maxbuf) ||
206 (defined $opt_use_gnutls)
208 our $interactive = !$non_interactive;
210 chomp(our $topdir = getcwd());
211 our $this = resolve_directory($topdir); # PWD, Regardless.
212 our @modlist = (); # Declare for Module List..
214 our %config = (); # Initiate Configuration Hash..
215 $config{ME} = resolve_directory($topdir); # Present Working Directory
217 $config{BASE_DIR} = $config{ME};
219 if (defined $opt_base_dir)
221 $config{BASE_DIR} = $opt_base_dir;
224 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Directory
225 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
226 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
227 $config{LIBRARY_DIR} = resolve_directory($config{BASE_DIR}."/lib"); # Library Directory
229 if (defined $opt_config_dir)
231 $config{CONFIG_DIR} = $opt_config_dir;
233 if (defined $opt_module_dir)
235 $config{MODULE_DIR} = $opt_module_dir;
237 if (defined $opt_binary_dir)
239 $config{BINARY_DIR} = $opt_binary_dir;
241 if (defined $opt_library_dir)
243 $config{LIBRARY_DIR} = $opt_library_dir;
245 chomp($config{HAS_GNUTLS} = `libgnutls-config --version 2>/dev/null | cut -c 1,2,3`); # GNUTLS Version.
246 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`); # Openssl version
247 chomp(our $gnutls_ver = $config{HAS_GNUTLS});
248 chomp(our $openssl_ver = $config{HAS_OPENSSL});
249 $config{USE_GNUTLS} = "n";
250 if (defined $opt_use_gnutls)
252 $config{USE_GNUTLS} = "y"; # Use gnutls.
254 $config{USE_OPENSSL} = "n"; # Use openssl.
255 if (defined $opt_use_openssl)
257 $config{USE_OPENSSL} = "y";
260 # no, let's not change these.
261 $config{OPTIMITEMP} = "0"; # Default Optimisation Value
262 if (!defined $opt_disable_debug)
264 $config{OPTIMISATI} = "-g1"; # Optimisation Flag
268 $config{OPTIMISATI} = "-O2"; # DEBUGGING OFF!
271 $config{NICK_LENGT} = "31"; # Default Nick Length
272 if (defined $opt_nick_length)
274 $config{NICK_LENGT} = $opt_nick_length;
276 $config{CHAN_LENGT} = "64"; # Default Channel Name Length
277 if (defined $opt_chan_length)
279 $config{CHAN_LENGT} = $opt_chan_length;
281 $config{MAXI_MODES} = "20"; # Default Max. Number of Modes set at once.
282 if (defined $opt_modes)
284 $config{MAXI_MODES} = $opt_modes;
286 $config{HAS_STRLCPY} = "false"; # strlcpy Check.
287 $config{HAS_STDINT} = "false"; # stdint.h check
288 $config{USE_KQUEUE} = "y"; # kqueue enabled
289 if (defined $opt_kqueue)
291 $config{USE_KQUEUE} = "y";
293 if (defined $opt_nokqueue)
295 $config{USE_KQUEUE} = "n";
297 $config{USE_EPOLL} = "y"; # epoll enabled
298 if (defined $opt_epoll)
300 $config{USE_EPOLL} = "y";
302 if (defined $opt_noepoll)
304 $config{USE_EPOLL} = "n";
306 $config{USE_PORTS} = "y"; # epoll enabled
307 if (defined $opt_ports)
309 $config{USE_PORTS} = "y";
311 if (defined $opt_noports)
313 $config{USE_PORTS} = "n";
315 $config{IPV6} = "n"; # IPv6 support (experimental)
316 if (defined $opt_ipv6)
320 $config{SUPPORT_IP6LINKS} = "y"; # IPv4 supporting IPv6 links (experimental)
321 if (defined $opt_ipv6links)
323 $config{SUPPORT_IP6LINKS} = "y";
325 if (defined $opt_noipv6links)
327 $config{SUPPORT_IP6LINKS} = "n";
329 chomp($config{MAX_CLIENT_T} = `sh -c \"ulimit -n\"`); # FD Limit
330 chomp($config{MAX_DESCRIPTORS} = `sh -c \"ulimit -n\"`); # Hard FD Limit
331 chomp($config{GCCVER} = `g++ -dumpversion | cut -c 1`); # Major GCC Version
332 $config{_SOMAXCONN} = SOMAXCONN; # Max connections in accept queue
333 $config{OSNAME} = $^O; # Operating System Name
334 $config{IS_DARWIN} = "NO"; # Is OSX?
335 $config{STARTSCRIPT} = "inspircd"; # start script?
336 $config{DESTINATION} = "BASE"; # Is target path.
337 $config{EXTRA_DIR} = ""; # Is empty.
338 if ($config{OSNAME} =~ /darwin/i)
340 $config{IS_DARWIN} = "YES";
341 $config{STARTSCRIPT} = "org.inspircd.plist"; # start script for OSX.
342 $config{DESTINATION} = "LAUNCHDPATH"; # Is OSX target.
343 $config{EXTRA_DIR} = " launchd_dir"; # Is OSX specific path.
345 $config{CC} = "g++"; # C++ compiler
348 $config{CC} = $opt_cc;
350 our $exec = $config{CC} . " -dumpversion | cut -c 1";
351 chomp($config{GCCVER} = `$exec`); # Major GCC Version
352 $config{MAKEORDER} = "ircd mods"; # build order
353 $config{MAX_IDENT} = "12"; # max ident size
354 $config{MAX_QUIT} = "255"; # max quit message size
355 $config{MAX_TOPIC} = "307"; # max topic size
356 $config{MAX_KICK} = "255"; # max kick message size
357 $config{MAX_GECOS} = "128"; # max GECOS size
358 $config{MAX_AWAY} = "200"; # max AWAY size
359 $config{MAXBUF} = "512"; # Max buffer size
360 if (defined $opt_ident)
362 $config{MAX_IDENT} = $opt_ident;
364 if (defined $opt_quit)
366 $config{MAX_QUIT} = $opt_quit;
368 if (defined $opt_topic)
370 $config{MAX_TOPIC} = $opt_topic;
372 if (defined $opt_kick)
374 $config{MAX_KICK} = $opt_kick;
376 if (defined $opt_gecos)
378 $config{MAX_GECOS} = $opt_gecos;
380 if (defined $opt_away)
382 $config{MAX_AWAY} = $opt_away;
385 if ($config{HAS_OPENSSL} =~ /^([-[:digit:].]+)([a-z])?(\-[a-z][0-9])?$/) {
386 $config{HAS_OPENSSL} = $1;
388 $config{HAS_OPENSSL} = "";
391 if ($config{GCCVER} eq "") {
392 print $config{CC} . " was not found! You require g++ (the GNU C++ compiler, part of GCC) to build InspIRCd!\n";
396 our $fd_scan_fail = "";
397 if (!$config{MAX_CLIENT_T}) {
398 $config{MAX_CLIENT_T} = 1024; # Set a reasonable 'Default'
399 $fd_scan_fail = "true"; # Used Later
402 # Get and Set some important vars..
407 unlink(".config.cache");
410 our ($has_epoll, $has_ports, $has_kqueue) = (0, 0, 0);
415 chomp($topdir = getcwd());
416 $this = resolve_directory($topdir); # PWD, Regardless.
418 # Does the cache file exist?
420 # No, No it doesn't.. *BASH*
421 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
424 print "Updating root files...\n";
426 if (defined($opt_disable_debug) && $opt_disable_debug == 1)
428 print "Disabling debug information (-g).\n";
429 $config{OPTIMISATI} = "";
432 $has_epoll = $config{HAS_EPOLL};
433 $has_ports = $config{HAS_PORTS};
434 $has_kqueue = $config{HAS_KQUEUE};
443 print "Configure update failed: $@\n";
451 chomp($topdir = getcwd());
452 $this = resolve_directory($topdir); # PWD, Regardless.
454 # Does the cache file exist?
456 # No, No it doesn't.. *BASH*
457 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
460 # We've Loaded the cache file and all our variables..
461 print "Updating files...\n";
463 if (defined($opt_disable_debug) && $opt_disable_debug == 1)
465 print "Disabling debug information (-g).\n";
466 $config{OPTIMISATI} = "";
469 $has_epoll = $config{HAS_EPOLL};
470 $has_ports = $config{HAS_PORTS};
471 $has_kqueue = $config{HAS_KQUEUE};
480 print "Configure update failed: $@\n";
488 chomp($topdir = getcwd());
489 $this = resolve_directory($topdir); # PWD, Regardless.
491 # Does the cache file exist?
493 # No, No it doesn't.. *BASH*
494 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
497 # We've Loaded the cache file and all our variables..
498 print "Updating files...\n";
500 $has_epoll = $config{HAS_EPOLL};
501 $has_ports = $config{HAS_PORTS};
502 $has_kqueue = $config{HAS_KQUEUE};
511 print "Module update failed: $@\n";
521 open(FH,"<.svn/entries") or $fail = 1;
523 print "This is not an SVN copy of InspIRCd.\n";
530 system("svn update");
531 system("perl configure -update");
532 if (defined $opt_rebuild) {
533 system("make install");
538 print "Running non-interactive configure...\n" unless $interactive;
539 print "Checking for cache from previous configure... ";
540 print ((!getcache()) ? "not found\n" : "found\n");
541 print "Checking operating system version... ";
542 print getosflags() . "\n";
544 if (defined $opt_maxclients)
546 $config{MAX_CLIENT} = $opt_maxclients;
549 if (!$config{MAX_CLIENT}) {
550 # If the cache hasn't set the max clients, copy the variable of MAX_CLIENT_T, this
551 # allows us to keep _T for testing purposes. (ie. "Are you sure you want to go
552 # higher than the found value" :))
553 $config{MAX_CLIENT} = $config{MAX_CLIENT_T};
556 printf "Checking if stdint.h exists... ";
557 $config{HAS_STDINT} = "true";
559 open(STDINT, "</usr/include/stdint.h") or $config{HAS_STDINT} = "false";
560 if ($config{HAS_STDINT} eq "true") {
563 print "yes\n" if $config{HAS_STDINT} eq "true";
564 print "no\n" if $config{HAS_STDINT} eq "false";
566 printf "Checking if strlcpy exists... ";
567 # Perform the strlcpy() test..
568 $config{HAS_STRLCPY} = "false";
570 open(STRLCPY, "</usr/include/string.h") or $fail = 1;
572 while (defined(my $line = <STRLCPY>)) {
574 # try and find the delcaration of:
575 # size_t strlcpy(...)
576 if ($line =~ /size_t(\0x9|\s)+strlcpy/) {
577 $config{HAS_STRLCPY} = "true";
582 print "yes\n" if $config{HAS_STRLCPY} eq "true";
583 print "no\n" if $config{HAS_STRLCPY} eq "false";
585 printf "Checking if kqueue exists... ";
588 open(KQUEUE, "</usr/include/sys/event.h") or $fail = 1;
590 while (defined(my $line = <KQUEUE>)) {
592 # try and find the delcaration of:
594 if ($line =~ /int(\0x9|\s)+kqueue/) {
600 print "yes\n" if $has_kqueue == 1;
601 print "no\n" if $has_kqueue == 0;
603 printf "Checking if epoll exists... ";
606 open(EPOLL, "</usr/include/sys/epoll.h") or $fail = 1;
612 my $kernel = `uname -r`;
614 if (($kernel =~ /^2\.0\./) || ($kernel =~ /^2\.2\./) || ($kernel =~ /^2\.4\./)) {
619 # Suggestion from nenolod, weed out odd systems which have glibc built
620 # against 2.4 kernels (ick)
621 my $kernel_arch = `uname -p`;
625 if ($kernel_arch =~ /x86_64/) {
626 open (FH,"/lib64/libc.so.6|") or $has_epoll = 0;
629 open (FH,"/lib/libc.so.6|") or $has_epoll = 0;
633 while (defined(my $line = <FH>))
636 if ($line =~ /GNU C Library .* version (.*?) /)
639 $libcv =~ /(\d+\.\d+)/;
642 elsif ($line =~ /Compiled on a Linux (.*?\..*?)\.* system/)
645 # Fix for some retarded libc builds, strip off >> and << etc.
646 $kernelv =~ /(\d+\.\d+)/;
654 printf "libc too old: $libcv... ";
659 printf "libc built against older kernel $kernelv... ";
664 print "yes\n" if $has_epoll == 1;
665 print "no\n" if $has_epoll == 0;
667 printf "Checking if Solaris I/O completion ports are available... ";
669 our $system = `uname -s`;
671 $has_ports = 1 if ($system eq "SunOS");
674 my $kernel = `uname -r`;
676 if (($kernel !~ /^5\.1./)) {
680 print "yes\n" if $has_ports == 1;
681 print "no\n" if $has_ports == 0;
683 $config{HAS_EPOLL} = $has_epoll;
684 $config{HAS_KQUEUE} = $has_kqueue;
686 printf "Checking for libgnutls... ";
687 if (defined($config{HAS_GNUTLS}) && (($config{HAS_GNUTLS}) || ($config{HAS_GNUTLS} eq "y"))) {
689 $config{HAS_GNUTLS} = "y";
692 $config{HAS_GNUTLS} = "n";
695 printf "Checking for openssl... ";
696 if (defined($config{HAS_OPENSSL}) && (($config{HAS_OPENSSL}) || ($config{HAS_OPENSSL} eq "y"))) {
698 $config{HAS_OPENSSL} = "y";
701 $config{HAS_OPENSSL} = "n";
704 printf "Checking if you are running an ancient, unsupported OS... ";
705 if ($config{OSNAME} =~ /FreeBSD/i)
707 my $version = `uname -r`;
708 if ($version =~ /^4\./)
710 my $foundit = `ls -l /usr/local/lib/libgnugetopt* | wc -l`;
713 # ICKY ICKY ICK, FREEBSD 4.x! GET AN UPGRADE!
714 $config{CRAQ} = "-L/usr/local/lib -lgnugetopt -DHAVE_DECL_GETOPT=1";
719 print "\n\nERROR: You require libgnugetopt (from ports or packages) to build InspIRCd on FreeBSD 4.11.\n";
725 print "no ($version)\n";
731 print "no ($config{OSNAME})\n";
734 ################################################################################
735 # BEGIN INTERACTIVE PART #
736 ################################################################################
741 print "\e[2J\e[0G\e[0d"; # J = Erase in Display, 2 = Entire Screen, (G, d) = Move cursor to (..,..)
744 my $rev = getrevision();
745 # Display Introduction Message..
747 Welcome to the \e[1mInspIRCd\e[0m Configuration program! (\e[1minteractive mode\e[0m)
748 \e[1mPackage maintainers: Type ./configure --help for non-interactive help\e[0m
750 *** If you are unsure of any of these values, leave it blank for ***
751 *** standard settings that will work, and your server will run ***
752 *** using them. Please consult your IRC network admin if in doubt. ***
754 Press \e[1m<RETURN>\e[0m to accept the default for any option, or enter
755 a new value. Please note: You will \e[1mHAVE\e[0m to read the docs
756 dir, otherwise you won't have a config file!
758 Your operating system is: \e[1;32m$config{OSNAME}\e[0m ($wholeos)
759 Maximum file descriptors: \e[1;32m$config{MAX_CLIENT_T}\e[0m
760 Your InspIRCd revision ID is \e[1;32mr$rev\e[0m
763 print " (Non-SVN build)";
767 $config{CHANGE_COMPILER} = "n";
768 print "I have detected the following compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.x\e[0m)\n";
770 while (($config{GCCVER} < 3) || ($config{GCCVER} eq "")) {
771 print "\e[1;32mIMPORTANT!\e[0m A GCC 2.x compiler has been detected, and
772 should NOT be used. You should probably specify a newer compiler.\n\n";
773 yesno('CHANGE_COMPILER',"Do you want to change the compiler?");
774 if ($config{CHANGE_COMPILER} =~ /y/i) {
775 print "What command do you want to use to invoke your compiler?\n";
776 print "[\e[1;32m$config{CC}\e[0m] -> ";
777 chomp($config{CC} = <STDIN>);
778 if ($config{CC} eq "") {
781 chomp(my $foo = `$config{CC} -dumpversion | cut -c 1`);
783 chomp($config{GCCVER} = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
784 print "Queried compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.x\e[0m)\n";
785 if ($config{GCCVER} < 3) {
786 print "\e[1;32mGCC 2.x WILL NOT WORK!\e[0m. Let's try that again, shall we?\n";
790 print "\e[1;32mWARNING!\e[0m Could not execute the compiler you specified. You may want to try again.\n";
797 # Directory Settings..
798 my $tmpbase = $config{BASE_DIR};
799 dir_check("do you wish to install the InspIRCd base", "BASE_DIR");
800 if ($tmpbase ne $config{BASE_DIR}) {
801 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Dir
802 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
803 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
804 $config{LIBRARY_DIR} = resolve_directory($config{BASE_DIR}."/lib"); # Library Directory
807 dir_check("are the configuration files", "CONFIG_DIR");
808 dir_check("are the modules to be compiled to", "MODULE_DIR");
809 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
810 dir_check("are the IRCd libraries to be placed", "LIBRARY_DIR");
813 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?");
817 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?");
821 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?");
824 my $chose_hiperf = (($config{USE_EPOLL} eq "y") || ($config{USE_KQUEUE} eq "y") || ($config{USE_PORTS} eq "y"));
825 if (!$chose_hiperf) {
826 print "No high-performance socket engines are available, or you chose\n";
827 print "not to enable one. Defaulting to select() engine.\n\n";
830 yesno('IPV6',"Would you like to build InspIRCd with IPv6 support?");
833 if ($config{IPV6} eq "y") {
834 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";
835 $config{SUPPORT_IP6LINKS} = "y";
837 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)");
841 if (($config{HAS_GNUTLS} eq "y") && ($config{HAS_OPENSSL} eq "y")) {
842 print "I have detected both \e[1;32mGnuTLS\e[0m and \e[1;32mOpenSSL\e[0m on your system.\n";
843 print "I will default to GnuTLS. If you wish to use OpenSSL\n";
844 print "instead, you should enable the OpenSSL module yourself\n";
845 print "by copying it from src/modules/extra to src/modules.\n\n";
846 print "Detected GnuTLS version: \e[1;32m" . $gnutls_ver . "\e[0m\n";
847 print "Detected OpenSSL version: \e[1;32m" . $openssl_ver . "\e[0m\n\n";
850 if ($config{HAS_GNUTLS} eq "y") {
851 yesno('USE_GNUTLS', "Would you like to enable SSL Support?");
852 if ($config{USE_GNUTLS} eq "y") {
853 print "\nUsing GnuTLS SSL module.\n";
855 } elsif ($config{HAS_OPENSSL} eq "y") {
856 yesno('USE_OPENSSL', "Would you like to enable SSL Support?");
857 if ($config{USE_OPENSSL} eq "y") {
858 print "\nUsing OpenSSL SSL module.\nYou will get better performance if you move to GnuTLS in the future.\n";
862 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";
865 print "\nThe following questions will ask you for various figures relating\n";
866 print "To your IRCd install. Please note that these should usually be left\n";
867 print "as defaults unless you have a real reason to change them. If they\n";
868 print "changed, then the values must be identical on all servers on your\n";
869 print "network, or malfunctions and/or crashes may occur, with the exception\n";
870 print "of the 'maximum number of clients' setting which may be different on\n";
871 print "different servers on the network.\n\n";
873 # File Descriptor Settings..
874 promptnumeric("number of clients at any one time", "MAX_CLIENT_T");
875 $config{MAX_CLIENT} = $config{MAX_CLIENT_T};
876 $config{MAX_DESCRIPTORS} = $config{MAX_CLIENT_T};
878 promptnumeric("length of nicknames", "NICK_LENGT");
879 promptnumeric("length of channel names", "CHAN_LENGT");
880 promptnumeric("number of mode changes in one line", "MAXI_MODES");
881 promptnumeric("length of an ident (username)", "MAX_IDENT");
882 promptnumeric("length of a quit message", "MAX_QUIT");
883 promptnumeric("length of a channel topic", "MAX_TOPIC");
884 promptnumeric("length of a kick message", "MAX_KICK");
885 promptnumeric("length of a GECOS (real name)", "MAX_GECOS");
886 promptnumeric("length of an away message", "MAX_AWAY");
891 if (($config{USE_GNUTLS} eq "y") && ($config{HAS_GNUTLS} ne "y"))
893 print "Sorry, but i couldn't detect gnutls. Make sure gnutls-config is in your path.\n";
896 if (($config{USE_OPENSSL} eq "y") && ($config{HAS_OPENSSL} ne "y"))
898 print "Sorry, but i couldn't detect openssl. Make sure openssl is in your path.\n";
903 if ($config{USE_GNUTLS} eq "y") {
904 unless (-r "src/modules/m_ssl_gnutls.cpp") {
905 print "Symlinking src/modules/m_ssl_gnutls.cpp from extra/\n";
906 symlink "extra/m_ssl_gnutls.cpp", "src/modules/m_ssl_gnutls.cpp" or print STDERR "Symlink failed: $!";
911 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
912 print "SSL Certificates Not found, Generating.. \n\n
913 *************************************************************
914 * Generating the Private Key may take some time, go grab a *
915 * Coffee. Even better, to generate some more entropy if it *
916 * is taking a while, open another console and type du / a *
917 * few times and get that HD going :) Then answer the *
918 * Questions which follow. If you are unsure, just hit enter *
919 *************************************************************\n\n";
920 $failed = make_gnutls_cert();
922 print "\n\e[1;32mCertificate generation failed!\e[0m\n\n";
924 print "\nCertificate generation complete, copying to config directory... ";
925 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
926 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
931 print "SSL Certificates found, skipping.\n\n";
936 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
938 } elsif ($config{USE_OPENSSL} eq "y") {
939 unless (-r "src/modules/m_ssl_openssl.cpp") {
940 print "Symlinking src/modules/m_ssl_openssl.cpp from extra/\n";
941 symlink "extra/m_ssl_openssl.cpp", "src/modules/m_ssl_openssl.cpp" or print STDERR "Symlink failed: $!";
947 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
948 print "SSL Certificates Not found, Generating.. \n\n
949 *************************************************************
950 * Generating the certificates may take some time, go grab a *
951 * coffee, or something. *
952 *************************************************************\n\n";
954 print "\nCertificate generation complete, copying to config directory... ";
955 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
956 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
957 File::Copy::move("dhparams.pem", "$config{CONFIG_DIR}/dhparams.pem") or print STDERR "Could not copy dhparams.pem!\n";
960 print "SSL Certificates found, skipping.\n\n"
965 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
968 if (($config{USE_GNUTLS} eq "n") && ($config{USE_OPENSSL} eq "n")) {
969 print "Skipping SSL Certificate generation, SSL support is not available.\n\n";
977 print "To build your server with these settings, please type '\e[1;32m$config{MAKEPROG}\e[0m' now.\n";
978 if (($config{USE_GNUTLS} eq "y") || ($config{USE_OPENSSL} eq "y")) {
979 print "Please note: for \e[1;32mSSL support\e[0m you will need to load required\n";
980 print "modules in your config. This configure script has added those modules to the\n";
981 print "build process. For more info please refer to:\n";
982 print "\e[1;32mhttp://www.inspircd.org/wiki/Installation_From_Tarball\e[0m\n";
984 print "*** \e[1;32mRemember to edit your configuration files!!!\e[0m ***\n\n\n";
985 if (($config{OSNAME} eq "OpenBSD") && ($config{CC} ne "eg++")) {
986 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";
989 if ($config{GCCVER} < "3") {
991 \e[1;32mWARNING!\e[0m You are attempting to compile InspIRCd on GCC 2.x!
992 GCC 2.x series compilers only had partial (read as broken) C++ support, and
993 your compile will most likely fail horribly! If you have any problems, do NOT
994 report them to the bugtracker or forums without first upgrading your compiler
995 to a newer 3.x or 4.x (or whatever is available currently) version.
999 ################################################################################
1000 # HELPER FUNCTIONS #
1001 ################################################################################
1003 # Retrieves the .config.cache file, and loads values into the main config hash.
1004 open(CACHE, ".config.cache") or return 0;
1007 # Ignore Blank lines, and comments..
1010 my ($key, $value) = split("=", $_, 2);
1011 $value =~ /^\"(.*)\"$/;
1012 # Do something with data here!
1020 # Dump the contents of %config
1021 print "Writing \e[1;32mcache file\e[0m for future ./configures ...\n";
1022 open(FILEHANDLE, ">.config.cache");
1023 foreach my $key (keys %config) {
1024 print FILEHANDLE "$key=\"$config{$key}\"\n";
1030 my ($desc, $hash_key) = @_;
1032 while (!$complete) {
1033 print "In what directory $desc?\n";
1034 print "[\e[1;32m$config{$hash_key}\e[0m] -> ";
1035 chomp(my $var = <STDIN>);
1037 $var = $config{$hash_key};
1039 if ($var =~ /^\~\/(.+)$/) {
1040 # Convert it to a full path..
1041 $var = resolve_directory($ENV{HOME} . "/" . $1);
1043 elsif ((($config{OSNAME} =~ /MINGW32/i) and ($var !~ /^[A-Z]{1}:\\.*/)) and (substr($var,0,1) ne "/"))
1045 # Assume relative Path was given.. fill in the rest.
1046 $var = $this . "/$var";
1049 $var = resolve_directory($var);
1051 print "$var does not exist. Create it?\n[\e[1;32my\e[0m] ";
1052 chomp(my $tmp = <STDIN>);
1053 if (($tmp eq "") || ($tmp =~ /^y/i)) {
1054 # Attempt to Create the Dir..
1057 File::Path::mkpath($var, 0, 0777);
1060 unless (defined($chk) && -d $var) {
1061 print "Unable to create directory. ($var)\n\n";
1066 # They said they don't want to create, and we can't install there.
1071 if (!is_dir($var)) {
1072 # Target exists, but is not a directory.
1073 print "File $var exists, but is not a directory.\n\n";
1077 # Either Dir Exists, or was created fine.
1078 $config{$hash_key} = $var;
1088 # Beware: Linux sets it's own cflags below for some retarded reason
1089 $config{LDLIBS} = "-pthread -lstdc++";
1090 $config{FLAGS} = "-fPIC -Woverloaded-virtual -Wshadow -Wall $config{OPTIMISATI}";
1091 $config{DEVELOPER} = "-fPIC -Woverloaded-virtual -Wshadow -Wall -g";
1092 $SHARED = "-Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared" unless defined $opt_disablerpath;
1093 $config{MAKEPROG} = "make";
1095 if ($config{OSNAME} =~ /darwin/i) {
1096 $config{FLAGS} = "-DDARWIN -frtti -fPIC -Wall $config{OPTIMISATI}";
1097 $SHARED = "-bundle -twolevel_namespace -undefined dynamic_lookup";
1098 $config{LDLIBS} = "-ldl -pthread -lstdc++";
1101 if ($config{OSNAME} =~ /OpenBSD/i) {
1102 $config{MAKEPROG} = "gmake";
1103 $config{LDLIBS} = $config{LDLIBS} . " -lunwind";
1104 chomp(my $foo = `eg++ -dumpversion | cut -c 1`);
1105 # theyre running the package version of gcc (eg++)... detect it and set up its version numbers.
1106 # if theyre not running this, configure lets the build continue but they probably wont manage to
1107 # compile as this standard version is 2.95.3!
1109 $config{CC} = "eg++";
1110 chomp($config{GCCVER} = `eg++ -dumpversion | cut -c 1`); # we must redo these if we change the compiler path
1115 if ($config{OSNAME} =~ /Linux/i) {
1116 $config{LDLIBS} = "-ldl -lstdc++ -pthread";
1117 $config{FLAGS} = "-fPIC -Woverloaded-virtual -Wshadow -Wall $config{OPTIMISATI}";
1118 $config{FLAGS} .= " " . $ENV{CXXFLAGS} if exists($ENV{CXXFLAGS});
1119 $config{LDLIBS} .= " " . $ENV{LDLIBS} if exists($ENV{LDLIBS});
1120 $config{MAKEPROG} = "make";
1123 if ($config{OSNAME} =~ /FreeBSD/i) {
1124 $config{FLAGS} .= " " . $ENV{CXXFLAGS} if exists($ENV{CXXFLAGS});
1125 $config{LDLIBS} .= " " . $ENV{LDLIBS} if exists($ENV{LDLIBS});
1128 if ($config{OSNAME} =~ /SunOS/i or $config{OSNAME} =~ /solaris/i)
1130 # solaris/sunos needs these
1131 # socket = bsd sockets api
1133 # rt = POSIX realtime extensions
1134 # resolv = inet_aton only (why isnt this in nsl?!)
1135 $config{MAKEPROG} = "gmake";
1136 $config{LDLIBS} .= " -lsocket -lnsl -lrt -lresolv -pthread";
1140 if($config{OSNAME} =~ /MINGW32/i)
1142 # All code is position-independent on windows
1143 $config{FLAGS} =~ s/-fPIC //;
1147 return $config{OSNAME};
1150 my ($mliflags, $mfrules, $mobjs, $mfcount) = ("", "", "", 0);
1152 sub write_root_files {
1153 # Create a Modules List..
1155 foreach my $i (@modlist)
1157 $modules .= "m_".$i.".so ";
1159 chomp($modules); # Remove Redundant whitespace..
1161 opendir(DIRHANDLE, "src/modules");
1162 foreach my $name (sort readdir(DIRHANDLE)) {
1163 if ($name =~ /^m_(.+?)$/) {
1164 if (defined(opendir(MDIRHANDLE, "src/modules/$name"))) {
1165 closedir(MDIRHANDLE);
1166 $modules .= "$name.so ";
1167 $uninstall_list = $uninstall_list . " -rm \$(MODULES)/$name.so\n";
1171 closedir(DIRHANDLE);
1173 # Write all .in files.
1174 my $exe = "inspircd";
1176 # Do this once here, and cache it in the .*.inc files,
1177 # rather than attempting to read src/version.sh from
1178 # compiled code -- we might not have the source to hand.
1179 # Fix for bug#177 by Brain.
1181 chomp(my $version = `sh ./src/version.sh`);
1182 chomp(my $revision = getrevision());
1183 $version = "$version(r$revision)";
1185 # We can actually parse any file starting with . and ending with .inc,
1186 # but right now we only parse .inspircd.inc to form './inspircd'
1188 opendir(DIRHANDLE, $this);
1190 foreach my $name (sort readdir(DIRHANDLE)) {
1191 if ($name =~ /^\.(.+)\.inc$/) {
1194 # Bug #353, omit this on non-darwin
1195 next if (($config{OSNAME} !~ /darwin/) && ($file eq "org.inspircd.plist"));
1197 # All .name.inc files need parsing!
1199 open(FILEHANDLE, ".$file.inc") or die ("Can't open .$file.inc");
1200 while (<FILEHANDLE>) {
1205 print "Writing \e[1;32m$file\e[0m ...\n";
1206 $tmp =~ s/\@CC\@/$config{CC}/ if defined $config{CC};
1207 $tmp =~ s/\@MAKEPROG\@/$config{MAKEPROG}/ if defined $config{MAKEPROG};
1208 $tmp =~ s/\@FLAGS\@/$config{FLAGS}/ if defined $config{FLAGS};
1209 $tmp =~ s/\@DEVELOPER\@/$config{DEVELOPER}/ if defined $config{DEVELOPER};
1210 $tmp =~ s/\@LDLIBS\@/$config{LDLIBS}/ if defined $config{LDLIBS};
1211 $tmp =~ s/\@BASE_DIR\@/$config{BASE_DIR}/ if defined $config{BASE_DIR};
1212 $tmp =~ s/\@CONFIG_DIR\@/$config{CONFIG_DIR}/ if defined $config{CONFIG_DIR};
1213 $tmp =~ s/\@MODULE_DIR\@/$config{MODULE_DIR}/ if defined $config{MODULE_DIR};
1214 $tmp =~ s/\@BINARY_DIR\@/$config{BINARY_DIR}/ if defined $config{BINARY_DIR};
1215 $tmp =~ s/\@LIBRARY_DIR\@/$config{LIBRARY_DIR}/ if defined $config{LIBRARY_DIR};
1216 $tmp =~ s/\@MODULES\@/$modules/ if defined $modules;
1217 $tmp =~ s/\@STARTSCRIPT\@/$config{STARTSCRIPT}/ if defined $config{STARTSCRIPT};
1218 $tmp =~ s/\@DESTINATION\@/$config{DESTINATION}/ if defined $config{DESTINATION};
1219 $tmp =~ s/\@EXTRA_DIR\@/$config{EXTRA_DIR}/ if defined $config{EXTRA_DIR};
1220 $tmp =~ s/\@EXECUTABLE\@/$exe/ if defined $exe;
1221 $tmp =~ s/\@MAKEORDER\@/$config{MAKEORDER}/ if defined $config{MAKEORDER};
1222 $tmp =~ s/\@VERSION\@/$version/ if defined $version;
1223 $tmp =~ s/\@INSTALL_LIST\@/$install_list/ if defined $install_list;
1224 $tmp =~ s/\@UNINSTALL_LIST\@/$uninstall_list/ if defined $uninstall_list;
1226 open(FILEHANDLE, ">$file");
1227 print FILEHANDLE $tmp;
1230 closedir(DIRHANDLE);
1232 # Make inspircd executable!
1233 chmod 0744, 'inspircd';
1238 my($writeheader) = @_;
1240 # First File.. inspircd_config.h
1241 chomp(my $incos = `uname -n -s -r`);
1242 chomp(my $version = `sh src/version.sh`);
1243 chomp(my $revision2 = getrevision());
1244 if ($writeheader == 1)
1246 print "Writing \e[1;32minspircd_config.h\e[0m\n";
1247 open(FILEHANDLE, ">include/inspircd_config.h");
1248 my $NL = $config{NICK_LENGT}+1;
1249 my $CL = $config{CHAN_LENGT}+1;
1250 print FILEHANDLE <<EOF;
1251 /* Auto generated by configure, do not modify! */
1252 #ifndef __CONFIGURATION_AUTO__
1253 #define __CONFIGURATION_AUTO__
1255 /* this is for windows support. */
1256 #define CoreExport /**/
1257 #define DllExport /**/
1259 #define CONFIG_FILE "$config{CONFIG_DIR}/inspircd.conf"
1260 #define MOD_PATH "$config{MODULE_DIR}"
1261 #define VERSION "$version"
1262 #define REVISION "$revision2"
1263 #define MAXCLIENTS $config{MAX_CLIENT}
1264 #define MAXCLIENTS_S "$config{MAX_CLIENT}"
1265 #define SOMAXCONN_S "$config{_SOMAXCONN}"
1266 #define MAX_DESCRIPTORS $config{MAX_DESCRIPTORS}
1269 #define MAXMODES $config{MAXI_MODES}
1270 #define IDENTMAX $config{MAX_IDENT}
1271 #define MAXQUIT $config{MAX_QUIT}
1272 #define MAXTOPIC $config{MAX_TOPIC}
1273 #define MAXKICK $config{MAX_KICK}
1274 #define MAXGECOS $config{MAX_GECOS}
1275 #define MAXAWAY $config{MAX_AWAY}
1276 #define OPTIMISATION $config{OPTIMITEMP}
1277 #define LIBRARYDIR "$config{LIBRARY_DIR}"
1278 #define SYSTEM "$incos"
1281 print FILEHANDLE "#define MAXBUF " . ($config{MAXBUF}+2) . "\n";
1283 if ($config{OSNAME} =~ /SunOS/i) {
1284 print FILEHANDLE "#define IS_SOLARIS\n";
1286 if ($config{OSNAME} =~ /MINGW32/i) {
1287 print FILEHANDLE "#define IS_MINGW\n";
1289 if ($config{GCCVER} >= 3) {
1290 print FILEHANDLE "#define GCC3\n";
1292 if ($config{HAS_STRLCPY} eq "true") {
1293 print FILEHANDLE "#define HAS_STRLCPY\n";
1295 if ($config{HAS_STDINT} eq "true") {
1296 print FILEHANDLE "#define HAS_STDINT\n";
1298 if ($config{IPV6} =~ /y/i) {
1299 print FILEHANDLE "#define IPV6\n";
1301 if ($config{SUPPORT_IP6LINKS} =~ /y/i) {
1302 print FILEHANDLE "#define SUPPORT_IP6LINKS\n";
1305 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
1306 print FILEHANDLE "#define USE_KQUEUE\n";
1307 $se = "socketengine_kqueue";
1310 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
1311 print FILEHANDLE "#define USE_EPOLL\n";
1312 $se = "socketengine_epoll";
1315 if (($has_ports) && ($config{USE_PORTS} eq "y")) {
1316 print FILEHANDLE "#define USE_PORTS\n";
1317 $se = "socketengine_ports";
1320 # user didn't choose either epoll or select for their OS.
1321 # default them to USE_SELECT (ewwy puke puke)
1323 print FILEHANDLE "#define USE_SELECT\n";
1324 $se = "socketengine_select";
1326 print FILEHANDLE "\n#include \"threadengines/threadengine_pthread.h\"\n\n#endif\n";
1332 open(FILEHANDLE, ">include/inspircd_se_config.h");
1333 print FILEHANDLE <<EOF;
1334 /* Auto generated by configure, do not modify or commit to svn! */
1335 #ifndef __CONFIGURATION_SOCKETENGINE__
1336 #define __CONFIGURATION_SOCKETENGINE__
1338 #include "socketengines/$se.h"
1347 print "Writing \e[1;32mMakefiles\e[0m\n";
1348 write_dynamic_modules_makefile();
1349 write_dynamic_makefile();
1353 sub write_dynamic_modules_makefile {
1354 # Modules Makefile..
1355 print "Writing \e[1;32msrc/modules/Makefile\e[0m\n";
1356 open(FILEHANDLE, ">src/modules/Makefile");
1359 # Module Makefile Header
1361 print FILEHANDLE <<EOF;
1362 ###################################################
1363 # Copyright 2002-2007 The InspIRCd Development Team
1364 # http://www.inspircd.org/wiki/index.php/Credits
1366 # Thanks to Andrew Church <achurch\@achurch.org>
1367 # for assisting with making this work right.
1369 # Automatically Generated by ./configure to add a
1370 # modules please run ./configure -modupdate
1371 ###################################################
1377 if ($config{OSNAME} =~ /darwin/) {
1378 print FILEHANDLE <<EOCHEESE;
1380 PICLDFLAGS = -twolevel_namespace -undefined dynamic_lookup -bundle
1384 print FILEHANDLE <<EOCHEESE;
1386 PICLDFLAGS = -fPIC -DPIC -shared
1392 # End Module Makefile Header
1395 # Create a Modules List..
1399 foreach my $i (@modlist) {
1401 # Write Entry to the MakeFile
1403 $cmflags = getcompilerflags("src/modules/m_".$i.".cpp");
1404 $liflags = getlinkerflags("src/modules/m_".$i.".cpp");
1405 my $deps = getdependencies("src/modules/m_".$i.".cpp");
1407 #print "file: $i: cmflags=$cmflags; liflags=$liflags; deps=$deps\n";
1410 if (nopedantic("src/modules/m_".$i.".cpp"))
1413 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
1414 \@../../make/run-cc.pl \$(CC) -pipe -I../../include \$(NICEFLAGS) $cmflags \$(PICLDFLAGS) $liflags -export-dynamic -o m_$i.so m_$i.cpp
1420 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
1421 \@../../make/run-cc.pl \$(CC) -pipe -I../../include \$(FLAGS) $cmflags \$(PICLDFLAGS) $liflags -export-dynamic -o m_$i.so m_$i.cpp
1424 $install_list = $install_list . " install -m \$(INSTMODE) src/modules/m_$i.so \$(MODPATH)\n";
1425 $uninstall_list = $uninstall_list . " -rm \$(MODULES)/m_$i.so\n";
1427 # End Write Entry to the MakeFile
1431 opendir(DIRHANDLE, "src/modules");
1432 foreach my $name (sort readdir(DIRHANDLE)) {
1433 if ($name =~ /^m_(.+?)$/) {
1438 # A module made of multiple files, in a dir, e.g. src/modules/m_spanningtree/
1439 if (defined(opendir(MDIRHANDLE, "src/modules/$name"))) {
1440 read_module_directory("src/modules/$name", $name);
1441 print "Composing Makefile rules for directory \e[1;32m$name\e[0m... (\e[1;32m$mfcount files found\e[0m)\n";
1442 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";
1443 if ($config{IS_DARWIN} eq "YES") {
1444 print FILEHANDLE " \@../../make/run-cc.pl \$(CC) -pipe -twolevel_namespace -undefined dynamic_lookup \$(FLAGS) $mliflags -bundle -o $name.so $mobjs\n";
1446 print FILEHANDLE " \@../../make/run-cc.pl \$(CC) -pipe \$(FLAGS) -shared $mliflags -o $name.so $mobjs\n";
1448 print FILEHANDLE "\n$mfrules\n";
1449 closedir(MDIRHANDLE);
1450 $install_list = $install_list . " install -m \$(INSTMODE) src/modules/$name.so \$(MODPATH)\n";
1454 closedir(DIRHANDLE);
1457 sub read_module_directory {
1458 my ($dpath, $reldpath) = @_;
1460 if (opendir(MDIRHANDLE, $dpath) == 0) {
1464 foreach my $fname (sort readdir(MDIRHANDLE)) {
1465 if ($fname =~ /\.cpp$/) {
1466 my $cmflags = getcompilerflags("$dpath/$fname");
1467 $mliflags = $mliflags . " " . getlinkerflags("$dpath/$fname");
1468 my $deps = getdependencies("$dpath/$fname");
1470 $oname =~ s/\.cpp$/.o/g;
1471 $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";
1472 $mfrules = $mfrules . " \@../../make/run-cc.pl \$(CC) -pipe -I../../include -I. \$(FLAGS) $cmflags -export-dynamic -o $reldpath/$oname -c $reldpath/$fname\n\n";
1473 $mobjs = $mobjs . " $reldpath/$oname";
1476 elsif ((-d "$dpath/$fname") && !($fname eq ".") && !($fname eq "..")) {
1477 read_module_directory($dpath."/".$fname, $reldpath."/".$fname);
1484 # Yes i know we could use gcc -M but it seems to ideneify a lot of 'deep'
1485 # dependencies which are not relevent in C++.
1489 open (CPP, "<$file") or die("Can't open $file for reading!");
1494 foreach my $d (@ignoredeps)
1500 foreach my $dep (@immutabledeps)
1502 $immutable = $immutable . "../include/$dep ";
1504 $immutable =~ s/ $//g;
1506 while (defined(my $line = <CPP>))
1509 if ($line =~ /#include "(.+\.h)"/)
1511 if (!exists($dupe{$1}))
1513 $retlist = $retlist . "../include/$1 ";
1519 return length($immutable) ? $immutable . " " . $retlist : $retlist;
1522 sub write_dynamic_makefile
1526 my %existing_install_list = ();
1527 opendir(DIRHANDLE, "src/commands");
1528 foreach my $name (sort readdir(DIRHANDLE))
1530 if ($name =~ /^cmd_(.+)\.cpp$/)
1532 $cmdlist[$i++] = $1;
1533 $install_list = $install_list . " -install -m \$(INSTMODE) src/commands/cmd_" . $1 . ".so \$(LIBPATH)\n";
1534 $uninstall_list = $uninstall_list . " -rm \$(LIBPATH)/cmd_$1.so\n";
1537 closedir(DIRHANDLE);
1541 $config{USE_EPOLL} = 0;
1545 $config{USE_KQUEUE} = 0;
1549 $config{USE_PORTS} = 0;
1552 foreach my $dir (("src","src/commands","src/modes","src/socketengines","src/modules"))
1554 print "Scanning \e[1;32m$dir\e[0m for core files ";
1555 opendir(DIRHANDLE, $dir);
1556 foreach my $name (sort readdir(DIRHANDLE))
1558 if ($name =~ /\.cpp$/)
1560 open (CPP, "<$dir/$name") or die("Can't open $dir/$name to scan it! oh bugger");
1562 while (defined(my $line = <CPP>))
1565 if ($line =~ /\/\* \$Core: (\w+) \*\//i)
1567 $filelist{$name} = $1;
1569 elsif ($line =~ /\/\* \$ExtraDeps: (.*?) \*\//i)
1571 $specialdeps{$name} = $1;
1573 elsif ($line =~ /\/\* \$ExtraObjects: (.*?) \*\//i)
1575 $extraobjects{$name} = $1;
1577 elsif ($line =~ /\/\* \$ExtraBuild: (.*?) \*\//i)
1579 $extrabuildlines{$name} = $1;
1581 elsif ($line =~ /\/\* \$ExtraSources: (.*?) \*\//i)
1583 $extrasources{$name} = $1;
1585 elsif ($line =~ /\/\* \$If: (\w+) \*\//i)
1587 if (defined $config{$1})
1589 if (($config{$1} !~ /y/i) and ($config{$1} ne "1"))
1592 while (defined($line = <CPP>))
1595 die ("\$If buildsystem instruction within another \$If in file $dir/$name") if ($line =~ /\/\* \$If: (\w+) \*\//i);
1596 last if ($line =~ /\/\* \$EndIf \*\//i);
1601 elsif ($line =~ /\/\* \$Install: (.*?) \*\//i)
1603 if (!exists($existing_install_list{$1}))
1605 $existing_install_list{$1} = 1;
1606 my $idir = (split(' ',$1))[1];
1607 my $ifile = (split(' ',$1))[0];
1608 $install_list = $install_list . " -install -m \$(INSTMODE) $1\n";
1609 $ifile =~ s/.*\///g;
1610 $uninstall_list = $uninstall_list . " -rm $idir/$ifile\n";
1613 elsif ($line =~ /\/\* \$CopyInstall: (.*?) \*\//i)
1615 if (!exists($existing_install_list{$1}))
1617 $existing_install_list{$1} = 1;
1618 my $idir = (split(' ',$1))[1];
1619 my $ifile = (split(' ',$1))[0];
1620 $install_list = $install_list . " -cp $1\n";
1621 $ifile =~ s/.*\///g;
1622 $uninstall_list = $uninstall_list . " -rm $idir/$ifile\n";
1629 closedir(DIRHANDLE);
1633 my $freebsd4libs = (defined $config{CRAQ} ? $config{CRAQ} : "");
1636 my $all_libsonly = "";
1638 my $libraryext = "";
1642 if ($config{IS_DARWIN} eq "YES")
1644 $libraryext = "dylib";
1645 $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 "
1650 $RPATH = "-Wl,--rpath -Wl,$config{LIBRARY_DIR}" unless defined $opt_disablerpath;
1651 $othercrap = " \@../make/run-cc.pl \$(CC) -pipe -I../include $RPATH \$(FLAGS) $freebsd4libs -rdynamic -L. inspircd.cpp -o inspircd \$(LDLIBS) ";
1654 foreach my $cpp (sort keys %filelist)
1656 $all = $all . $filelist{$cpp} . "." . $libraryext . " ";
1657 $all_libsonly = $all_libsonly . $filelist{$cpp} . "." . $libraryext . " ";
1658 $install_list = $install_list . " -install -m \$(INSTMODE) src/" . $filelist{$cpp} . "." . $libraryext . " \$(LIBPATH)\n";
1659 $uninstall_list = $uninstall_list . " -rm \$(LIBPATH)/" . $filelist{$cpp} . "." . $libraryext . "\n";
1661 $all = $all . "moo inspircd\n";
1663 $othercrap = $othercrap . " $all_libsonly\n\n";
1665 open(FH,">src/Makefile") or die("Could not write src/Makefile");
1668 CC = im a cheezeball
1669 CXXFLAGS = -I../include \${FLAGS}
1670 CPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* //' | grep -v svn)
1671 RELCPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* /modes\\//' | grep -v svn)
1675 print FH "$all\n\n";
1677 my $deps = calcdeps("src/inspircd.cpp");
1678 print FH "inspircd: inspircd.cpp $deps $all_libsonly\n";
1679 print FH "$othercrap\n";
1681 foreach my $cpp (sort keys %filelist)
1683 my $thislib = $filelist{$cpp} . "." . $libraryext;
1687 $objs =~ s/\.cpp$/.o/;
1688 if (exists($extraobjects{$cpp}))
1690 $objs = $objs . " " . $extraobjects{$cpp};
1692 if (exists($extrasources{$cpp}))
1694 $rawcpp = $rawcpp . " " . $extrasources{$cpp};
1696 if ($config{IS_DARWIN} eq "YES")
1698 $libcrap = "-install_name " . $config{LIBRARY_DIR} . "/" . $thislib . " -dynamiclib -twolevel_namespace -undefined dynamic_lookup";
1702 if (defined $opt_disablerpath)
1704 $libcrap = " -shared";
1708 $libcrap = "-Wl,--rpath -Wl," . $config{LIBRARY_DIR} . " -shared";
1711 $deps = calcdeps("src/$cpp");
1712 if (exists($extrasources{$cpp}))
1714 foreach my $seperate (sort split(' ',$extrasources{$cpp}))
1716 my $d = calcdeps("src/$extrasources{$cpp}") . " ";
1719 $deps = $deps . $d . " ";
1723 print FH $thislib . ": $cpp $deps ". (defined($specialdeps{$cpp}) ? $specialdeps{$cpp} : "") . "\n";
1724 print FH " \@../make/run-cc.pl \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c $rawcpp\n";
1725 if (exists($extrabuildlines{$cpp}))
1727 print FH " " . $extrabuildlines{$cpp} . "\n";
1729 print FH " \@../make/run-cc.pl \$(CC) -pipe $libcrap -o " . $thislib . " " . $objs . "\n\n";
1732 print FH "moo:\n \@\${MAKE} -C \"commands\" DIRNAME=\"src/commands\" CC=\"\$(CC)\" \$(MAKEARGS)\n\n";
1734 # close main makefile
1738 # generate a list of .so
1739 foreach my $cmd (@cmdlist) {
1740 $cmdobjs = $cmdobjs . "cmd_$cmd.so ";
1743 # and now reopen the commands makefile
1744 open(FH,">src/commands/Makefile") or die("Could not write src/commands/Makefile");
1747 CXXFLAGS = -I../../include \${FLAGS}
1754 # now print the command file details.
1755 foreach my $cmd (@cmdlist) {
1757 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
1758 \@../../make/run-cc.pl \$(CC) -pipe -I../../include \$(FLAGS) -export-dynamic $SHARED -o cmd_$cmd.so cmd_$cmd.cpp
1764 # Routine to list out the extra/ modules that have been enabled.
1765 # Note: when getting any filenames out and comparing, it's important to lc it if the
1766 # file system is not case-sensitive (== Epoc, MacOS, OS/2 (incl DOS/DJGPP), VMS, Win32
1767 # (incl NetWare, Symbian)). Cygwin may or may not be case-sensitive, depending on
1768 # configuration, however, File::Spec does not currently tell us (it assumes Unix behavior).
1769 sub list_extras () {
1772 my $srcdir = File::Spec->catdir("src", "modules");
1773 my $abs_srcdir = File::Spec->rel2abs($srcdir);
1776 opendir $dd, File::Spec->catdir($abs_srcdir, "extra") or die (File::Spec->catdir($abs_srcdir, "extra") . ": $!\n");
1777 my @extras = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1780 opendir $dd, $abs_srcdir or die "$abs_srcdir: $!\n";
1781 my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1784 my $maxlen = (sort { $b <=> $a } (map {length($_)} (@extras)))[0];
1786 EXTRA: for my $extra (@extras) {
1787 next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra);
1788 next if ($extra eq '.svn');
1789 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1790 my $abs_source = File::Spec->catfile($abs_srcdir, $extra);
1791 next unless ($extra =~ m/\.(cpp|h)$/ || (-d $abs_extra)); # C++ Source/Header, or directory
1792 if (-l $abs_source) {
1793 # Symlink, is it in the right place?
1794 my $targ = readlink($abs_source);
1795 my $abs_targ = File::Spec->rel2abs($targ, $abs_srcdir);
1796 if ($abs_targ eq $abs_extra) {
1797 $extras{$extra} = "\e[32;1menabled\e[0m";
1799 $extras{$extra} = sprintf("\e[31;1mwrong symlink target (%s)\e[0m", $abs_targ);
1801 } elsif (-e $abs_source) {
1802 my ($devext, $inoext) = stat($abs_extra);
1803 my ($devsrc, $inosrc, undef, $lnksrc) = stat($abs_source);
1805 if ($devsrc == $devext && $inosrc == $inoext) {
1806 $extras{$extra} = "\e[32;1menabled\e[0m";
1808 $extras{$extra} = sprintf("\e[31;1mwrong hardlink target (%d:%d)\e[0m", $devsrc, $inosrc);
1811 open my $extfd, "<", $abs_extra;
1812 open my $srcfd, "<", $abs_source;
1814 if (scalar(<$extfd>) eq scalar(<$srcfd>)) {
1815 $extras{$extra} = "\e[32;1menabled\e[0m";
1817 $extras{$extra} = sprintf("\e[31;1mout of synch (re-copy)\e[0m");
1821 $extras{$extra} = "\e[33;1mdisabled\e[0m";
1824 # Now let's add dependency info
1825 for my $extra (keys(%extras)) {
1826 next unless $extras{$extra} =~ m/enabled/; # only process enabled extras.
1827 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1828 my @deps = split / +/, getdependencies($abs_extra);
1829 for my $dep (@deps) {
1830 if (exists($extras{$dep})) {
1831 my $ref = \$extras{$dep}; # Take reference.
1832 if ($$ref !~ m/needed by/) {
1833 # First dependency found.
1834 if ($$ref =~ m/enabled/) {
1835 $$ref .= " (needed by \e[32;1m$extra\e[0m";
1837 $$ref =~ s/\e\[.*?m//g; # Strip out previous coloring. Will be set in bold+red+blink later.
1838 $$ref .= " (needed by \e[0;32;1;5m$extra\e[0;31;1;5m";
1841 if ($$ref =~ m/enabled/) {
1842 $$ref .= ", \e[32;1m$extra\e[0m";
1844 $$ref .= ", \e[0;32;1;5m$extra\e[0;31;1;5m";
1850 for my $extra (sort {$a cmp $b} keys(%extras)) {
1851 my $text = $extras{$extra};
1852 if ($text =~ m/needed by/ && $text !~ m/enabled/) {
1853 printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? ")" : "");
1855 printf "%-*s = %s%s\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? "\e[0m)" : "");
1858 return keys(%extras) if wantarray; # Can be used by manage_extras.
1861 sub enable_extras (@) {
1863 for my $extra (@extras) {
1864 my $extrapath = "src/modules/extra/$extra";
1865 if (!-e $extrapath) {
1866 print STDERR "Cannot enable \e[32;1m$extra\e[0m : No such file or directory in src/modules/extra\n";
1869 my $source = "src/modules/$extra";
1871 print STDERR "Cannot enable \e[32;1m$extra\e[0m : destination in src/modules exists (might already be enabled?)\n";
1874 # Get dependencies, and add them to be processed.
1875 my @deps = split / +/, getdependencies($extrapath);
1876 for my $dep (@deps) {
1877 next if scalar(grep { $_ eq $dep } (@extras)) > 0; # Skip if we're going to be enabling it anyway.
1878 if (!-e "src/modules/$dep") {
1879 if (-e "src/modules/extra/$dep") {
1880 print STDERR "Will also enable extra \e[32;1m$dep\e[0m (needed by \e[32;1m$extra\e[0m)\n";
1883 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";
1887 print "Enabling $extra ... \n";
1888 symlink "extra/$extra", $source or print STDERR "$source: Cannot link to 'extra/$extra': $!\n";
1892 sub disable_extras (@)
1894 opendir my $dd, "src/modules/extra/";
1895 my @files = readdir($dd);
1898 EXTRA: for my $extra (@extras) {
1899 my $extrapath = "src/modules/extra/$extra";
1900 my $source = "src/modules/$extra";
1901 if (!-e $extrapath) {
1902 print STDERR "Cannot disable \e[32;1m$extra\e[0m : Is not an extra\n";
1905 if ((! -l $source) || readlink($source) ne "extra/$extra") {
1906 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";
1909 # Check if anything needs this.
1910 for my $file (@files) {
1911 my @deps = split / +/, getdependencies("src/modules/extra/$file");
1912 # File depends on this extra...
1913 if (scalar(grep { $_ eq $extra } @deps) > 0) {
1914 # And is both enabled and not about to be disabled.
1915 if (-e "src/modules/$file" && scalar(grep { $_ eq $file } @extras) < 1) {
1916 print STDERR "Cannot disable \e[32;1m$extra\e[0m : is needed by \e[32;1m$file\e[0m\n";
1922 print "Disabling $extra ... \n";
1923 unlink "src/modules/$extra" or print STDERR "Cannot disable \e[32;1m$extra\e[0m : $!\n";