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 ###################################################
18 use warnings FATAL => qw(all);
22 $Data::Dumper::Sortkeys = 1;
23 $Data::Dumper::Useqq = 1;
32 # Utility functions for our buildsystem
36 use make::opensslcert;
38 ###############################################################################################
42 ###############################################################################################
44 # If you wish to ignore a dependency throughout the entire core, add it here.
47 "inspircd_win32wrapper.h", # windows has its own configure program
50 # If you wish for all files in the entire core to have a given dependency, insert it here.
51 # You should keep this to an absolute minimum to avoid rebuilds that are not neccessary.
53 our @immutabledeps = (
54 "inspircd_config.h", # auto re-generated by configure
58 ###############################################################################################
60 # NON-EDITABLE VARIABLES
62 ###############################################################################################
64 # List of commands that make up 'make install' and 'make deinstall'
66 our $install_list = "";
67 our $uninstall_list = "";
69 # This is a list of all files in the core. Each cpp file is mapped to a shared object file,
70 # whos file extension is omitted (these can vary from system to system). Auto detected by
71 # scanning the src/*.cpp files for files containing /* $Core: */ identifiers.
75 # If you wish for a file to have special dependencies in the makefile, add an entry here.
76 # Auto populated by /* $ExtraDeps: */ instruction
78 our %specialdeps = ();
80 # If you wish for a file to have extra make lines (in between the compile and link steps)
81 # then insert them here.
82 # Auto populated by /* $ExtraBuild: */ instruction
84 our %extrabuildlines = ();
86 # If you wish for a file to be linked against extra objects or arctives, insert them here.
87 # Auto populated by /* $ExtraObjects: */ instruction
89 our %extraobjects = ();
91 # If you wish to compile extra cpp sources into an object, define them here.
92 # NOTE: Certain cpp files such as the socket engines have a value auto calculated
93 # for this table so that their derived class is built.
94 # Auto populated by /* $ExtraSources: */ instruction
96 our %extrasources = ();
98 our ($opt_use_gnutls, $opt_rebuild, $opt_use_openssl, $opt_nointeractive, $opt_nick_length,
99 $opt_chan_length, $opt_maxclients, $opt_ports, $opt_epoll, $opt_kqueue, $opt_noports,
100 $opt_noepoll, $opt_nokqueue, $opt_disablerpath, $opt_ipv6, $opt_ipv6links,
101 $opt_noipv6links, $opt_ident, $opt_quit, $opt_topic, $opt_maxbuf, $opt_kick,
102 $opt_gecos, $opt_away, $opt_modes, $opt_disable_debug, $opt_maxchans,
105 our ($opt_cc, $opt_base_dir, $opt_config_dir, $opt_module_dir, $opt_binary_dir,
110 sub enable_extras (@);
112 sub disable_extras (@);
114 my @opt_enableextras;
115 my @opt_disableextras;
118 'enable-gnutls' => \$opt_use_gnutls,
119 'rebuild' => \$opt_rebuild,
120 'enable-openssl' => \$opt_use_openssl,
121 'disable-interactive' => \$opt_nointeractive,
122 'with-nick-length=i' => \$opt_nick_length,
123 'with-channel-length=i' => \$opt_chan_length,
124 'with-max-clients=i' => \$opt_maxclients,
125 'enable-ports' => \$opt_ports,
126 'enable-epoll' => \$opt_epoll,
127 'enable-kqueue' => \$opt_kqueue,
128 'disable-ports' => \$opt_noports,
129 'disable-epoll' => \$opt_noepoll,
130 'disable-kqueue' => \$opt_nokqueue,
131 'disable-rpath' => \$opt_disablerpath,
132 'enable-ipv6' => \$opt_ipv6,
133 'enable-remote-ipv6' => \$opt_ipv6links,
134 'disable-remote-ipv6' => \$opt_noipv6links,
135 'with-cc=s' => \$opt_cc,
136 'with-ident-length=i' => \$opt_ident,
137 'with-quit-length=i' => \$opt_quit,
138 'with-topic-length=i' => \$opt_topic,
139 'with-maxbuf=i' => \$opt_maxbuf,
140 'with-kick-length=i' => \$opt_kick,
141 'with-gecos-length=i' => \$opt_gecos,
142 'with-away-length=i' => \$opt_away,
143 'with-max-modes=i' => \$opt_modes,
144 'prefix=s' => \$opt_base_dir,
145 'config-dir=s' => \$opt_config_dir,
146 'module-dir=s' => \$opt_module_dir,
147 'binary-dir=s' => \$opt_binary_dir,
148 'library-dir=s' => \$opt_library_dir,
149 'disable-debuginfo' => sub { $opt_disable_debug = 1 },
150 'help' => sub { showhelp(); },
151 'modupdate' => sub { modupdate(); },
152 'update' => sub { update(); },
153 'svnupdate' => sub { svnupdate(); },
154 'clean' => sub { clean(); },
155 'list-extras' => sub { list_extras; exit 0; }, # This, --enable-extras, and --disable-extras are for non-interactive managing.
156 'enable-extras=s@' => \@opt_enableextras, # ^
157 'disable-extras=s@' => \@opt_disableextras, # ^
160 if (scalar(@opt_enableextras) + scalar(@opt_disableextras) > 0) {
161 @opt_enableextras = split /,/, join(',', @opt_enableextras);
162 @opt_disableextras = split /,/, join(',', @opt_disableextras);
163 enable_extras(@opt_enableextras);
164 disable_extras(@opt_disableextras);
166 print "Remember: YOU are responsible for making sure any libraries needed have been installed!\n";
167 print "Run $0 -modupdate after you've done this to update the makefiles.\n";
171 our $non_interactive = (
172 (defined $opt_library_dir) ||
173 (defined $opt_base_dir) ||
174 (defined $opt_config_dir) ||
175 (defined $opt_module_dir) ||
176 (defined $opt_base_dir) ||
177 (defined $opt_binary_dir) ||
178 (defined $opt_nointeractive) ||
179 (defined $opt_away) ||
180 (defined $opt_gecos) ||
181 (defined $opt_kick) ||
182 (defined $opt_maxclients) ||
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.
242 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`); # Openssl version
243 chomp(our $gnutls_ver = $config{HAS_GNUTLS});
244 chomp(our $openssl_ver = $config{HAS_OPENSSL});
245 $config{USE_GNUTLS} = "n";
246 if (defined $opt_use_gnutls)
248 $config{USE_GNUTLS} = "y"; # Use gnutls.
250 $config{USE_OPENSSL} = "n"; # Use openssl.
251 if (defined $opt_use_openssl)
253 $config{USE_OPENSSL} = "y";
256 # no, let's not change these.
257 $config{OPTIMITEMP} = "0"; # Default Optimisation Value
258 if (!defined $opt_disable_debug)
260 $config{OPTIMISATI} = "-g1"; # Optimisation Flag
264 $config{OPTIMISATI} = "-O2"; # DEBUGGING OFF!
267 $config{NICK_LENGT} = "31"; # Default Nick Length
268 if (defined $opt_nick_length)
270 $config{NICK_LENGT} = $opt_nick_length;
272 $config{CHAN_LENGT} = "64"; # Default Channel Name Length
273 if (defined $opt_chan_length)
275 $config{CHAN_LENGT} = $opt_chan_length;
277 $config{MAXI_MODES} = "20"; # Default Max. Number of Modes set at once.
278 if (defined $opt_modes)
280 $config{MAXI_MODES} = $opt_modes;
282 $config{HAS_STRLCPY} = "false"; # strlcpy Check.
283 $config{HAS_STDINT} = "false"; # stdint.h check
284 $config{USE_KQUEUE} = "y"; # kqueue enabled
285 if (defined $opt_kqueue)
287 $config{USE_KQUEUE} = "y";
289 if (defined $opt_nokqueue)
291 $config{USE_KQUEUE} = "n";
293 $config{USE_EPOLL} = "y"; # epoll enabled
294 if (defined $opt_epoll)
296 $config{USE_EPOLL} = "y";
298 if (defined $opt_noepoll)
300 $config{USE_EPOLL} = "n";
302 $config{USE_PORTS} = "y"; # epoll enabled
303 if (defined $opt_ports)
305 $config{USE_PORTS} = "y";
307 if (defined $opt_noports)
309 $config{USE_PORTS} = "n";
311 $config{IPV6} = "n"; # IPv6 support (experimental)
312 if (defined $opt_ipv6)
316 $config{SUPPORT_IP6LINKS} = "y"; # IPv4 supporting IPv6 links (experimental)
317 if (defined $opt_ipv6links)
319 $config{SUPPORT_IP6LINKS} = "y";
321 if (defined $opt_noipv6links)
323 $config{SUPPORT_IP6LINKS} = "n";
325 chomp($config{MAX_CLIENT_T} = `sh -c \"ulimit -n\"`); # FD Limit
326 chomp($config{MAX_DESCRIPTORS} = `sh -c \"ulimit -n\"`); # Hard FD Limit
327 chomp($config{GCCVER} = `g++ -dumpversion | cut -c 1`); # Major GCC Version
328 $config{_SOMAXCONN} = SOMAXCONN; # Max connections in accept queue
329 $config{OSNAME} = $^O; # Operating System Name
330 $config{IS_DARWIN} = "NO"; # Is OSX?
331 $config{STARTSCRIPT} = "inspircd"; # start script?
332 $config{DESTINATION} = "BASE"; # Is target path.
333 $config{EXTRA_DIR} = ""; # Is empty.
334 if ($config{OSNAME} =~ /darwin/i)
336 $config{IS_DARWIN} = "YES";
337 $config{STARTSCRIPT} = "org.inspircd.plist"; # start script for OSX.
338 $config{DESTINATION} = "LAUNCHDPATH"; # Is OSX target.
339 $config{EXTRA_DIR} = " launchd_dir"; # Is OSX specific path.
341 $config{CC} = "g++"; # C++ compiler
344 $config{CC} = $opt_cc;
346 our $exec = $config{CC} . " -dumpversion | cut -c 1";
347 chomp($config{GCCVER} = `$exec`); # Major GCC Version
348 $config{MAKEORDER} = "ircd mods"; # build order
349 $config{MAX_IDENT} = "12"; # max ident size
350 $config{MAX_QUIT} = "255"; # max quit message size
351 $config{MAX_TOPIC} = "307"; # max topic size
352 $config{MAX_KICK} = "255"; # max kick message size
353 $config{MAX_GECOS} = "128"; # max GECOS size
354 $config{MAX_AWAY} = "200"; # max AWAY size
355 $config{MAXBUF} = "512"; # Max buffer size
356 if (defined $opt_ident)
358 $config{MAX_IDENT} = $opt_ident;
360 if (defined $opt_quit)
362 $config{MAX_QUIT} = $opt_quit;
364 if (defined $opt_topic)
366 $config{MAX_TOPIC} = $opt_topic;
368 if (defined $opt_kick)
370 $config{MAX_KICK} = $opt_kick;
372 if (defined $opt_gecos)
374 $config{MAX_GECOS} = $opt_gecos;
376 if (defined $opt_away)
378 $config{MAX_AWAY} = $opt_away;
381 $config{HAS_OPENSSL} =~ /^([-[:digit:].]+)([a-z])?(\-[a-z][0-9])?$/;
382 $config{HAS_OPENSSL} = $1;
384 if ($config{GCCVER} eq "") {
385 print $config{CC} . " was not found! You require g++ (the GNU C++ compiler, part of GCC) to build InspIRCd!\n";
389 our $fd_scan_fail = "";
390 if (!$config{MAX_CLIENT_T}) {
391 $config{MAX_CLIENT_T} = 1024; # Set a reasonable 'Default'
392 $fd_scan_fail = "true"; # Used Later
395 # Get and Set some important vars..
400 unlink(".config.cache");
403 our ($has_epoll, $has_ports, $has_kqueue) = (0, 0, 0);
408 chomp($topdir = getcwd());
409 $this = resolve_directory($topdir); # PWD, Regardless.
411 # Does the cache file exist?
413 # No, No it doesn't.. *BASH*
414 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
417 # We've Loaded the cache file and all our variables..
418 print "Updating files...\n";
420 if (defined($opt_disable_debug) && $opt_disable_debug == 1)
422 print "Disabling debug information (-g).\n";
423 $config{OPTIMISATI} = "";
426 $has_epoll = $config{HAS_EPOLL};
427 $has_ports = $config{HAS_PORTS};
428 $has_kqueue = $config{HAS_KQUEUE};
437 print "Configure update failed: $@\n";
445 chomp($topdir = getcwd());
446 $this = resolve_directory($topdir); # PWD, Regardless.
448 # Does the cache file exist?
450 # No, No it doesn't.. *BASH*
451 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
454 # We've Loaded the cache file and all our variables..
455 print "Updating files...\n";
457 $has_epoll = $config{HAS_EPOLL};
458 $has_ports = $config{HAS_PORTS};
459 $has_kqueue = $config{HAS_KQUEUE};
468 print "Module update failed: $@\n";
478 open(FH,"<.svn/entries") or $fail = 1;
480 print "This is not an SVN copy of InspIRCd.\n";
487 system("svn update");
488 system("perl configure -update");
489 if (defined $opt_rebuild) {
490 system("make install");
495 print "Running non-interactive configure...\n" unless $interactive;
496 print "Checking for cache from previous configure... ";
497 print ((!getcache()) ? "not found\n" : "found\n");
498 print "Checking operating system version... ";
499 print getosflags() . "\n";
501 if (defined $opt_maxclients)
503 $config{MAX_CLIENT} = $opt_maxclients;
506 if (!$config{MAX_CLIENT}) {
507 # If the cache hasn't set the max clients, copy the variable of MAX_CLIENT_T, this
508 # allows us to keep _T for testing purposes. (ie. "Are you sure you want to go
509 # higher than the found value" :))
510 $config{MAX_CLIENT} = $config{MAX_CLIENT_T};
513 printf "Checking if stdint.h exists... ";
514 $config{HAS_STDINT} = "true";
516 open(STDINT, "</usr/include/stdint.h") or $config{HAS_STDINT} = "false";
517 if ($config{HAS_STDINT} eq "true") {
520 print "yes\n" if $config{HAS_STDINT} eq "true";
521 print "no\n" if $config{HAS_STDINT} eq "false";
523 printf "Checking if strlcpy exists... ";
524 # Perform the strlcpy() test..
525 $config{HAS_STRLCPY} = "false";
527 open(STRLCPY, "</usr/include/string.h") or $fail = 1;
529 while (defined(my $line = <STRLCPY>)) {
531 # try and find the delcaration of:
532 # size_t strlcpy(...)
533 if ($line =~ /size_t(\0x9|\s)+strlcpy/) {
534 $config{HAS_STRLCPY} = "true";
539 print "yes\n" if $config{HAS_STRLCPY} eq "true";
540 print "no\n" if $config{HAS_STRLCPY} eq "false";
542 printf "Checking if kqueue exists... ";
545 open(KQUEUE, "</usr/include/sys/event.h") or $fail = 1;
547 while (defiined(my $line = <KQUEUE>)) {
549 # try and find the delcaration of:
551 if ($line =~ /int(\0x9|\s)+kqueue/) {
557 print "yes\n" if $has_kqueue == 1;
558 print "no\n" if $has_kqueue == 0;
560 printf "Checking if epoll exists... ";
563 open(EPOLL, "</usr/include/sys/epoll.h") or $fail = 1;
569 my $kernel = `uname -r`;
571 if (($kernel =~ /^2\.0\./) || ($kernel =~ /^2\.2\./) || ($kernel =~ /^2\.4\./)) {
576 # Suggestion from nenolod, weed out odd systems which have glibc built
577 # against 2.4 kernels (ick)
578 my $kernel_arch = `uname -p`;
582 if ($kernel_arch =~ /x86_64/) {
583 open (FH,"/lib64/libc.so.6|") or $has_epoll = 0;
586 open (FH,"/lib/libc.so.6|") or $has_epoll = 0;
590 while (defined(my $line = <FH>))
593 if ($line =~ /GNU C Library .* version (.*?) /)
596 $libcv =~ /(\d+\.\d+)/;
599 elsif ($line =~ /Compiled on a Linux (.*?\..*?)\.* system/)
602 # Fix for some retarded libc builds, strip off >> and << etc.
603 $kernelv =~ /(\d+\.\d+)/;
611 printf "libc too old: $libcv... ";
616 printf "libc built against older kernel $kernelv... ";
621 print "yes\n" if $has_epoll == 1;
622 print "no\n" if $has_epoll == 0;
624 printf "Checking if Solaris I/O completion ports are available... ";
626 our $system = `uname -s`;
628 $has_ports = 1 if ($system eq "SunOS");
631 my $kernel = `uname -r`;
633 if (($kernel !~ /^5\.1./)) {
637 print "yes\n" if $has_ports == 1;
638 print "no\n" if $has_ports == 0;
640 $config{HAS_EPOLL} = $has_epoll;
641 $config{HAS_KQUEUE} = $has_kqueue;
643 printf "Checking for libgnutls... ";
644 if (($config{HAS_GNUTLS}) || ($config{HAS_GNUTLS} eq "y")) {
646 $config{HAS_GNUTLS} = "y";
649 $config{HAS_GNUTLS} = "n";
652 printf "Checking for openssl... ";
653 if (($config{HAS_OPENSSL}) || ($config{HAS_OPENSSL} eq "y")) {
655 $config{HAS_OPENSSL} = "y";
658 $config{HAS_OPENSSL} = "n";
661 printf "Checking if you are running an ancient, unsupported OS... ";
662 if ($config{OSNAME} =~ /FreeBSD/i)
664 my $version = `uname -r`;
665 if ($version =~ /^4\./)
667 my $foundit = `ls -l /usr/local/lib/libgnugetopt* | wc -l`;
670 # ICKY ICKY ICK, FREEBSD 4.x! GET AN UPGRADE!
671 $config{CRAQ} = "-L/usr/local/lib -lgnugetopt -DHAVE_DECL_GETOPT=1";
676 print "\n\nERROR: You require libgnugetopt (from ports or packages) to build InspIRCd on FreeBSD 4.11.\n";
682 print "no ($version)\n";
688 print "no ($config{OSNAME})\n";
691 ################################################################################
692 # BEGIN INTERACTIVE PART #
693 ################################################################################
698 print "\e[2J\e[0G\e[0d"; # J = Erase in Display, 2 = Entire Screen, (G, d) = Move cursor to (..,..)
701 my $rev = getrevision();
702 # Display Introduction Message..
704 Welcome to the \e[1mInspIRCd\e[0m Configuration program! (\e[1minteractive mode\e[0m)
705 \e[1mPackage maintainers: Type ./configure --help for non-interactive help\e[0m
707 *** If you are unsure of any of these values, leave it blank for ***
708 *** standard settings that will work, and your server will run ***
709 *** using them. Please consult your IRC network admin if in doubt. ***
711 Press \e[1m<RETURN>\e[0m to accept the default for any option, or enter
712 a new value. Please note: You will \e[1mHAVE\e[0m to read the docs
713 dir, otherwise you won't have a config file!
715 Your operating system is: \e[1;32m$config{OSNAME}\e[0m ($wholeos)
716 Maximum file descriptors: \e[1;32m$config{MAX_CLIENT_T}\e[0m
717 Your InspIRCd revision ID is \e[1;32mr$rev\e[0m
720 print " (Non-SVN build)";
724 $config{CHANGE_COMPILER} = "n";
725 print "I have detected the following compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.x\e[0m)\n";
727 while (($config{GCCVER} < 3) || ($config{GCCVER} eq "")) {
728 print "\e[1;32mIMPORTANT!\e[0m A GCC 2.x compiler has been detected, and
729 should NOT be used. You should probably specify a newer compiler.\n\n";
730 yesno('CHANGE_COMPILER',"Do you want to change the compiler?");
731 if ($config{CHANGE_COMPILER} =~ /y/i) {
732 print "What command do you want to use to invoke your compiler?\n";
733 print "[\e[1;32m$config{CC}\e[0m] -> ";
734 chomp($config{CC} = <STDIN>);
735 if ($config{CC} eq "") {
738 chomp(my $foo = `$config{CC} -dumpversion | cut -c 1`);
740 chomp($config{GCCVER} = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
741 print "Queried compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.x\e[0m)\n";
742 if ($config{GCCVER} < 3) {
743 print "\e[1;32mGCC 2.x WILL NOT WORK!\e[0m. Let's try that again, shall we?\n";
747 print "\e[1;32mWARNING!\e[0m Could not execute the compiler you specified. You may want to try again.\n";
754 # Directory Settings..
755 my $tmpbase = $config{BASE_DIR};
756 dir_check("do you wish to install the InspIRCd base", "BASE_DIR");
757 if ($tmpbase ne $config{BASE_DIR}) {
758 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Dir
759 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
760 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
761 $config{LIBRARY_DIR} = resolve_directory($config{BASE_DIR}."/lib"); # Library Directory
764 dir_check("are the configuration files", "CONFIG_DIR");
765 dir_check("are the modules to be compiled to", "MODULE_DIR");
766 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
767 dir_check("are the IRCd libraries to be placed", "LIBRARY_DIR");
770 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?");
774 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?");
778 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?");
781 my $chose_hiperf = (($config{USE_EPOLL} eq "y") || ($config{USE_KQUEUE} eq "y") || ($config{USE_PORTS} eq "y"));
782 if (!$chose_hiperf) {
783 print "No high-performance socket engines are available, or you chose\n";
784 print "not to enable one. Defaulting to select() engine.\n\n";
787 yesno('IPV6',"Would you like to build InspIRCd with IPv6 support?");
790 if ($config{IPV6} eq "y") {
791 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";
792 $config{SUPPORT_IP6LINKS} = "y";
794 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)");
798 if (($config{HAS_GNUTLS} eq "y") && ($config{HAS_OPENSSL} eq "y")) {
799 print "I have detected both \e[1;32mGnuTLS\e[0m and \e[1;32mOpenSSL\e[0m on your system.\n";
800 print "I will default to GnuTLS. If you wish to use OpenSSL\n";
801 print "instead, you should enable the OpenSSL module yourself\n";
802 print "by copying it from src/modules/extra to src/modules.\n\n";
803 print "Detected GnuTLS version: \e[1;32m" . $gnutls_ver . "\e[0m\n";
804 print "Detected OpenSSL version: \e[1;32m" . $openssl_ver . "\e[0m\n\n";
807 if ($config{HAS_GNUTLS} eq "y") {
808 yesno('USE_GNUTLS', "Would you like to enable SSL Support?");
809 if ($config{USE_GNUTLS} eq "y") {
810 print "\nUsing GnuTLS SSL module.\n";
812 } elsif ($config{HAS_OPENSSL} eq "y") {
813 yesno('USE_OPENSSL', "Would you like to enable SSL Support?");
814 if ($config{USE_OPENSSL} eq "y") {
815 print "\nUsing OpenSSL SSL module.\nYou will get better performance if you move to GnuTLS in the future.\n";
819 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";
822 print "\nThe following questions will ask you for various figures relating\n";
823 print "To your IRCd install. Please note that these should usually be left\n";
824 print "as defaults unless you have a real reason to change them. If they\n";
825 print "changed, then the values must be identical on all servers on your\n";
826 print "network, or malfunctions and/or crashes may occur, with the exception\n";
827 print "of the 'maximum number of clients' setting which may be different on\n";
828 print "different servers on the network.\n\n";
830 # File Descriptor Settings..
831 promptnumeric("number of clients at any one time", "MAX_CLIENT_T");
832 $config{MAX_CLIENT} = $config{MAX_CLIENT_T};
833 $config{MAX_DESCRIPTORS} = $config{MAX_CLIENT_T};
835 promptnumeric("length of nicknames", "NICK_LENGT");
836 promptnumeric("length of channel names", "CHAN_LENGT");
837 promptnumeric("number of mode changes in one line", "MAXI_MODES");
838 promptnumeric("length of an ident (username)", "MAX_IDENT");
839 promptnumeric("length of a quit message", "MAX_QUIT");
840 promptnumeric("length of a channel topic", "MAX_TOPIC");
841 promptnumeric("length of a kick message", "MAX_KICK");
842 promptnumeric("length of a GECOS (real name)", "MAX_GECOS");
843 promptnumeric("length of an away message", "MAX_AWAY");
848 if (($config{USE_GNUTLS} eq "y") && ($config{HAS_GNUTLS} ne "y"))
850 print "Sorry, but i couldn't detect gnutls. Make sure gnutls-config is in your path.\n";
853 if (($config{USE_OPENSSL} eq "y") && ($config{HAS_OPENSSL} ne "y"))
855 print "Sorry, but i couldn't detect openssl. Make sure openssl is in your path.\n";
860 if ($config{USE_GNUTLS} eq "y") {
861 unless (-r "src/modules/m_ssl_gnutls.cpp") {
862 print "Symlinking src/modules/m_ssl_gnutls.cpp from extra/\n";
863 symlink "extra/m_ssl_gnutls.cpp", "src/modules/m_ssl_gnutls.cpp" or print STDERR "Symlink failed: $!";
868 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
869 print "SSL Certificates Not found, Generating.. \n\n
870 *************************************************************
871 * Generating the Private Key may take some time, go grab a *
872 * Coffee. Even better, to generate some more entropy if it *
873 * is taking a while, open another console and type du / a *
874 * few times and get that HD going :) Then answer the *
875 * Questions which follow. If you are unsure, just hit enter *
876 *************************************************************\n\n";
877 $failed = make_gnutls_cert();
879 print "\n\e[1;32mCertificate generation failed!\e[0m\n\n";
881 print "\nCertificate generation complete, copying to config directory... ";
882 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
883 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
888 print "SSL Certificates found, skipping.\n\n";
893 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
895 } elsif ($config{USE_OPENSSL} eq "y") {
896 unless (-r "src/modules/m_ssl_openssl.cpp") {
897 print "Symlinking src/modules/m_ssl_openssl.cpp from extra/\n";
898 symlink "extra/m_ssl_openssl.cpp", "src/modules/m_ssl_openssl.cpp" or print STDERR "Symlink failed: $!";
904 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
905 print "SSL Certificates Not found, Generating.. \n\n
906 *************************************************************
907 * Generating the certificates may take some time, go grab a *
908 * coffee, or something. *
909 *************************************************************\n\n";
911 print "\nCertificate generation complete, copying to config directory... ";
912 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
913 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
914 File::Copy::move("dhparams.pem", "$config{CONFIG_DIR}/dhparams.pem") or print STDERR "Could not copy dhparams.pem!\n";
917 print "SSL Certificates found, skipping.\n\n"
922 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
925 if (($config{USE_GNUTLS} eq "n") && ($config{USE_OPENSSL} eq "n")) {
926 print "Skipping SSL Certificate generation, SSL support is not available.\n\n";
934 print "To build your server with these settings, please type '\e[1;32m$config{MAKEPROG}\e[0m' now.\n";
935 if (($config{USE_GNUTLS} eq "y") || ($config{USE_OPENSSL} eq "y")) {
936 print "Please remember that to enable \e[1;32mSSL support\e[0m you must\n";
937 print "load the required modules in your config. This configure process\n";
938 print "has just prepared these modules to be compiled for you, and has not\n";
939 print "configured them to be compiled into the core of the ircd.\n";
941 print "*** \e[1;32mRemember to edit your configuration files!!!\e[0m ***\n\n\n";
942 if (($config{OSNAME} eq "OpenBSD") && ($config{CC} ne "eg++")) {
943 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";
946 if ($config{GCCVER} < "3") {
948 \e[1;32mWARNING!\e[0m You are attempting to compile InspIRCd on GCC 2.x!
949 GCC 2.x series compilers only had partial (read as broken) C++ support, and
950 your compile will most likely fail horribly! If you have any problems, do NOT
951 report them to the bugtracker or forums without first upgrading your compiler
952 to a newer 3.x or 4.x (or whatever is available currently) version.
956 ################################################################################
958 ################################################################################
960 # Retrieves the .config.cache file, and loads values into the main config hash.
961 open(CACHE, ".config.cache") or return 0;
964 # Ignore Blank lines, and comments..
967 my ($key, $value) = split("=", $_, 2);
968 $value =~ /^\"(.*)\"$/;
969 # Do something with data here!
977 # Dump the contents of %config
978 print "Writing \e[1;32mcache file\e[0m for future ./configures ...\n";
979 open(FILEHANDLE, ">.config.cache");
980 foreach my $key (keys %config) {
981 print FILEHANDLE "$key=\"$config{$key}\"\n";
987 my ($desc, $hash_key) = @_;
990 print "In what directory $desc?\n";
991 print "[\e[1;32m$config{$hash_key}\e[0m] -> ";
992 chomp(my $var = <STDIN>);
994 $var = $config{$hash_key};
996 if ($var =~ /^\~\/(.+)$/) {
997 # Convert it to a full path..
998 $var = resolve_directory($ENV{HOME} . "/" . $1);
1000 elsif ((($config{OSNAME} =~ /MINGW32/i) and ($var !~ /^[A-Z]{1}:\\.*/)) and (substr($var,0,1) ne "/"))
1002 # Assume relative Path was given.. fill in the rest.
1003 $var = $this . "/$var";
1006 $var = resolve_directory($var);
1008 print "$var does not exist. Create it?\n[\e[1;32my\e[0m] ";
1009 chomp(my $tmp = <STDIN>);
1010 if (($tmp eq "") || ($tmp =~ /^y/i)) {
1011 # Attempt to Create the Dir..
1014 File::Path::mkpath($var, 0, 0777);
1017 unless (defined($chk) && -d $var) {
1018 print "Unable to create directory. ($var)\n\n";
1023 # They said they don't want to create, and we can't install there.
1028 if (!is_dir($var)) {
1029 # Target exists, but is not a directory.
1030 print "File $var exists, but is not a directory.\n\n";
1034 # Either Dir Exists, or was created fine.
1035 $config{$hash_key} = $var;
1045 $config{LDLIBS} = "-lstdc++";
1046 $config{FLAGS} = "-fPIC -Wall $config{OPTIMISATI}";
1047 $config{DEVELOPER} = "-fPIC -Wall -g";
1048 $SHARED = "-Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared" unless defined $opt_disablerpath;
1049 $config{MAKEPROG} = "make";
1051 if ($config{OSNAME} =~ /darwin/i) {
1052 $config{FLAGS} = "-DDARWIN -frtti -fPIC -Wall $config{OPTIMISATI}";
1053 $SHARED = "-bundle -twolevel_namespace -undefined dynamic_lookup";
1054 $config{LDLIBS} = "-ldl -lstdc++";
1057 if ($config{OSNAME} =~ /OpenBSD/i) {
1058 $config{MAKEPROG} = "gmake";
1059 $config{LDLIBS} = $config{LDLIBS} . " -lunwind";
1060 chomp(my $foo = `eg++ -dumpversion | cut -c 1`);
1061 # theyre running the package version of gcc (eg++)... detect it and set up its version numbers.
1062 # if theyre not running this, configure lets the build continue but they probably wont manage to
1063 # compile as this standard version is 2.95.3!
1065 $config{CC} = "eg++";
1066 chomp($config{GCCVER} = `eg++ -dumpversion | cut -c 1`); # we must redo these if we change the compiler path
1071 if ($config{OSNAME} =~ /Linux/i) {
1072 $config{LDLIBS} = "-ldl -lstdc++";
1073 $config{FLAGS} = "-fPIC -Wall $config{OPTIMISATI}";
1074 $config{FLAGS} .= " " . $ENV{CXXFLAGS} if exists($ENV{CXXFLAGS});
1075 $config{LDLIBS} .= " " . $ENV{LDLIBS} if exists($ENV{LDLIBS});
1076 $config{MAKEPROG} = "make";
1079 if ($config{OSNAME} =~ /FreeBSD/i) {
1080 $config{FLAGS} .= " " . $ENV{CXXFLAGS} if exists($ENV{CXXFLAGS});
1081 $config{LDLIBS} .= " " . $ENV{LDLIBS} if exists($ENV{LDLIBS});
1084 if ($config{OSNAME} =~ /SunOS/i or $config{OSNAME} =~ /solaris/i)
1086 # solaris/sunos needs these
1087 # socket = bsd sockets api
1089 # rt = POSIX realtime extensions
1090 # resolv = inet_aton only (why isnt this in nsl?!)
1091 $config{MAKEPROG} = "gmake";
1092 $config{LDLIBS} .= " -lsocket -lnsl -lrt -lresolv";
1096 if($config{OSNAME} =~ /MINGW32/i)
1098 # All code is position-independent on windows
1099 $config{FLAGS} =~ s/-fPIC //;
1103 return $config{OSNAME};
1106 my ($mliflags, $mfrules, $mobjs, $mfcount) = ("", "", "", 0);
1109 my($writeheader) = @_;
1111 # First File.. inspircd_config.h
1112 chomp(my $incos = `uname -n -s -r`);
1113 chomp(my $version = `sh src/version.sh`);
1114 chomp(my $revision2 = getrevision());
1115 if ($writeheader == 1)
1117 print "Writing \e[1;32minspircd_config.h\e[0m\n";
1118 open(FILEHANDLE, ">include/inspircd_config.h");
1119 my $NL = $config{NICK_LENGT}+1;
1120 my $CL = $config{CHAN_LENGT}+1;
1121 print FILEHANDLE <<EOF;
1122 /* Auto generated by configure, do not modify! */
1123 #ifndef __CONFIGURATION_AUTO__
1124 #define __CONFIGURATION_AUTO__
1126 /* this is for windows support. */
1127 #define CoreExport /**/
1128 #define DllExport /**/
1130 #define CONFIG_FILE "$config{CONFIG_DIR}/inspircd.conf"
1131 #define MOD_PATH "$config{MODULE_DIR}"
1132 #define VERSION "$version"
1133 #define REVISION "$revision2"
1134 #define MAXCLIENTS $config{MAX_CLIENT}
1135 #define MAXCLIENTS_S "$config{MAX_CLIENT}"
1136 #define SOMAXCONN_S "$config{_SOMAXCONN}"
1137 #define MAX_DESCRIPTORS $config{MAX_DESCRIPTORS}
1140 #define MAXMODES $config{MAXI_MODES}
1141 #define IDENTMAX $config{MAX_IDENT}
1142 #define MAXQUIT $config{MAX_QUIT}
1143 #define MAXTOPIC $config{MAX_TOPIC}
1144 #define MAXKICK $config{MAX_KICK}
1145 #define MAXGECOS $config{MAX_GECOS}
1146 #define MAXAWAY $config{MAX_AWAY}
1147 #define OPTIMISATION $config{OPTIMITEMP}
1148 #define LIBRARYDIR "$config{LIBRARY_DIR}"
1149 #define SYSTEM "$incos"
1151 print FILEHANDLE "#define MAXBUF " . ($config{MAXBUF}+2) . "\n";
1153 if ($config{OSNAME} =~ /SunOS/i) {
1154 print FILEHANDLE "#define IS_SOLARIS\n";
1156 if ($config{OSNAME} =~ /MINGW32/i) {
1157 print FILEHANDLE "#define IS_MINGW\n";
1159 if ($config{GCCVER} >= 3) {
1160 print FILEHANDLE "#define GCC3\n";
1162 if ($config{HAS_STRLCPY} eq "true") {
1163 print FILEHANDLE "#define HAS_STRLCPY\n";
1165 if ($config{HAS_STDINT} eq "true") {
1166 print FILEHANDLE "#define HAS_STDINT\n";
1168 if ($config{IPV6} =~ /y/i) {
1169 print FILEHANDLE "#define IPV6\n";
1171 if ($config{SUPPORT_IP6LINKS} =~ /y/i) {
1172 print FILEHANDLE "#define SUPPORT_IP6LINKS\n";
1175 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
1176 print FILEHANDLE "#define USE_KQUEUE\n";
1177 $se = "socketengine_kqueue";
1180 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
1181 print FILEHANDLE "#define USE_EPOLL\n";
1182 $se = "socketengine_epoll";
1185 if (($has_ports) && ($config{USE_PORTS} eq "y")) {
1186 print FILEHANDLE "#define USE_PORTS\n";
1187 $se = "socketengine_ports";
1190 # user didn't choose either epoll or select for their OS.
1191 # default them to USE_SELECT (ewwy puke puke)
1193 print FILEHANDLE "#define USE_SELECT\n";
1194 $se = "socketengine_select";
1196 print FILEHANDLE "\n#endif\n";
1202 open(FILEHANDLE, ">include/inspircd_se_config.h");
1203 print FILEHANDLE <<EOF;
1204 /* Auto generated by configure, do not modify or commit to svn! */
1205 #ifndef __CONFIGURATION_SOCKETENGINE__
1206 #define __CONFIGURATION_SOCKETENGINE__
1208 #include "socketengines/$se.h"
1216 # Create a Modules List..
1218 foreach my $i (@modlist)
1220 $modules .= "m_".$i.".so ";
1222 chomp($modules); # Remove Redundant whitespace..
1224 opendir(DIRHANDLE, "src/modules");
1225 foreach my $name (sort readdir(DIRHANDLE)) {
1226 if ($name =~ /^m_(.+?)$/) {
1227 if (defined(opendir(MDIRHANDLE, "src/modules/$name"))) {
1228 closedir(MDIRHANDLE);
1229 $modules .= "$name.so ";
1230 $uninstall_list = $uninstall_list . " -rm \$(MODULES)/$name.so\n";
1234 closedir(DIRHANDLE);
1237 # Write all .in files.
1240 my $exe = "inspircd";
1242 # Do this once here, and cache it in the .*.inc files,
1243 # rather than attempting to read src/version.sh from
1244 # compiled code -- we might not have the source to hand.
1245 # Fix for bug#177 by Brain.
1247 chomp($version = `sh ./src/version.sh`);
1248 chomp(my $revision = getrevision());
1249 $version = "$version(r$revision)";
1251 # We can actually parse any file starting with . and ending with .inc,
1252 # but right now we only parse .inspircd.inc to form './inspircd'
1254 print "Writing \e[1;32mMakefiles\e[0m\n";
1255 write_dynamic_modules_makefile();
1256 write_dynamic_makefile();
1258 opendir(DIRHANDLE, $this);
1260 foreach my $name (sort readdir(DIRHANDLE)) {
1261 if ($name =~ /^\.(.+)\.inc$/) {
1264 # Bug #353, omit this on non-darwin
1265 next if (($config{OSNAME} !~ /darwin/) && ($file eq "org.inspircd.plist"));
1267 # All .name.inc files need parsing!
1269 open(FILEHANDLE, ".$file.inc") or die ("Can't open .$file.inc");
1270 while (<FILEHANDLE>) {
1275 print "Writing \e[1;32m$file\e[0m ...\n";
1276 $tmp =~ s/\@CC\@/$config{CC}/ if defined $config{CC};
1277 $tmp =~ s/\@MAKEPROG\@/$config{MAKEPROG}/ if defined $config{MAKEPROG};
1278 $tmp =~ s/\@FLAGS\@/$config{FLAGS}/ if defined $config{FLAGS};
1279 $tmp =~ s/\@DEVELOPER\@/$config{DEVELOPER}/ if defined $config{DEVELOPER};
1280 $tmp =~ s/\@LDLIBS\@/$config{LDLIBS}/ if defined $config{LDLIBS};
1281 $tmp =~ s/\@BASE_DIR\@/$config{BASE_DIR}/ if defined $config{BASE_DIR};
1282 $tmp =~ s/\@CONFIG_DIR\@/$config{CONFIG_DIR}/ if defined $config{CONFIG_DIR};
1283 $tmp =~ s/\@MODULE_DIR\@/$config{MODULE_DIR}/ if defined $config{MODULE_DIR};
1284 $tmp =~ s/\@BINARY_DIR\@/$config{BINARY_DIR}/ if defined $config{BINARY_DIR};
1285 $tmp =~ s/\@LIBRARY_DIR\@/$config{LIBRARY_DIR}/ if defined $config{LIBRARY_DIR};
1286 $tmp =~ s/\@MODULES\@/$modules/ if defined $modules;
1287 $tmp =~ s/\@STARTSCRIPT\@/$config{STARTSCRIPT}/ if defined $config{STARTSCRIPT};
1288 $tmp =~ s/\@DESTINATION\@/$config{DESTINATION}/ if defined $config{DESTINATION};
1289 $tmp =~ s/\@EXTRA_DIR\@/$config{EXTRA_DIR}/ if defined $config{EXTRA_DIR};
1290 $tmp =~ s/\@EXECUTABLE\@/$exe/ if defined $exe;
1291 $tmp =~ s/\@MAKEORDER\@/$config{MAKEORDER}/ if defined $config{MAKEORDER};
1292 $tmp =~ s/\@VERSION\@/$version/ if defined $version;
1293 $tmp =~ s/\@INSTALL_LIST\@/$install_list/ if defined $install_list;
1294 $tmp =~ s/\@UNINSTALL_LIST\@/$uninstall_list/ if defined $uninstall_list;
1296 open(FILEHANDLE, ">$file");
1297 print FILEHANDLE $tmp;
1300 closedir(DIRHANDLE);
1302 # Make inspircd executable!
1303 chmod 0744, 'inspircd';
1306 sub write_dynamic_modules_makefile {
1307 # Modules Makefile..
1308 print "Writing \e[1;32msrc/modules/Makefile\e[0m\n";
1309 open(FILEHANDLE, ">src/modules/Makefile");
1312 # Module Makefile Header
1314 print FILEHANDLE <<EOF;
1315 ###################################################
1316 # Copyright 2002-2007 The InspIRCd Development Team
1317 # http://www.inspircd.org/wiki/index.php/Credits
1319 # Thanks to Andrew Church <achurch\@achurch.org>
1320 # for assisting with making this work right.
1322 # Automatically Generated by ./configure to add a
1323 # modules please run ./configure -modupdate
1324 ###################################################
1330 if ($config{OSNAME} =~ /darwin/) {
1331 print FILEHANDLE <<EOCHEESE;
1333 PICLDFLAGS = -twolevel_namespace -undefined dynamic_lookup -bundle
1337 print FILEHANDLE <<EOCHEESE;
1339 PICLDFLAGS = -fPIC -DPIC -shared
1345 # End Module Makefile Header
1348 # Create a Modules List..
1352 foreach my $i (@modlist) {
1354 # Write Entry to the MakeFile
1356 $cmflags = getcompilerflags("src/modules/m_".$i.".cpp");
1357 $liflags = getlinkerflags("src/modules/m_".$i.".cpp");
1358 my $deps = getdependencies("src/modules/m_".$i.".cpp");
1360 #print "file: $i: cmflags=$cmflags; liflags=$liflags; deps=$deps\n";
1363 if (nopedantic("src/modules/m_".$i.".cpp"))
1366 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
1367 \$(CC) -pipe -I../../include \$(NICEFLAGS) $cmflags \$(PICLDFLAGS) $liflags -export-dynamic -o m_$i.so m_$i.cpp
1373 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
1374 \$(CC) -pipe -I../../include \$(FLAGS) $cmflags \$(PICLDFLAGS) $liflags -export-dynamic -o m_$i.so m_$i.cpp
1377 $install_list = $install_list . " install -m \$(INSTMODE) src/modules/m_$i.so \$(MODPATH)\n";
1378 $uninstall_list = $uninstall_list . " -rm \$(MODULES)/m_$i.so\n";
1380 # End Write Entry to the MakeFile
1384 opendir(DIRHANDLE, "src/modules");
1385 foreach my $name (sort readdir(DIRHANDLE)) {
1386 if ($name =~ /^m_(.+?)$/) {
1391 # A module made of multiple files, in a dir, e.g. src/modules/m_spanningtree/
1392 if (defined(opendir(MDIRHANDLE, "src/modules/$name"))) {
1393 read_module_directory("src/modules/$name", $name);
1394 print "Composing Makefile rules for directory \e[1;32m$name\e[0m... (\e[1;32m$mfcount files found\e[0m)\n";
1395 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";
1396 if ($config{IS_DARWIN} eq "YES") {
1397 print FILEHANDLE " \$(CC) -pipe -twolevel_namespace -undefined dynamic_lookup \$(FLAGS) $mliflags -bundle -o $name.so $mobjs\n";
1399 print FILEHANDLE " \$(CC) -pipe \$(FLAGS) -shared $mliflags -o $name.so $mobjs\n";
1401 print FILEHANDLE "\n$mfrules\n";
1402 closedir(MDIRHANDLE);
1403 $install_list = $install_list . " install -m \$(INSTMODE) src/modules/$name.so \$(MODPATH)\n";
1407 closedir(DIRHANDLE);
1410 sub read_module_directory {
1411 my ($dpath, $reldpath) = @_;
1413 if (opendir(MDIRHANDLE, $dpath) == 0) {
1417 foreach my $fname (sort readdir(MDIRHANDLE)) {
1418 if ($fname =~ /\.cpp$/) {
1419 my $cmflags = getcompilerflags("$dpath/$fname");
1420 $mliflags = $mliflags . " " . getlinkerflags("$dpath/$fname");
1421 my $deps = getdependencies("$dpath/$fname");
1423 $oname =~ s/\.cpp$/.o/g;
1424 $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";
1425 $mfrules = $mfrules . " \$(CC) -pipe -I../../include -I. \$(FLAGS) $cmflags -export-dynamic -o $reldpath/$oname -c $reldpath/$fname\n\n";
1426 $mobjs = $mobjs . " $reldpath/$oname";
1429 elsif ((-d "$dpath/$fname") && !($fname eq ".") && !($fname eq "..")) {
1430 read_module_directory($dpath."/".$fname, $reldpath."/".$fname);
1437 # Yes i know we could use gcc -M but it seems to ideneify a lot of 'deep'
1438 # dependencies which are not relevent in C++.
1442 open (CPP, "<$file") or die("Can't open $file for reading!");
1447 foreach my $d (@ignoredeps)
1453 foreach my $dep (@immutabledeps)
1455 $immutable = $immutable . "../include/$dep ";
1457 $immutable =~ s/ $//g;
1459 while (defined(my $line = <CPP>))
1462 if ($line =~ /#include "(.+\.h)"/)
1464 if (!exists($dupe{$1}))
1466 $retlist = $retlist . "../include/$1 ";
1472 return length($immutable) ? $immutable . " " . $retlist : $retlist;
1475 sub write_dynamic_makefile
1479 my %existing_install_list = ();
1480 opendir(DIRHANDLE, "src/commands");
1481 foreach my $name (sort readdir(DIRHANDLE))
1483 if ($name =~ /^cmd_(.+)\.cpp$/)
1485 $cmdlist[$i++] = $1;
1486 $install_list = $install_list . " -install -m \$(INSTMODE) src/commands/cmd_" . $1 . ".so \$(LIBPATH)\n";
1487 $uninstall_list = $uninstall_list . " -rm \$(LIBPATH)/cmd_$1.so\n";
1490 closedir(DIRHANDLE);
1494 $config{USE_EPOLL} = 0;
1498 $config{USE_KQUEUE} = 0;
1502 $config{USE_PORTS} = 0;
1505 foreach my $dir (("src","src/commands","src/modes","src/socketengines","src/modules"))
1507 print "Scanning \e[1;32m$dir\e[0m for core files ";
1508 opendir(DIRHANDLE, $dir);
1509 foreach my $name (sort readdir(DIRHANDLE))
1511 if ($name =~ /\.cpp$/)
1513 open (CPP, "<$dir/$name") or die("Can't open $dir/$name to scan it! oh bugger");
1515 while (defined(my $line = <CPP>))
1518 if ($line =~ /\/\* \$Core: (\w+) \*\//i)
1520 $filelist{$name} = $1;
1522 elsif ($line =~ /\/\* \$ExtraDeps: (.*?) \*\//i)
1524 $specialdeps{$name} = $1;
1526 elsif ($line =~ /\/\* \$ExtraObjects: (.*?) \*\//i)
1528 $extraobjects{$name} = $1;
1530 elsif ($line =~ /\/\* \$ExtraBuild: (.*?) \*\//i)
1532 $extrabuildlines{$name} = $1;
1534 elsif ($line =~ /\/\* \$ExtraSources: (.*?) \*\//i)
1536 $extrasources{$name} = $1;
1538 elsif ($line =~ /\/\* \$If: (\w+) \*\//i)
1540 if (($config{$1} !~ /y/i) and ($config{$1} ne "1"))
1543 while (defined($line = <CPP>))
1546 die ("\$If buildsystem instruction within another \$If in file $dir/$name") if ($line =~ /\/\* \$If: (\w+) \*\//i);
1547 last if ($line =~ /\/\* \$EndIf \*\//i);
1551 elsif ($line =~ /\/\* \$Install: (.*?) \*\//i)
1553 if (!exists($existing_install_list{$1}))
1555 $existing_install_list{$1} = 1;
1556 my $idir = (split(' ',$1))[1];
1557 my $ifile = (split(' ',$1))[0];
1558 $install_list = $install_list . " -install -m \$(INSTMODE) $1\n";
1559 $ifile =~ s/.*\///g;
1560 $uninstall_list = $uninstall_list . " -rm $idir/$ifile\n";
1563 elsif ($line =~ /\/\* \$CopyInstall: (.*?) \*\//i)
1565 if (!exists($existing_install_list{$1}))
1567 $existing_install_list{$1} = 1;
1568 my $idir = (split(' ',$1))[1];
1569 my $ifile = (split(' ',$1))[0];
1570 $install_list = $install_list . " -cp $1\n";
1571 $ifile =~ s/.*\///g;
1572 $uninstall_list = $uninstall_list . " -rm $idir/$ifile\n";
1579 closedir(DIRHANDLE);
1583 my $freebsd4libs = (defined $config{CRAQ} ? $config{CRAQ} : "");
1586 my $all_libsonly = "";
1588 my $libraryext = "";
1592 if ($config{IS_DARWIN} eq "YES")
1594 $libraryext = "dylib";
1595 $othercrap = " \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c inspircd.cpp\n \$(CC) -pipe -dynamic -bind_at_load -L. -o inspircd \$(LDLIBS) inspircd.o "
1600 $RPATH = "-Wl,--rpath -Wl,$config{LIBRARY_DIR}" unless defined $opt_disablerpath;
1601 $othercrap = " \$(CC) -pipe -I../include $RPATH \$(FLAGS) $freebsd4libs -rdynamic -L. inspircd.cpp -o inspircd \$(LDLIBS) ";
1604 foreach my $cpp (sort keys %filelist)
1606 $all = $all . $filelist{$cpp} . "." . $libraryext . " ";
1607 $all_libsonly = $all_libsonly . $filelist{$cpp} . "." . $libraryext . " ";
1608 $install_list = $install_list . " -install -m \$(INSTMODE) src/" . $filelist{$cpp} . "." . $libraryext . " \$(LIBPATH)\n";
1609 $uninstall_list = $uninstall_list . " -rm \$(LIBPATH)/" . $filelist{$cpp} . "." . $libraryext . "\n";
1611 $all = $all . "moo inspircd\n";
1613 $othercrap = $othercrap . " $all_libsonly\n\n";
1615 open(FH,">src/Makefile") or die("Could not write src/Makefile");
1618 CC = im a cheezeball
1619 CXXFLAGS = -I../include \${FLAGS}
1620 CPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* //' | grep -v svn)
1621 RELCPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* /modes\\//' | grep -v svn)
1625 print FH "$all\n\n";
1627 my $deps = calcdeps("src/inspircd.cpp");
1628 print FH "inspircd: inspircd.cpp $deps $all_libsonly\n";
1629 print FH "$othercrap\n";
1631 foreach my $cpp (sort keys %filelist)
1633 my $thislib = $filelist{$cpp} . "." . $libraryext;
1637 $objs =~ s/\.cpp$/.o/;
1638 if (exists($extraobjects{$cpp}))
1640 $objs = $objs . " " . $extraobjects{$cpp};
1642 if (exists($extrasources{$cpp}))
1644 $rawcpp = $rawcpp . " " . $extrasources{$cpp};
1646 if ($config{IS_DARWIN} eq "YES")
1648 $libcrap = "-install_name " . $config{LIBRARY_DIR} . "/" . $thislib . " -dynamiclib -twolevel_namespace -undefined dynamic_lookup";
1652 if (defined $opt_disablerpath)
1654 $libcrap = " -shared";
1658 $libcrap = "-Wl,--rpath -Wl," . $config{LIBRARY_DIR} . " -shared";
1661 $deps = calcdeps("src/$cpp");
1662 if (exists($extrasources{$cpp}))
1664 foreach my $seperate (sort split(' ',$extrasources{$cpp}))
1666 my $d = calcdeps("src/$extrasources{$cpp}") . " ";
1669 $deps = $deps . $d . " ";
1673 print FH $thislib . ": $cpp $deps ". (defined($specialdeps{$cpp}) ? $specialdeps{$cpp} : "") . "\n";
1674 print FH " \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c $rawcpp\n";
1675 if (exists($extrabuildlines{$cpp}))
1677 print FH " " . $extrabuildlines{$cpp} . "\n";
1679 print FH " \$(CC) -pipe $libcrap -o " . $thislib . " " . $objs . "\n\n";
1682 print FH "moo:\n \${MAKE} -C \"commands\" DIRNAME=\"src/commands\" CC=\"\$(CC)\" \$(MAKEARGS)\n\n";
1684 # close main makefile
1688 # generate a list of .so
1689 foreach my $cmd (@cmdlist) {
1690 $cmdobjs = $cmdobjs . "cmd_$cmd.so ";
1693 # and now reopen the commands makefile
1694 open(FH,">src/commands/Makefile") or die("Could not write src/commands/Makefile");
1697 CXXFLAGS = -I../../include \${FLAGS}
1704 # now print the command file details.
1705 foreach my $cmd (@cmdlist) {
1707 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
1708 \$(CC) -pipe -I../../include \$(FLAGS) -export-dynamic -c cmd_$cmd.cpp
1709 \$(CC) -pipe $SHARED -o cmd_$cmd.so cmd_$cmd.o
1713 #try build a .so, no intermediate .o
1714 # \$(CC) -pipe -I../../include \$(FLAGS) -export-dynamic $SHARED -o cmd_$cmd.so
1716 #this works for sure
1717 # \$(CC) -pipe -I../../include \$(FLAGS) -export-dynamic -c cmd_$cmd.cpp
1718 # \$(CC) -pipe $SHARED -o cmd_$cmd.so cmd_$cmd.o
1721 # Routine to list out the extra/ modules that have been enabled.
1722 # Note: when getting any filenames out and comparing, it's important to lc it if the
1723 # file system is not case-sensitive (== Epoc, MacOS, OS/2 (incl DOS/DJGPP), VMS, Win32
1724 # (incl NetWare, Symbian)). Cygwin may or may not be case-sensitive, depending on
1725 # configuration, however, File::Spec does not currently tell us (it assumes Unix behavior).
1726 sub list_extras () {
1729 my $srcdir = File::Spec->catdir("src", "modules");
1730 my $abs_srcdir = File::Spec->rel2abs($srcdir);
1733 opendir $dd, File::Spec->catdir($abs_srcdir, "extra") or die (File::Spec->catdir($abs_srcdir, "extra") . ": $!\n");
1734 my @extras = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1737 opendir $dd, $abs_srcdir or die "$abs_srcdir: $!\n";
1738 my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1741 my $maxlen = (sort { $b <=> $a } (map {length($_)} (@extras)))[0];
1743 EXTRA: for my $extra (@extras) {
1744 next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra);
1745 next if ($extra eq '.svn');
1746 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1747 my $abs_source = File::Spec->catfile($abs_srcdir, $extra);
1748 next unless ($extra =~ m/\.(cpp|h)$/ || (-d $abs_extra)); # C++ Source/Header, or directory
1749 if (-l $abs_source) {
1750 # Symlink, is it in the right place?
1751 my $targ = readlink($abs_source);
1752 my $abs_targ = File::Spec->rel2abs($targ, $abs_srcdir);
1753 if ($abs_targ eq $abs_extra) {
1754 $extras{$extra} = "\e[32;1menabled\e[0m";
1756 $extras{$extra} = sprintf("\e[31;1mwrong symlink target (%s)\e[0m", $abs_targ);
1758 } elsif (-e $abs_source) {
1759 my ($devext, $inoext) = stat($abs_extra);
1760 my ($devsrc, $inosrc, undef, $lnksrc) = stat($abs_source);
1762 if ($devsrc == $devext && $inosrc == $inoext) {
1763 $extras{$extra} = "\e[32;1menabled\e[0m";
1765 $extras{$extra} = sprintf("\e[31;1mwrong hardlink target (%d:%d)\e[0m", $devsrc, $inosrc);
1768 open my $extfd, "<", $abs_extra;
1769 open my $srcfd, "<", $abs_source;
1771 if (scalar(<$extfd>) eq scalar(<$srcfd>)) {
1772 $extras{$extra} = "\e[32;1menabled\e[0m";
1774 $extras{$extra} = sprintf("\e[31;1mout of synch (re-copy)\e[0m");
1778 $extras{$extra} = "\e[33;1mdisabled\e[0m";
1781 # Now let's add dependency info
1782 for my $extra (keys(%extras)) {
1783 next unless $extras{$extra} =~ m/enabled/; # only process enabled extras.
1784 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1785 my @deps = split / +/, getdependencies($abs_extra);
1786 for my $dep (@deps) {
1787 if (exists($extras{$dep})) {
1788 my $ref = \$extras{$dep}; # Take reference.
1789 if ($$ref !~ m/needed by/) {
1790 # First dependency found.
1791 if ($$ref =~ m/enabled/) {
1792 $$ref .= " (needed by \e[32;1m$extra\e[0m";
1794 $$ref =~ s/\e\[.*?m//g; # Strip out previous coloring. Will be set in bold+red+blink later.
1795 $$ref .= " (needed by \e[0;32;1;5m$extra\e[0;31;1;5m";
1798 if ($$ref =~ m/enabled/) {
1799 $$ref .= ", \e[32;1m$extra\e[0m";
1801 $$ref .= ", \e[0;32;1;5m$extra\e[0;31;1;5m";
1807 for my $extra (sort {$a cmp $b} keys(%extras)) {
1808 my $text = $extras{$extra};
1809 if ($text =~ m/needed by/ && $text !~ m/enabled/) {
1810 printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? ")" : "");
1812 printf "%-*s = %s%s\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? "\e[0m)" : "");
1815 return keys(%extras) if wantarray; # Can be used by manage_extras.
1818 sub enable_extras (@) {
1820 for my $extra (@extras) {
1821 my $extrapath = "src/modules/extra/$extra";
1822 if (!-e $extrapath) {
1823 print STDERR "Cannot enable \e[32;1m$extra\e[0m : No such file or directory in src/modules/extra\n";
1826 my $source = "src/modules/$extra";
1828 print STDERR "Cannot enable \e[32;1m$extra\e[0m : destination in src/modules exists (might already be enabled?)\n";
1831 # Get dependencies, and add them to be processed.
1832 my @deps = split / +/, getdependencies($extrapath);
1833 for my $dep (@deps) {
1834 next if scalar(grep { $_ eq $dep } (@extras)) > 0; # Skip if we're going to be enabling it anyway.
1835 if (!-e "src/modules/$dep") {
1836 if (-e "src/modules/extra/$dep") {
1837 print STDERR "Will also enable extra \e[32;1m$dep\e[0m (needed by \e[32;1m$extra\e[0m)\n";
1840 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";
1844 print "Enabling $extra ... \n";
1845 symlink "extra/$extra", $source or print STDERR "$source: Cannot link to 'extra/$extra': $!\n";
1849 sub disable_extras (@)
1851 opendir my $dd, "src/modules/extra/";
1852 my @files = readdir($dd);
1855 EXTRA: for my $extra (@extras) {
1856 my $extrapath = "src/modules/extra/$extra";
1857 my $source = "src/modules/$extra";
1858 if (!-e $extrapath) {
1859 print STDERR "Cannot disable \e[32;1m$extra\e[0m : Is not an extra\n";
1862 if ((! -l $source) || readlink($source) ne "extra/$extra") {
1863 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";
1866 # Check if anything needs this.
1867 for my $file (@files) {
1868 my @deps = split / +/, getdependencies("src/modules/extra/$file");
1869 # File depends on this extra...
1870 if (scalar(grep { $_ eq $extra } @deps) > 0) {
1871 # And is both enabled and not about to be disabled.
1872 if (-e "src/modules/$file" && scalar(grep { $_ eq $file } @extras) < 1) {
1873 print STDERR "Cannot disable \e[32;1m$extra\e[0m : is needed by \e[32;1m$file\e[0m\n";
1879 print "Disabling $extra ... \n";
1880 unlink "src/modules/$extra" or print STDERR "Cannot disable \e[32;1m$extra\e[0m : $!\n";