diff options
Diffstat (limited to 'infrastructure')
-rw-r--r-- | infrastructure/BoxPlatform.pm | 78 | ||||
-rwxr-xr-x | infrastructure/buildenv-testmain-template.cpp | 144 | ||||
-rwxr-xr-x | infrastructure/makebuildenv.pl | 1126 | ||||
-rwxr-xr-x | infrastructure/makedistribution.pl | 312 | ||||
-rwxr-xr-x | infrastructure/makeparcels.pl | 166 | ||||
-rwxr-xr-x | infrastructure/setupexternal.pl | 55 | ||||
-rw-r--r-- | infrastructure/tests/common_tests.pl | 178 |
7 files changed, 2059 insertions, 0 deletions
diff --git a/infrastructure/BoxPlatform.pm b/infrastructure/BoxPlatform.pm new file mode 100644 index 00000000..4c8280a3 --- /dev/null +++ b/infrastructure/BoxPlatform.pm @@ -0,0 +1,78 @@ +package BoxPlatform; +use Exporter; +@ISA = qw/Exporter/; +@EXPORT = qw/$build_os $make_command $bsd_make $platform_define $gcc_v3 $gcc_v4 $product_version $product_name $install_into_dir $sub_make_options $platform_compile_line_extra $platform_link_line_extra/; + +BEGIN +{ + + # which OS are we building under? + $build_os = `uname`; + chomp $build_os; + # Cygwin Builds usually something like CYGWIN_NT-5.0, CYGWIN_NT-5.1 + # Box Backup tried on Win2000,XP only :) + $build_os = 'CYGWIN' if $build_os =~ m/CYGWIN/; + + $make_command = ($build_os ne 'Darwin')?'make':'bsdmake'; + $bsd_make = ($build_os ne 'Linux' && $build_os ne 'CYGWIN'); + $platform_define = 'PLATFORM_'.uc($build_os); + + # blank extra flags by default + $platform_compile_line_extra = ''; + $platform_link_line_extra = ''; + + # compiler version? + $gcc_v3 = 0; + $gcc_v4 = 0; + open COMPILER,"gcc -v 2>&1 |" or die "Can't open gcc -v"; + while(<COMPILER>) + { + $gcc_v3 = 1 if (m/version gcc 3/ || m/gcc version 3/ || m/gcc \(GCC\) 3/i || m/gcc.Version\s+3/i); + $gcc_v4 = 1 if (m/version gcc 4/ || m/gcc version 4/ || m/gcc \(GCC\) 4/i || m/gcc.Version\s+4/i); + } + close COMPILER; + $gcc_v3 = 1 if $gcc_v4; # hacks are about the same + + # get version + open VERSION,"VERSION.txt"; + $product_version = <VERSION>; + chomp $product_version; + $product_name = <VERSION>; + chomp $product_name; + close VERSION; + + # where to put the files + $install_into_dir = '/usr/local/bin'; + + # if it's Darwin, + if($build_os eq 'Darwin') + { + # see how many processors there are, and set make flags accordingly + my $cpus = `sysctl hw.ncpu`; + if($cpus =~ m/hw.ncpu:\s(\d+)/ && $1 > 1) + { + print "$1 processors detected, will set make to perform concurrent jobs\n"; + $sub_make_options = ' -j '.($1 + 1); + } + + # test for fink installation + if(-d '/sw/include' && -d '/sw/lib') + { + print "Fink installation detected, will use headers and libraries\n"; + $platform_compile_line_extra = '-I/sw/include '; + $platform_link_line_extra = '-L/sw/lib '; + } + } +} + +sub make_flag +{ + if($bsd_make) + { + return "-D $_[0]" + } + return $_[0].'=1'; +} + +1; + diff --git a/infrastructure/buildenv-testmain-template.cpp b/infrastructure/buildenv-testmain-template.cpp new file mode 100755 index 00000000..36cc4da0 --- /dev/null +++ b/infrastructure/buildenv-testmain-template.cpp @@ -0,0 +1,144 @@ +// +// AUTOMATICALLY GENERATED FILE +// do not edit +// + + +// -------------------------------------------------------------------------- +// +// File +// Name: testmain.template.h +// Purpose: Template file for running tests +// Created: 2003/07/08 +// +// -------------------------------------------------------------------------- + +#include "Box.h" + +#include "stdio.h" +#include <exception> +#include <sys/types.h> +#include <unistd.h> +#include <stdlib.h> +#include <syslog.h> +#include <stdarg.h> +#include <fcntl.h> +#include <errno.h> + +#include "MemLeakFindOn.h" + +int test(int argc, const char *argv[]); + +#ifdef NDEBUG + #define MODE_TEXT "release" +#else + #define MODE_TEXT "debug" +#endif + +int failures = 0; + +int filedes_open_at_beginning = -1; + +int count_filedes() +{ + int c = 0; + + // See how many file descriptors there are with values < 256 + for(int d = 0; d < 256; ++d) + { + if(::fcntl(d, F_GETFD) != -1) + { + // File descriptor obviously exists + ++c; + } + } + + return c; +} + +bool checkfilesleftopen() +{ + if(filedes_open_at_beginning == -1) + { + // Not used correctly, pretend that there were things left open so this gets invesitgated + return true; + } + + // make sure syslog log file is closed, if it was opened + ::closelog(); + + // Count the file descriptors open + return filedes_open_at_beginning != count_filedes(); +} + +int main(int argc, const char *argv[]) +{ + // Start memory leak testing + MEMLEAKFINDER_START + + // If there is more than one argument, then the test is doing something advanced, so leave it alone + bool fulltestmode = (argc == 1); + + if(fulltestmode) + { + // Count open file descriptors for a very crude "files left open" test + filedes_open_at_beginning = count_filedes(); + + // banner + printf("Running test TEST_NAME in " MODE_TEXT " mode...\n"); + } + try + { + int returncode = test(argc, argv); + + // check for memory leaks, if enabled + #ifdef BOX_MEMORY_LEAK_TESTING + if(memleakfinder_numleaks() != 0) + { + failures++; + printf("FAILURE: Memory leaks detected\n"); + printf("==== MEMORY LEAKS =================================\n"); + memleakfinder_reportleaks(); + printf("===================================================\n"); + } + #endif + + if(fulltestmode) + { + bool filesleftopen = checkfilesleftopen(); + if(filesleftopen) + { + failures++; + printf("IMPLICIT TEST FAILED: Something left files open\n"); + } + if(failures > 0) + { + printf("FAILED: %d tests failed\n", failures); + } + else + { + printf("PASSED\n"); + } + } + + return returncode; + } + catch(std::exception &e) + { + printf("FAILED: Exception caught: %s\n", e.what()); + return 1; + } + catch(...) + { + printf("FAILED: Unknown exception caught\n"); + return 1; + } + if(fulltestmode) + { + if(checkfilesleftopen()) + { + printf("WARNING: Files were left open\n"); + } + } +} + diff --git a/infrastructure/makebuildenv.pl b/infrastructure/makebuildenv.pl new file mode 100755 index 00000000..99455cc2 --- /dev/null +++ b/infrastructure/makebuildenv.pl @@ -0,0 +1,1126 @@ +#!/usr/bin/perl +use strict; +use Symbol; + +my @modules; +my %module_dependency; +my %module_library_link_opts; +my %header_dependency; + +$|=1; + + +# note: Mac OS X resource forks and .DS_Store files are explicity ignored + +print "Box build environment setup.\n\nChecking environment...\n"; + + +my $implicit_dep = 'lib/common'; + +# work out platform variables +use lib 'infrastructure'; +use BoxPlatform; + +# don't allow old versions of openssl by default. +my $old_version_of_openssl_ok = 0; + +# keep copy of command line args +my $makebuildenv_args = join(' ',@ARGV); + +# do command line arguments +my $compile_line_extra = $platform_compile_line_extra; +my $link_line_extra = $platform_link_line_extra; +for(@ARGV) +{ + if($_ eq 'allow-old-openssl') + { + $old_version_of_openssl_ok = 1; + next; + } + my ($k,$v) = split /:/,$_,2; + if($k eq 'compile') + { + $compile_line_extra .= $v . ' '; + } + elsif($k eq 'link') + { + $link_line_extra .= $v . ' '; + } + elsif($k eq 'openssl') + { + # assume that the bin/lib/include dirs are under the specified path + chop $v if ($v =~ /\/$/); + $compile_line_extra = "-I$v/include $compile_line_extra"; + $link_line_extra = "-L$v/lib $link_line_extra"; + } + else + { + die "invalid option $_ specified on command line" + } +} + +# make sure local files directory exists +unless(-d 'local') +{ + mkdir 'local',0755; +} + + +# flags about the environment +my %env_flags; +# messages on test failure +my $test_failure_text; + +# run all tests +{ + opendir DIR,'infrastructure/tests' or die "Can't read the tests directory"; + my @tests = grep {m/_tests\.pl\Z/} readdir DIR; + closedir DIR; + for(@tests) + { + require "infrastructure/tests/$_"; + } +} + + +# ---- LINUX start -------------------------------------------------------------------------- +# do configuration on Linux... find out what's available, and configure appropraitely. +if($build_os eq 'Linux') +{ + # setup the basic library translation flags -- these will omit those libraries from the compile line + $env_flags{'LIBTRANS_-lreadline'} = ''; + $env_flags{'LIBTRANS_-lLINUX_DB'} = ''; + + my $curses_lib = '-lcurses'; + if((!exists($env_flags{'curses_PRESENT'})) && exists($env_flags{'ncurses_PRESENT'})) + { + # got to use ncurses instead... + $env_flags{'LIBTRANS_-lcurses'} = '-lncurses'; + $curses_lib = '-lncurses'; + } + + my ($linux_readline_h, $linux_db_h); + my $db_ver = -1; + + open H_FILES,"find /usr/include |" or die "Can't open find"; + while(<H_FILES>) + { + chomp; + + if(m~/readline.h\Z~) + { + my $rlh = strip_h_name($_); + if(check_readline_h($rlh,$curses_lib)) + { + $linux_readline_h = $rlh; + # allow readline library to be used + delete $env_flags{'LIBTRANS_-lreadline'}; + } + } + if(m~/db(|_1\d+).h\Z~) + { + # version? + my $dv = 0; + $dv = $1 if m~(\d+)/db~; + my $fn = $_; + + # check this file mentions dbopen + open DB_H,$_ or die "Can't open $_"; + my $found = 0; + while(<DB_H>) + { + if(m/dbopen/) + { + $found = 1; + last; + } + } + close DB_H; + next unless $found; + + # see if this version works + print("Checking db version...\n"); + my $db_h = strip_h_name($fn); + my $db_lib = 'db'; + $db_lib .= $db_ver if $db_ver > 0; + if(!check_db_lib($db_h, $db_lib)) + { + # try another + $db_lib = 'db'; + next unless check_db_lib($db_h, $db_lib) + } + + # good version? + if($dv > $db_ver) + { + $linux_db_h = $db_h; + $db_ver = $dv; + $env_flags{'LIBTRANS_-lLINUX_DB'} = '-l'.$db_lib; + } + } + } + print "Finished checking headers\n"; + close H_FILES; + + # write the platform file accordingly and tell the user what's happened. + open LIN,">local/_linux_platform.h" or die "Can't open file for writing"; + if($linux_readline_h eq '') + { + print("---------------------\nWARNING: readline isn't installed\n---------------------\n"); + print LIN "#define PLATFORM_READLINE_NOT_SUPPORTED\n"; + + } + else + { + open RL_H,">local/_linux_readline.h" or die "Can't open file for writing"; + print RL_H "#include <$linux_readline_h>\n"; + my $hist = $linux_readline_h; + $hist =~ s/readline\.h/history.h/; + print RL_H "#include <$hist>\n"; + close RL_H; + } + if($linux_db_h eq '') + { + print("---------------------\nWARNING: db is not installed -- will run in reduced efficiency mode without it.\n---------------------\n"); + print LIN "#define PLATFORM_BERKELEY_DB_NOT_SUPPORTED\n"; + } + else + { + open DB_H,">local/_linux_db.h" or die "Can't open file for writing"; + print DB_H "#include <$linux_db_h>\n"; + close DB_H; + } + close LIN; +} +sub strip_h_name +{ + my $i = $_[0]; + $i =~ s~\A/usr/include/~~; + return $i; +} +sub check_readline_h +{ + my ($h,$curses_lib) = @_; + print "Check readline from $h...\n"; + my $hist = $h; + $hist =~ s/readline\.h/history.h/; + open READLINEH,">readlineh.cpp" or die "Can't open readline test file for writing"; + print READLINEH <<__E; +#include <unistd.h> +#include <stdio.h> +#include <sys/types.h> +#include <$h> +#include <$hist> +int main(int argc, char *argv[]) +{ + using_history(); + add_history(0); + readline(0); + return 0; +} +__E + close READLINEH; + # attempt to compile + my $r = system("g++ readlineh.cpp -lreadline $curses_lib -o readlineh $compile_line_extra $link_line_extra 2>/dev/null >/dev/null"); + # delete test files + unlink 'readlineh'; + unlink 'readlineh.cpp'; + return $r == 0; # compilation succeeded +} +sub check_db_lib +{ + my ($h,$db) = @_; + open TESTDBLIB,">testdblib.cpp" or die "Can't open db test file for writing"; + print TESTDBLIB <<__E; +#include <$h> +int main(int argc, char *argv[]) +{ + DB *dbp = 0; + dbp = dbopen(0, 0, 0, DB_HASH, 0); + dbp->close(dbp); + DBT data; + dbp->put(dbp, &data, &data, 0); + dbp->get(dbp, &data, &data, 0); + return 0; +} +__E + close TESTDBLIB; + # attempt to compile + my $r = system("g++ testdblib.cpp -l$db -o testdblib $compile_line_extra $link_line_extra 2>/dev/null >/dev/null"); + # delete test files + unlink 'testdblib'; + unlink 'testdblib.cpp'; + return $r == 0; # compilation succeeded +} +# ---- LINUX end -------------------------------------------------------------------------- + +# print "Flag: $_\n" for(keys %env_flags); + +# check the version of openssl installed +if(!exists $env_flags{'OPENSSL_OK'}) +{ + # failed somehow... + + # is an old version present? + my $old_version = (exists $env_flags{'OLD_OPENSSL_OK'}); + + if(!$old_version && !-e '/usr/include/openssl/evp.h') + { + # headers not installed? + print "\n\nERROR: OpenSSL library and headers need to be installed.\n\nSee documentation on web site if you need to add extra search paths.\n\n"; + exit(1); + } + else + { + if($old_version) + { + if($old_version_of_openssl_ok) + { + print "\n\nWARNING: Configuring for old version of OpenSSL.\nPerformance will be lower than with version 0.9.7\n\n"; + $compile_line_extra .= '-DPLATFORM_OLD_OPENSSL '; + } + else + { + # tell user how they might try anyway with an old version of openssl + print <<__E; + +=============================================================================== + +You appear to have a version of OpenSSL installed which is less than 0.9.7. + +It is possible to configure to use this old version, but performance will be +lower than if you have 0.9.7 -- the later version is recommended. + +If you wish to use this old version, repeat the configuration with the extra +argument 'allow-old-openssl', like this: + + ./configure allow-old-openssl + +* Please do not distribute binary packages with this option enabled. + +* Please do not distribute ports which set this option by default. + +IMPORTANT: Support for older versions of OpenSSL should be considered +experimental. It is not recommended for production use, but provided to allow +easier evaluation of this software before installing the latest OpenSSL. + +=============================================================================== + +__E + exit(1); + } + } + else + { + print "\n\nERROR: You need to install OpenSSL, preferably at least version 0.9.7.\n\n"; + print "If you believe you have installed OpenSSL, check that the headers are installed\nas well ('dev' packages?)\n\nSee documentation on web site if you need to add extra search paths.\n\n"; + exit(1); + } + } +} + + +# finished checking the environment +print "done\n\n"; + + +# seed autogen code +print "Seeding autogen code...\n"; +open FINDAUTOGEN,"find . -follow -name Makefile.extra |" or die "Can't use find for locating files"; +while(<FINDAUTOGEN>) +{ + chomp; + my $file = $_; + $file =~ m~\A(.+)/[^/]+\Z~; + my $dir = $1; + open FL,$file or die "Can't open $_ for reading"; + my %vars; + my $do_cmds = 0; + while(<FL>) + { + chomp; + if(m/\A(.+)\s+=\s+(.+)\Z/) + { + # is a variable + $vars{$1} = $2; + next; + } + next unless m/\S/; + if(m/AUTOGEN SEEDING/) + { + $do_cmds = 1; + } + elsif(m/\A\S/) + { + $do_cmds = 0 if $do_cmds == 2; + } + else + { + # command, run it? + if($do_cmds) + { + $do_cmds = 2; # flag something has been done + + # subsitute variables, repeatedly + my $c = $_; + $c =~ s/\A\s+//; + while(1) + { + my $did_subst = 0; + + for my $k (keys %vars) + { + $did_subst = 1 if $c =~ s/\$\($k\)/$vars{$k}/g; + } + + last unless $did_subst; + } + + # run command + die "Couldn't run command $c" unless (0 == system("(cd $dir; $c)")) + } + } + } + close FL; +} +close FINDAUTOGEN; +print "done\n\n"; + + +# open test mail program template file +my $test_template_file = 'infrastructure/buildenv-testmain-template.cpp'; +open FL,$test_template_file or die "Can't open test template file\n"; +my $test_template; +read FL,$test_template,-s $test_template_file; +close FL; + + +# extra platform defines +my $extra_platform_defines = ''; +if($gcc_v3 && !$gcc_v4) +{ + $extra_platform_defines .= ' -DPLATFORM_GCC3' +} +if($gcc_v4) +{ + $extra_platform_defines .= ' -DPLATFORM_GCC4' +} + +# read in module definitions file, and any files it includes +my @modules_files; +sub read_modules_file +{ + my ($mf) = @_; + my $f = gensym; + open $f,$mf or die "Can't open modules file '$mf'\n"; + while(<$f>) + { + if(m/\AINCLUDE\s+(\S+)\Z/) + { + # include another file + read_modules_file($1) + } + else + { + push @modules_files,$_ + } + } + close $f; +} +read_modules_file('modules.txt'); + +# prepare directories... +mkdir "release",0755; +mkdir "debug",0755; + +# is the library code in another directory? +my $external_lib = readlink('lib'); +if($external_lib ne '') +{ + # adjust to root of the library distribution + $external_lib =~ s!/lib\Z!!; + $external_lib = '../'.$external_lib; + # make symlinks + make_obj_symlink('debug'); + make_obj_symlink('release'); +} +sub make_obj_symlink +{ + my $m = $_[0]; + my $target = $external_lib."/$m/lib/"; + my $link = "$m/lib"; + # check link + if(-e $link) + { + if(-l $link) + { + if(readlink($link) ne $target) + { + print "Warning: replacing $link with new link to $target\n"; + unlink $link; + } + } + else + { + die "$link already exists, but it isn't a symbolic link" + } + } + if(!-e $link) + { + symlink $target,$link or die "Can't make $m/lib symlink"; + } +} + +print "Scanning code...\n"; + +my $modules_omitted = 0; + +# process lines in flattened modules files +for(@modules_files) +{ + # clean up line + chomp; s/\A\s+//; s/#.*\Z//; s/\s+\Z//; s/\s+/ /g; + next unless m/\S/; + + # omit bits on some platforms? + next if m/\AEND-OMIT/; + if(m/\AOMIT:(.+)/) + { + if($1 eq $build_os) + { + $modules_omitted = 1; + while(<MODULES>) + { + last if m/\AEND-OMIT/; + } + } + next; + } + + # split up... + my ($mod, @deps_i) = split / /; + + # ignore this module? + next if ignore_module($mod); + + # deps for this platform + my @deps; + for(@deps_i) + { + my ($dep,$exclude_from) = split /!/; + # generic library translation + $dep = $env_flags{'LIBTRANS_'.$dep} if exists($env_flags{'LIBTRANS_'.$dep}); + next if $dep eq ''; + if($exclude_from =~ m/\A\+(.+)\Z/) + { + $exclude_from = $1; + my $inc = 0; + for(split /,/,$exclude_from) + { + $inc = 1 if $_ eq $build_os + } + push @deps,$dep if $inc + } + else + { + my $inc = 1; + for(split /,/,$exclude_from) + { + $inc = 0 if $_ eq $build_os + } + push @deps,$dep if $inc + } + } + + # check directory exists + die "Module $mod can't be found\n" unless -d $mod; + + # and put in lists + push @modules,$mod; + my @md; # module dependencies + my @lo; # link line options + for(@deps) + { + if(/\A-l/) + { + push @lo,$_ + } + else + { + push @md,$_ unless ignore_module($_) + } + } + $module_dependency{$mod} = [$implicit_dep,@md]; + $module_library_link_opts{$mod} = [@lo]; + + # make directories, but not if we're using an external library and this a library module + my ($s,$d) = split /\//,$mod; + if($s ne 'lib' || $external_lib eq '') + { + mkdir "release/$s",0755; + mkdir "release/$s/$d",0755; + mkdir "debug/$s",0755; + mkdir "debug/$s/$d",0755; + } +} + +# make dirs for implicit dep +mkdir "release/$implicit_dep",0755; +mkdir "debug/$implicit_dep",0755; + +# write a list of all the modules we've configured to use +open CONFIGURED_MODS,'>local/modules.h' or die "Can't write configured modules list"; +print CONFIGURED_MODS <<__E; +// automatically generated file, do not edit +#ifndef _CONFIGURED_MODULES__H +#define _CONFIGURED_MODULES__H +__E +for($implicit_dep,@modules) +{ + my $m = $_; + $m =~ s~/~_~; + print CONFIGURED_MODS "#define MODULE_$m\n"; +} +print CONFIGURED_MODS <<__E; +#endif // _CONFIGURED_MODULES__H +__E +close CONFIGURED_MODS; + + +# now make a list of all the .h files we can find, recording which module they're in +my %hfiles; +for my $mod (@modules, $implicit_dep) +{ + opendir DIR,$mod; + my @items = readdir DIR; + closedir DIR; + + # add in items from autogen directories, and create output directories + { + my @autogen_items; + + for my $di (@items) + { + if($di =~ m/\Aautogen/ && -d "$mod/$di") + { + # Read items + my $d = "$mod/$di"; + opendir DIR,$d; + my @i = readdir DIR; + closedir DIR; + for(@i) + { + next if m/\A\./; + push @autogen_items,"$di/$_" + } + } + } + @items = (@items, @autogen_items); + } + + for(grep /\.h\Z/i, @items) + { + next if /\A\._/; # Temp Mac OS Resource hack + die "Header file $_ already used in module ".$hfiles{$_}."\n" if exists $hfiles{$_}; + $hfiles{$_} = $mod + } +} + +for my $mod (@modules, $implicit_dep) +{ + opendir DIR,$mod; + for my $h (grep /\.h\Z/i, readdir DIR) + { + next if /\A\._/; # Temp Mac OS Resource hack + + open FL,"$mod/$h" or die "can't open $mod/$h"; + my $f; + read FL,$f,-s "$mod/$h"; + close FL; + + while($f =~ m/\#include\s+"([^"]+?)"/g) + { + my $i = $1; + # ignore autogen exceptions + next if $i =~ m/\Aautogen_.+?Exception.h\Z/; + # record dependency + ${$header_dependency{$h}}{$i} = 1 if exists $hfiles{$i}; + } + } + closedir DIR; +} + +print "done\n\nGenerating Makefiles...\n"; + + +# Then write a makefile for each module +for my $mod (@modules, $implicit_dep) +{ + print $mod,"\n"; + + my ($type,$name) = split /\//,$mod; + + # add additional files for tests + if($type eq 'test') + { + my $testmain = $test_template; + $testmain =~ s/TEST_NAME/$name/g; + open TESTMAIN,">$mod/_main.cpp" or die "Can't open test main file for $mod for writing\n"; + print TESTMAIN $testmain; + close TESTMAIN; + + # test file... + sub writetestfile + { + my ($filename,$runcmd,$module) = @_; + open TESTFILE,">$filename" or die "Can't open test script file for $module for writing\n"; + print TESTFILE "#!/bin/sh\necho TEST: $module\n"; + if(-d "$module/testfiles") + { + print TESTFILE <<__E; +echo Removing old test files... +rm -rf testfiles +echo Copying new test files... +cp -p -R ../../../$module/testfiles . +__E + } + if(-e "$module/testextra") + { + open FL,"$module/testextra" or die "Can't open $module/testextra"; + while(<FL>) {print TESTFILE} + close FL; + } + print TESTFILE "$runcmd\n"; + close TESTFILE; + } + + writetestfile("$mod/_t", './test $1 $2 $3 $4 $5', $mod); + writetestfile("$mod/_t-gdb", 'gdb ./test', $mod); + + } + + my @all_deps_for_module; + { + # work out what dependencies need to be run + my @deps_raw; + sub add_mod_deps + { + my ($arr_r,$nm) = @_; + if($#{$module_dependency{$nm}} >= 0) + { + push @$arr_r,@{$module_dependency{$nm}}; + for(@{$module_dependency{$nm}}) + { + add_mod_deps($arr_r,$_) + } + } + } + add_mod_deps(\@deps_raw, $mod); + # and then dedup and reorder them + my %d_done; + for(my $a = $#deps_raw; $a >= 0; $a--) + { + if(!exists $d_done{$deps_raw[$a]}) + { + # insert + push @all_deps_for_module, $deps_raw[$a]; + # mark as done + $d_done{$deps_raw[$a]} = 1; + } + } + } + + + # make include path + my $include_paths = join(' ',map {'-I../../'.$_} @all_deps_for_module); + + # is target a library? + my $target_is_library = ($type ne 'bin' && $type ne 'test'); + + # make target name + my $end_target = $name; + $end_target .= '.a' if $target_is_library; + $end_target = 'test' if $type eq 'test'; + # adjust for outdir + $end_target = '$(OUTDIR)/' . $end_target; + + # start the makefile + my $mk_name_extra = ($bsd_make)?'':'X'; + open MAKE,">$mod/Makefile".$mk_name_extra or die "Can't open Makefile for $mod\n"; + my $debug_link_extra = ($target_is_library)?'':'../../debug/lib/debug/debug.a'; + print MAKE <<__E; +# +# AUTOMATICALLY GENERATED FILE +# do not edit! +# +# +CXX = g++ +AR = ar +RANLIB = ranlib +.ifdef RELEASE +CXXFLAGS = -DNDEBUG -O2 -Wall $include_paths -D$platform_define$extra_platform_defines -DBOX_VERSION="\\"$product_version\\"" +OUTBASE = ../../release +OUTDIR = ../../release/$mod +DEPENDMAKEFLAGS = -D RELEASE +VARIENT = RELEASE +.else +CXXFLAGS = -g -Wall $include_paths -D$platform_define$extra_platform_defines -DBOX_VERSION="\\"$product_version\\"" +OUTBASE = ../../debug +OUTDIR = ../../debug/$mod +DEPENDMAKEFLAGS = +VARIENT = DEBUG +.endif + +__E + + # read directory + opendir DIR,$mod; + my @items = readdir DIR; + closedir DIR; + + # add in items from autogen directories, and create output directories + { + my @autogen_items; + for my $di (@items) + { + if($di =~ m/\Aautogen/ && -d "$mod/$di") + { + # Read items + my $d = "$mod/$di"; + opendir DIR,$d; + my @i = readdir DIR; + closedir DIR; + for(@i) + { + next if m/\A\./; + push @autogen_items,"$di/$_" + } + + # output directories + mkdir "release/$mod/$di",0755; + mkdir "debug/$mod/$di",0755; + } + } + @items = (@items, @autogen_items); + } + + # first, obtain a list of depenencies within the .h files + my %headers; + for my $h (grep /\.h\Z/i, @items) + { + open FL,"$mod/$h"; + my $f; + read FL,$f,-s "$mod/$h"; + close FL; + + while($f =~ m/\#include\s+"([^"]+?)"/g) + { + ${$headers{$h}}{$1} = 1 if exists $hfiles{$1}; + } + } + + # ready for the rest of the details... + my $make; + + # then... do the cpp files... + my @obj_base; + for my $cpp (@items) + { + next unless $cpp =~ m/\A(.+)\.cpp\Z/i; + next if $cpp =~ /\A\._/; # Temp Mac OS Resource hack + + # store for later + my $base = $1; + push @obj_base,$base; + + # get the file... + open FL,"$mod/$cpp"; + my $f; + read FL,$f,-s "$mod/$cpp"; + close FL; + + my %dep; + + while($f =~ m/\#include\s+"([^"]+?)"/g) + { + insert_dep($1, \%dep) if exists $hfiles{$1}; + } + + # output filename + my $out_name = '$(OUTDIR)/'.$base.'.o'; + + # write the line for this cpp file + $make .= $out_name.': '.join(' ',$cpp,map + { ($hfiles{$_} eq $mod)?$_:'../../'.$hfiles{$_}."/$_" } keys %dep)."\n"; + $make .= "\t\$(CXX) \$(CXXFLAGS) $compile_line_extra -c $cpp -o $out_name\n\n"; + + } + + my $has_deps = ($#{$module_dependency{$mod}} >= 0); +# ----- # always has dependencies with debug library + $has_deps = 1; + + # Depenency stuff + my $deps_makeinfo; + if($has_deps) + { + if($bsd_make) + { + $deps_makeinfo = <<'__E'; +.BEGIN:: +.ifndef NODEPS +. if $(.TARGETS) == "" +__E + } + else + { + # gnu make + $deps_makeinfo = <<'__E'; +.PHONY: dep_modules +dep_modules: +ifndef NODEPS +ifeq ($(strip $(.TARGETS)),) +__E + } + + # run make for things we require + for my $dep (@all_deps_for_module) + { + $deps_makeinfo .= "\t\t(cd ../../$dep; $make_command$sub_make_options \$(DEPENDMAKEFLAGS) -D NODEPS)\n"; + } + $deps_makeinfo .= ".\tendif\n.endif\n\n"; + } + print MAKE $deps_makeinfo if $bsd_make; + + # get the list of library things to add -- in order of dependency so things link properly + my $lib_files = join(' ',map {($_ =~ m/lib\/(.+)\Z/)?('$(OUTBASE)/'.$_.'/'.$1.'.a'):undef} (reverse(@all_deps_for_module))); + + # need to see if the extra makefile fragments require extra object files + # or include any more makefiles + my @objs = @obj_base; + my @makefile_includes; + + additional_objects_from_make_fragment("$mod/Makefile.extra", \@objs, \@makefile_includes); + additional_objects_from_make_fragment("$mod/Makefile.extra.$build_os", \@objs, \@makefile_includes); + + my $o_file_list = join(' ',map {'$(OUTDIR)/'.$_.'.o'} @objs); + print MAKE $end_target,': ',$o_file_list; + print MAKE ' dep_modules' if !$bsd_make; + print MAKE " ",$lib_files unless $target_is_library; + print MAKE "\n"; + + # stuff to make the final target... + if($target_is_library) + { + # make a library archive... + print MAKE "\t(echo -n > $end_target; rm $end_target)\n"; + print MAKE "\t\$(AR) -q $end_target $o_file_list\n"; + print MAKE "\t\$(RANLIB) $end_target\n"; + } + else + { + # work out library options + # need to be... least used first, in absolute order they appear in the modules.txt file + my @libops; + sub libops_fill + { + my ($m,$r) = @_; + push @$r,$_ for(@{$module_library_link_opts{$m}}); + libops_fill($_,$r) for(@{$module_dependency{$m}}); + } + libops_fill($mod,\@libops); + my $lo = ''; + my %ldone; + for(@libops) + { + next if exists $ldone{$_}; + $lo .= ' '.$_; + $ldone{$_} = 1; + } + + # link line... + print MAKE "\t\$(CXX) $link_line_extra -o $end_target $o_file_list $lib_files$lo\n"; + } + # tests need to copy the test file over + if($type eq 'test') + { + print MAKE "\tcp _t \$(OUTDIR)/t\n\tchmod u+x \$(OUTDIR)/t\n"; + print MAKE "\tcp _t-gdb \$(OUTDIR)/t-gdb\n\tchmod u+x \$(OUTDIR)/t-gdb\n"; + } + # dependency line? + print MAKE "\n"; + + # module dependcies for GNU make? + print MAKE $deps_makeinfo if !$bsd_make; + + # print the rest of the file + print MAKE $make,"\n"; + + # and a clean target + print MAKE "clean:\n\t-rm -rf \$(OUTDIR)/*\n.\tifndef SUBCLEAN\n"; + for my $dep (@all_deps_for_module) + { + print MAKE "\t(cd ../../$dep; $make_command \$(DEPENDMAKEFLAGS) -D SUBCLEAN clean)\n"; + } + print MAKE ".\tendif\n"; + + # include any extra stuff + print MAKE "\n\n"; + if(-e "$mod/Makefile.extra") + { + print MAKE ".include <Makefile.extra>\n\n"; + } + if(-e "$mod/Makefile.extra.$build_os") + { + print MAKE ".include <Makefile.extra.$build_os>\n\n"; + } + for(@makefile_includes) + { + print MAKE ".include <$_>\n\n"; + } + + # and finally a target for rebuilding the build system + print MAKE "\nbuildsystem:\n\t(cd ../..; perl ./infrastructure/makebuildenv.pl $makebuildenv_args)\n\n"; + + close MAKE; + + if(!$bsd_make) + { + # need to post process this into a GNU makefile + open MAKE,">$mod/Makefile"; + open MAKEB,"$mod/MakefileX"; + + while(<MAKEB>) + { + s/\A\.\s*(ifdef|else|endif|ifndef)/$1/; + s/\A\.\s*include\s+<(.+?)>/include $1/; + s/-D\s+(\w+)/$1=1/; + print MAKE; + } + + close MAKEB; + close MAKE; + unlink "$mod/MakefileX"; + } +} + +print "\nType 'cd <module_dir>; $make_command' to build a module\n\n"; + +print $test_failure_text; + +if($modules_omitted) +{ + print "\nNOTE: Some modules have been omitted on this platform\n\n" +} + +sub insert_dep +{ + my ($h,$dep_r) = @_; + + # stop random recusion + return if exists $$dep_r{$h}; + + # insert more depencies + insert_dep($_,$dep_r) for keys %{$header_dependency{$h}}; + + # mark this one as a dependency + $$dep_r{$h} = 1; +} + + +sub additional_objects_from_make_fragment +{ + my ($fn,$objs_r,$include_r) = @_; + + if(-e $fn) + { + open FL,$fn or die "Can't open $fn"; + + while(<FL>) + { + chomp; + if(m/link-extra:\s*(.+)\Z/) + { + my @o = split /\s+/,$1; + for(@o) + { + push @$objs_r,$1 if m/\A(.+)\.o\Z/; + } + } + elsif(m/include-makefile:\s*(\S+)/) + { + push @$include_r,$1 + } + } + + close FL; + } +} + + +sub ignore_module +{ + exists $env_flags{'IGNORE_'.$_[0]} +} + +# how to run a test +sub do_test +{ + my %t = @_; + + print $t{'Name'},':'; + open TEST_CODE,">envtest.cpp" or die "Can't open envtest.cpp for writing"; + print TEST_CODE $t{'Code'}; + close TEST_CODE; + my $result = (system("g++ envtest.cpp ".$t{'TestCompileFlags'}." -o envtest $compile_line_extra $link_line_extra 2>/dev/null >/dev/null") == 0); + if($result && exists $t{'RunCode'}) + { + $result = 0 unless (system('./envtest') == 0); + } + unlink 'envtest.cpp'; + unlink 'envtest'; + print $result?" yes\n":" no\n"; + if($result) + { + # success + if(exists $t{'SuccessFlags'}) + { + for(@{$t{'SuccessFlags'}}) + { + my ($k,$v) = split /=>/,$_; + $v = 1 if $v eq ''; + $env_flags{$k} = $v + } + } + $compile_line_extra .= $t{'SuccessCompileFlags'}.' ' if exists $t{'SuccessCompileFlags'}; + $link_line_extra .= $t{'SuccessLinkFlags'}.' ' if exists $t{'SuccessLinkFlags'}; + } + else + { + # aborting failure? + if(exists $t{'AbortOnFailure'}) + { + print $t{'FailureText'}; + print "\nAborting configuration, cannot build in this environment.\n"; + exit(1); + } + + # failure + if(exists $t{'FailureFlags'}) + { + for(@{$t{'FailureFlags'}}) + { + my ($k,$v) = split /=>/,$_; + $v = 1 if $v eq ''; + $env_flags{$k} = $v + } + } + $compile_line_extra .= $t{'FailureCompileFlags'}.' ' if exists $t{'FailureCompileFlags'}; + $link_line_extra .= $t{'FailureLinkFlags'}.' ' if exists $t{'FailureLinkFlags'}; + $test_failure_text .= $t{'FailureText'} if exists $t{'FailureText'}; + } + $result +} + + + diff --git a/infrastructure/makedistribution.pl b/infrastructure/makedistribution.pl new file mode 100755 index 00000000..712b068c --- /dev/null +++ b/infrastructure/makedistribution.pl @@ -0,0 +1,312 @@ +#!/usr/bin/perl +use strict; +use Symbol; + +# comment string for various endings +my %comment_chars = ('cpp' => '// ', 'h' => '// ', 'pl' => '# ', 'pm' => '# ', '' => '# '); + +# other extensions which need text copying, just to remove the private stuff +my %text_files = ('txt' => 1); + +# files which don't get the license added +my %no_license = (); # 'filename' => 1 + +# ---------------------------------------------- + +# filled in from the manifest file +my %no_license_dir = (); + +# distribution name +my $distribution = $ARGV[0]; +die "No distribution name specified on the command line" if $distribution eq ''; +my $dist_root = "distribution/$distribution"; + +# check distribution exists +die "Distribution '$distribution' does not exist" unless -d $dist_root; + +# get version +open VERSION,"$dist_root/VERSION.txt" or die "Can't open $dist_root/VERSION.txt"; +my $version = <VERSION>; +chomp $version; +my $archive_name = <VERSION>; +chomp $archive_name; +close VERSION; + +# consistency check +die "Archive name '$archive_name' is not equal to the distribution name '$distribution'" + unless $archive_name eq $distribution; + +# make initial directory +my $base_name = "$archive_name-$version"; +system "rm -rf $base_name"; +system "rm $base_name.tgz"; +mkdir $base_name,0755; + +# get license file +open LICENSE,"$dist_root/LICENSE.txt" or die "Can't open $dist_root/LICENSE.txt"; +my $license_f; +read LICENSE,$license_f,100000; +close LICENSE; +my @license = ('distribution '.$base_name,'',split(/\n/,$license_f)); + +# copy files, make a note of all the modules included +my %modules_included; +my $private_sections_removed = 0; +my $non_distribution_sections_removed = 0; +sub copy_from_list +{ + my $list = $_[0]; + open LIST,$list or die "Can't open $list"; + + while(<LIST>) + { + next unless m/\S/; + chomp; + my ($src,$dst) = split /\s+/; + $dst = $src if $dst eq ''; + if($src eq 'MKDIR') + { + # actually we just need to make a directory here + mkdir "$base_name/$dst",0755; + } + elsif($src eq 'NO-LICENSE-IN-DIR') + { + # record that this directory shouldn't have the license added + $no_license_dir{$dst} = 1; + } + elsif($src eq 'REPLACE-VERSION-IN') + { + replace_version_in($dst); + } + elsif(-d $src) + { + $modules_included{$_} = 1; + copy_dir($src,$dst); + } + else + { + copy_file($src,$dst); + } + } + + close LIST; +} +copy_from_list("distribution/COMMON-MANIFEST.txt"); +copy_from_list("$dist_root/DISTRIBUTION-MANIFEST.txt"); + +# Copy in the root directory and delete the DISTRIBUTION-MANIFEST file +(system("cp $dist_root/*.* $base_name/") == 0) + or die "Copy of root extra files failed"; +unlink "$base_name/DISTRIBUTION-MANIFEST.txt" + or die "Delete of DISTRIBUTION-MANIFEST.txt file failed"; + +# produce a new modules file +my $modules = gensym; +open $modules,"modules.txt" or die "Can't open modules.txt for reading"; +open MODULES_OUT,">$base_name/modules.txt"; + +while(<$modules>) +{ + # skip lines for modules which aren't included + next if m/\A(\w+\/\w+)\s/ && !exists $modules_included{$1}; + + # skip private sections + unless(skip_non_applicable_section($_, $modules, 'modules.txt')) + { + # copy line to out files + print MODULES_OUT + } +} + +close MODULES_OUT; +close $modules; + +# report on how many private sections were removed +print "Private sections removed: $private_sections_removed\nNon-distribution sections removed: $non_distribution_sections_removed\n"; + +# tar it up +system "tar cf - $base_name | gzip -9 - > $base_name.tgz"; + +sub copy_file +{ + my ($fn,$dst_fn) = @_; + + my $ext; + $ext = $1 if $fn =~ m/\.(\w+)\Z/; + + # licenses not used in this directory? + my $license_in_dir = 1; + $dst_fn =~ m~\A(.+)/[^/]+?\Z~; + $license_in_dir = 0 if exists $no_license_dir{$1}; + + # licensed or not? + if(exists $comment_chars{$ext} && !exists $no_license{$fn} && $license_in_dir) + { + my $b = $comment_chars{$ext}; + + # copy as text, inserting license + my $in = gensym; + open $in,$fn; + open OUT,">$base_name/$dst_fn"; + + my $first = <$in>; + if($first =~ m/\A#!/) + { + print OUT $first; + $first = ''; + } + + # write license + for(@license) + { + print OUT $b,$_,"\n" + } + + if($first ne '') + { + print OUT $first; + } + + while(<$in>) + { + unless(skip_non_applicable_section($_, $in, $fn)) + { + print OUT + } + } + + close OUT; + close $in; + } + else + { + if(exists $text_files{$ext}) + { + # copy this as text, to remove private stuff + my $in = gensym; + open $in,$fn; + open OUT,">$base_name/$dst_fn"; + + while(<$in>) + { + unless(skip_non_applicable_section($_, $in, $fn)) + { + print OUT + } + } + + close OUT; + close $in; + } + else + { + # copy as binary + system 'cp',$fn,"$base_name/$dst_fn" + } + } + + # make sure perl scripts are marked as executable, and other things aren't + if($ext eq 'pl' || $ext eq '') + { + system 'chmod','a+x',"$base_name/$dst_fn" + } + else + { + system 'chmod','a-x',"$base_name/$dst_fn" + } +} + +sub skip_non_applicable_section +{ + my ($l, $filehandle, $filename) = @_; + if($l =~ m/BOX_PRIVATE_BEGIN/) + { + # skip private section + print "Removing private section from $filename\n"; + $private_sections_removed++; + while(<$filehandle>) {last if m/BOX_PRIVATE_END/} + + # skipped something + return 1; + } + elsif($l =~ m/IF_DISTRIBUTION\((.+?)\)/) + { + # which distributions does this apply to? + my $applies = 0; + for(split /,/,$1) + { + $applies = 1 if $_ eq $distribution + } + unless($applies) + { + # skip section? + print "Removing distribution specific section from $filename\n"; + $non_distribution_sections_removed++; + while(<$filehandle>) {last if m/END_IF_DISTRIBUTION/} + } + # hide this line + return 1; + } + elsif($l =~ m/END_IF_DISTRIBUTION/) + { + # hide these lines + return 1; + } + else + { + # no skipping, return this line + return 0; + } +} + +sub copy_dir +{ + my ($dir,$dst_dir) = @_; + + # copy an entire directory... first make sure it exists + my @n = split /\//,$dst_dir; + my $d = $base_name; + for(@n) + { + $d .= '/'; + $d .= $_; + mkdir $d,0755; + } + + # then do each of the files within in + opendir DIR,$dir; + my @items = readdir DIR; + closedir DIR; + + for(@items) + { + next if m/\A\./; + next if m/\A_/; + next if m/\AMakefile\Z/; + next if m/\Aautogen/; + next if !-f "$dir/$_"; + + copy_file("$dir/$_","$dst_dir/$_"); + } +} + +sub replace_version_in +{ + my ($file) = @_; + + my $fn = $base_name . '/' . $file; + open IN,$fn or die "Can't open $fn"; + open OUT,'>'.$fn.'.new' or die "Can't open $fn.new for writing"; + + while(<IN>) + { + s/###DISTRIBUTION-VERSION-NUMBER###/$version/g; + print OUT + } + + close OUT; + close IN; + + rename($fn.'.new', $fn) or die "Can't rename in place $fn"; +} + diff --git a/infrastructure/makeparcels.pl b/infrastructure/makeparcels.pl new file mode 100755 index 00000000..6cd3e8f2 --- /dev/null +++ b/infrastructure/makeparcels.pl @@ -0,0 +1,166 @@ +#!/usr/bin/perl + +use strict; +use lib 'infrastructure'; +use BoxPlatform; + +my $os_suffix = ''; +if($build_os eq 'OpenBSD') +{ + $os_suffix = `uname -r`; + $os_suffix =~ tr/0-9//cd; +} + +my @parcels; +my %parcel_contents; + +open PARCELS,"parcels.txt" or die "Can't open parcels file"; +{ + my $cur_parcel = ''; + while(<PARCELS>) + { + chomp; s/#.+\Z//; s/\s+\Z//; s/\s+/ /g; + next unless m/\S/; + + # omit bits on some platforms? + next if m/\AEND-OMIT/; + if(m/\AOMIT:(.+)/) + { + if($1 eq $build_os) + { + while(<PARCELS>) + { + last if m/\AEND-OMIT/; + } + } + next; + } + + # new parcel, or a new parcel definition? + if(m/\A\s+(.+)\Z/) + { + push @{$parcel_contents{$cur_parcel}},$1 + } + else + { + $cur_parcel = $_; + push @parcels,$_; + } + } +} +close PARCELS; + +# create parcels directory +mkdir "parcels",0755; +mkdir "parcels/scripts",0755; + +# write master makefile + +open MAKE,">Makefile" or die "Can't open master Makefile for writing"; + +print MAKE <<__E; +# +# AUTOMATICALLY GENERATED FILE +# do not edit! +# +# + +__E + +print MAKE "all:\t",join(' ',map {parcel_target($_)} @parcels),"\n\n"; + +print MAKE "clean:\n"; +for my $parcel (@parcels) +{ + print MAKE "\trm -rf ",parcel_dir($parcel),"\n"; + print MAKE "\trm -f ",parcel_target($parcel),"\n"; +} +print MAKE "\n"; + +print MAKE "test:\trelease/common/test\n\nrelease/common/test:\n\t./runtest.pl ALL release\n\n"; + +my $release_flag = BoxPlatform::make_flag('RELEASE'); + +for my $parcel (@parcels) +{ + my $target = parcel_target($parcel); + print MAKE $target,":\n"; + + my $dir = parcel_dir($parcel); + print MAKE "\tmkdir $dir\n"; + + open SCRIPT,">parcels/scripts/install-$parcel" or die "Can't open installer script for $parcel for writing"; + print SCRIPT "#!/bin/sh\n\n"; + + for(@{$parcel_contents{$parcel}}) + { + my ($type,$name) = split /\s+/; + + if($type eq 'bin') + { + my $exeext = ($build_os eq 'CYGWIN')?'.exe':''; + print MAKE "\t(cd bin/$name; $make_command $release_flag)\n"; + print MAKE "\tcp release/bin/$name/$name$exeext $dir\n"; + } + elsif ($type eq 'script') + { + print MAKE "\tcp $name $dir\n"; + # remove path from script name + $name =~ m~/([^/]+)\Z~; + $name = $1; + } + + print SCRIPT "install $name $install_into_dir\n"; + } + + close SCRIPT; + + chmod 0755,"parcels/scripts/install-$parcel"; + + my $root = parcel_root($parcel); + print MAKE "\tcp parcels/scripts/install-$parcel $dir\n"; + print MAKE "\t(cd parcels; tar cf - $root | gzip -9 - > $root.tgz )\n"; + + print MAKE "\n"; + + print MAKE "install-$parcel:\n"; + print MAKE "\t(cd $dir; ./install-$parcel)\n\n"; +} + +print MAKE <<__E; +install: + cat local/install.msg + +__E + +close MAKE; + +open INSTALLMSG,">local/install.msg" or die "Can't open install message file for writing"; +print INSTALLMSG <<__E; + +Parcels need to be installed separately, and as root. Type one of the following: + +__E + +for(@parcels) +{ + print INSTALLMSG " make install-".$_."\n"; +} +print INSTALLMSG "\n"; + +close INSTALLMSG; + +sub parcel_root +{ + $product_name.'-'.$product_version.'-'.$_[0].'-'.$build_os.$os_suffix +} + +sub parcel_dir +{ + 'parcels/'.parcel_root($_[0]) +} + +sub parcel_target +{ + parcel_dir($_[0]).'.tgz' +} diff --git a/infrastructure/setupexternal.pl b/infrastructure/setupexternal.pl new file mode 100755 index 00000000..e21403e1 --- /dev/null +++ b/infrastructure/setupexternal.pl @@ -0,0 +1,55 @@ +#!/usr/bin/perl +use strict; + +# This script links in the essential directories and processes various +# files to allow the Box libraries to be used in projects outside the main +# box library tree. + +# directories to link through +my @linkdirs = qw/lib infrastructure/; + +# ---------------------------------------------------- + +my $libdir = $ARGV[0]; +die "Provided library dir $libdir does not exist" unless -d $libdir; + +# Check and remove links from the directory, then add new symlinks +for my $d (@linkdirs) +{ + if(-e $d) + { + die "In project, $d is not a symbolic link" + unless -l $d; + print "Removing existing symlink $d\n"; + unlink $d; + } + my $link_target = "$libdir/$d"; + print "Add symlink $d -> $link_target\n"; + die "Can't create symlink $d" unless + symlink $link_target, $d; +} + +# Copy and create a base modules file which includes all the libraries +print "Create new modules_base.txt file\n"; +open OUT,">modules_base.txt" or die "Can't open modules_base.txt file for writing"; +print OUT <<__E; +# +# Automatically generated file, do not edit +# +# Source: $libdir/modules.txt +# + +__E + +open IN,"$libdir/modules.txt" or die "Can't open $libdir/modules.txt for reading"; + +while(<IN>) +{ + if(m/\A(lib\/.+?)\s/) + { + print OUT + } +} + +close IN; +close OUT; diff --git a/infrastructure/tests/common_tests.pl b/infrastructure/tests/common_tests.pl new file mode 100644 index 00000000..454f09c7 --- /dev/null +++ b/infrastructure/tests/common_tests.pl @@ -0,0 +1,178 @@ + +# perl fragment, not directly runnable + +{ + # test for a C++ compiler + do_test('Name' => 'Compiler 1', + 'AbortOnFailure' => 1, + 'FailureText' => <<__E, + +================ + +You do not appear to have the g++ compiler installed. Please fix and try again. +(Tested for C++ compilation and use of standard STL C++ library.) + +Some distributions rename the g++ compiler to something including the version number, +and fail to create a symlink to the expected name. Investigate this if you believe +you have the C++ compiler installed. + +================ + +__E + 'Code' => <<__E); +#include <string> +int main(int argc, char *argv[]) +{ + std::string str; + str = "Test"; + str += "_test"; +} +__E + + # test for a properly working C++ compiler + do_test('Name' => 'Compiler 2', + 'AbortOnFailure' => 1, + 'RunCode' => 1, + 'FailureText' => <<__E, + +================ + +The C++ compiler fails basic C++ tests. It is impossible to compile and deploy this +software on this platform. + +Some less common platforms do not have a working C++ implementation, especially +regarding modern language features such as exceptions. A basic test failed. It is +unlikely that you will be able to use this software without fixing the compiler. + +You could try a later version of the compiler, if available. + +================ + +__E + 'Code' => <<__E); +#include <string> +class test_class +{ +public: + test_class(const char *str) : mString(str) {} + ~test_class() {} +private: + std::string mString; +}; +int main(int argc, char *argv[]) +{ + try + { + throw test_class("Test exception"); + } + catch(test_class &e) + { + return 0; + } + return 1; +} +__E + + # test for any version of OpenSSL + do_test('Name' => 'OpenSSL 1', + 'SuccessFlags' => ['OLD_OPENSSL_OK'], + 'TestCompileFlags' => '-lcrypto ', + 'Code' => <<__E); +#include <openssl/evp.h> +int main(int argc, char *argv[]) +{ + EVP_CipherInit(0, 0, 0, 0, 0); + return 0; +} +__E + + # test for new version of OpenSSL + do_test('Name' => 'OpenSSL 2', + 'SuccessFlags' => ['OPENSSL_OK'], + 'TestCompileFlags' => '-lcrypto ', + 'Code' => <<__E); +#include <openssl/evp.h> +int main(int argc, char *argv[]) +{ + EVP_CipherInit_ex(0, 0, 0, 0, 0, 0); + return 0; +} +__E + + # Linux is always more fun + if($build_os eq 'Linux') + { + # see if curses is available + sub curses_test + { + my $c = $_[0]; + do_test('Name' => $c, + 'SuccessFlags' => [$c.'_PRESENT'], + 'TestCompileFlags' => '-l'.$c.' ', + 'Code' => <<__E); +#include <curses.h> +int main(int argc, char *argv[]) +{ + initscr(); cbreak(); noecho(); + nonl(); + intrflush(stdscr, 0); + keypad(stdscr, 0); + return 0; +} +__E + } + curses_test('curses'); + curses_test('ncurses'); + + # see if LFS support is available + do_test('Name' => 'Linux LFS support', + 'RunCode' => 1, + 'TestCompileFlags' => '-D_FILE_OFFSET_BITS=64 ', + 'SuccessCompileFlags' => '-D_FILE_OFFSET_BITS=64', + 'Code' => <<__E); +#include <sys/types.h> +#include <sys/stat.h> +int main(int argc, char *argv[]) +{ + struct stat st; + if(sizeof(st.st_size) == 8 && sizeof(off_t) == 8) + { + return 0; + } + return 1; +} +__E + + } + + # USE_MALLOC doesn't work on some < gcc3 platforms + if(!$gcc_v3) + { + do_test('Name' => 'USE_MALLOC', + 'FailureCompileFlags' => '-DPLATFORM_STL_USE_MALLOC_BROKEN', + 'FailureText' => <<__E, + +================ +WARNING: The implementation of the C++ STL on this platform may have a flaw +which causes it to apparently leak memory, and this flaw cannot be worked +around. + +When running the daemons, check their memory usage does not constantly +increase. The STL flaw can cause excessive memory use. +================ + +__E + 'Code' => <<__E); +#define __USE_MALLOC +#include <string> +int main(int argc, char *argv[]) +{ + std::string s; + s = "test"; +} +__E + } +} + + +1; |