Script to make a testing Makefile for cygwin

Geoffrey Hausheer i134rth8d9s at
Sun Mar 31 14:33:06 CST 2002

Included here is a perl script which will build a Makefile for running C 
tests on Windows through Cygwin/gcc.

The script can be run from unix, or from windows (Assuming you have cygwin's 
perl installed).

It will generate 'Makefile.cyg' at the top level of the cvs directory.  From 
a bash prompt in cygwin, 'make -f Makefile.cyg' will run the tests.

You can also generate a tar.gz or .zip package (using the -g or -z otions 
respectively) containing only the necessary files to run the tests.

While this works fine if you have a reasonably complete cygwin installation, 
it is not perfect.  Currently all paths are in unix format (which should work 
fine for cygwin), but it requires using the 'make' included with cygwin as 

Once the path formatting stuff is fixed, it should be easy to make this work 
with mingW too.

As always, I am licensing this code under X11, so that anyone who wants it 
can have it.

Comments are appreciated.

The script should be installed in programs/winetest
-------------- next part --------------
#!/usr/bin/perl -w
 * Script to generate a Cygwin makefile for running unit tests.
 * Copyright 2002 Geoffrey Hausheer
use strict;

sub usage;
sub fix_dir;
sub get_testname;
sub create_archive($$\@);

# set this variable to point to your windows headers
my ($windows_includes) ="/usr/include/w32api";
# set this variable to your compiler options
my($cc_opts)= "-g -O2 -Wall -mpreferred-stack-boundary=2 -D_REENTRANT";

# 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);
    if ($arg eq "-z") {
      $afile = shift @ARGV;
      $archive = "z";
    if ($arg eq "-g") {
      $afile = shift @ARGV;
      $archive = "g";

# 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;
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";

chdir $topobjdir;
# Locate all tests
open FIND_FH, "find . -type d -name tests -print |";
while(<FIND_FH>) {
  push @testdirs,$_;
close FIND_FH;

#start writing the makefile in the root directory
open MAKE_FH,">Makefile.cyg";
print MAKE_FH "CC = gcc\n";
print MAKE_FH "WINDOWS_HEADERS = $windows_includes\n";
print MAKE_FH "INCLUDE_DIRS = -I\$(WINDOWS_HEADERS) -I./include\n";
print MAKE_FH "CC_OPTS = \$(INCLUDE_DIRS) $cc_opts -include \$(WINDOWS_HEADERS)/windows.h\n";

# iterate over each 'tests' directory
foreach $dir (@testdirs) {
  # 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) {
      ($newfile = $file) =~ s/c$/ok/;
    # create the testslist.c file for each directory
    system("./programs/winetest/make_ctests $dir/*.c > $dir/testlist.c");
    push @filelist,"$dir/testlist.c";
    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 "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 make the executables
foreach $dir (@gooddirs) {
  print MAKE_FH "\$(TEST_EXE_${rootdir}): \$(TEST_O_FILES_${rootdir}) ./programs/winetest/wtmain.o\n";
  print MAKE_FH "	\$(CC) \$(CC_OPTS) \$(TEST_O_FILES_${rootdir}) ./programs/winetest/wtmain.o -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, at testdirs);
exit 0;

sub usage
    print STDERR <<EOF;

Usage: $0 [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
    -h       Show this message
    NOTE: You can specify either -g or -z but not both
    exit 1;
sub fix_dir {
  my($dir)=shift @_;
  my($rootdir)=($dir =~ /^[^\\\/]*[\\\/]+(.+)[\\\/]+tests/);
  $rootdir =~ s/[\\\/]+/_/g;

sub get_testname {
  my($dir)=shift @_;
  my($testname)=($dir =~ /[\\\/]+([^\\\/]+)[\\\/]+tests/i);
  return $testname;

sub create_archive($$\@) {
  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) {
    foreach $cfile (grep(!/\.spec/,glob "$dir/*.c")) {
      $cmd .= "$cfile ";
  $cmd .= " ./programs/winetest/wtmain.c";
  $cmd .= " ./include/wine";
  $cmd .= " ./Makefile.cyg";
  system "$cmd";

More information about the wine-patches mailing list