#!/usr/bin/env perl #this script generates the internal release use Cwd; use File::Find; use Getopt::Std; sub usage() { print STDERR<<"EOF"; usage: $0 (-h|-r) [-n version number] [-d releasedir] [-a allpackagesdir] [-l lockfile] Exactly one of the options -h or -r must be present. -h show this message and quit -r release version to be created -n version number (CGAL_VERSION_NR) -d releasedir, default releasedir is the current dir -a allpackagesdir, default is releasedir/trunk -l lockfile, default is releasedir/release_creation.lock The version number is stored in include/CGAL/version.h. The RELEASEDIR is the place where the new release will be created. The ALLPACKAGESDIR is the directory that contains the checked out packages from the SVN. Could be trunk or some branch. The LOCKFILE is some file used by lockfile command as a mutex. Example of how to use the script: >svn co svn+ssh://scm.gforge.inria.fr/svn/cgal/trunk >./create_internal_release -r CGAL-3.3-I-1 or >./create_internal_release -r CGAL-3.3-I-7 -d \$HOME -a \$HOME/CGALSVN/trunk -l release_creation.lock EOF } my $TEMPFILE="TEMPFILE.$$"; #----------------------------------------------------# # Initialisation # #----------------------------------------------------# my ( $VERSION, $VERSION_NR, $LOCKFILE, $ALLPACKAGESDIR, $RELEASEDIR, $MAINDIR, $SCRIPTSDIR, $LOCKCMD, $packages_file ); sub termination_signal_handler { unlink $LOCKFILE; exit 1; } sub lock() { if (system("$LOCKCMD", "-r", '10', "$LOCKFILE") != 0) { print STDERR <<"TOTHIER"; The script could not proceed because it could not acquire the needed lock on file $LOCKFILE. TOTHIER exit 1; } $SIG{INT} = \&termination_signal_handler; $SIG{TERM} = \&termination_signal_handler; } sub unlock() { unlink $LOCKFILE; $SIG{INT} = 'DEFAULT'; $SIG{TERM} = 'DEFAULT'; } sub create_packages_dir(){ print "Creating $VERSION/Packages directory ...\n"; chdir $RELEASEDIR or die; if (! -f $packages_file){ print STDERR "$packages_file file does not exist\n"; unlock; die "\n"; } open PACKAGES_TO_INCLUDE, "$packages_file" or die; while (){ chomp; s/\s*//g; next if /^$/; $is_permitted_package{$_}=1; } close PACKAGES_TO_INCLUDE; opendir ALLPACKAGESDIR, $ALLPACKAGESDIR or die; while (defined($package_name = readdir(ALLPACKAGESDIR))) { next unless $is_permitted_package{$package_name}; chdir "$RELEASEDIR/$VERSION" or die; mkdir('Packages', 0775); chdir 'Packages'; mkdir($package_name, 0775); if (-f "$ALLPACKAGESDIR/$package_name/maintainer"){ system('cp', "$ALLPACKAGESDIR/$package_name/maintainer", "$RELEASEDIR/$VERSION/Packages/$package_name"); } if (-f "$ALLPACKAGESDIR/$package_name/changes.txt"){ system('cp', "$ALLPACKAGESDIR/$package_name/changes.txt", "$RELEASEDIR/$VERSION/Packages/$package_name"); } if (-f "$ALLPACKAGESDIR/$package_name/description.txt"){ system('cp', "$ALLPACKAGESDIR/$package_name/description.txt", "$RELEASEDIR/$VERSION/Packages/$package_name"); } } closedir ALLPACKAGESDIR; } sub create_global_makefile{ printf("Creating the global makefile in the test dir ...\n"); chdir "$RELEASEDIR/$VERSION" or die; if ( -e "test/Makefile"){ system("rm -f Makefile"); } opendir testdir, "test"; @dirs = readdir testdir; closedir testdir; shift @dirs; shift @dirs; chdir "test" or die; open(TEMPFILE, ">tempfile") or die; print TEMPFILE "testsuite: "; foreach $dir (@dirs){ if ( -d $dir){ print TEMPFILE "test_$dir "; } } print TEMPFILE "\n"; foreach $dir (@dirs){ if ( -d $dir){ print TEMPFILE "test_$dir:\n\t+ ./run_testsuite $dir\n"; } } system('mv', "tempfile", 'Makefile'); }; sub install_packages() { my ($filename, $direc, %is_permited_package, $package_name, $tmp_package_name); print "Installing packages ...\n"; chdir $RELEASEDIR or die; if (! -f $packages_file){ print STDERR "$packages_file file does not exist\n"; unlock; die "\n"; } open PACKAGES_TO_INCLUDE, "$packages_file" or die; while (){ chomp; s/\s*//g; next if /^$/; $is_permitted_package{$_}=1; } close PACKAGES_TO_INCLUDE; opendir ALLPACKAGESDIR, $ALLPACKAGESDIR or die; while (defined($package_name = readdir(ALLPACKAGESDIR))) { next unless $is_permitted_package{$package_name}; $dont_submit="$ALLPACKAGESDIR/$package_name/dont_submit"; $exclude_command="--exclude-from=$dont_submit"; chdir "$ALLPACKAGESDIR" or die; if(-f $dont_submit){ system('tar', '-cf', "$RELEASEDIR/temppack.tar", '--exclude=.svn', "$exclude_command", '--exclude=TODO', '--exclude=dont_submit', '--exclude=maintainer', '--exclude=description.txt', '--exclude=changes.txt', "$package_name"); } else { system('tar', '-cf', "$RELEASEDIR/temppack.tar", '--exclude=.svn', '--exclude=dont_submit', '--exclude=maintainer', '--exclude=description.txt', '--exclude=changes.txt', '--exclude=TODO', "$package_name"); } system('mv', "$RELEASEDIR/temppack.tar", "$RELEASEDIR/$VERSION/"); chdir "$RELEASEDIR/$VERSION" or die; system('tar', '-xf', "temppack.tar"); $tmp_package_name = "temp_${package_name}"; system("mv", "$package_name", "$tmp_package_name"); opendir packagename, "$tmp_package_name"; @fichiers = readdir packagename; closedir packagename; shift @fichiers; shift @fichiers; foreach $fichier (@fichiers){ system('cp', '-r', "$tmp_package_name/$fichier", "$RELEASEDIR/$VERSION"); } system('rm', '-rf', "$tmp_package_name"); } closedir ALLPACKAGESDIR; unlink 'temppack.tar', 'description.txt', 'long_description.txt', 'changes.txt'; } #-----------------------------------------------------------------------# # set the version information in the include/CGAL/version.h # #-----------------------------------------------------------------------# sub create_version_file() { chdir "$RELEASEDIR/$VERSION/include/CGAL" or die; open(TEMPFILE, ">tempfile") or die; #if VERSION starts with CGAL-, we remove "CGAL-" from version #the $newver variable will store the right version if ($result = $VERSION =~ /CGAL-(.*)/){ $newver = $1; } else { $newver = $VERSION; } # TODO : add `svnversion` Revision. print TEMPFILE << 'EOF'; // Copyright (c) 2006 Utrecht University (The Netherlands), // ETH Zurich (Switzerland), Freie Universitaet Berlin (Germany), // INRIA Sophia-Antipolis (France), Martin-Luther-University Halle-Wittenberg // (Germany), Max-Planck-Institute Saarbruecken (Germany), RISC Linz (Austria), // and Tel-Aviv University (Israel). All rights reserved. // // This file is part of CGAL (www.cgal.org); you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; version 2.1 of the License. // See the file LICENSE.LGPL distributed with CGAL. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // Author(s) : - // This file is automatically created by create_internal_release. // Do not edit manually. #ifndef CGAL_VERSION_H #define CGAL_VERSION_H EOF print TEMPFILE "#define CGAL_VERSION $newver\n"; print TEMPFILE "#define CGAL_VERSION_NR $VERSION_NR\n"; print TEMPFILE "#define CGAL_SVN_REVISION 0\n\n#endif\n"; close TEMPFILE || die "Error closing temporary file: $!\n"; system('mv', "tempfile", 'version.h'); chdir '../..' or die; } #-----------------------------------------------------------------------# # set the version information in the doc_tex/version.tex # #-----------------------------------------------------------------------# sub create_version_tex_file() { chdir "$RELEASEDIR/$VERSION/doc_tex" or die; open(TEMPFILE, ">tempfile") or die; #if VERSION starts with CGAL-, we remove "CGAL-" from version #the $newver variable will store the right version if ($result = $VERSION =~ /CGAL-(.*)/){ $newver = $1; } else { $newver = $VERSION; } print TEMPFILE << 'EOF'; %% This file is automatically created by create_internal_release. %% Do not edit manually. EOF print TEMPFILE "\\gdef\\cgalversion{$newver}\n"; my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); my @months = ( "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ); print TEMPFILE "\\gdef\\cgalversiondate{$mday $months[$mon] ", 1900 + $year, "}\n"; close TEMPFILE || die "Error closing temporary file: $!\n"; system('mv', "tempfile", 'version.tex'); chdir '../..' or die; } #---------------------------------------------------------------# # CreateExampleTestDirs #---------------------------------------------------------------# sub CreateExampleTestDirs() { my $DIR; print "Creating $VERSION/test/example directories ...\n"; chdir "$RELEASEDIR/$VERSION" or die; chdir 'examples' or return; foreach $DIR (glob("*")) { if ( -d $DIR ) { system('cp', '-r', "$DIR", "../test/${DIR}_Examples"); } } chdir '..'; } #---------------------------------------------------------------# # CreateDemoTestDirs #---------------------------------------------------------------# sub CreateDemoTestDirs() { my $DIR; print "Creating $VERSION/test/demo directories ...\n"; chdir "$RELEASEDIR/$VERSION" or die; chdir 'demo' or return; foreach $DIR (glob("*")) { if ( -d $DIR ) { system('cp', '-r', "$DIR", "../test/${DIR}_Demo"); open(CGAL_TEST,">../test/${DIR}_Demo/cgal_test"); print CGAL_TEST <<'EOF'; #! /bin/sh # This is a script for the CGAL test suite. Such a script must obey # the following rules: # # - the name of the script is cgal_test # - for every target two one line messages are written to the file 'error.txt' # the first one indicates if the compilation was successful # the second one indicates if the execution was successful # if one of the two was not successful, the line should start with 'ERROR:' # - running the script should not require any user interaction # - the script should clean up object files and executables ERRORFILE=error.txt #---------------------------------------------------------------------# # compile #---------------------------------------------------------------------# compile() { if eval 'make CGAL_MAKEFILE=$CGAL_MAKEFILE \ TESTSUITE_CXXFLAGS="$TESTSUITE_CXXFLAGS" \ TESTSUITE_LDFLAGS="$TESTSUITE_LDFLAGS" all' >compiler_output 2>&1 ; then echo " succesful compilation " >> $ERRORFILE cat compiler_output else echo " ERROR: compilation " >> $ERRORFILE eval "2>&1 make CGAL_MAKEFILE=$CGAL_MAKEFILE clean > /dev/null " eval 'make -k CGAL_MAKEFILE=$CGAL_MAKEFILE \ TESTSUITE_CXXFLAGS="$TESTSUITE_CXXFLAGS" \ TESTSUITE_LDFLAGS="$TESTSUITE_LDFLAGS" all' fi rm compiler_output eval "2>&1 make CGAL_MAKEFILE=$CGAL_MAKEFILE clean > /dev/null " } #---------------------------------------------------------------------# # remove the previous error file #---------------------------------------------------------------------# rm -f $ERRORFILE touch $ERRORFILE #---------------------------------------------------------------------# # compile and run the tests #---------------------------------------------------------------------# compile EOF close(CGAL_TEST); chmod 0755, "../test/${DIR}_Demo/cgal_test"; } } chdir '..'; } sub CreateConfigurationTestdir(){ print "Creating $VERSION/test/Configuration directory ...\n"; chdir "$RELEASEDIR/$VERSION" or die; system('cp', '-r', 'config/testfiles', 'test/Configuration'); } #---------------------------------------------------------------# # create cgal_test script in tests #---------------------------------------------------------------# sub create_test(){ open(CGAL_TEST,">cgal_test"); print CGAL_TEST <<'EOF'; #! /bin/sh # This is a script for the CGAL test suite. Such a script must obey # the following rules: # # - the name of the script is cgal_test # - for every target two one line messages are written to the file 'error.txt' # the first one indicates if the compilation was successful # the second one indicates if the execution was successful # if one of the two was not successful, the line should start with 'ERROR:' # - running the script should not require any user interaction # - the script should clean up object files and executables ERRORFILE=error.txt #---------------------------------------------------------------------# # compile_and_run #---------------------------------------------------------------------# compile_and_run() { echo "Compiling $1 ... " SUCCES="y" if eval 'make CGAL_MAKEFILE=$CGAL_MAKEFILE \ TESTSUITE_CXXFLAGS="$TESTSUITE_CXXFLAGS" \ TESTSUITE_LDFLAGS="$TESTSUITE_LDFLAGS" $1' ; then echo " succesful compilation of $1" >> $ERRORFILE else echo " ERROR: compilation of $1" >> $ERRORFILE SUCCES="" fi if [ -n "${SUCCES}" ] ; then OUTPUTFILE=ProgramOutput.$1.$PLATFORM rm -f $OUTPUTFILE COMMAND="./$1" if [ -f $1.cmd ] ; then COMMAND="$COMMAND `cat $1.cmd`" fi if [ -f $1.cin ] ; then COMMAND="cat $1.cin | $COMMAND" fi echo "Executing $1 ... " echo ulimit -t 3600 2> /dev/null if eval $COMMAND > $OUTPUTFILE 2>&1 ; then echo " succesful execution of $1" >> $ERRORFILE else echo " ERROR: execution of $1" >> $ERRORFILE fi else echo " ERROR: not executed $1" >> $ERRORFILE fi eval "make CGAL_MAKEFILE=$CGAL_MAKEFILE clean > /dev/null 2>&1 " } #---------------------------------------------------------------------# # remove the previous error file #---------------------------------------------------------------------# rm -f $ERRORFILE touch $ERRORFILE #---------------------------------------------------------------------# # compile and run the tests #---------------------------------------------------------------------# if [ $# -ne 0 ] ; then for file in $* ; do compile_and_run $file done else EOF close(CGAL_TEST); open(CGAL_TEST,">>cgal_test"); my $cfile; foreach $cfile (glob("*.C")) { substr($cfile, -2, 2) = ""; print CGAL_TEST " compile_and_run $cfile\n"; } print CGAL_TEST "fi\n"; close(CGAL_TEST); chmod 0755, 'cgal_test'; } #---------------------------------------------------------------# # make_testscripts and generate makefiles in test and examples #---------------------------------------------------------------# sub make_testscripts() { my ($DIR, $BASEDIR); chdir "$RELEASEDIR/$VERSION" or die; $BASEDIR = cwd(); print "Creating and checking makefiles ...\n"; chdir 'test'; foreach $DIR (glob("*")) { if ( -d $DIR ) { chdir $DIR; if ( -f 'Makefile') { rename 'Makefile', 'makefile'; } if ( -f 'makefile' ) { open MAKEFILE, "makefile"; open NEW_MAKEFILE, ">makefile.new"; while () { s/\.o\b/\$(OBJ_EXT)/g; s/-g\b/\$(DEBUG_OPT)/g; print NEW_MAKEFILE $_; } close NEW_MAKEFILE; close MAKEFILE; rename("makefile.new","makefile"); } else { my $options = '-t'; if ( -f 'cgal_create_makefile_options') { if (open(OPTIONS, "; chomp; if (/^[\w\s-]+$/) { $options = $_; } else { print STDERR "Rejected cgal_create_makefile_options in $DIR\n"; } close OPTIONS; } } system("$SCRIPTSDIR/cgal_create_makefile", $options) == 0 or die "Execution of $SCRIPTSDIR/cgal_create_makefile failed"; } if ( ! -f 'cgal_test' ) { create_test(); } chdir '..'; } } chdir $BASEDIR; chdir 'examples'; # Windows specific stuff print "Creating VC++ projects in examples\n"; system("../developer_scripts/examples/C2vcproj", glob("*")); print "Creating makefiles in examples\n"; foreach $DIR (glob("*")) { if ( -d $DIR ) { chdir $DIR; if ( -f 'Makefile') { rename 'Makefile', 'makefile'; } if ( -f 'makefile' ) { open MAKEFILE, "makefile"; open NEW_MAKEFILE, ">makefile.new"; while () { s/\.o\b/\$(OBJ_EXT)/g; s/-g\b/\$(DEBUG_OPT)/g; print NEW_MAKEFILE $_; } close NEW_MAKEFILE; close MAKEFILE; rename("makefile.new","makefile"); } else { my $options = '-d'; if ( -f 'cgal_create_makefile_options') { if (open(OPTIONS, "; chomp; if (/^[\w\s-]+$/) { $options = $_; } else { print STDERR "Rejected cgal_create_makefile_options in $DIR\n"; } close OPTIONS; } } system("$SCRIPTSDIR/cgal_create_makefile", $options) == 0 or die "Execution of $SCRIPTSDIR/cgal_create_makefile failed"; } chdir '..'; } } chdir $BASEDIR; } #----------------------------------------------------------------# # check_and_update_file # #----------------------------------------------------------------# sub check_and_update_file($$) { my ($filename, $filename_with_dir) = @_; my $header_type = 0; my $lines_exceeding_length = 0; my $has_line_directives = 0; unlink $TEMPFILE; open SOURCE_FILE, "<$filename" || die "Error opening $filename_with_dir: $!\n"; open TEMPFILE, ">$TEMPFILE" || die; while ( ) { $header_type = 1 if m|^Copyright \(c\) \d{4](,\s?\d{4})* The CGAL Consortium|; $header_type = 2 if m|^// Copyright \(c\) \d{4}(,\s?\d{4})* The CGAL Consortium|; $lines_exceeding_length +=1 if length $_ > 80; $has_line_directives = 1 if m|^\s*#\s*line\s|; print TEMPFILE $_; } close SOURCE_FILE || die "Error closing $filename_with_dir: $!"; close TEMPFILE || die "Error closing temporary file: $!\n"; rename($TEMPFILE, $filename ) || system('mv', "$TEMPFILE", "$filename") || warn "Could not update file $filename_with_dir\n"; if ($header_type == 0) { print FILE_CHECKS "$filename_with_dir has unrecognised header.\n"; } elsif ($header_type == 1) { print FILE_CHECKS "$filename_with_dir has old style header.\n"; } if ($lines_exceeding_length) { print FILE_CHECKS "$filename_with_dir has $lines_exceeding_length", " lines over 80 characters.\n"; } if ($has_line_directives) { print FILE_CHECKS "$filename_with_dir has line directives.\n"; } } #----------------------------------------------------------------# # set_file_headers # #----------------------------------------------------------------# sub set_file_headers() { print "Setting file headers...\n"; chdir "$RELEASEDIR/$VERSION"; open(FILE_CHECKS,">$PARENT_DIR/code_check_$VERSION"); find(\&file_header_setting, 'include', 'src', 'examples', 'config/testfiles'); close FILE_CHECKS; chdir $MAIN_DIR; } sub file_header_setting { my ($filename,$dev,$ino,$mode,$nlink,$uid,$gid,$filetype); $filename = $_; if ( ! /\.[h|C]$/ || ! (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($filename)) || ! -f _ ) { return; } check_and_update_file($filename, $File::Find::name); } #----------------------------------------------------# # Main entry point # #----------------------------------------------------# sub main(){ $RELEASEDIR=cwd(); $ALLPACKAGESDIR="$RELEASEDIR/trunk"; $LOCKFILE="$RELEASEDIR/release_creation.lock"; $LOCKCMD='lockfile'; getopts('hr:a:d:l:p:s:n:'); if ($::opt_h ) { usage(); die "\n"; } if ($::opt_d){ $RELEASEDIR = $::opt_d; $ALLPACKAGESDIR = "$RELEASEDIR/trunk"; $LOCKFILE="$RELEASEDIR/release_creation.lock"; } if ($::opt_r){ $VERSION = $::opt_r; if ($::opt_n){ $VERSION_NR = $::opt_n; } else { $VERSION_NR = $VERSION; } } else { usage(); die "\n"; } if ($::opt_a){ $ALLPACKAGESDIR = $::opt_a; } if ($::opt_l){ $LOCKFILE = $::opt_l; } $SCRIPTSDIR="$ALLPACKAGESDIR/Scripts/scripts"; $packages_file="$ALLPACKAGESDIR/Maintenance/release_building/include_in_release"; print "Initializing variables ...\n"; print " Release dir: $RELEASEDIR\n"; print " All packages dir: $ALLPACKAGESDIR\n"; print " Scripts dir: $SCRIPTSDIR\n"; print " Lockfile: $LOCKFILE\n"; print " Packages file : $packages_file\n"; umask(002); chdir $RELEASEDIR or die; if (! -d $VERSION){ print "Creating release directory ${VERSION} ...\n"; mkdir($VERSION, 0775); } else { print "$VERSION already exists in $RELEASEDIR\n"; print "Please remove it first\n"; exit 1; } lock; create_packages_dir(); install_packages(); CreateConfigurationTestdir(); CreateDemoTestDirs(); CreateExampleTestDirs(); create_version_file(); create_version_tex_file(); make_testscripts(); set_file_headers(); create_global_makefile(); unlock; } main();