[1/2]tools/winemaker: add project-file support(try3)

André Hentschel nerv at dawncrow.de
Tue Feb 17 10:08:01 CST 2009


---
 tools/winemaker |  761 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 741 insertions(+), 20 deletions(-)

diff --git a/tools/winemaker b/tools/winemaker
index 8c78987..4b8b393 100755
--- a/tools/winemaker
+++ b/tools/winemaker
@@ -3,6 +3,7 @@ use strict;
 
 # Copyright 2000-2004 Francois Gouget for CodeWeavers
 # Copyright 2004 Dimitrie O. Paun
+# Copyright 2009 André Hentschel
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -19,7 +20,7 @@ use strict;
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 #
 
-my $version="0.6.0";
+my $version="0.7.0";
 
 use Cwd;
 use File::Basename;
@@ -70,6 +71,10 @@ my $OPT_ASK_SKIP=-1;
 my $opt_work_dir;
 
 ##
+# This is the file in which winemaker will operate if a project file is specified.
+my $opt_work_file;
+
+##
 # Make a backup of the files
 my $opt_backup;
 
@@ -819,6 +824,7 @@ sub source_scan_directory($$$$)
     }
     if ((@$target[$T_FLAGS] & $TF_NOMSVCRT) == 0) {
       push @{@$target[$T_LDFLAGS]},"-mno-cygwin";
+       push @{@$target[$T_LDFLAGS]},"-m32";
     }
     push @{@$project[$P_TARGETS]},$target;
 
@@ -955,25 +961,712 @@ sub source_scan_directory($$$$)
 }
 
 ##
-# Scan the source directories in search of things to build
-sub source_scan()
+# Scans the specified project file to:
+# - get a list of targets for this project
+# - get some settings
+# - get the list of source files
+sub source_scan_project_file($$$);
+sub source_scan_project_file($$$)
 {
-  # If there's a single target then this is going to be the default target
-  if (defined $opt_single_target) {
-    # Create the main target
-    my $main_target=[];
-    target_init($main_target);
-    @$main_target[$T_NAME]=$opt_single_target;
-    @$main_target[$T_TYPE]=$opt_target_type;
+  # a reference to the parent's project
+  my $parent_project=$_[0];
+  # 0 if it is a single project, 1 if it is part of a workspace
+  my $is_sub_project=$_[1];
+  # the name of the project file, with complete path, or without if in
+  # the same directory
+  my $filename=$_[2];
 
-    # Add it to the list
-    push @{$main_project[$P_TARGETS]},$main_target;
+  # reference to the project for this file. May not be used
+  my $project;
+  # list of targets found in the current file
+  my %targets;
+  # list of sources found in the current file
+  my @sources_c=();
+  my @sources_cxx=();
+  my @sources_rc=();
+  my @sources_misc=();
+  # true if this directory contains headers
+  my $has_headers=0;
+  # some more settings
+  my $path=dirname($filename);
+  my $prj_target_cflags;
+  my $prj_target_ldflags;
+  my $prj_target_libs;
+  my $prj_name;
+  my $found_cfg=0;
+  my $prj_cfg;
+  my $prj_target_type=1;
+  my @prj_target_options;
+  
+  if (!($path=~/\/$/)) {
+    $path=$path."/";
+  }
+
+  if (defined $opt_single_target or $is_sub_project == 0) {
+    # Either there is a single target and thus a single project,
+    # or we are a single project-file for which a project
+    # already exists
+    $project=$parent_project;
+  } else {
+    $project=[];
+    project_init($project,$path);
   }
+  my $project_settings=@$project[$P_SETTINGS];
 
-  # The main directory is always going to be there
-  push @projects,\@main_project;
+  if ($filename =~ /.dsp$/i) {
+    # First find out what this project file contains:
+    # collect all sources, find targets and settings
+    if (!open(FILEI,$filename)) {
+      print STDERR "error: unable to open $filename for reading:\n";
+      print STDERR "       $!\n";
+      return;
+      }
+    my $sfilet;
+    while (<FILEI>) {
+       # Remove any trailing CtrlZ, which isn't strictly in the file
+      if (/\x1A/) {
+        s/\x1A//;
+        last if (/^$/)
+      }
+
+      # Remove any trailing CrLf
+      s/\r\n$/\n/;
+      if (!/\n$/) {
+        # Make sure all lines are '\n' terminated
+        $_ .= "\n";
+      }
+      
+      if (/^\# Microsoft Developer Studio Project File - Name=\"([^\"]+)/) {
+          $prj_name="$1.exe";
+          $targets{$prj_name}=1;
+          #print $prj_name;
+          next;
+      } elsif(/^# TARGTYPE/) {
+          if (/[[:space:]]0x0101$/) {
+            # Win32 (x86) Application
+            $prj_target_type=1;
+          }elsif (/[[:space:]]0x0102$/) {
+            # Win32 (x86) Dynamic-Link Library
+            $prj_target_type=3;
+          }elsif (/[[:space:]]0x0103$/) {
+            # Win32 (x86) Console Application
+            $prj_target_type=2;
+          }elsif (/[[:space:]]0x0104$/) {
+            # Win32 (x86) Static Library
+          }
+          next;
+      } elsif(/^# ADD CPP(.*)/ && $found_cfg==1) {
+          $prj_target_cflags=$1;
+          @prj_target_options=split(" /", $prj_target_cflags);
+          $prj_target_cflags="";
+          foreach ( @prj_target_options ) {
+            if($_ eq "") {
+              # empty
+            } elsif(/nologo/) {
+              # Suppress Startup Banner and Information Messages
+            } elsif (/^W0$/) {
+              # Turns off all warning messages
+              $prj_target_cflags=$prj_target_cflags."-w ";
+            } elsif (/^W[123]$/) {
+              # Warning Level
+              $prj_target_cflags=$prj_target_cflags."-W ";
+            } elsif (/^W4$/) {
+              # Warning Level
+              $prj_target_cflags=$prj_target_cflags."-Wall ";
+            } elsif (/^WX$/) {
+              # Warnings As Errors
+              $prj_target_cflags=$prj_target_cflags."-Werror ";
+            } elsif (/^Gm$/) {
+              # Enable Minimal Rebuild
+            } elsif (/^GX$/) {
+              # Enable Exception Handling
+              $prj_target_cflags=$prj_target_cflags."-fexceptions ";
+            } elsif (/^Z[d7iI]$/) {
+              # Debug Info
+              $prj_target_cflags=$prj_target_cflags."-g ";
+            } elsif (/^Od$/) {
+              # Disable Optimizations
+              $prj_target_cflags=$prj_target_cflags."-O0 ";
+            } elsif (/^O1$/) {
+              # Minimize Size
+              $prj_target_cflags=$prj_target_cflags."-Os ";
+            } elsif (/^O2$/) {
+              # Maximize Speed
+              $prj_target_cflags=$prj_target_cflags."-O2 ";
+            } elsif (/^Ob0$/) {
+              # Disables inline Expansion 
+              $prj_target_cflags=$prj_target_cflags."-fno-inline ";
+            } elsif (/^Ob1$/) {
+              # In-line Function Expansion
+            } elsif (/^Ob2$/) {
+              # auto In-line Function Expansion
+              $prj_target_cflags=$prj_target_cflags."-finline-functions ";
+            } elsif (/^Oy$/) {
+              # Frame-Pointer Omission
+              $prj_target_cflags=$prj_target_cflags."-fomit-frame-pointer ";
+            } elsif (/^GZ$/) {
+              # Catch Release-Build Errors in Debug Build
+            } elsif (/^M[DLT]d?$/) {
+              # Use Multithreaded Run-Time Library
+            } elsif (/^D\s*\"(.*)\"/) {
+              # Preprocessor Definitions
+              $prj_target_cflags=$prj_target_cflags."-D".$1." ";
+            } elsif (/^I/) {
+              # Additional Include Directories
+              #$prj_target_cflags=$prj_target_cflags."-I" fixpath(option)
+            } elsif (/^U\s*\"(.*)\"/) {
+              # Undefines a previously defined symbol
+              $prj_target_cflags=$prj_target_cflags."-U".$1." ";
+            } elsif (/^Fp/) {
+              # Name .PCH File
+            } elsif (/^F[Rr]/) {
+              # Create .SBR File
+            } elsif (/^YX$/) {
+              # Automatic Use of Precompiled Headers
+            } elsif (/^FD$/) {
+              # Generate File Dependencies
+            } elsif (/^c$/) {
+              # Compile Without Linking
+              # this option is always present and is already specified in the suffix rules
+            } elsif (/^GB$/) {
+              # Blend Optimization
+              $prj_target_cflags=$prj_target_cflags."-mcpu=pentiumpro -D_M_IX86=500 ";
+            } elsif (/^G6$/) {
+              # Pentium Pro Optimization
+              $prj_target_cflags=$prj_target_cflags."-march=pentiumpro -D_M_IX86=600 ";
+            } elsif (/^G5$/) {
+              # Pentium Optimization
+              $prj_target_cflags=$prj_target_cflags."-mcpu=pentium -D_M_IX86=500 ";
+            } elsif (/^G3$/) {
+              # 80386 Optimization
+              $prj_target_cflags=$prj_target_cflags."-mcpu=i386 -D_M_IX86=300 ";
+            } elsif (/^G4$/) {
+              # 80486 Optimization
+              $prj_target_cflags=$prj_target_cflags."-mcpu=i486 -D_M_IX86=400 ";
+            } elsif (/^Yc/) {
+              # Create Precompiled Header
+            } elsif (/^Yu/) {
+              # Use Precompiled Header
+            } elsif (/^Za$/) {
+              # Disable Language Extensions
+              $prj_target_cflags=$prj_target_cflags."-ansi ";
+            } elsif (/^Ze$/) {
+              # Enable Microsoft Extensions
+            } elsif (/^Zm[[:digit:]]+$/) {
+              # Specify Memory Allocation Limit
+            } elsif (/^Zp1$/) {
+              # Packs structures on 1-byte boundaries
+              $prj_target_cflags=$prj_target_cflags."-fpack-struct ";
+            } elsif (/^Zp(2|4|8|16)?$/) {
+              # Struct Member Alignment
+            } else {
+              print "C compiler option $_ not implemented\n";
+            }    
+          }
+          
+          #print "\nOptions: $prj_target_cflags\n";
+          next;
+      } elsif(/^# ADD LINK32(.*)/ && $found_cfg==1) {
+          $prj_target_ldflags=$1;
+          @prj_target_options=split(" /", $prj_target_ldflags);
+          $prj_target_ldflags="";
+          $prj_target_libs=$prj_target_options[0];
+          #print "\n$prj_target_libs bevor\n";
+          $prj_target_libs=~s/\\/\//g;
+          $prj_target_libs=~s/\.lib//g;
+          $prj_target_libs=~s/\s/ -l/g;
+          #print "\n$prj_target_libs after\n";
+          shift (@prj_target_options);
+          foreach ( @prj_target_options ) {      
+            if($_ eq "") {
+              # empty
+            } elsif (/^base:(.*)/) {
+              # Base Address
+              $prj_target_ldflags=$prj_target_ldflags."--image-base ".$1." ";
+            } elsif (/^debug$/) {
+              # Generate Debug Info
+            } elsif (/^dll$/) {
+              # Build a DLL
+              $prj_target_type=3;
+            } elsif (/^incremental:[[:alpha:]]+$/) {
+              # Link Incrmentally
+            } elsif (/^implib:/) {
+              # Name import library
+            } elsif (/^libpath:\"(.*)\"/) {
+              # Additional Libpath
+              push @{@$project_settings[$T_DLL_PATH]},"-L$1";
+            } elsif (/^machine:[[:alnum:]]+$/) {
+              # Specify Target Platform
+            } elsif (/^map/) {
+              # Generate Mapfile
+              if (/^map:(.*)/) {
+                $prj_target_ldflags=$prj_target_ldflags."-Map ".$1." ";
+              } else {
+                $prj_target_ldflags=$prj_target_ldflags."-Map ".$prj_name.".map ";
+              }
+            } elsif(/^nologo$/) {
+              # Suppress Startup Banner and Information Messages
+            } elsif (/^out:/) {
+              # Output File Name
+              # may use it as Target?
+            } elsif (/^pdbtype:/) {
+              # Program Database Storage
+            } elsif (/^subsystem:/) {
+              # Specify Subsystem  
+            } elsif (/^version:[[:digit:].]+$/) {
+              # Version Information
+            } else {
+              print "Linker option $_ not implemented\n";
+            }  
+          }  
+          next;
+      } elsif(/^LIB32=/ && $found_cfg==1) {
+          #$libflag = 1;
+          next;
+      } elsif (/^SOURCE=(.*)$/) {
+        $sfilet=$1;
+        if (($opt_lower == $OPT_LOWER_ALL and $sfilet =~ /[A-Z]/) or ($opt_lower == $OPT_LOWER_UPPERCASE and $sfilet !~ /[a-z]/)) {
+          $sfilet=lc $sfilet; #to lowercase if necessary
+        }
+        $sfilet=~s/\\\\/\\/g; #remove double backslash
+        $sfilet=~s/^\.\\//; #remove starting 'this directory'
+        $sfilet=~s/\\/\//g; #make slashes out of backslashes
+    #    if ($sfilet =~ /^((\.\.\/)+)/){
+    #        print "Fix files and directories in $1 ? y or n: ";
+    #      
+    #      if (<STDIN>=~/^y/i) {
+    #      fix_file_and_directory_names("$1"); #referenced files in upper directories? fix them!
+    #      }
+    #    }
+        if ($sfilet =~ /\.(exe|dll)$/i) {
+          $targets{$sfilet}=1;
+        } elsif ($sfilet =~ /\.c$/i and $sfilet !~ /\.(dbg|spec)\.c$/) {
+          push @sources_c,$sfilet;
+        } elsif ($sfilet =~ /\.(cpp|cxx)$/i) {
+          if ($sfilet =~ /^stdafx.cpp$/i && !(@$project_settings[$T_FLAGS] & $TF_NOMFC)) {
+            push @sources_misc,$sfilet;
+            @$project_settings[$T_FLAGS]|=$TF_MFC;
+          } else {
+            push @sources_cxx,$sfilet;
+          }
+        } elsif ($sfilet =~ /\.rc$/i) {
+          push @sources_rc,$sfilet;
+        } elsif ($sfilet =~ /\.(h|hxx|hpp|inl|rc2|dlg)$/i) {
+          $has_headers=1;
+          push @sources_misc,$sfilet;
+          if ($sfilet =~ /^stdafx.h$/i && !(@$project_settings[$T_FLAGS] & $TF_NOMFC)) {
+          @$project_settings[$T_FLAGS]|=$TF_MFC;
+          }
+        }
+          next;
+          
+      } elsif(/^# (Begin|End) Source File/) {
+          # Source-Files already handled
+          next;
+      } elsif (/^# (Begin|End) Group/) {
+          # Groups are ignored
+          next;
+      } elsif(/^# (Begin|End) Custom Build/) {
+          # Custom Builds are ignored
+          next;
+
+      } elsif(/^# ADD LIB32 /) {
+          #"ARFLAGS=rus"
+          next;
+      } elsif(/^# Begin Target$/) {
+          # Targets are ignored
+          next;
+      } elsif(/^# End Target$/) {
+          # Targets are ignored
+          next;
+      } elsif(/^!/) {
+          if ($found_cfg == 1) {
+            $found_cfg=0;
+          }
+          if(/IF(.*)\(CFG\)" == "(.*)"/) {
+            if ($2 eq $prj_cfg) {
+              $found_cfg=1;
+            }
+          }
+          next;
+      } elsif(/^CFG=(.*)/) {
+          $prj_cfg=$1;
+          next;
+      }
+        
+      else { # Line recognized
+      # print "|\n";
+        }
+    }
+    close(FILEI);
+    
+    push @{@$project_settings[$T_LIBRARIES]},$prj_target_libs;
+    push @{@$project_settings[$T_CXXEXTRA]},$prj_target_cflags;
+    push @{@$project_settings[$T_LDFLAGS]},$prj_target_ldflags;
+  } elsif ($filename =~ /.vcproj$/i) {
+    # Import des Moduls XML::Simple
+    use XML::Simple;
+    
+    my $project_xml = XMLin($filename, forcearray=>1);
+
+    $targets{$project_xml->{'Name'}.".exe"}=1;
+    my $sfilet;
+    for my $vc_files (@{$project_xml->{'Files'}}) {
+      for my $vc_filter (@{$vc_files->{'Filter'}}) {
+        for my $vc_file (@{$vc_filter->{'File'}}) {
+          $sfilet=$vc_file->{'RelativePath'};
+          if (($opt_lower == $OPT_LOWER_ALL and $sfilet =~ /[A-Z]/) or ($opt_lower == $OPT_LOWER_UPPERCASE and $sfilet !~ /[a-z]/)) {
+            $sfilet=lc $sfilet; #to lowercase if necessary
+          }
+          $sfilet=~s/\\\\/\\/g; #remove double backslash
+          $sfilet=~s/^\.\\//; #remove starting 'this directory'
+          $sfilet=~s/\\/\//g; #make slashes out of backslashes
+          if ($sfilet =~ /\.(exe|dll)$/i) {
+            $targets{$sfilet}=1;
+          } elsif ($sfilet =~ /\.c$/i and $sfilet !~ /\.(dbg|spec)\.c$/) {
+            push @sources_c,$sfilet;
+          } elsif ($sfilet =~ /\.(cpp|cxx)$/i) {
+            if ($sfilet =~ /^stdafx.cpp$/i && !(@$project_settings[$T_FLAGS] & $TF_NOMFC)) {
+              push @sources_misc,$sfilet;
+              @$project_settings[$T_FLAGS]|=$TF_MFC;
+            } else {
+              push @sources_cxx,$sfilet;
+            }
+          } elsif ($sfilet =~ /\.rc$/i) {
+            push @sources_rc,$sfilet;
+          } elsif ($sfilet =~ /\.(h|hxx|hpp|inl|rc2|dlg)$/i) {
+            $has_headers=1;
+            push @sources_misc,$sfilet;
+            if ($sfilet =~ /^stdafx.h$/i && !(@$project_settings[$T_FLAGS] & $TF_NOMFC)) {
+            @$project_settings[$T_FLAGS]|=$TF_MFC;
+            }
+          }
+        }
+      }
+    }
+    $prj_target_cflags="";
+    for my $vc_configurations (@{$project_xml->{'Configurations'}}) {
+      for my $vc_configuration (@{$vc_configurations->{'Configuration'}}) {
+        for my $vc_tool (@{$vc_configuration->{'Tool'}}) {
+          if ($vc_tool->{'Name'} ne 'VCCLCompilerTool') { next; }
+            if (defined $vc_tool->{'Optimization'}) {$prj_target_cflags=$prj_target_cflags."-O".$vc_tool->{'Optimization'}." ";}
+            if (defined $vc_tool->{'WarningLevel'}) {
+              if ($vc_tool->{'WarningLevel'}==0) {
+              $prj_target_cflags=$prj_target_cflags."-w ";
+              } elsif ($vc_tool->{'WarningLevel'}<4) {
+              $prj_target_cflags=$prj_target_cflags."-W ";
+              } elsif ($vc_tool->{'WarningLevel'}==4) {
+              $prj_target_cflags=$prj_target_cflags."-Wall ";
+              } elsif ($vc_tool->{'WarningLevel'} eq "X") {
+              $prj_target_cflags=$prj_target_cflags."-Werror ";
+              } 
+            }
+            if (defined $vc_tool->{'PreprocessorDefinitions'}) {
+                $vc_tool->{'PreprocessorDefinitions'}=~s/;/ -D/g;
+                $prj_target_cflags=$prj_target_cflags."-D".$vc_tool->{'PreprocessorDefinitions'}." ";
+            }
+        }
+        last;
+      }
+    }
+
+    push @{@$project_settings[$T_CXXEXTRA]},$prj_target_cflags;
+  }
+
+  if ($has_headers) {
+    push @{@$project_settings[$T_INCLUDE_PATH]},"-I.";
+  }
+
+  my $target_count;
+  $target_count=keys %targets;
+
+
+  # Add this project to the project list, except for
+  # the main project which is already in the list.
+  if ($is_sub_project == 1) {
+    push @projects,$project;
+  }
+
+  # Ask for project-wide options
+  if ($opt_ask_project_options == $OPT_ASK_YES) {
+    my $flag_desc="";
+    if ((@$project_settings[$T_FLAGS] & $TF_MFC)!=0) {
+      $flag_desc="mfc";
+    }
+    print "* Type any project-wide options (-D/-I/-P/-i/-L/-l/--mfc),\n";
+    if (defined $flag_desc) {
+      print "* (currently $flag_desc)\n";
+    }
+    print "* or 'skip' to skip the target specific options,\n";
+    print "* or 'never' to not be asked this question again:\n";
+    while (1) {
+      my $options=<STDIN>;
+      chomp $options;
+      if ($options eq "skip") {
+        $opt_ask_target_options=$OPT_ASK_SKIP;
+        last;
+      } elsif ($options eq "never") {
+        $opt_ask_project_options=$OPT_ASK_NO;
+        last;
+      } elsif (source_set_options($project_settings,$options)) {
+        last;
+      }
+      print "Please re-enter the options:\n";
+    }
+  }
+
+  # - Create the targets
+  # - Check if we have both libraries and programs
+  # - Match each target with source files (sort in reverse
+  #   alphabetical order to get the longest matches first)
+  my @local_dlls=();
+  my @local_depends=();
+  my @exe_list=();
+  foreach my $target_name (map (lc, (sort { $b cmp $a } keys %targets))) {
+    # Create the target...
+    my $target=[];
+    target_init($target);
+    @$target[$T_NAME]=$target_name;
+    @$target[$T_FLAGS]|=@$project_settings[$T_FLAGS];
+    if ($target_name =~ /\.dll$/) {
+      @$target[$T_TYPE]=$TT_DLL;
+      push @local_depends,"$target_name.so";
+      push @local_dlls,$target_name;
+      my $canon=canonize($target_name);
+      push @{@$target[$T_LDFLAGS]},("-shared","\$(${canon}_MODULE:%=%.spec)");
+    } else {
+      @$target[$T_TYPE]=$opt_target_type;
+      push @exe_list,$target;
+      push @{@$target[$T_LDFLAGS]},(@$target[$T_TYPE] == $TT_CUIEXE ? "-mconsole" : "-mwindows");
+    }
+    my $basename=$target_name;
+    $basename=~ s/\.(dll|exe)$//i;
+    # This is the default link list of Visual Studio
+    my @std_imports=qw(odbc32 ole32 oleaut32 winspool odbccp32);
+    my @std_libraries=qw(uuid);
+    if ((@$target[$T_FLAGS] & $TF_NODLLS) == 0) {
+      @$target[$T_DLLS]=\@std_imports;
+      @$target[$T_LIBRARIES]=\@std_libraries;
+    } else {
+      @$target[$T_DLLS]=[];
+      @$target[$T_LIBRARIES]=[];
+    }
+    if ((@$target[$T_FLAGS] & $TF_NOMSVCRT) == 0) {
+      push @{@$target[$T_LDFLAGS]},"-mno-cygwin";
+    push @{@$target[$T_LDFLAGS]},"-m32";
+    }
+    push @{@$project[$P_TARGETS]},$target;
+
+    # Ask for target-specific options
+    if ($opt_ask_target_options == $OPT_ASK_YES) {
+      my $flag_desc="";
+      if ((@$target[$T_FLAGS] & $TF_MFC)!=0) {
+  $flag_desc=" (mfc";
+      }
+      if ($flag_desc ne "") {
+  $flag_desc.=")";
+      }
+      print "* Specify any link option (-P/-i/-L/-l/--mfc) specific to the target\n";
+      print "* \"$target_name\"$flag_desc or 'never' to not be asked this question again:\n";
+      while (1) {
+        my $options=<STDIN>;
+        chomp $options;
+        if ($options eq "never") {
+          $opt_ask_target_options=$OPT_ASK_NO;
+          last;
+        } elsif (source_set_options($target,$options)) {
+          last;
+        }
+        print "Please re-enter the options:\n";
+      }
+    }
+    if (@$target[$T_FLAGS] & $TF_MFC) {
+      @$project_settings[$T_FLAGS]|=$TF_MFC;
+      push @{@$target[$T_DLL_PATH]},"\$(MFC_LIBRARY_PATH)";
+      push @{@$target[$T_DLLS]},"mfc.dll";
+      # FIXME: Link with the MFC in the Unix sense, until we
+      # start exporting the functions properly.
+      push @{@$target[$T_LIBRARY_PATH]},"\$(MFC_LIBRARY_PATH)";
+      push @{@$target[$T_LIBRARIES]},"mfc";
+    }
+
+    # Match sources...
+    if ($target_count == 1) {
+      push @{@$target[$T_SOURCES_C]},@{@$project_settings[$T_SOURCES_C]}, at sources_c;
+      @$project_settings[$T_SOURCES_C]=[];
+      @sources_c=();
+
+      push @{@$target[$T_SOURCES_CXX]},@{@$project_settings[$T_SOURCES_CXX]}, at sources_cxx;
+      @$project_settings[$T_SOURCES_CXX]=[];
+      @sources_cxx=();
+
+      push @{@$target[$T_SOURCES_RC]},@{@$project_settings[$T_SOURCES_RC]}, at sources_rc;
+      @$project_settings[$T_SOURCES_RC]=[];
+      @sources_rc=();
+
+      push @{@$target[$T_SOURCES_MISC]},@{@$project_settings[$T_SOURCES_MISC]}, at sources_misc;
+      # No need for sorting these sources
+      @$project_settings[$T_SOURCES_MISC]=[];
+      @sources_misc=();
+    } else {
+      foreach my $source (@sources_c) {
+  if ($source =~ /^$basename/i) {
+    push @{@$target[$T_SOURCES_C]},$source;
+    $source="";
+  }
+      }
+      foreach my $source (@sources_cxx) {
+  if ($source =~ /^$basename/i) {
+    push @{@$target[$T_SOURCES_CXX]},$source;
+    $source="";
+  }
+      }
+      foreach my $source (@sources_rc) {
+  if ($source =~ /^$basename/i) {
+    push @{@$target[$T_SOURCES_RC]},$source;
+    $source="";
+  }
+      }
+      foreach my $source (@sources_misc) {
+  if ($source =~ /^$basename/i) {
+    push @{@$target[$T_SOURCES_MISC]},$source;
+    $source="";
+  }
+      }
+    }
+    @$target[$T_SOURCES_C]=[sort @{@$target[$T_SOURCES_C]}];
+    @$target[$T_SOURCES_CXX]=[sort @{@$target[$T_SOURCES_CXX]}];
+    @$target[$T_SOURCES_RC]=[sort @{@$target[$T_SOURCES_RC]}];
+    @$target[$T_SOURCES_MISC]=[sort @{@$target[$T_SOURCES_MISC]}];
+  }
+  if ($opt_ask_target_options == $OPT_ASK_SKIP) {
+    $opt_ask_target_options=$OPT_ASK_YES;
+  }
+
+  if ((@$project_settings[$T_FLAGS] & $TF_NOMSVCRT) == 0) {
+    push @{@$project_settings[$T_CEXTRA]},"-mno-cygwin";
+    push @{@$project_settings[$T_CXXEXTRA]},"-mno-cygwin";
+  }
+
+  if (@$project_settings[$T_FLAGS] & $TF_MFC) {
+    push @{@$project_settings[$T_INCLUDE_PATH]},"\$(MFC_INCLUDE_PATH)";
+  }
+  # The sources that did not match, if any, go to the extra
+  # source list of the project settings
+  foreach my $source (@sources_c) {
+    if ($source ne "") {
+      push @{@$project_settings[$T_SOURCES_C]},$source;
+    }
+  }
+  @$project_settings[$T_SOURCES_C]=[sort @{@$project_settings[$T_SOURCES_C]}];
+  foreach my $source (@sources_cxx) {
+    if ($source ne "") {
+      push @{@$project_settings[$T_SOURCES_CXX]},$source;
+    }
+  }
+  @$project_settings[$T_SOURCES_CXX]=[sort @{@$project_settings[$T_SOURCES_CXX]}];
+  foreach my $source (@sources_rc) {
+    if ($source ne "") {
+      push @{@$project_settings[$T_SOURCES_RC]},$source;
+    }
+  }
+  @$project_settings[$T_SOURCES_RC]=[sort @{@$project_settings[$T_SOURCES_RC]}];
+  foreach my $source (@sources_misc) {
+    if ($source ne "") {
+      push @{@$project_settings[$T_SOURCES_MISC]},$source;
+    }
+  }
+  @$project_settings[$T_SOURCES_MISC]=[sort @{@$project_settings[$T_SOURCES_MISC]}];
+
+  # Finally if we are building both libraries and programs in
+  # this project, then the programs should be linked with all
+  # the libraries
+  if (@local_dlls > 0 and @exe_list > 0) {
+    foreach my $target (@exe_list) {
+      push @{@$target[$T_DLL_PATH]},"-L.";
+      push @{@$target[$T_DLLS]}, at local_dlls;
+    }
+  }
+}
+
+##
+# Scans the specified workspace file to find the project files
+sub source_scan_workspace_file($);
+sub source_scan_workspace_file($)
+{
+  my $filename=$_[0];
+
+  if (! -e $filename) {
+    return;
+  }
 
-  # Now scan the directory tree looking for source files and, maybe, targets
+  if (!open(FILEIWS,$filename)) {
+    print STDERR "error: unable to open $filename for reading:\n";
+    print STDERR "       $!\n";
+    return;
+  }
+
+  my $prj_name;
+  my $prj_path;
+  
+  if ($filename =~ /.dsw$/i) {
+    while (<FILEIWS>) {
+      # Remove any trailing CrLf
+      s/\r\n$/\n/;
+      
+        # catch a project definition
+        if(/^Project:\s\"(.*)\"=(.*)\s-/) {
+          $prj_name=$1;
+          $prj_path=$2;
+          $prj_path=~s/\\\\/\\/g; #remove double backslash
+          $prj_path=~s/^\.\\//; #remove starting 'this directory'
+          $prj_path=~s/\\/\//g; #make slashes out of backslashes
+          print "Name: $prj_name\nPfad: $prj_path\n";
+          source_scan_project_file(\@main_project,1,$prj_path);
+          next;
+        } elsif(/^#/)
+        {
+          # ignore Comments
+        } elsif(/\w:/)
+        {
+          print STDERR "unknown section $_\n";
+        } elsif(/^Microsoft(.*)Studio(.*)File,\sFormat Version\s(.*)/)
+        {
+          print "\nFileversion: $3\n";
+        }
+    }
+    close(FILEIWS);
+  } elsif ($filename =~ /.sln$/i) {
+    while (<FILEIWS>) {
+      # Remove any trailing CrLf
+      s/\r\n$/\n/;
+      
+        # catch a project definition
+        if(/^Project(.*)=\s*"(.*)",\s*"(.*)",\s*"(.*)"/) {
+          $prj_name=$2;
+          $prj_path=$3;
+          $prj_path=~s/\\\\/\\/g; #remove double backslash
+          $prj_path=~s/^\.\\//; #remove starting 'this directory'
+          $prj_path=~s/\\/\//g; #make slashes out of backslashes
+          print "Name: $prj_name\nPfad: $prj_path\n";
+          source_scan_project_file(\@main_project,1,$prj_path);
+          next;
+        } elsif(/^Microsoft(.*)Studio(.*)File,\sFormat Version\s(.*)/)
+        {
+          print "\nFileversion: $3\n";
+        }
+    }
+    close(FILEIWS);
+  }
+
+  @projects=sort { @$a[$P_PATH] cmp @$b[$P_PATH] } @projects;
+}
+
+##
+# Scan the source directories in search of things to build
+sub source_scan()
+{
+  # Scan the directory tree looking for source files and, maybe, targets
   print "Scanning the source directories...\n";
   source_scan_directory(\@main_project,"","",0);
 
@@ -1823,7 +2516,7 @@ sub usage()
   print STDERR "                 [-Dmacro[=defn]] [-Idir] [-Pdir] [-idll] [-Ldir] [-llibrary]\n";
   print STDERR "                 [--nodlls] [--nomsvcrt] [--interactive] [--single-target name]\n";
   print STDERR "                 [--generated-files|--nogenerated-files]\n";
-  print STDERR "                 work_directory\n";
+  print STDERR "                 work_directory|project_file|workspace_file\n";
   print STDERR "\nWinemaker is designed to recursively convert all the Windows sources found in\n";
   print STDERR "the specified directory so that they can be compiled with Winelib. During this\n";
   print STDERR "process it will modify and rename some of the files in that directory.\n";
@@ -1897,8 +2590,13 @@ while (@ARGV>0) {
   # Catch errors
   } else {
     if ($arg ne "--help" and $arg ne "-h" and $arg ne "-?") {
-      if (!defined $opt_work_dir) {
+      if (!defined $opt_work_dir and !defined $opt_work_file) {
+    if (-f $arg) {
+      $opt_work_file=$arg;
+    }
+    else {
         $opt_work_dir=$arg;
+    }
       } else {
         print STDERR "error: the work directory, \"$arg\", has already been specified (was \"$opt_work_dir\")\n";
         usage();
@@ -1909,10 +2607,10 @@ while (@ARGV>0) {
   }
 }
 
-if (!defined $opt_work_dir) {
-  print STDERR "error: you must specify the directory containing the sources to be converted\n";
+if (!defined $opt_work_dir and !defined $opt_work_file) {
+  print STDERR "error: you must specify the directory or project file containing the sources to be converted\n";
   usage();
-} elsif (!chdir $opt_work_dir) {
+} elsif (defined $opt_work_dir and !chdir $opt_work_dir) {
   print STDERR "error: could not chdir to the work directory\n";
   print STDERR "       $!\n";
   usage();
@@ -1927,8 +2625,31 @@ project_init(\@main_project,"");
 # Fix the file and directory names
 fix_file_and_directory_names(".");
 
+# If there's a single target then this is going to be the default target
+if (defined $opt_single_target) {
+  # Create the main target
+  my $main_target=[];
+  target_init($main_target);
+  @$main_target[$T_NAME]=$opt_single_target;
+  @$main_target[$T_TYPE]=$opt_target_type;
+
+  # Add it to the list
+  push @{$main_project[$P_TARGETS]},$main_target;
+}
+
+# The main directory is always going to be there
+push @projects,\@main_project;
+
+if (defined $opt_work_dir) {
 # Scan the sources to identify the projects and targets
 source_scan();
+} elsif (defined $opt_work_file) {
+  if ($opt_work_file =~ /.dsp$/i or $opt_work_file =~ /.vcproj$/i) {
+    source_scan_project_file(\@main_project,0,$opt_work_file);
+  } elsif ($opt_work_file =~ /.dsw$/i or $opt_work_file =~ /.sln$/i) {
+    source_scan_workspace_file($opt_work_file);
+  }
+}
 
 # Fix the source files
 if (! $opt_no_source_fix) {
-- 
1.6.0.4


--------------070703040901030607090400--



More information about the wine-patches mailing list