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;
30 # Utility functions for our buildsystem
34 use make::opensslcert;
36 ###############################################################################################
40 ###############################################################################################
42 # If you wish to ignore a dependency throughout the entire core, add it here.
45 "inspircd_win32wrapper.h", # windows has its own configure program
48 # If you wish for all files in the entire core to have a given dependency, insert it here.
49 # You should keep this to an absolute minimum to avoid rebuilds that are not neccessary.
51 our @immutabledeps = (
52 "inspircd_config.h", # auto re-generated by configure
56 ###############################################################################################
58 # NON-EDITABLE VARIABLES
60 ###############################################################################################
62 # List of commands that make up 'make install' and 'make deinstall'
64 our $install_list = "";
65 our $uninstall_list = "";
67 # This is a list of all files in the core. Each cpp file is mapped to a shared object file,
68 # whos file extension is omitted (these can vary from system to system). Auto detected by
69 # scanning the src/*.cpp files for files containing /* $Core: */ identifiers.
73 # If you wish for a file to have special dependencies in the makefile, add an entry here.
74 # Auto populated by /* $ExtraDeps: */ instruction
76 our %specialdeps = ();
78 # If you wish for a file to have extra make lines (in between the compile and link steps)
79 # then insert them here.
80 # Auto populated by /* $ExtraBuild: */ instruction
82 our %extrabuildlines = ();
84 # If you wish for a file to be linked against extra objects or arctives, insert them here.
85 # Auto populated by /* $ExtraObjects: */ instruction
87 our %extraobjects = ();
89 # If you wish to compile extra cpp sources into an object, define them here.
90 # NOTE: Certain cpp files such as the socket engines have a value auto calculated
91 # for this table so that their derived class is built.
92 # Auto populated by /* $ExtraSources: */ instruction
94 our %extrasources = ();
96 our ($opt_use_gnutls, $opt_rebuild, $opt_use_openssl, $opt_nointeractive, $opt_nick_length,
97 $opt_chan_length, $opt_maxclients, $opt_ports, $opt_epoll, $opt_kqueue, $opt_noports,
98 $opt_noepoll, $opt_nokqueue, $opt_disablerpath, $opt_ipv6, $opt_ipv6links,
99 $opt_noipv6links, $opt_ident, $opt_quit, $opt_topic, $opt_maxbuf, $opt_kick,
100 $opt_gecos, $opt_away, $opt_modes, $opt_disable_debug, $opt_maxchans,
103 our ($opt_cc, $opt_base_dir, $opt_config_dir, $opt_module_dir, $opt_binary_dir,
108 sub enable_extras (@);
110 sub disable_extras (@);
112 my @opt_enableextras;
113 my @opt_disableextras;
116 'enable-gnutls' => \$opt_use_gnutls,
117 'rebuild' => \$opt_rebuild,
118 'enable-openssl' => \$opt_use_openssl,
119 'disable-interactive' => \$opt_nointeractive,
120 'with-nick-length=i' => \$opt_nick_length,
121 'with-channel-length=i' => \$opt_chan_length,
122 'with-max-clients=i' => \$opt_maxclients,
123 'enable-ports' => \$opt_ports,
124 'enable-epoll' => \$opt_epoll,
125 'enable-kqueue' => \$opt_kqueue,
126 'disable-ports' => \$opt_noports,
127 'disable-epoll' => \$opt_noepoll,
128 'disable-kqueue' => \$opt_nokqueue,
129 'disable-rpath' => \$opt_disablerpath,
130 'enable-ipv6' => \$opt_ipv6,
131 'enable-remote-ipv6' => \$opt_ipv6links,
132 'disable-remote-ipv6' => \$opt_noipv6links,
133 'with-cc=s' => \$opt_cc,
134 'with-ident-length=i' => \$opt_ident,
135 'with-quit-length=i' => \$opt_quit,
136 'with-topic-length=i' => \$opt_topic,
137 'with-maxbuf=i' => \$opt_maxbuf,
138 'with-kick-length=i' => \$opt_kick,
139 'with-gecos-length=i' => \$opt_gecos,
140 'with-away-length=i' => \$opt_away,
141 'with-max-modes=i' => \$opt_modes,
142 'prefix=s' => \$opt_base_dir,
143 'config-dir=s' => \$opt_config_dir,
144 'module-dir=s' => \$opt_module_dir,
145 'binary-dir=s' => \$opt_binary_dir,
146 'library-dir=s' => \$opt_library_dir,
147 'disable-debuginfo' => sub { $opt_disable_debug = 1 },
148 'help' => sub { showhelp(); },
149 'modupdate' => sub { modupdate(); },
150 'update' => sub { update(); },
151 'svnupdate' => sub { svnupdate(); },
152 'clean' => sub { clean(); },
153 'list-extras' => sub { list_extras; exit 0; }, # This, --enable-extras, and --disable-extras are for non-interactive managing.
154 'enable-extras=s@' => \@opt_enableextras, # ^
155 'disable-extras=s@' => \@opt_disableextras, # ^
158 if (scalar(@opt_enableextras) + scalar(@opt_disableextras) > 0) {
159 @opt_enableextras = split /,/, join(',', @opt_enableextras);
160 @opt_disableextras = split /,/, join(',', @opt_disableextras);
161 enable_extras(@opt_enableextras);
162 disable_extras(@opt_disableextras);
164 print "Remember: YOU are responsible for making sure any libraries needed have been installed!\n";
165 print "Run $0 -modupdate after you've done this to update the makefiles.\n";
169 our $non_interactive = (
170 (defined $opt_library_dir) ||
171 (defined $opt_base_dir) ||
172 (defined $opt_config_dir) ||
173 (defined $opt_module_dir) ||
174 (defined $opt_base_dir) ||
175 (defined $opt_binary_dir) ||
176 (defined $opt_nointeractive) ||
177 (defined $opt_away) ||
178 (defined $opt_gecos) ||
179 (defined $opt_kick) ||
180 (defined $opt_maxclients) ||
181 (defined $opt_modes) ||
182 (defined $opt_topic) ||
183 (defined $opt_quit) ||
184 (defined $opt_ident) ||
186 (defined $opt_ipv6) ||
187 (defined $opt_ipv6links) ||
188 (defined $opt_noipv6links) ||
189 (defined $opt_kqueue) ||
190 (defined $opt_epoll) ||
191 (defined $opt_ports) ||
192 (defined $opt_maxchans) ||
193 (defined $opt_opermaxchans) ||
194 (defined $opt_chan_length) ||
195 (defined $opt_nick_length) ||
196 (defined $opt_use_openssl) ||
197 (defined $opt_nokqueue) ||
198 (defined $opt_noepoll) ||
199 (defined $opt_noports) ||
200 (defined $opt_maxbuf) ||
201 (defined $opt_use_gnutls)
203 our $interactive = !$non_interactive;
205 chomp(our $topdir = getcwd());
206 our $this = resolve_directory($topdir); # PWD, Regardless.
207 our @modlist = (); # Declare for Module List..
208 our %config = (); # Initiate Configuration Hash..
209 $config{ME} = resolve_directory($topdir); # Present Working Directory
211 $config{BASE_DIR} = $config{ME};
213 if (defined $opt_base_dir)
215 $config{BASE_DIR} = $opt_base_dir;
218 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Directory
219 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
220 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
221 $config{LIBRARY_DIR} = resolve_directory($config{BASE_DIR}."/lib"); # Library Directory
223 if (defined $opt_config_dir)
225 $config{CONFIG_DIR} = $opt_config_dir;
227 if (defined $opt_module_dir)
229 $config{MODULE_DIR} = $opt_module_dir;
231 if (defined $opt_binary_dir)
233 $config{BINARY_DIR} = $opt_binary_dir;
235 if (defined $opt_library_dir)
237 $config{LIBRARY_DIR} = $opt_library_dir;
239 chomp($config{HAS_GNUTLS} = `libgnutls-config --version 2>/dev/null | cut -c 1,2,3`); # GNUTLS Version.
240 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`); # Openssl version
241 chomp(our $gnutls_ver = $config{HAS_GNUTLS});
242 chomp(our $openssl_ver = $config{HAS_OPENSSL});
243 $config{USE_GNUTLS} = "n";
244 if (defined $opt_use_gnutls)
246 $config{USE_GNUTLS} = "y"; # Use gnutls.
248 $config{USE_OPENSSL} = "n"; # Use openssl.
249 if (defined $opt_use_openssl)
251 $config{USE_OPENSSL} = "y";
254 # no, let's not change these.
255 $config{OPTIMITEMP} = "0"; # Default Optimisation Value
256 if (!defined $opt_disable_debug)
258 $config{OPTIMISATI} = "-g1"; # Optimisation Flag
262 $config{OPTIMISATI} = "-O2"; # DEBUGGING OFF!
265 $config{NICK_LENGT} = "31"; # Default Nick Length
266 if (defined $opt_nick_length)
268 $config{NICK_LENGT} = $opt_nick_length;
270 $config{CHAN_LENGT} = "64"; # Default Channel Name Length
271 if (defined $opt_chan_length)
273 $config{CHAN_LENGT} = $opt_chan_length;
275 $config{MAXI_MODES} = "20"; # Default Max. Number of Modes set at once.
276 if (defined $opt_modes)
278 $config{MAXI_MODES} = $opt_modes;
280 $config{HAS_STRLCPY} = "false"; # strlcpy Check.
281 $config{HAS_STDINT} = "false"; # stdint.h check
282 $config{USE_KQUEUE} = "y"; # kqueue enabled
283 if (defined $opt_kqueue)
285 $config{USE_KQUEUE} = "y";
287 if (defined $opt_nokqueue)
289 $config{USE_KQUEUE} = "n";
291 $config{USE_EPOLL} = "y"; # epoll enabled
292 if (defined $opt_epoll)
294 $config{USE_EPOLL} = "y";
296 if (defined $opt_noepoll)
298 $config{USE_EPOLL} = "n";
300 $config{USE_PORTS} = "y"; # epoll enabled
301 if (defined $opt_ports)
303 $config{USE_PORTS} = "y";
305 if (defined $opt_noports)
307 $config{USE_PORTS} = "n";
309 $config{IPV6} = "n"; # IPv6 support (experimental)
310 if (defined $opt_ipv6)
314 $config{SUPPORT_IP6LINKS} = "y"; # IPv4 supporting IPv6 links (experimental)
315 if (defined $opt_ipv6links)
317 $config{SUPPORT_IP6LINKS} = "y";
319 if (defined $opt_noipv6links)
321 $config{SUPPORT_IP6LINKS} = "n";
323 chomp($config{MAX_CLIENT_T} = `sh -c \"ulimit -n\"`); # FD Limit
324 chomp($config{MAX_DESCRIPTORS} = `sh -c \"ulimit -n\"`); # Hard FD Limit
325 chomp($config{GCCVER} = `g++ -dumpversion | cut -c 1`); # Major GCC Version
326 $config{_SOMAXCONN} = SOMAXCONN; # Max connections in accept queue
327 $config{OSNAME} = $^O; # Operating System Name
328 $config{IS_DARWIN} = "NO"; # Is OSX?
329 $config{STARTSCRIPT} = "inspircd"; # start script?
330 $config{DESTINATION} = "BASE"; # Is target path.
331 $config{EXTRA_DIR} = ""; # Is empty.
332 if ($config{OSNAME} =~ /darwin/i)
334 $config{IS_DARWIN} = "YES";
335 $config{STARTSCRIPT} = "org.inspircd.plist"; # start script for OSX.
336 $config{DESTINATION} = "LAUNCHDPATH"; # Is OSX target.
337 $config{EXTRA_DIR} = " launchd_dir"; # Is OSX specific path.
339 $config{CC} = "g++"; # C++ compiler
342 $config{CC} = $opt_cc;
344 our $exec = $config{CC} . " -dumpversion | cut -c 1";
345 chomp($config{GCCVER} = `$exec`); # Major GCC Version
346 $config{MAKEORDER} = "ircd mods"; # build order
347 $config{MAX_IDENT} = "12"; # max ident size
348 $config{MAX_QUIT} = "255"; # max quit message size
349 $config{MAX_TOPIC} = "307"; # max topic size
350 $config{MAX_KICK} = "255"; # max kick message size
351 $config{MAX_GECOS} = "128"; # max GECOS size
352 $config{MAX_AWAY} = "200"; # max AWAY size
353 $config{MAXBUF} = "512"; # Max buffer size
354 if (defined $opt_ident)
356 $config{MAX_IDENT} = $opt_ident;
358 if (defined $opt_quit)
360 $config{MAX_QUIT} = $opt_quit;
362 if (defined $opt_topic)
364 $config{MAX_TOPIC} = $opt_topic;
366 if (defined $opt_kick)
368 $config{MAX_KICK} = $opt_kick;
370 if (defined $opt_gecos)
372 $config{MAX_GECOS} = $opt_gecos;
374 if (defined $opt_away)
376 $config{MAX_AWAY} = $opt_away;
379 $config{HAS_OPENSSL} =~ /^([-[:digit:].]+)([a-z])?(\-[a-z][0-9])?$/;
380 $config{HAS_OPENSSL} = $1;
382 if ($config{GCCVER} eq "") {
383 print $config{CC} . " was not found! You require g++ (the GNU C++ compiler, part of GCC) to build InspIRCd!\n";
387 our $fd_scan_fail = "";
388 if (!$config{MAX_CLIENT_T}) {
389 $config{MAX_CLIENT_T} = 1024; # Set a reasonable 'Default'
390 $fd_scan_fail = "true"; # Used Later
393 # Get and Set some important vars..
398 unlink(".config.cache");
401 our ($has_epoll, $has_ports, $has_kqueue) = (0, 0, 0);
406 chomp($topdir = getcwd());
407 $this = resolve_directory($topdir); # PWD, Regardless.
409 # Does the cache file exist?
411 # No, No it doesn't.. *BASH*
412 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
415 # We've Loaded the cache file and all our variables..
416 print "Updating files...\n";
418 if (defined($opt_disable_debug) && $opt_disable_debug == 1)
420 print "Disabling debug information (-g).\n";
421 $config{OPTIMISATI} = "";
424 $has_epoll = $config{HAS_EPOLL};
425 $has_ports = $config{HAS_PORTS};
426 $has_kqueue = $config{HAS_KQUEUE};
435 print "Configure update failed: $@\n";
443 chomp($topdir = getcwd());
444 $this = resolve_directory($topdir); # PWD, Regardless.
446 # Does the cache file exist?
448 # No, No it doesn't.. *BASH*
449 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
452 # We've Loaded the cache file and all our variables..
453 print "Updating files...\n";
455 $has_epoll = $config{HAS_EPOLL};
456 $has_ports = $config{HAS_PORTS};
457 $has_kqueue = $config{HAS_KQUEUE};
466 print "Module update failed: $@\n";
476 open(FH,"<.svn/entries") or $fail = 1;
478 print "This is not an SVN copy of InspIRCd.\n";
485 system("svn update");
486 system("perl configure -update");
487 if (defined $opt_rebuild) {
488 system("make install");
493 print "Running non-interactive configure...\n" unless $interactive;
494 print "Checking for cache from previous configure... ";
495 print ((!getcache()) ? "not found\n" : "found\n");
496 print "Checking operating system version... ";
497 print getosflags() . "\n";
499 if (defined $opt_maxclients)
501 $config{MAX_CLIENT} = $opt_maxclients;
504 if (!$config{MAX_CLIENT}) {
505 # If the cache hasn't set the max clients, copy the variable of MAX_CLIENT_T, this
506 # allows us to keep _T for testing purposes. (ie. "Are you sure you want to go
507 # higher than the found value" :))
508 $config{MAX_CLIENT} = $config{MAX_CLIENT_T};
511 printf "Checking if stdint.h exists... ";
512 $config{HAS_STDINT} = "true";
514 open(STDINT, "</usr/include/stdint.h") or $config{HAS_STDINT} = "false";
515 if ($config{HAS_STDINT} eq "true") {
518 print "yes\n" if $config{HAS_STDINT} eq "true";
519 print "no\n" if $config{HAS_STDINT} eq "false";
521 printf "Checking if strlcpy exists... ";
522 # Perform the strlcpy() test..
523 $config{HAS_STRLCPY} = "false";
525 open(STRLCPY, "</usr/include/string.h") or $fail = 1;
527 while (defined(my $line = <STRLCPY>)) {
529 # try and find the delcaration of:
530 # size_t strlcpy(...)
531 if ($line =~ /size_t(\0x9|\s)+strlcpy/) {
532 $config{HAS_STRLCPY} = "true";
537 print "yes\n" if $config{HAS_STRLCPY} eq "true";
538 print "no\n" if $config{HAS_STRLCPY} eq "false";
540 printf "Checking if kqueue exists... ";
543 open(KQUEUE, "</usr/include/sys/event.h") or $fail = 1;
545 while (defiined(my $line = <KQUEUE>)) {
547 # try and find the delcaration of:
549 if ($line =~ /int(\0x9|\s)+kqueue/) {
555 print "yes\n" if $has_kqueue == 1;
556 print "no\n" if $has_kqueue == 0;
558 printf "Checking if epoll exists... ";
561 open(EPOLL, "</usr/include/sys/epoll.h") or $fail = 1;
567 my $kernel = `uname -r`;
569 if (($kernel =~ /^2\.0\./) || ($kernel =~ /^2\.2\./) || ($kernel =~ /^2\.4\./)) {
574 # Suggestion from nenolod, weed out odd systems which have glibc built
575 # against 2.4 kernels (ick)
576 my $kernel_arch = `uname -p`;
580 if ($kernel_arch =~ /x86_64/) {
581 open (FH,"/lib64/libc.so.6|") or $has_epoll = 0;
584 open (FH,"/lib/libc.so.6|") or $has_epoll = 0;
588 while (defined(my $line = <FH>))
591 if ($line =~ /GNU C Library .* version (.*?) /)
594 $libcv =~ /(\d+\.\d+)/;
597 elsif ($line =~ /Compiled on a Linux (.*?\..*?)\.* system/)
600 # Fix for some retarded libc builds, strip off >> and << etc.
601 $kernelv =~ /(\d+\.\d+)/;
609 printf "libc too old: $libcv... ";
614 printf "libc built against older kernel $kernelv... ";
619 print "yes\n" if $has_epoll == 1;
620 print "no\n" if $has_epoll == 0;
622 printf "Checking if Solaris I/O completion ports are available... ";
624 our $system = `uname -s`;
626 $has_ports = 1 if ($system eq "SunOS");
629 my $kernel = `uname -r`;
631 if (($kernel !~ /^5\.1./)) {
635 print "yes\n" if $has_ports == 1;
636 print "no\n" if $has_ports == 0;
638 $config{HAS_EPOLL} = $has_epoll;
639 $config{HAS_KQUEUE} = $has_kqueue;
641 printf "Checking for libgnutls... ";
642 if (($config{HAS_GNUTLS}) || ($config{HAS_GNUTLS} eq "y")) {
644 $config{HAS_GNUTLS} = "y";
647 $config{HAS_GNUTLS} = "n";
650 printf "Checking for openssl... ";
651 if (($config{HAS_OPENSSL}) || ($config{HAS_OPENSSL} eq "y")) {
653 $config{HAS_OPENSSL} = "y";
656 $config{HAS_OPENSSL} = "n";
659 printf "Checking if you are running an ancient, unsupported OS... ";
660 if ($config{OSNAME} =~ /FreeBSD/i)
662 my $version = `uname -r`;
663 if ($version =~ /^4\./)
665 my $foundit = `ls -l /usr/local/lib/libgnugetopt* | wc -l`;
668 # ICKY ICKY ICK, FREEBSD 4.x! GET AN UPGRADE!
669 $config{CRAQ} = "-L/usr/local/lib -lgnugetopt -DHAVE_DECL_GETOPT=1";
674 print "\n\nERROR: You require libgnugetopt (from ports or packages) to build InspIRCd on FreeBSD 4.11.\n";
680 print "no ($version)\n";
686 print "no ($config{OSNAME})\n";
689 ################################################################################
690 # BEGIN INTERACTIVE PART #
691 ################################################################################
699 my $rev = getrevision();
700 # Display Introduction Message..
702 Welcome to the \033[1mInspIRCd\033[0m Configuration program! (\033[1minteractive mode\033[0m)
703 \033[1mPackage maintainers: Type ./configure --help for non-interactive help\033[0m
705 *** If you are unsure of any of these values, leave it blank for ***
706 *** standard settings that will work, and your server will run ***
707 *** using them. Please consult your IRC network admin if in doubt. ***
709 Press \033[1m<RETURN>\033[0m to accept the default for any option, or enter
710 a new value. Please note: You will \033[1mHAVE\033[0m to read the docs
711 dir, otherwise you won't have a config file!
713 Your operating system is: \033[1;32m$config{OSNAME}\033[0m ($wholeos)
714 Maximum file descriptors: \033[1;32m$config{MAX_CLIENT_T}\033[0m
715 Your InspIRCd revision ID is \033[1;32mr$rev\033[0m";
717 print " (Non-SVN build)";
721 $config{CHANGE_COMPILER} = "n";
722 print "I have detected the following compiler: \033[1;32m$config{CC}\033[0m (version \033[1;32m$config{GCCVER}.x\033[0m)\n";
724 while (($config{GCCVER} < 3) || ($config{GCCVER} eq "")) {
725 print "\033[1;32mIMPORTANT!\033[0m A GCC 2.x compiler has been detected, and
726 should NOT be used. You should probably specify a newer compiler.\n\n";
727 yesno('CHANGE_COMPILER',"Do you want to change the compiler?");
728 if ($config{CHANGE_COMPILER} =~ /y/i) {
729 print "What command do you want to use to invoke your compiler?\n";
730 print "[\033[1;32m$config{CC}\033[0m] -> ";
731 chomp($config{CC} = <STDIN>);
732 if ($config{CC} eq "") {
735 chomp(my $foo = `$config{CC} -dumpversion | cut -c 1`);
737 chomp($config{GCCVER} = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
738 print "Queried compiler: \033[1;32m$config{CC}\033[0m (version \033[1;32m$config{GCCVER}.x\033[0m)\n";
739 if ($config{GCCVER} < 3) {
740 print "\033[1;32mGCC 2.x WILL NOT WORK!\033[0m. Let's try that again, shall we?\n";
744 print "\033[1;32mWARNING!\033[0m Could not execute the compiler you specified. You may want to try again.\n";
751 # Directory Settings..
752 my $tmpbase = $config{BASE_DIR};
753 dir_check("do you wish to install the InspIRCd base", "BASE_DIR");
754 if ($tmpbase ne $config{BASE_DIR}) {
755 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Dir
756 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
757 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
758 $config{LIBRARY_DIR} = resolve_directory($config{BASE_DIR}."/lib"); # Library Directory
761 dir_check("are the configuration files", "CONFIG_DIR");
762 dir_check("are the modules to be compiled to", "MODULE_DIR");
763 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
764 dir_check("are the IRCd libraries to be placed", "LIBRARY_DIR");
767 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?");
771 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?");
775 yesno('USE_PORTS',"You are running Solaris 10.\nWould you like to enable I/O completion ports support?\nThis is likely to increase performance.\nIf you are unsure, answer yes.\n\nEnable support for I/O completion ports?");
778 my $chose_hiperf = (($config{USE_EPOLL} eq "y") || ($config{USE_KQUEUE} eq "y") || ($config{USE_PORTS} eq "y"));
779 if (!$chose_hiperf) {
780 print "No high-performance socket engines are available, or you chose\n";
781 print "not to enable one. Defaulting to select() engine.\n\n";
784 yesno('IPV6',"Would you like to build InspIRCd with IPv6 support?");
787 if ($config{IPV6} eq "y") {
788 print "You have chosen to build an \033[1;32mIPV6-enabled\033[0m server.\nTo accept IPV4 users, you can still use IPV4 addresses\nin your port bindings..\n\n";
789 $config{SUPPORT_IP6LINKS} = "y";
791 yesno('SUPPORT_IP6LINKS',"You have chosen to build an \033[1;32mIPV4-only\033[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)");
795 if (($config{HAS_GNUTLS} eq "y") && ($config{HAS_OPENSSL} eq "y")) {
796 print "I have detected both \033[1;32mGnuTLS\033[0m and \033[1;32mOpenSSL\033[0m on your system.\n";
797 print "I will default to GnuTLS. If you wish to use OpenSSL\n";
798 print "instead, you should enable the OpenSSL module yourself\n";
799 print "by copying it from src/modules/extra to src/modules.\n\n";
800 print "Detected GnuTLS version: \033[1;32m" . $gnutls_ver . "\033[0m\n";
801 print "Detected OpenSSL version: \033[1;32m" . $openssl_ver . "\033[0m\n\n";
804 if ($config{HAS_GNUTLS} eq "y") {
805 yesno('USE_GNUTLS', "Would you like to enable SSL Support?");
806 if ($config{USE_GNUTLS} eq "y") {
807 print "\nUsing GnuTLS SSL module.\n";
809 } elsif ($config{HAS_OPENSSL} eq "y") {
810 yesno('USE_OPENSSL', "Would you like to enable SSL Support?");
811 if ($config{USE_OPENSSL} eq "y") {
812 print "\nUsing OpenSSL SSL module.\nYou will get better performance if you move to GnuTLS in the future.\n";
816 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";
819 print "\nThe following questions will ask you for various figures relating\n";
820 print "To your IRCd install. Please note that these should usually be left\n";
821 print "as defaults unless you have a real reason to change them. If they\n";
822 print "changed, then the values must be identical on all servers on your\n";
823 print "network, or malfunctions and/or crashes may occur, with the exception\n";
824 print "of the 'maximum number of clients' setting which may be different on\n";
825 print "different servers on the network.\n\n";
827 # File Descriptor Settings..
828 promptnumeric("number of clients at any one time", "MAX_CLIENT_T");
829 $config{MAX_CLIENT} = $config{MAX_CLIENT_T};
830 $config{MAX_DESCRIPTORS} = $config{MAX_CLIENT_T};
832 promptnumeric("length of nicknames", "NICK_LENGT");
833 promptnumeric("length of channel names", "CHAN_LENGT");
834 promptnumeric("number of mode changes in one line", "MAXI_MODES");
835 promptnumeric("length of an ident (username)", "MAX_IDENT");
836 promptnumeric("length of a quit message", "MAX_QUIT");
837 promptnumeric("length of a channel topic", "MAX_TOPIC");
838 promptnumeric("length of a kick message", "MAX_KICK");
839 promptnumeric("length of a GECOS (real name)", "MAX_GECOS");
840 promptnumeric("length of an away message", "MAX_AWAY");
845 if (($config{USE_GNUTLS} eq "y") && ($config{HAS_GNUTLS} ne "y"))
847 print "Sorry, but i couldn't detect gnutls. Make sure gnutls-config is in your path.\n";
850 if (($config{USE_OPENSSL} eq "y") && ($config{HAS_OPENSSL} ne "y"))
852 print "Sorry, but i couldn't detect openssl. Make sure openssl is in your path.\n";
857 if ($config{USE_GNUTLS} eq "y") {
859 open(TMP, "<src/modules/m_ssl_gnutls.cpp") or $failed = 1;
862 print "Symlinking src/modules/m_ssl_gnutls.cpp from extra/\n";
863 chdir("src/modules");
864 system("ln -s extra/m_ssl_gnutls.cpp");
871 open(TMP, "<$config{CONFIG_DIR}/key.pem") or $failed = 1;
873 open(TMP, "<$config{CONFIG_DIR}/cert.pem") or $failed = 1;
876 print "SSL Certificates Not found, Generating.. \n\n
877 *************************************************************
878 * Generating the Private Key may take some time, go grab a *
879 * Coffee. Even better, to generate some more entropy if it *
880 * is taking a while, open another console and type du / a *
881 * few times and get that HD going :) Then answer the *
882 * Questions which follow. If you are unsure, just hit enter *
883 *************************************************************\n\n";
884 $failed = make_gnutls_cert();
886 print "\n\033[1;32mCertificate generation failed!\033[0m\n\n";
888 print "\nCertificate generation complete, copying to config directory... ";
889 system("mv key.pem $config{CONFIG_DIR}/key.pem");
890 system("mv cert.pem $config{CONFIG_DIR}/cert.pem");
895 print "SSL Certificates found, skipping.\n\n";
900 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
902 } elsif ($config{USE_OPENSSL} eq "y") {
904 open(TMP, "<src/modules/m_ssl_openssl.cpp") or $failed = 1;
907 print "Symlinking src/modules/m_ssl_openssl.cpp from extra/\n";
908 chdir("src/modules");
909 system("ln -s extra/m_ssl_openssl.cpp");
916 open(TMP, "<$config{CONFIG_DIR}/key.pem") or $failed = 1;
918 open(TMP, "<$config{CONFIG_DIR}/cert.pem") or $failed = 1;
921 print "SSL Certificates Not found, Generating.. \n\n
922 *************************************************************
923 * Generating the certificates may take some time, go grab a *
924 * coffee, or something. *
925 *************************************************************\n\n";
927 print "\nCertificate generation complete, copying to config directory... ";
928 system("mv key.pem $config{CONFIG_DIR}/key.pem");
929 system("mv cert.pem $config{CONFIG_DIR}/cert.pem");
930 system("mv dhparams.pem $config{CONFIG_DIR}/dhparams.pem");
933 print "SSL Certificates found, skipping.\n\n"
938 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
941 if (($config{USE_GNUTLS} eq "n") && ($config{USE_OPENSSL} eq "n")) {
942 print "Skipping SSL Certificate generation, SSL support is not available.\n\n";
950 print "To build your server with these settings, please type '\033[1;32m$config{MAKEPROG}\033[0m' now.\n";
951 if (($config{USE_GNUTLS} eq "y") || ($config{USE_OPENSSL} eq "y")) {
952 print "Please remember that to enable \033[1;32mSSL support\033[0m you must\n";
953 print "load the required modules in your config. This configure process\n";
954 print "has just prepared these modules to be compiled for you, and has not\n";
955 print "configured them to be compiled into the core of the ircd.\n";
957 print "*** \033[1;32mRemember to edit your configuration files!!!\033[0m ***\n\n\n";
958 if (($config{OSNAME} eq "OpenBSD") && ($config{CC} ne "eg++")) {
959 print "\033[1;32mWARNING!\033[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";
962 if ($config{GCCVER} < "3") {
964 \033[1;32mWARNING!\033[0m You are attempting to compile InspIRCd on GCC 2.x!
965 GCC 2.x series compilers only had partial (read as broken) C++ support, and
966 your compile will most likely fail horribly! If you have any problems, do NOT
967 report them to the bugtracker or forums without first upgrading your compiler
968 to a newer 3.x or 4.x (or whatever is available currently) version.
972 ################################################################################
974 ################################################################################
976 # Retrieves the .config.cache file, and loads values into the main config hash.
977 open(CACHE, ".config.cache") or return 0;
980 # Ignore Blank lines, and comments..
983 my ($key, $value) = split("=", $_, 2);
984 $value =~ /^\"(.*)\"$/;
985 # Do something with data here!
993 # Dump the contents of %config
994 print "Writing \033[1;32mcache file\033[0m for future ./configures ...\n";
995 open(FILEHANDLE, ">.config.cache");
996 foreach my $key (keys %config) {
997 print FILEHANDLE "$key=\"$config{$key}\"\n";
1003 my ($desc, $hash_key) = @_;
1005 while (!$complete) {
1006 print "In what directory $desc?\n";
1007 print "[\033[1;32m$config{$hash_key}\033[0m] -> ";
1008 chomp(my $var = <STDIN>);
1010 $var = $config{$hash_key};
1012 if ($var =~ /^\~\/(.+)$/) {
1013 # Convert it to a full path..
1014 $var = resolve_directory($ENV{HOME} . "/" . $1);
1016 elsif ((($config{OSNAME} =~ /MINGW32/i) and ($var !~ /^[A-Z]{1}:\\.*/)) and (substr($var,0,1) ne "/"))
1018 # Assume relative Path was given.. fill in the rest.
1019 $var = $this . "/$var";
1022 $var = resolve_directory($var);
1024 print "$var does not exist. Create it?\n[\033[1;32my\033[0m] ";
1025 chomp(my $tmp = <STDIN>);
1026 if (($tmp eq "") || ($tmp =~ /^y/i)) {
1027 # Attempt to Create the Dir..
1029 system("mkdir -p \"$var\" >> /dev/null 2>&1");
1030 my $chk = system("mkdir -p \"$var\" >> /dev/null 2>&1") / 256;
1032 print "Unable to create directory. ($var)\n\n";
1037 # They said they don't want to create, and we can't install there.
1042 if (!is_dir($var)) {
1043 # Target exists, but is not a directory.
1044 print "File $var exists, but is not a directory.\n\n";
1048 # Either Dir Exists, or was created fine.
1049 $config{$hash_key} = $var;
1059 $config{LDLIBS} = "-lstdc++";
1060 $config{FLAGS} = "-fPIC -Wall $config{OPTIMISATI}";
1061 $config{DEVELOPER} = "-fPIC -Wall -g";
1062 $SHARED = "-Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared" unless defined $opt_disablerpath;
1063 $config{MAKEPROG} = "make";
1065 if ($config{OSNAME} =~ /darwin/i) {
1066 $config{FLAGS} = "-DDARWIN -frtti -fPIC -Wall $config{OPTIMISATI}";
1067 $SHARED = "-bundle -twolevel_namespace -undefined dynamic_lookup";
1068 $config{LDLIBS} = "-ldl -lstdc++";
1071 if ($config{OSNAME} =~ /OpenBSD/i) {
1072 $config{MAKEPROG} = "gmake";
1073 $config{LDLIBS} = $config{LDLIBS} . " -lunwind";
1074 chomp(my $foo = `eg++ -dumpversion | cut -c 1`);
1075 # theyre running the package version of gcc (eg++)... detect it and set up its version numbers.
1076 # if theyre not running this, configure lets the build continue but they probably wont manage to
1077 # compile as this standard version is 2.95.3!
1079 $config{CC} = "eg++";
1080 chomp($config{GCCVER} = `eg++ -dumpversion | cut -c 1`); # we must redo these if we change the compiler path
1085 if ($config{OSNAME} =~ /Linux/i) {
1086 $config{LDLIBS} = "-ldl -lstdc++";
1087 $config{FLAGS} = "-fPIC -Wall $config{OPTIMISATI}";
1088 $config{FLAGS} .= " " . $ENV{CXXFLAGS} if exists($ENV{CXXFLAGS});
1089 $config{LDLIBS} .= " " . $ENV{LDLIBS} if exists($ENV{LDLIBS});
1090 $config{MAKEPROG} = "make";
1093 if ($config{OSNAME} =~ /FreeBSD/i) {
1094 $config{FLAGS} .= " " . $ENV{CXXFLAGS} if exists($ENV{CXXFLAGS});
1095 $config{LDLIBS} .= " " . $ENV{LDLIBS} if exists($ENV{LDLIBS});
1098 if ($config{OSNAME} =~ /SunOS/i or $config{OSNAME} =~ /solaris/i)
1100 # solaris/sunos needs these
1101 # socket = bsd sockets api
1103 # rt = POSIX realtime extensions
1104 # resolv = inet_aton only (why isnt this in nsl?!)
1105 $config{MAKEPROG} = "gmake";
1106 $config{LDLIBS} .= " -lsocket -lnsl -lrt -lresolv";
1110 if($config{OSNAME} =~ /MINGW32/i)
1112 # All code is position-independent on windows
1113 $config{FLAGS} =~ s/-fPIC //;
1117 return $config{OSNAME};
1120 my ($mliflags, $mfrules, $mobjs, $mfcount) = ("", "", "", 0);
1123 my($writeheader) = @_;
1125 # First File.. inspircd_config.h
1126 chomp(my $incos = `uname -n -s -r`);
1127 chomp(my $version = `sh src/version.sh`);
1128 chomp(my $revision2 = getrevision());
1129 if ($writeheader == 1)
1131 print "Writing \033[1;32minspircd_config.h\033[0m\n";
1132 open(FILEHANDLE, ">include/inspircd_config.h");
1133 my $NL = $config{NICK_LENGT}+1;
1134 my $CL = $config{CHAN_LENGT}+1;
1135 print FILEHANDLE <<EOF;
1136 /* Auto generated by configure, do not modify! */
1137 #ifndef __CONFIGURATION_AUTO__
1138 #define __CONFIGURATION_AUTO__
1140 /* this is for windows support. */
1141 #define CoreExport /**/
1142 #define DllExport /**/
1144 #define CONFIG_FILE "$config{CONFIG_DIR}/inspircd.conf"
1145 #define MOD_PATH "$config{MODULE_DIR}"
1146 #define VERSION "$version"
1147 #define REVISION "$revision2"
1148 #define MAXCLIENTS $config{MAX_CLIENT}
1149 #define MAXCLIENTS_S "$config{MAX_CLIENT}"
1150 #define SOMAXCONN_S "$config{_SOMAXCONN}"
1151 #define MAX_DESCRIPTORS $config{MAX_DESCRIPTORS}
1154 #define MAXMODES $config{MAXI_MODES}
1155 #define IDENTMAX $config{MAX_IDENT}
1156 #define MAXQUIT $config{MAX_QUIT}
1157 #define MAXTOPIC $config{MAX_TOPIC}
1158 #define MAXKICK $config{MAX_KICK}
1159 #define MAXGECOS $config{MAX_GECOS}
1160 #define MAXAWAY $config{MAX_AWAY}
1161 #define OPTIMISATION $config{OPTIMITEMP}
1162 #define LIBRARYDIR "$config{LIBRARY_DIR}"
1163 #define SYSTEM "$incos"
1165 print FILEHANDLE "#define MAXBUF " . ($config{MAXBUF}+2) . "\n";
1167 if ($config{OSNAME} =~ /SunOS/i) {
1168 print FILEHANDLE "#define IS_SOLARIS\n";
1170 if ($config{OSNAME} =~ /MINGW32/i) {
1171 print FILEHANDLE "#define IS_MINGW\n";
1173 if ($config{GCCVER} >= 3) {
1174 print FILEHANDLE "#define GCC3\n";
1176 if ($config{HAS_STRLCPY} eq "true") {
1177 print FILEHANDLE "#define HAS_STRLCPY\n";
1179 if ($config{HAS_STDINT} eq "true") {
1180 print FILEHANDLE "#define HAS_STDINT\n";
1182 if ($config{IPV6} =~ /y/i) {
1183 print FILEHANDLE "#define IPV6\n";
1185 if ($config{SUPPORT_IP6LINKS} =~ /y/i) {
1186 print FILEHANDLE "#define SUPPORT_IP6LINKS\n";
1189 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
1190 print FILEHANDLE "#define USE_KQUEUE\n";
1191 $se = "socketengine_kqueue";
1194 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
1195 print FILEHANDLE "#define USE_EPOLL\n";
1196 $se = "socketengine_epoll";
1199 if (($has_ports) && ($config{USE_PORTS} eq "y")) {
1200 print FILEHANDLE "#define USE_PORTS\n";
1201 $se = "socketengine_ports";
1204 # user didn't choose either epoll or select for their OS.
1205 # default them to USE_SELECT (ewwy puke puke)
1207 print FILEHANDLE "#define USE_SELECT\n";
1208 $se = "socketengine_select";
1210 print FILEHANDLE "\n#endif\n";
1216 open(FILEHANDLE, ">include/inspircd_se_config.h");
1217 print FILEHANDLE <<EOF;
1218 /* Auto generated by configure, do not modify or commit to svn! */
1219 #ifndef __CONFIGURATION_SOCKETENGINE__
1220 #define __CONFIGURATION_SOCKETENGINE__
1222 #include "socketengines/$se.h"
1230 # Create a Modules List..
1232 foreach my $i (@modlist)
1234 $modules .= "m_".$i.".so ";
1236 chomp($modules); # Remove Redundant whitespace..
1238 opendir(DIRHANDLE, "src/modules");
1239 foreach my $name (sort readdir(DIRHANDLE)) {
1240 if ($name =~ /^m_(.+?)$/) {
1241 if (defined(opendir(MDIRHANDLE, "src/modules/$name"))) {
1242 closedir(MDIRHANDLE);
1243 $modules .= "$name.so ";
1244 $uninstall_list = $uninstall_list . " -rm \$(MODULES)/$name.so\n";
1248 closedir(DIRHANDLE);
1251 # Write all .in files.
1254 my $exe = "inspircd";
1256 # Do this once here, and cache it in the .*.inc files,
1257 # rather than attempting to read src/version.sh from
1258 # compiled code -- we might not have the source to hand.
1259 # Fix for bug#177 by Brain.
1261 chomp($version = `sh ./src/version.sh`);
1262 chomp(my $revision = getrevision());
1263 $version = "$version(r$revision)";
1265 # We can actually parse any file starting with . and ending with .inc,
1266 # but right now we only parse .inspircd.inc to form './inspircd'
1268 print "Writing \033[1;32mMakefiles\033[0m\n";
1269 write_dynamic_modules_makefile();
1270 write_dynamic_makefile();
1272 opendir(DIRHANDLE, $this);
1274 foreach my $name (sort readdir(DIRHANDLE)) {
1275 if ($name =~ /^\.(.+)\.inc$/) {
1278 # Bug #353, omit this on non-darwin
1279 next if (($config{OSNAME} !~ /darwin/) && ($file eq "org.inspircd.plist"));
1281 # All .name.inc files need parsing!
1283 open(FILEHANDLE, ".$file.inc") or die ("Can't open .$file.inc");
1284 while (<FILEHANDLE>) {
1289 print "Writing \033[1;32m$file\033[0m ...\n";
1290 $tmp =~ s/\@CC\@/$config{CC}/ if defined $config{CC};
1291 $tmp =~ s/\@MAKEPROG\@/$config{MAKEPROG}/ if defined $config{MAKEPROG};
1292 $tmp =~ s/\@FLAGS\@/$config{FLAGS}/ if defined $config{FLAGS};
1293 $tmp =~ s/\@DEVELOPER\@/$config{DEVELOPER}/ if defined $config{DEVELOPER};
1294 $tmp =~ s/\@LDLIBS\@/$config{LDLIBS}/ if defined $config{LDLIBS};
1295 $tmp =~ s/\@BASE_DIR\@/$config{BASE_DIR}/ if defined $config{BASE_DIR};
1296 $tmp =~ s/\@CONFIG_DIR\@/$config{CONFIG_DIR}/ if defined $config{CONFIG_DIR};
1297 $tmp =~ s/\@MODULE_DIR\@/$config{MODULE_DIR}/ if defined $config{MODULE_DIR};
1298 $tmp =~ s/\@BINARY_DIR\@/$config{BINARY_DIR}/ if defined $config{BINARY_DIR};
1299 $tmp =~ s/\@LIBRARY_DIR\@/$config{LIBRARY_DIR}/ if defined $config{LIBRARY_DIR};
1300 $tmp =~ s/\@MODULES\@/$modules/ if defined $modules;
1301 $tmp =~ s/\@STARTSCRIPT\@/$config{STARTSCRIPT}/ if defined $config{STARTSCRIPT};
1302 $tmp =~ s/\@DESTINATION\@/$config{DESTINATION}/ if defined $config{DESTINATION};
1303 $tmp =~ s/\@EXTRA_DIR\@/$config{EXTRA_DIR}/ if defined $config{EXTRA_DIR};
1304 $tmp =~ s/\@EXECUTABLE\@/$exe/ if defined $exe;
1305 $tmp =~ s/\@MAKEORDER\@/$config{MAKEORDER}/ if defined $config{MAKEORDER};
1306 $tmp =~ s/\@VERSION\@/$version/ if defined $version;
1307 $tmp =~ s/\@INSTALL_LIST\@/$install_list/ if defined $install_list;
1308 $tmp =~ s/\@UNINSTALL_LIST\@/$uninstall_list/ if defined $uninstall_list;
1310 open(FILEHANDLE, ">$file");
1311 print FILEHANDLE $tmp;
1314 closedir(DIRHANDLE);
1316 # Make inspircd executable!
1317 chmod 0744, 'inspircd';
1320 sub write_dynamic_modules_makefile {
1321 # Modules Makefile..
1322 print "Writing \033[1;32msrc/modules/Makefile\033[0m\n";
1323 open(FILEHANDLE, ">src/modules/Makefile");
1326 # Module Makefile Header
1328 print FILEHANDLE <<EOF;
1329 ###################################################
1330 # Copyright 2002-2007 The InspIRCd Development Team
1331 # http://www.inspircd.org/wiki/index.php/Credits
1333 # Thanks to Andrew Church <achurch\@achurch.org>
1334 # for assisting with making this work right.
1336 # Automatically Generated by ./configure to add a
1337 # modules please run ./configure -modupdate
1338 ###################################################
1344 if ($config{OSNAME} =~ /darwin/) {
1345 print FILEHANDLE <<EOCHEESE;
1347 PICLDFLAGS = -twolevel_namespace -undefined dynamic_lookup -bundle
1351 print FILEHANDLE <<EOCHEESE;
1353 PICLDFLAGS = -fPIC -DPIC -shared
1359 # End Module Makefile Header
1362 # Create a Modules List..
1366 foreach my $i (@modlist) {
1368 # Write Entry to the MakeFile
1370 $cmflags = getcompilerflags("src/modules/m_".$i.".cpp");
1371 $liflags = getlinkerflags("src/modules/m_".$i.".cpp");
1372 my $deps = getdependencies("src/modules/m_".$i.".cpp");
1374 #print "file: $i: cmflags=$cmflags; liflags=$liflags; deps=$deps\n";
1377 if (nopedantic("src/modules/m_".$i.".cpp"))
1380 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
1381 \$(CC) -pipe -I../../include \$(NICEFLAGS) $cmflags \$(PICLDFLAGS) $liflags -export-dynamic -o m_$i.so m_$i.cpp
1387 m_$i.so: m_$i.cpp ../../include/modules.h ../../include/users.h ../../include/channels.h ../../include/base.h ../../include/inspircd_config.h ../../include/inspircd.h ../../include/configreader.h $deps
1388 \$(CC) -pipe -I../../include \$(FLAGS) $cmflags \$(PICLDFLAGS) $liflags -export-dynamic -o m_$i.so m_$i.cpp
1391 $install_list = $install_list . " install -m \$(INSTMODE) src/modules/m_$i.so \$(MODPATH)\n";
1392 $uninstall_list = $uninstall_list . " -rm \$(MODULES)/m_$i.so\n";
1394 # End Write Entry to the MakeFile
1398 opendir(DIRHANDLE, "src/modules");
1399 foreach my $name (sort readdir(DIRHANDLE)) {
1400 if ($name =~ /^m_(.+?)$/) {
1405 # A module made of multiple files, in a dir, e.g. src/modules/m_spanningtree/
1406 if (defined(opendir(MDIRHANDLE, "src/modules/$name"))) {
1407 read_module_directory("src/modules/$name", $name);
1408 print "Composing Makefile rules for directory \033[1;32m$name\033[0m... (\033[1;32m$mfcount files found\033[0m)\n";
1409 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";
1410 if ($config{IS_DARWIN} eq "YES") {
1411 print FILEHANDLE " \$(CC) -pipe -twolevel_namespace -undefined dynamic_lookup \$(FLAGS) $mliflags -bundle -o $name.so $mobjs\n";
1413 print FILEHANDLE " \$(CC) -pipe \$(FLAGS) -shared $mliflags -o $name.so $mobjs\n";
1415 print FILEHANDLE "\n$mfrules\n";
1416 closedir(MDIRHANDLE);
1417 $install_list = $install_list . " install -m \$(INSTMODE) src/modules/$name.so \$(MODPATH)\n";
1421 closedir(DIRHANDLE);
1424 sub read_module_directory {
1425 my ($dpath, $reldpath) = @_;
1427 if (opendir(MDIRHANDLE, $dpath) == 0) {
1431 foreach my $fname (sort readdir(MDIRHANDLE)) {
1432 if ($fname =~ /\.cpp$/) {
1433 my $cmflags = getcompilerflags("$dpath/$fname");
1434 $mliflags = $mliflags . " " . getlinkerflags("$dpath/$fname");
1435 my $deps = getdependencies("$dpath/$fname");
1437 $oname =~ s/\.cpp$/.o/g;
1438 $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";
1439 $mfrules = $mfrules . " \$(CC) -pipe -I../../include -I. \$(FLAGS) $cmflags -export-dynamic -o $reldpath/$oname -c $reldpath/$fname\n\n";
1440 $mobjs = $mobjs . " $reldpath/$oname";
1443 elsif ((-d "$dpath/$fname") && !($fname eq ".") && !($fname eq "..")) {
1444 read_module_directory($dpath."/".$fname, $reldpath."/".$fname);
1451 # Yes i know we could use gcc -M but it seems to ideneify a lot of 'deep'
1452 # dependencies which are not relevent in C++.
1456 open (CPP, "<$file") or die("Can't open $file for reading!");
1461 foreach my $d (@ignoredeps)
1467 foreach my $dep (@immutabledeps)
1469 $immutable = $immutable . "../include/$dep ";
1471 $immutable =~ s/ $//g;
1473 while (defined(my $line = <CPP>))
1476 if ($line =~ /#include "(.+\.h)"/)
1478 if (!exists($dupe{$1}))
1480 $retlist = $retlist . "../include/$1 ";
1486 return length($immutable) ? $immutable . " " . $retlist : $retlist;
1489 sub write_dynamic_makefile
1493 my %existing_install_list = ();
1494 opendir(DIRHANDLE, "src/commands");
1495 foreach my $name (sort readdir(DIRHANDLE))
1497 if ($name =~ /^cmd_(.+)\.cpp$/)
1499 $cmdlist[$i++] = $1;
1500 $install_list = $install_list . " -install -m \$(INSTMODE) src/commands/cmd_" . $1 . ".so \$(LIBPATH)\n";
1501 $uninstall_list = $uninstall_list . " -rm \$(LIBPATH)/cmd_$1.so\n";
1504 closedir(DIRHANDLE);
1508 $config{USE_EPOLL} = 0;
1512 $config{USE_KQUEUE} = 0;
1516 $config{USE_PORTS} = 0;
1519 foreach my $dir (("src","src/commands","src/modes","src/socketengines","src/modules"))
1521 print "Scanning \033[1;32m$dir\033[0m for core files ";
1522 opendir(DIRHANDLE, $dir);
1523 foreach my $name (sort readdir(DIRHANDLE))
1525 if ($name =~ /\.cpp$/)
1527 open (CPP, "<$dir/$name") or die("Can't open $dir/$name to scan it! oh bugger");
1529 while (defined(my $line = <CPP>))
1532 if ($line =~ /\/\* \$Core: (\w+) \*\//i)
1534 $filelist{$name} = $1;
1536 elsif ($line =~ /\/\* \$ExtraDeps: (.*?) \*\//i)
1538 $specialdeps{$name} = $1;
1540 elsif ($line =~ /\/\* \$ExtraObjects: (.*?) \*\//i)
1542 $extraobjects{$name} = $1;
1544 elsif ($line =~ /\/\* \$ExtraBuild: (.*?) \*\//i)
1546 $extrabuildlines{$name} = $1;
1548 elsif ($line =~ /\/\* \$ExtraSources: (.*?) \*\//i)
1550 $extrasources{$name} = $1;
1552 elsif ($line =~ /\/\* \$If: (\w+) \*\//i)
1554 if (($config{$1} !~ /y/i) and ($config{$1} ne "1"))
1557 while (defined($line = <CPP>))
1560 die ("\$If buildsystem instruction within another \$If in file $dir/$name") if ($line =~ /\/\* \$If: (\w+) \*\//i);
1561 last if ($line =~ /\/\* \$EndIf \*\//i);
1565 elsif ($line =~ /\/\* \$Install: (.*?) \*\//i)
1567 if (!exists($existing_install_list{$1}))
1569 $existing_install_list{$1} = 1;
1570 my $idir = (split(' ',$1))[1];
1571 my $ifile = (split(' ',$1))[0];
1572 $install_list = $install_list . " -install -m \$(INSTMODE) $1\n";
1573 $ifile =~ s/.*\///g;
1574 $uninstall_list = $uninstall_list . " -rm $idir/$ifile\n";
1577 elsif ($line =~ /\/\* \$CopyInstall: (.*?) \*\//i)
1579 if (!exists($existing_install_list{$1}))
1581 $existing_install_list{$1} = 1;
1582 my $idir = (split(' ',$1))[1];
1583 my $ifile = (split(' ',$1))[0];
1584 $install_list = $install_list . " -cp $1\n";
1585 $ifile =~ s/.*\///g;
1586 $uninstall_list = $uninstall_list . " -rm $idir/$ifile\n";
1593 closedir(DIRHANDLE);
1597 my $freebsd4libs = (defined $config{CRAQ} ? $config{CRAQ} : "");
1600 my $all_libsonly = "";
1602 my $libraryext = "";
1606 if ($config{IS_DARWIN} eq "YES")
1608 $libraryext = "dylib";
1609 $othercrap = " \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c inspircd.cpp\n \$(CC) -pipe -dynamic -bind_at_load -L. -o inspircd \$(LDLIBS) inspircd.o "
1614 $RPATH = "-Wl,--rpath -Wl,$config{LIBRARY_DIR}" unless defined $opt_disablerpath;
1615 $othercrap = " \$(CC) -pipe -I../include $RPATH \$(FLAGS) $freebsd4libs -rdynamic -L. inspircd.cpp -o inspircd \$(LDLIBS) ";
1618 foreach my $cpp (sort keys %filelist)
1620 $all = $all . $filelist{$cpp} . "." . $libraryext . " ";
1621 $all_libsonly = $all_libsonly . $filelist{$cpp} . "." . $libraryext . " ";
1622 $install_list = $install_list . " -install -m \$(INSTMODE) src/" . $filelist{$cpp} . "." . $libraryext . " \$(LIBPATH)\n";
1623 $uninstall_list = $uninstall_list . " -rm \$(LIBPATH)/" . $filelist{$cpp} . "." . $libraryext . "\n";
1625 $all = $all . "moo inspircd\n";
1627 $othercrap = $othercrap . " $all_libsonly\n\n";
1629 open(FH,">src/Makefile") or die("Could not write src/Makefile");
1632 CC = im a cheezeball
1633 CXXFLAGS = -I../include \${FLAGS}
1634 CPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* //' | grep -v svn)
1635 RELCPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* /modes\\//' | grep -v svn)
1639 print FH "$all\n\n";
1641 my $deps = calcdeps("src/inspircd.cpp");
1642 print FH "inspircd: inspircd.cpp $deps $all_libsonly\n";
1643 print FH "$othercrap\n";
1645 foreach my $cpp (sort keys %filelist)
1647 my $thislib = $filelist{$cpp} . "." . $libraryext;
1651 $objs =~ s/\.cpp$/.o/;
1652 if (exists($extraobjects{$cpp}))
1654 $objs = $objs . " " . $extraobjects{$cpp};
1656 if (exists($extrasources{$cpp}))
1658 $rawcpp = $rawcpp . " " . $extrasources{$cpp};
1660 if ($config{IS_DARWIN} eq "YES")
1662 $libcrap = "-install_name " . $config{LIBRARY_DIR} . "/" . $thislib . " -dynamiclib -twolevel_namespace -undefined dynamic_lookup";
1666 if (defined $opt_disablerpath)
1668 $libcrap = " -shared";
1672 $libcrap = "-Wl,--rpath -Wl," . $config{LIBRARY_DIR} . " -shared";
1675 $deps = calcdeps("src/$cpp");
1676 if (exists($extrasources{$cpp}))
1678 foreach my $seperate (sort split(' ',$extrasources{$cpp}))
1680 my $d = calcdeps("src/$extrasources{$cpp}") . " ";
1683 $deps = $deps . $d . " ";
1687 print FH $thislib . ": $cpp $deps ". (defined($specialdeps{$cpp}) ? $specialdeps{$cpp} : "") . "\n";
1688 print FH " \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c $rawcpp\n";
1689 if (exists($extrabuildlines{$cpp}))
1691 print FH " " . $extrabuildlines{$cpp} . "\n";
1693 print FH " \$(CC) -pipe $libcrap -o " . $thislib . " " . $objs . "\n\n";
1696 print FH "moo:\n \${MAKE} -C \"commands\" DIRNAME=\"src/commands\" CC=\"\$(CC)\" \$(MAKEARGS)\n\n";
1698 # close main makefile
1702 # generate a list of .so
1703 foreach my $cmd (@cmdlist) {
1704 $cmdobjs = $cmdobjs . "cmd_$cmd.so ";
1707 # and now reopen the commands makefile
1708 open(FH,">src/commands/Makefile") or die("Could not write src/commands/Makefile");
1711 CXXFLAGS = -I../../include \${FLAGS}
1718 # now print the command file details.
1719 foreach my $cmd (@cmdlist) {
1721 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
1722 \$(CC) -pipe -I../../include \$(FLAGS) -export-dynamic -c cmd_$cmd.cpp
1723 \$(CC) -pipe $SHARED -o cmd_$cmd.so cmd_$cmd.o
1727 #try build a .so, no intermediate .o
1728 # \$(CC) -pipe -I../../include \$(FLAGS) -export-dynamic $SHARED -o cmd_$cmd.so
1730 #this works for sure
1731 # \$(CC) -pipe -I../../include \$(FLAGS) -export-dynamic -c cmd_$cmd.cpp
1732 # \$(CC) -pipe $SHARED -o cmd_$cmd.so cmd_$cmd.o
1735 # Routine to list out the extra/ modules that have been enabled.
1736 # Note: when getting any filenames out and comparing, it's important to lc it if the
1737 # file system is not case-sensitive (== Epoc, MacOS, OS/2 (incl DOS/DJGPP), VMS, Win32
1738 # (incl NetWare, Symbian)). Cygwin may or may not be case-sensitive, depending on
1739 # configuration, however, File::Spec does not currently tell us (it assumes Unix behavior).
1740 sub list_extras () {
1743 my $srcdir = File::Spec->catdir("src", "modules");
1744 my $abs_srcdir = File::Spec->rel2abs($srcdir);
1747 opendir $dd, File::Spec->catdir($abs_srcdir, "extra") or die (File::Spec->catdir($abs_srcdir, "extra") . ": $!\n");
1748 my @extras = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1751 opendir $dd, $abs_srcdir or die "$abs_srcdir: $!\n";
1752 my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1755 my $maxlen = (sort { $b <=> $a } (map {length($_)} (@extras)))[0];
1757 EXTRA: for my $extra (@extras) {
1758 next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra);
1759 next if ($extra eq '.svn');
1760 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1761 my $abs_source = File::Spec->catfile($abs_srcdir, $extra);
1762 next unless ($extra =~ m/\.(cpp|h)$/ || (-d $abs_extra)); # C++ Source/Header, or directory
1763 if (-l $abs_source) {
1764 # Symlink, is it in the right place?
1765 my $targ = readlink($abs_source);
1766 my $abs_targ = File::Spec->rel2abs($targ, $abs_srcdir);
1767 if ($abs_targ eq $abs_extra) {
1768 $extras{$extra} = "\e[32;1menabled\e[0m";
1770 $extras{$extra} = sprintf("\e[31;1mwrong symlink target (%s)\e[0m", $abs_targ);
1772 } elsif (-e $abs_source) {
1773 my ($devext, $inoext) = stat($abs_extra);
1774 my ($devsrc, $inosrc, undef, $lnksrc) = stat($abs_source);
1776 if ($devsrc == $devext && $inosrc == $inoext) {
1777 $extras{$extra} = "\e[32;1menabled\e[0m";
1779 $extras{$extra} = sprintf("\e[31;1mwrong hardlink target (%d:%d)\e[0m", $devsrc, $inosrc);
1782 open my $extfd, "<", $abs_extra;
1783 open my $srcfd, "<", $abs_source;
1785 if (scalar(<$extfd>) eq scalar(<$srcfd>)) {
1786 $extras{$extra} = "\e[32;1menabled\e[0m";
1788 $extras{$extra} = sprintf("\e[31;1mout of synch (re-copy)\e[0m");
1792 $extras{$extra} = "\e[33;1mdisabled\e[0m";
1795 # Now let's add dependency info
1796 for my $extra (keys(%extras)) {
1797 next unless $extras{$extra} =~ m/enabled/; # only process enabled extras.
1798 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1799 my @deps = split / +/, getdependencies($abs_extra);
1800 for my $dep (@deps) {
1801 if (exists($extras{$dep})) {
1802 my $ref = \$extras{$dep}; # Take reference.
1803 if ($$ref !~ m/needed by/) {
1804 # First dependency found.
1805 if ($$ref =~ m/enabled/) {
1806 $$ref .= " (needed by \e[32;1m$extra\e[0m";
1808 $$ref =~ s/\e\[.*?m//g; # Strip out previous coloring. Will be set in bold+red+blink later.
1809 $$ref .= " (needed by \e[0;32;1;5m$extra\e[0;31;1;5m";
1812 if ($$ref =~ m/enabled/) {
1813 $$ref .= ", \e[32;1m$extra\e[0m";
1815 $$ref .= ", \e[0;32;1;5m$extra\e[0;31;1;5m";
1821 for my $extra (sort {$a cmp $b} keys(%extras)) {
1822 my $text = $extras{$extra};
1823 if ($text =~ m/needed by/ && $text !~ m/enabled/) {
1824 printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? ")" : "");
1826 printf "%-*s = %s%s\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? "\e[0m)" : "");
1829 return keys(%extras) if wantarray; # Can be used by manage_extras.
1832 sub enable_extras (@) {
1834 for my $extra (@extras) {
1835 my $extrapath = "src/modules/extra/$extra";
1836 if (!-e $extrapath) {
1837 print STDERR "Cannot enable \e[32;1m$extra\e[0m : No such file or directory in src/modules/extra\n";
1839 my $source = "src/modules/$extra";
1841 print STDERR "Cannot enable \e[32;1m$extra\e[0m : destination in src/modules exists (might already be enabled?)\n";
1844 # Get dependencies, and add them to be processed.
1845 my @deps = split / +/, getdependencies($extrapath);
1846 for my $dep (@deps) {
1847 next if scalar(grep { $_ eq $dep } (@extras)) > 0; # Skip if we're going to be enabling it anyway.
1848 if (!-e "src/modules/$dep") {
1849 if (-e "src/modules/extra/$dep") {
1850 print STDERR "Will also enable extra \e[32;1m$dep\e[0m (needed by \e[32;1m$extra\e[0m)\n";
1853 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";
1857 print "Enabling $extra ... \n";
1858 symlink "extra/$extra", $source or print STDERR "$source: Cannot link to 'extra/$extra': $!\n";
1862 sub disable_extras (@)
1864 opendir my $dd, "src/modules/extra/";
1865 my @files = readdir($dd);
1868 EXTRA: for my $extra (@extras) {
1869 my $extrapath = "src/modules/extra/$extra";
1870 my $source = "src/modules/$extra";
1871 if (!-e $extrapath) {
1872 print STDERR "Cannot disable \e[32;1m$extra\e[0m : Is not an extra\n";
1875 if ((! -l $source) || readlink($source) ne "extra/$extra") {
1876 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";
1879 # Check if anything needs this.
1880 for my $file (@files) {
1881 my @deps = split / +/, getdependencies("src/modules/extra/$file");
1882 # File depends on this extra...
1883 if (scalar(grep { $_ eq $extra } @deps) > 0) {
1884 # And is both enabled and not about to be disabled.
1885 if (-e "src/modules/$file" && scalar(grep { $_ eq $file } @extras) < 1) {
1886 print STDERR "Cannot disable \e[32;1m$extra\e[0m : is needed by \e[32;1m$file\e[0m\n";
1892 print "Disabling $extra ... \n";
1893 unlink "src/modules/$extra" or print STDERR "Cannot disable \e[32;1m$extra\e[0m : $!\n";