| #!/usr/bin/perl -w | |
| # | |
| # Script to generate a Cygwin/Mingw makefile for running unit tests. | |
| # | |
| # Copyright 2002 Geoffrey Hausheer | |
| # | |
| # This library is free software; 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; either | |
| # version 2.1 of the License, or (at your option) any later version. | |
| # | |
| # This library is distributed in the hope that it will be useful, | |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| # Lesser General Public License for more details. | |
| # | |
| # You should have received a copy of the GNU Lesser General Public | |
| # License along with this library; if not, write to the Free Software | |
| # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| # | |
| use strict; | |
| sub usage; | |
| sub fix_dir; | |
| sub get_testname; | |
| sub create_archive($$\@); | |
| # set this variable to point to your windows headers | |
| my ($cygwin_windows_includes) ="/usr/include/w32api"; | |
| my ($mingw_windows_includes) ="/mingw/include"; | |
| my ($wine_windows_includes) ="./include"; | |
| my ($windows_includes)=""; | |
| #set the default headers to use | |
| my ($default_headers) =\$cygwin_windows_includes; | |
| # set this variable to your compiler options | |
| my($cc_opts)= "-g -O2 -Wall -mpreferred-stack-boundary=2 -D_REENTRANT"; | |
| my($topobjdir); | |
| my(@testdirs); | |
| my(@gooddirs); | |
| my(@ok_list)=(); | |
| my($dir); | |
| my($file); | |
| my($afile)=""; | |
| my($archive)=""; | |
| # parse command-line options | |
| while ($#ARGV >= 0) | |
| { | |
| my $arg = shift @ARGV; | |
| if ($arg eq "-h") { usage; } | |
| if ($arg eq "-T") | |
| { | |
| $topobjdir = shift @ARGV; | |
| usage unless (-d $topobjdir); | |
| next; | |
| } | |
| if ($arg eq "-z") { | |
| $afile = shift @ARGV; | |
| $archive = "z"; | |
| } | |
| if ($arg eq "-g") { | |
| $afile = shift @ARGV; | |
| $archive = "g"; | |
| } | |
| if ($arg eq "-i") { | |
| $windows_includes = shift @ARGV; | |
| $default_headers = \$windows_includes; | |
| } | |
| if ($arg eq "-s") { | |
| my($sys) = shift @ARGV; | |
| if ($sys eq "cygwin") { | |
| $default_headers = \$cygwin_windows_includes; | |
| } elsif ($sys eq "mingw") { | |
| $default_headers = \$mingw_windows_includes; | |
| } elsif ($sys eq "wine") { | |
| $default_headers = \$wine_windows_includes; | |
| } else { | |
| usage; | |
| } | |
| } | |
| } | |
| # check/detect topobjdir | |
| # NOTE: Checking for configure is not ideal, but it seems to work | |
| if (defined($topobjdir)) | |
| { | |
| unless (-f $topobjdir . "/configure") | |
| { | |
| printf STDERR "Wrong -T argument, %s/configure does not exist\n", $topobjdir; | |
| usage; | |
| } | |
| } | |
| else # try to detect it automatically | |
| { | |
| if (-f "./configure") { $topobjdir = "."; } | |
| elsif (-f "../configure") { $topobjdir = ".."; } | |
| elsif (-f "../../configure") { $topobjdir = "../.."; } | |
| elsif (-f "../../../configure") { $topobjdir = "../../.."; } | |
| else { | |
| printf STDERR "Couldn't locate 'configure', and so no top-level directory\n"; | |
| usage; | |
| } | |
| } | |
| chdir $topobjdir; | |
| # Locate all tests | |
| open FIND_FH, "find . -type d -name tests -print |"; | |
| while(<FIND_FH>) { | |
| chomp; | |
| push @testdirs,$_; | |
| } | |
| close FIND_FH; | |
| #start writing the makefile in the root directory | |
| open MAKE_FH,">Makefile.win"; | |
| print MAKE_FH <<EOH ; | |
| #Define WINDOWS_HEADERS to point at the directory where windows.h lives | |
| #Here are some examples | |
| # For Cygwin | |
| #WINDOWS_HEADERS = $cygwin_windows_includes | |
| # For Mingw | |
| #WINDOWS_HEADERS = $mingw_windows_includes | |
| # For Wine | |
| #WINDOWS_HEADERS = $wine_windows_includes | |
| WINDOWS_HEADERS = $$default_headers | |
| CC = gcc | |
| RM = rm -f | |
| TOUCH = touch | |
| INCLUDE_DIRS = -I\$(WINDOWS_HEADERS) -I./include | |
| CC_OPTS = \$(INCLUDE_DIRS) $cc_opts -include \$(WINDOWS_HEADERS)/windows.h | |
| EOH | |
| # iterate over each 'tests' directory | |
| print MAKE_FH "TEST_O_FILES_wtmain = ./programs/winetest/wtmain.o\n"; | |
| foreach $dir (@testdirs) { | |
| my($rootdir); | |
| my($testname)=get_testname($dir); | |
| $rootdir=fix_dir($dir); | |
| unlink("$dir/testlist.c"); | |
| # Locate all '.c' files that arent 'spec' | |
| my(@filelist)=grep(!/\.spec/,glob "$dir/*.c"); | |
| if(scalar(@filelist)) { | |
| # Create a global list of all tests | |
| foreach $file (@filelist) { | |
| my($newfile); | |
| ($newfile = $file) =~ s/c$/ok/; | |
| push(@ok_list,$newfile); | |
| } | |
| # create the testslist.c file for each directory | |
| system("./programs/winetest/make_ctests @filelist > $dir/testlist.c"); | |
| push @filelist,"$dir/testlist.c"; | |
| push(@gooddirs,$dir); | |
| print MAKE_FH "# $dir\n"; | |
| # List all object files needed for this test | |
| print MAKE_FH "TEST_O_FILES_$rootdir = \\\n"; | |
| foreach $file (@filelist) { | |
| $file =~ s/c$/o/; | |
| if($file ne $filelist[$#filelist]) { | |
| print MAKE_FH " $file\\\n"; | |
| } else { | |
| print MAKE_FH " $file\n"; | |
| } | |
| } | |
| print MAKE_FH "TEST_EXE_$rootdir = $dir/$testname.exe\n"; | |
| } | |
| } | |
| die "No C files found\n" if (!scalar(@gooddirs)); | |
| # The prerequisites for the tests are that the .ok fiels get created | |
| print MAKE_FH "\n# .ok result files\n"; | |
| print MAKE_FH "TEST_OK_FILES = \\\n"; | |
| foreach $file (@ok_list) { | |
| if($file ne $ok_list[$#ok_list]) { | |
| print MAKE_FH " $file\\\n"; | |
| } else { | |
| print MAKE_FH " $file\n"; | |
| } | |
| } | |
| print MAKE_FH "\n"; | |
| print MAKE_FH "all: \$(TEST_OK_FILES)\n"; | |
| print MAKE_FH "\n"; | |
| #define how to clean everything up | |
| print MAKE_FH "clean:\n"; | |
| print MAKE_FH " \$(RM) \$(TEST_OK_FILES)\n"; | |
| print MAKE_FH "\n"; | |
| print MAKE_FH "distclean:\n"; | |
| print MAKE_FH " \$(RM) \$(TEST_OK_FILES)\n"; | |
| print MAKE_FH " \$(RM) \$(TEST_O_FILES_wtmain)\n"; | |
| foreach $dir (@gooddirs) { | |
| my($rootdir)=fix_dir($dir); | |
| print MAKE_FH " \$(RM) \$(TEST_EXE_${rootdir}) \$(TEST_O_FILES_${rootdir})\n"; | |
| } | |
| print MAKE_FH "\n"; | |
| #define how to make the executables | |
| foreach $dir (@gooddirs) { | |
| my($rootdir)=fix_dir($dir); | |
| print MAKE_FH "\$(TEST_EXE_${rootdir}): \$(TEST_O_FILES_${rootdir}) \$(TEST_O_FILES_wtmain)\n"; | |
| print MAKE_FH " \$(CC) \$(CC_OPTS) \$(TEST_O_FILES_${rootdir}) \$(TEST_O_FILES_wtmain) -o \$@\n"; | |
| } | |
| # define how to make to .ok files | |
| foreach $file (@ok_list) { | |
| my($dir,$test) = ($file =~ /^(.*[\\\/]+tests)[\\\/]+(.*)\.ok$/); | |
| print MAKE_FH "$file: \$(TEST_EXE_". fix_dir($file) . ")\n"; | |
| print MAKE_FH " \$< $test && \$(TOUCH) \$@\n"; | |
| } | |
| # define how to make the .o files | |
| print MAKE_FH "%.o: %.c\n"; | |
| print MAKE_FH " \$(CC) \$(CC_OPTS) -c -o \$@ \$<\n"; | |
| close MAKE_FH; | |
| if($archive ne "") { | |
| create_archive($afile,$archive,@testdirs); | |
| } | |
| exit 0; | |
| sub fix_dir { | |
| my($dir)=shift @_; | |
| my($rootdir)=($dir =~ /^[^\\\/]*[\\\/]+(.+)[\\\/]+tests/); | |
| $rootdir =~ s/[\\\/]+/_/g; | |
| return($rootdir); | |
| } | |
| sub get_testname { | |
| my($dir)=shift @_; | |
| my($testname)=($dir =~ /[\\\/]+([^\\\/]+)[\\\/]+tests/i); | |
| return $testname; | |
| } | |
| sub create_archive($$\@) { | |
| my($file,$arch,$dirlist)=@_; | |
| my($dir); | |
| my($cmd); | |
| if($arch eq "z") { | |
| print "Creating zip archive : $file\n"; | |
| $cmd = "zip -r $file "; | |
| } else { | |
| print "Creating tar.gz archive : $file\n"; | |
| $cmd = "tar -cvzf $file "; | |
| } | |
| foreach $dir (@$dirlist) { | |
| my($cfile); | |
| foreach $cfile (grep(!/\.spec/,glob "$dir/*.c")) { | |
| $cmd .= "$cfile "; | |
| } | |
| } | |
| $cmd .= " ./programs/winetest/wtmain.c"; | |
| $cmd .= " ./include"; | |
| $cmd .= " ./Makefile.win"; | |
| system "$cmd"; | |
| } | |
| sub usage | |
| { | |
| print STDERR <<EOF; | |
| Usage: $0 [options] | |
| Options: | |
| -v verbose mode (can be specified multiple times) | |
| -T dir set Wine tree top directory (autodetected if not specified) | |
| -z file archive (zip) all needed files for test | |
| -g file archive (tar.gz) all needed files for test | |
| -i dir specify directory where windows.h lives | |
| -s sys specify system to build on (this sets the default header dir) | |
| Valid values for 'sys' are: cygwin, mingw, and wine | |
| -h Show this message | |
| NOTE: You can specify either -g or -z but not both | |
| EOF | |
| exit 1; | |
| } |