2007-10-17 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / tools / prj2make / MsPrjHelper.cs
1 using System;
2 using System.Diagnostics;
3 using System.Collections;
4 using System.IO;
5 using System.Text;
6 using System.Text.RegularExpressions;
7 using System.Xml;
8 using System.Xml.Serialization;
9 using Mfconsulting.General.Prj2Make.Schema.Prjx;
10 using Mfconsulting.General.Prj2Make.Schema.Csproj;
11
12 namespace Mfconsulting.General.Prj2Make
13 {
14         public class SlnMaker
15         { 
16                 public static string slash;
17                 static Hashtable projNameInfo = new Hashtable();
18                 static Hashtable projGuidInfo = new Hashtable();
19                 private string prjxFileName = null;
20                 private string cmbxFileName = null;
21                 private string m_strSlnVer;
22                 private string m_strCsprojVer;
23                 private bool m_bIsUnix;
24                 private bool m_bIsMcs;
25                 private bool m_bIsUsingLib;
26  
27                 // Flag use to determine if the LIB variable will be used in
28                 // the Makefile that prj2make generates
29                 public bool IsUsingLib
30                 {
31                         get{ return m_bIsUsingLib; }
32                         set{ m_bIsUsingLib = value; }
33                 }
34
35
36                 // Determines if the makefile is intended for nmake or gmake for urposes of path separator character
37                 public bool IsUnix
38                 {
39                         get{ return m_bIsUnix; }
40                         set{ m_bIsUnix = value; }
41                 }
42
43                 // Determines if using MCS or CSC
44                 public bool IsMcs
45                 {
46                         get{ return m_bIsMcs; }
47                         set{ m_bIsMcs = value; }
48                 }
49
50                 public string SlnVersion
51                 {
52                         get { return m_strSlnVer; }
53                         set { m_strSlnVer = value; }
54                 }
55
56                 public string CsprojVersion
57                 {
58                         get { return m_strCsprojVer; }
59                         set { m_strCsprojVer = value; }
60                 }
61
62                 // Shuld contain the file name 
63                 // of the most resent prjx generation
64                 public string PrjxFileName {
65                         get { return prjxFileName; }
66                 }
67
68                 // Shuld contain the file name 
69                 // of the most resent cmbx generation
70                 public string CmbxFileName {
71                         get { return cmbxFileName; }
72                 }
73
74                 // Default constructor
75                 public SlnMaker()
76                 {
77                         m_bIsUnix = false;
78                         m_bIsMcs = false;
79                         m_bIsUsingLib = false;
80                 }
81
82                 // Utility function to determine the sln file version
83                 protected string GetSlnFileVersion(string strInSlnFile)
84                 {
85                         string strVersion = null;
86                         string strInput = null;
87                         Match match;
88                         FileStream fis = new FileStream(strInSlnFile, FileMode.Open, FileAccess.Read, FileShare.Read);
89                         StreamReader reader = new StreamReader(fis);
90                         Regex regex = new Regex(@"Microsoft Visual Studio Solution File, Format Version (\d.\d\d)");
91                         
92                         strInput = reader.ReadLine();
93
94                         match = regex.Match(strInput);
95                         if (match.Success)
96                         {
97                                 strVersion = match.Groups[1].Value;
98                         }
99                         
100                         // Close the stream
101                         reader.Close();
102
103                         // Close the File Stream
104                         fis.Close();
105     
106                         return strVersion;
107                 }
108         
109                 // Utility function to determine the csproj file version
110                 protected string GetCsprojFileVersion(string strInCsprojFile)
111                 {
112                         string strRetVal = null;
113                         XmlDocument xmlDoc = new XmlDocument();
114
115                         xmlDoc.Load(strInCsprojFile);
116                         strRetVal = xmlDoc.SelectSingleNode("/VisualStudioProject/CSHARP/@ProductVersion").Value;
117
118                         return strRetVal;
119                 }
120
121                 protected void ParseMsCsProj(string fname)
122                 {
123                         string projectName = System.IO.Path.GetFileNameWithoutExtension (fname);
124                         string csprojPath = System.IO.Path.GetFileName (fname);
125                         string projectGuid = "";
126             
127                         CsprojInfo pi = new CsprojInfo (m_bIsUnix, m_bIsMcs, projectName, projectGuid, csprojPath);
128             
129                         projNameInfo[projectName] = pi;
130                         projGuidInfo[projectGuid] = pi;
131                 }
132
133                 protected void ParseSolution(string fname)
134                 {
135                         FileStream fis = new FileStream(fname,FileMode.Open, FileAccess.Read, FileShare.Read);
136                         StreamReader reader = new StreamReader(fis);
137                         Regex regex = new Regex(@"Project\(""\{(.*)\}""\) = ""(.*)"", ""(.*)"", ""(\{.*\})""");
138                         
139                         while (true)
140                         {
141                                 string s = reader.ReadLine();
142                                 Match match;
143     
144                                 match = regex.Match(s);
145                                 if (match.Success)
146                                 {
147                                         string projectName = match.Groups[2].Value;
148                                         string csprojPath = match.Groups[3].Value;
149                                         string projectGuid = match.Groups[4].Value;
150     
151                                         if (csprojPath.StartsWith("http://"))
152                                         {
153                                                 Console.WriteLine("WARNING: got http:// project, guessing actual path.");
154                                                 csprojPath = Path.Combine(projectName, Path.GetFileName(csprojPath));
155                                         }
156                                         if (csprojPath.EndsWith (".csproj"))
157                                         {
158                                                 CsprojInfo pi = new CsprojInfo (m_bIsUnix, m_bIsMcs, projectName, projectGuid, csprojPath);
159     
160                                                 projNameInfo[projectName] = pi;
161                                                 projGuidInfo[projectGuid] = pi;
162                                         }
163                                 }
164     
165                                 if (s.StartsWith("Global"))
166                                 {
167                                         break;
168                                 }
169                         }
170                 }
171
172                 private bool CheckReference(string referenceFilename)
173                 {
174                         foreach (CsprojInfo pi in projNameInfo.Values)
175                         {
176                                 if (referenceFilename.ToLower() == pi.name.ToLower())
177                                 {
178                                         return true;
179                                 }
180                         }
181                         return false;
182                 }
183     
184                 public string MsSlnHelper(bool isUnixMode, bool isMcsMode, bool isSln, string slnFile)
185                 {
186                         bool noCommonTargets = false;
187                         bool noProjectTargets = false;
188                         bool noFlags = false;
189                         StringBuilder MakefileBuilder = new StringBuilder();
190     
191                         m_bIsUnix = isUnixMode;
192                         m_bIsMcs = isMcsMode;
193                         
194                         if(m_bIsUnix == true && m_bIsMcs == true)
195                         {
196                                 m_bIsUsingLib = true;
197                         }
198
199                         if (m_bIsUnix)
200                         {
201                                 slash = "/";
202                         }
203                         else
204                         {
205                                 slash = "\\";
206                         }
207     
208                         try
209                         {
210                                 string d = Path.GetDirectoryName(slnFile);
211                                 if (d != "")
212                                         Directory.SetCurrentDirectory(d);
213
214                                 if (isSln == true) 
215                                 {
216                                         // Get the sln file version
217                                         m_strSlnVer = GetSlnFileVersion(slnFile);
218
219                                         // We invoke the ParseSolution 
220                                         // by passing the file obtained
221                                         ParseSolution (slnFile);
222                                 } 
223                                 else 
224                                 {
225                                         // Get the Csproj version
226                                         m_strCsprojVer = GetCsprojFileVersion(slnFile);
227
228                                         // We invoke the ParseMsCsProj 
229                                         // by passing the file obtained 
230                                         ParseMsCsProj (slnFile);
231                                 }
232     
233                                 if (!noFlags)
234                                 {
235                                         if (m_bIsUnix) // gmake
236                                         {
237                                                 MakefileBuilder.Append("ifndef TARGET\n");
238                                                 MakefileBuilder.Append("\tTARGET=./bin/Debug\n");                                       
239                                                 MakefileBuilder.Append("else\n");
240                                                 MakefileBuilder.Append("\tTARGET=./bin/$(TARGET)\n");
241                                                 MakefileBuilder.Append("endif\n\n");
242                                         
243                                                 if (this.m_bIsMcs == false)
244                                                 {
245                                                         MakefileBuilder.Append("MCS=csc\n");
246                                                         MakefileBuilder.Append("RESGEN=resgen\n");
247                                                         MakefileBuilder.Append("MCSFLAGS=-nologo\n\n");
248                                                         MakefileBuilder.Append("ifdef (RELEASE)\n");
249                                                         MakefileBuilder.Append("\tMCSFLAGS=$(MCSFLAGS) -optimize+ -d:TRACE\n");
250                                                         MakefileBuilder.Append("else\n");
251                                                         MakefileBuilder.Append("\tMCSFLAGS=$(MCSFLAGS) -debug+ -d:TRACE,DEBUG\n");
252                                                         MakefileBuilder.Append("endif\n");
253                                                 }
254                                                 else
255                                                 {
256                                                         MakefileBuilder.Append("MCS=mcs\n");
257                                                         MakefileBuilder.Append("RESGEN=resgen\n");
258                                                         MakefileBuilder.Append("ifndef (RELEASE)\n");
259                                                         MakefileBuilder.Append("\tMCSFLAGS=-debug \n");
260                                                         MakefileBuilder.Append("endif\n");
261                                                         // Define and add the information used in the -lib: arguments passed to the
262                                                         // compiler to assist in finding non-fullyqualified assembly references.
263                                                         if(m_bIsMcs == true)
264                                                         {
265                                                                 string strlibDir = PkgConfigInvoker.GetPkgVariableValue("mono", "libdir");
266
267                                                                 if (strlibDir == null)
268                                                                 {
269                                                                         strlibDir = "/usr/lib";
270                                                                 }                                                       
271                                                                 
272                                                                 MakefileBuilder.AppendFormat("LIBS=-lib:{0} -lib:{1}\n\n", 
273                                                                      Utils.Escape (Path.Combine(strlibDir.TrimEnd(), "mono/1.0")),
274                                                                      Utils.Escape (Path.Combine(strlibDir.TrimEnd(), "mono/gtk-sharp"))
275                                                                                              );
276                                                         }
277                                                 }                       
278                                         }
279                                         else // nmake
280                                         {
281                                                 MakefileBuilder.Append("!if !defined (TARGET)\n");
282                                                 MakefileBuilder.Append("TARGET=.\\bin\\Debug\n");                                       
283                                                 MakefileBuilder.Append("!else\n");
284                                                 MakefileBuilder.Append("TARGET=.\\bin\\$(TARGET)\n");
285                                                 MakefileBuilder.Append("!endif\n\n");
286                                         
287                                                 if (m_bIsMcs == false)
288                                                 {
289                                                         MakefileBuilder.Append("MCS=csc\n");
290                                                         MakefileBuilder.Append("RESGEN=resgen\n");
291                                                         MakefileBuilder.Append("MCSFLAGS=-nologo\n\n");
292                                                         MakefileBuilder.Append("!if !defined(RELEASE)\n");
293                                                         MakefileBuilder.Append("MCSFLAGS=$(MCSFLAGS) -optimize+ -d:TRACE\n");
294                                                         MakefileBuilder.Append("!else\n");
295                                                         MakefileBuilder.Append("MCSFLAGS=$(MCSFLAGS) -debug+ -d:TRACE,DEBUG\n");
296                                                         MakefileBuilder.Append("!endif\n");
297                                                 }
298                                                 else
299                                                 {
300                                                         MakefileBuilder.Append("MCS=mcs\n");
301                                                         MakefileBuilder.Append("RESGEN=resgen\n");
302                                                         MakefileBuilder.Append("!if !defined(RELEASE)\n");
303                                                         MakefileBuilder.Append("MCSFLAGS=-debug \n");
304                                                         MakefileBuilder.Append("!endif\n");
305                                                 }                               
306                                         }
307     
308                                         MakefileBuilder.Append("\n");
309                                 }
310                                 else
311                                 {
312                                         MakefileBuilder.Append("!if !defined(MCS)\n");
313                                         MakefileBuilder.Append("!error You must provide MCS when making\n");
314                                         MakefileBuilder.Append("!endif\n\n");
315                                 }
316     
317                                 foreach (CsprojInfo pi in projNameInfo.Values)
318                                 {
319                                         MakefileBuilder.AppendFormat("{0}=$(TARGET){1}{2}\n", pi.makename_ext, slash, pi.assembly_name);
320                                         MakefileBuilder.AppendFormat("{0}_PDB=$(TARGET){1}{2}\n", pi.makename, slash, pi.assembly_name.Replace(".dll",".pdb"));
321                                         MakefileBuilder.AppendFormat("{0}_SRC={1}\n", pi.makename, pi.src);
322                                         MakefileBuilder.AppendFormat("{0}_RESX={1}\n", pi.makename, pi.resgen);
323                                         MakefileBuilder.AppendFormat("{0}_RES={1}\n\n", pi.makename, pi.res);
324                                 }
325                                 
326      
327                                 MakefileBuilder.Append("all: ");
328
329                                 foreach (CsprojInfo pi in projNameInfo.Values)
330                                 {
331                                         MakefileBuilder.AppendFormat("\\\n$({0})", pi.makename_ext);
332                                 }
333                                 
334                                 MakefileBuilder.Append("\n");
335
336                                 foreach (CsprojInfo pi in projNameInfo.Values)
337                                 {
338                                         string refs = "";
339                                         string deps = "";
340                                         
341                                         Hashtable libdirs = new Hashtable();
342                                         
343                                         foreach (Mfconsulting.General.Prj2Make.Schema.Csproj.Reference rf in pi.Proyecto.CSHARP.Build.References)
344                                         {
345                                                 if(rf.Package == null || rf.Package.CompareTo("") == 0)
346                                                 {
347                                                         // Add space in between references as
348                                                         // it becomes necessary
349                                                         if (refs != "")
350                                                                 refs += " ";
351
352                                                         string assemblyName = rf.AssemblyName;
353                                                         if (rf.HintPath != null) 
354                                                         {
355                                                                 string potentialPath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(pi.csprojpath), rf.HintPath));
356                                                                 if (isUnixMode)
357                                                                         potentialPath = potentialPath.Replace('\\', '/');
358                                                                 if (System.IO.File.Exists(potentialPath)) 
359                                                                 {
360                                                                         // assemblyName = potentialPath;
361                                                                         pi.libdirs.Add(Path.GetDirectoryName(potentialPath));
362                                                                 }
363                                                         }
364
365                                                         // HACK - under Unix filenames are case sensitive
366                                                         // Under Windows there's no agreement on Xml vs XML ;-)                                         
367                                                         if (0 == String.Compare(assemblyName, "System.Xml", true))
368                                                         {
369                                                                 assemblyName = "System.Xml";
370                                                         }
371
372                                                         // Check if this assembly is actually one compiled earlier in the project.
373                                                         // If so we must add the TARGET path to this line.
374                                                         string thisref;
375                                                         if (CheckReference(rf.AssemblyName) == true)
376                                                         {
377                                                                 thisref = "-r:$(TARGET)" + Path.DirectorySeparatorChar + assemblyName;
378                                                         }
379                                                         else
380                                                         {
381                                                                 thisref = "-r:" + assemblyName;
382                                                         }
383                                                         
384                                                         if (!thisref.EndsWith(".dll"))
385                                                                 thisref += ".dll";
386                                                         refs += thisref;
387                                                 }
388                                                 else
389                                                 {
390                                                         try
391                                                         {
392                                                                 CsprojInfo pi2 = (CsprojInfo)projGuidInfo[rf.Project];
393
394                                                                 if (refs != "")
395                                                                         refs += " ";
396
397                                                                 if (deps != "")
398                                                                         deps += " ";
399
400                                                                 refs += "-r:$(" + pi2.makename_ext + ")";
401                                                                 deps += "$(" + pi2.makename_ext + ")";
402                                                                 
403                                                                 foreach (string libdir in pi2.libdirs)
404                                                                 {
405                                                                         if (!libdirs.ContainsKey(libdir))
406                                                                                 libdirs[libdir] = 1;
407                                                                 }
408                                                                 
409                                                         }
410                                                         catch(System.NullReferenceException)
411                                                         {
412                                                                 refs += String.Format("-r:{0}.dll", rf.Name);
413                                                                 deps += String.Format("# Missing dependency project {1} ID:{0}?", 
414                                                                 rf.Project,
415                                                                 rf.Name
416                                                                 );
417                                                                 
418                                                                 
419                                                                 Console.WriteLine(String.Format(
420                                                                         "Warning: The project {0}, ID: {1} may be required and appears missing.",
421                                                                         rf.Name, rf.Project)
422                                                                         );
423                                                         }
424                                                 }
425                                         }
426     
427                                         MakefileBuilder.AppendFormat("$({0}): $({1}_SRC) {2}\n", pi.makename_ext, pi.makename, deps);
428                 
429                                         if (isUnixMode)
430                                         {
431                                                 MakefileBuilder.Append("\t-mkdir -p $(TARGET)\n");
432                                         }
433                                         else
434                                         {
435                                                 MakefileBuilder.Append("\t-md $(TARGET)\n");
436                                         }
437
438                                         if (pi.resgen != null && pi.resgen != String.Empty)
439                                                 MakefileBuilder.AppendFormat ("\t$(RESGEN) /compile {0}\n", pi.resgen);
440
441                                         MakefileBuilder.Append("\t$(MCS) $(MCSFLAGS)");
442
443                                         foreach (string libdir in libdirs.Keys)
444                                         {
445                                                 MakefileBuilder.AppendFormat(" -lib:{0}", Utils.Escape (libdir));
446                                         }
447                                         
448                                         foreach (string libdir in pi.libdirs) 
449                                         {
450                                                 MakefileBuilder.AppendFormat(" -lib:{0}", Utils.Escape (libdir));
451                                         }
452                                         
453                                         // Test to see if any configuratino has the Allow unsafe blocks on
454                                         if(pi.AllowUnsafeCode == true ) {
455                                                 MakefileBuilder.Append(" -unsafe");
456                                         }
457
458                                         // Test for LIBS usage
459                                         if(m_bIsUsingLib == true) {
460                                                 MakefileBuilder.Append(" $(LIBS)");
461                                         }
462
463                                         MakefileBuilder.AppendFormat(" {2}{3} -out:$({0}) $({1}_RES) $({1}_SRC)\n", 
464                                                         pi.makename_ext, pi.makename, refs, pi.switches);
465                                                                         
466                                         MakefileBuilder.Append("\n");
467                                 }
468     
469                                 if (!noCommonTargets)
470                                 {
471                                         MakefileBuilder.Append("\n");
472                                         MakefileBuilder.Append("# common targets\n\n");
473                                         MakefileBuilder.Append("all:\t");
474     
475                                         bool first = true;
476     
477                                         foreach (CsprojInfo pi in projNameInfo.Values)
478                                         {
479                                                 if (!first)
480                                                 {
481                                                         MakefileBuilder.Append(" \\\n\t");
482                                                 }
483                                                 MakefileBuilder.AppendFormat("$({0})", pi.makename_ext);
484                                                 first = false;
485                                         }
486                                         MakefileBuilder.Append("\n\n");
487     
488                                         MakefileBuilder.Append("clean:\n");
489     
490                                         foreach (CsprojInfo pi in projNameInfo.Values)
491                                         {
492                                                 if (isUnixMode)
493                                                 {
494                                                         MakefileBuilder.AppendFormat("\t-rm -f \"$({0})\" 2> /dev/null\n", pi.makename_ext);
495                                                         MakefileBuilder.AppendFormat("\t-rm -f \"$({0}_PDB)\" 2> /dev/null\n", pi.makename);
496                                                 }
497                                                 else
498                                                 {
499                                                         MakefileBuilder.AppendFormat("\t-del \"$({0})\" 2> nul\n", pi.makename_ext);
500                                                         MakefileBuilder.AppendFormat("\t-del \"$({0}_PDB)\" 2> nul\n", pi.makename);
501                                                 }
502                                         }
503                                         MakefileBuilder.Append("\n");
504                                 }
505     
506                                 if (!noProjectTargets)
507                                 {
508                                         MakefileBuilder.Append("\n");
509                                         MakefileBuilder.Append("# project names as targets\n\n");
510                                         foreach (CsprojInfo pi in projNameInfo.Values)
511                                         {
512                                                 MakefileBuilder.AppendFormat("{0}: $({1})\n", pi.name, pi.makename_ext);
513                                         }
514                                 }
515                         
516                                 return MakefileBuilder.ToString();
517                         }
518                         catch (Exception e)
519                         {
520                                 Console.WriteLine("EXCEPTION: {0}\n", e);
521                                 return "";
522                         }
523                 }
524                 
525                 public void CreatePrjxFromCsproj(string csprojFileName)
526                 {
527                         int nCnt = 0;
528                         FileStream fsIn = null;
529                         XmlSerializer xmlDeSer = null;
530                         FileStream fsOut = null;
531                         XmlSerializer xmlSer = null;
532                         Mfconsulting.General.Prj2Make.Schema.Csproj.VisualStudioProject csprojObj = null;
533                         Mfconsulting.General.Prj2Make.Schema.Prjx.Project prjxObj = new Mfconsulting.General.Prj2Make.Schema.Prjx.Project();
534                         string PrjxFileName = String.Format ("{0}.prjx",
535                                 Path.Combine(Path.GetDirectoryName(csprojFileName),
536                                 Path.GetFileNameWithoutExtension(csprojFileName))
537                                 );
538                         
539                         // convert backslashes to slashes               
540                         csprojFileName = csprojFileName.Replace("\\", "/");                     
541                         Console.WriteLine(String.Format("Will create project filename:{0}", PrjxFileName));
542
543                         // Load the csproj
544                         fsIn = new FileStream (csprojFileName, FileMode.Open);      
545                         xmlDeSer = new XmlSerializer (typeof(VisualStudioProject));
546                         csprojObj = (VisualStudioProject) xmlDeSer.Deserialize (fsIn);      
547                         fsIn.Close();
548
549                         // Begin prjxObj population
550                         prjxObj.name = Path.GetFileNameWithoutExtension(csprojFileName);
551                         prjxObj.description = "";
552                         prjxObj.newfilesearch = "None";
553                         prjxObj.enableviewstate = "True";
554                         prjxObj.version = (decimal)1.1;
555                         prjxObj.projecttype = "C#";
556
557                         prjxObj.Contents = GetContents (csprojObj.CSHARP.Files.Include);
558                         prjxObj.References = GetReferences(csprojObj.CSHARP.Build.References);
559                         prjxObj.DeploymentInformation = new Mfconsulting.General.Prj2Make.Schema.Prjx.DeploymentInformation();
560                         prjxObj.DeploymentInformation.target = "";
561                         prjxObj.DeploymentInformation.script = "";
562                         prjxObj.DeploymentInformation.strategy = "File";
563
564                         nCnt = csprojObj.CSHARP.Build.Settings.Config.Length;
565                         prjxObj.Configurations = new Configurations();
566                         prjxObj.Configurations.Configuration = new Configuration[nCnt];
567                         for(int i = 0; i < nCnt; i++)
568                         {
569                                 prjxObj.Configurations.Configuration[i] = CreateConfigurationBlock(
570                                         csprojObj.CSHARP.Build.Settings.Config[i],
571                                         csprojObj.CSHARP.Build.Settings.AssemblyName,
572                                         csprojObj.CSHARP.Build.Settings.OutputType
573                                         );
574                         }
575                         prjxObj.Configurations.active = prjxObj.Configurations.Configuration[0].name;
576
577                         prjxObj.Configuration = prjxObj.Configurations.Configuration[0];
578
579                         // Serialize
580                         fsOut = new FileStream (PrjxFileName, FileMode.Create);     
581                         xmlSer = new XmlSerializer (typeof(Project));
582                         xmlSer.Serialize(fsOut, prjxObj);
583                         fsOut.Close();
584
585                         return;
586                 }
587
588                 public void MsSlnToCmbxHelper(string slnFileName)
589                 {
590                         int i = 0;
591                         FileStream fsOut = null;
592                         XmlSerializer xmlSer = null;
593                         StringBuilder MakefileBuilder = new StringBuilder();
594                         Mfconsulting.General.Prj2Make.Schema.Cmbx.Combine cmbxObj = new Mfconsulting.General.Prj2Make.Schema.Cmbx.Combine();
595                         string cmbxFileName = String.Format ("{0}.cmbx",
596                                 Path.Combine(Path.GetDirectoryName(slnFileName),
597                                 Path.GetFileNameWithoutExtension(slnFileName))
598                                 );
599                         
600                         Console.WriteLine(String.Format("Will create combine filename:{0}", cmbxFileName));
601
602                         try
603                         {
604                                 string d = Path.GetDirectoryName(slnFileName);
605                                 if (d != "")
606                                         Directory.SetCurrentDirectory(d);
607
608                                 // We invoke the ParseSolution 
609                                 // by passing the file obtained
610                                 ParseSolution (slnFileName);
611
612                                 // Create all of the prjx files form the csproj files
613                                 foreach (CsprojInfo pi in projNameInfo.Values)
614                                 {
615                                         CreatePrjxFromCsproj(pi.csprojpath);
616                                 }
617
618                                 // Begin prjxObj population
619                                 cmbxObj.name = Path.GetFileNameWithoutExtension(slnFileName);
620                                 cmbxObj.description = "";
621                                 cmbxObj.fileversion = (decimal)1.0;
622
623                                 // Create and attach the StartMode element
624                                 Mfconsulting.General.Prj2Make.Schema.Cmbx.StartMode startModeElem = new Mfconsulting.General.Prj2Make.Schema.Cmbx.StartMode();
625
626                                 // Create the array of Execute objects
627                                 Mfconsulting.General.Prj2Make.Schema.Cmbx.Execute[] executeElem = new Mfconsulting.General.Prj2Make.Schema.Cmbx.Execute[projNameInfo.Count];
628
629                                 // Populate the Element objects instances
630                                 i = 0;
631                                 foreach (CsprojInfo pi in projNameInfo.Values)
632                                 {
633                                         Mfconsulting.General.Prj2Make.Schema.Cmbx.Execute execElem = new Mfconsulting.General.Prj2Make.Schema.Cmbx.Execute();
634                                         execElem.entry = pi.name;
635                                         execElem.type = "None";
636
637                     executeElem[i++] = execElem;
638                                 }
639
640                                 startModeElem.startupentry = executeElem[0].entry;
641                                 startModeElem.single = "True";
642                                 startModeElem.Execute = executeElem;
643
644                                 // Attach the StartMode Object to the
645                                 // Combine object
646                                 cmbxObj.StartMode = startModeElem;
647
648                                 // Gnerate the entries array
649                                 Mfconsulting.General.Prj2Make.Schema.Cmbx.Entry[] entriesObj = new Mfconsulting.General.Prj2Make.Schema.Cmbx.Entry[projNameInfo.Count];
650                                 // Populate the Entry objects instances
651                                 i = 0;
652                                 foreach (CsprojInfo pi in projNameInfo.Values)
653                                 {
654                                         Mfconsulting.General.Prj2Make.Schema.Cmbx.Entry entryObj = new Mfconsulting.General.Prj2Make.Schema.Cmbx.Entry();
655                                         string PrjxFileName = String.Format (".{0}{1}.prjx",
656                                                 Path.DirectorySeparatorChar,
657                                                 Path.Combine(Path.GetDirectoryName(pi.csprojpath),
658                                                 Path.GetFileNameWithoutExtension(pi.csprojpath))
659                                                 );
660
661                                         entryObj.filename = PrjxFileName; 
662
663                                         entriesObj[i++] = entryObj;
664                                 }
665
666                                 // Attach the Entries Object to the
667                                 // Combine object
668                                 cmbxObj.Entries = entriesObj;
669
670                                 Mfconsulting.General.Prj2Make.Schema.Cmbx.Configurations configurationsObj = new Mfconsulting.General.Prj2Make.Schema.Cmbx.Configurations();
671                                 
672                                 // Hack hardcoded configuration value must get the one
673                                 // from analyzing the different configuration entries
674                                 configurationsObj.active = "Debug";
675
676                                 // Hack hardcoded number of configuration object
677                                 // assuming 2 for Debug and Release
678                                 configurationsObj.Configuration = new Mfconsulting.General.Prj2Make.Schema.Cmbx.Configuration[2];
679                                 Mfconsulting.General.Prj2Make.Schema.Cmbx.Configuration confObj1 = new Mfconsulting.General.Prj2Make.Schema.Cmbx.Configuration();
680                                 configurationsObj.Configuration[0] = confObj1;
681                                 Mfconsulting.General.Prj2Make.Schema.Cmbx.Configuration confObj2 = new Mfconsulting.General.Prj2Make.Schema.Cmbx.Configuration();
682                                 configurationsObj.Configuration[1] = confObj2;
683
684                                 configurationsObj.Configuration[0].name = "Release";
685                                 configurationsObj.Configuration[0].Entry = CreateArrayOfConfEntries();
686                                 configurationsObj.Configuration[1].name = "Debug";
687                                 configurationsObj.Configuration[1].Entry = CreateArrayOfConfEntries();
688
689                                 // Attach the Configurations object to the 
690                                 // Combine Object
691                                 cmbxObj.Configurations = configurationsObj;
692
693                                 // Serialize
694                                 fsOut = new FileStream (cmbxFileName, FileMode.Create);     
695                                 xmlSer = new XmlSerializer (typeof(Mfconsulting.General.Prj2Make.Schema.Cmbx.Combine));
696                                 xmlSer.Serialize(fsOut, cmbxObj);
697                                 fsOut.Close();
698
699                                 return;
700                         }
701                         catch (Exception e)
702                         {
703                                 Console.WriteLine("EXCEPTION: {0}\n", e);
704                                 return;
705                         }
706                 }
707
708                 protected Mfconsulting.General.Prj2Make.Schema.Prjx.Reference[] GetReferences(Mfconsulting.General.Prj2Make.Schema.Csproj.Reference[] References)
709                 {
710                         Mfconsulting.General.Prj2Make.Schema.Prjx.Reference[] theReferences = null;
711                         int i = 0;
712
713                         // Get the GAC path
714                         string strlibDir = PkgConfigInvoker.GetPkgVariableValue("mono", "libdir");
715
716                         if (strlibDir == null)
717                         {
718                                 strlibDir = "/usr/lib";
719                         }                                                       
720                                                                 
721                         string strBasePathMono1_0 = Path.Combine(
722                                         strlibDir.TrimEnd(),
723                                         "mono/1.0");
724
725                         string strBasePathMono2_0 = Path.Combine(
726                                 strlibDir.TrimEnd(),
727                                 "mono/2.0");
728
729                         string strBasePathGtkSharp = Path.Combine(
730                                 strlibDir.TrimEnd(),
731                                 "mono/gtk-sharp");
732
733                         if(References != null && References.Length > 0)
734                         {
735                                 theReferences = new Mfconsulting.General.Prj2Make.Schema.Prjx.Reference[References.Length];
736                         }
737                         else
738                         {
739                                 return null;
740                         }
741
742                         // Iterate through the reference collection of the csproj file
743                         foreach(Mfconsulting.General.Prj2Make.Schema.Csproj.Reference rf in References)
744                         {
745                                 Mfconsulting.General.Prj2Make.Schema.Prjx.Reference rfOut = new Mfconsulting.General.Prj2Make.Schema.Prjx.Reference();
746                                 string strRefFileName;
747
748                                 if(rf.Package == null || rf.Package.CompareTo("") == 0)
749                                 {
750                                         bool bIsWhereExpected = false;
751
752                                         // HACK - under Unix filenames are case sensitive
753                                         // Under Windows there's no agreement on Xml vs XML ;-)                                         
754                                         if(Path.GetFileName(rf.HintPath).CompareTo("System.XML.dll") == 0)
755                                         {
756                                                 strRefFileName = Path.Combine (strBasePathMono1_0, Path.GetFileName("System.Xml.dll"));
757
758                                                 // Test to see if file exist in GAC location
759                                                 if(System.IO.File.Exists(strRefFileName) == true) {
760                                                         try {
761                                                                 rfOut.refto = System.Reflection.Assembly.LoadFrom(strRefFileName).FullName;
762                                                                 rfOut.type = Mfconsulting.General.Prj2Make.Schema.Prjx.ReferenceType.Gac;
763                                                                 rfOut.localcopy = Mfconsulting.General.Prj2Make.Schema.Prjx.ReferenceLocalcopy.True;
764                                                                 bIsWhereExpected = true;
765                                                         } catch (Exception exc) {
766                                                                 Console.WriteLine ("Error doing Assembly.LoadFrom with File: {0}\nErr Msg: {1}",
767                                                                         strRefFileName,
768                                                                         exc.Message );
769                                                         }
770                                                 }
771
772                                                 strRefFileName = Path.Combine (strBasePathMono2_0, Path.GetFileName("System.Xml.dll"));
773
774                                                 // Test to see if file exist in GAC location
775                                                 if(System.IO.File.Exists(strRefFileName) == true) {
776                                                         try {
777                                                                 rfOut.refto = System.Reflection.Assembly.LoadFrom(strRefFileName).FullName;
778                                                                 rfOut.type = Mfconsulting.General.Prj2Make.Schema.Prjx.ReferenceType.Gac;
779                                                                 rfOut.localcopy = Mfconsulting.General.Prj2Make.Schema.Prjx.ReferenceLocalcopy.True;
780                                                                 bIsWhereExpected = true;
781                                                         } catch (Exception exc) {
782                                                                 Console.WriteLine ("Error doing Assembly.LoadFrom with File: {0}\nErr Msg: {1}",
783                                                                         strRefFileName,
784                                                                         exc.Message );
785                                                         }
786                                                 }
787                                         } else {
788                                                 strRefFileName = Path.Combine (strBasePathMono1_0, Path.GetFileName(rf.HintPath));
789
790                                                 // Test to see if file exist in GAC location
791                                                 if(System.IO.File.Exists(strRefFileName) == true) {
792                                                         try {
793                                                                 rfOut.refto = System.Reflection.Assembly.LoadFrom(strRefFileName).FullName;
794                                                                 rfOut.type = Mfconsulting.General.Prj2Make.Schema.Prjx.ReferenceType.Gac;
795                                                                 rfOut.localcopy = Mfconsulting.General.Prj2Make.Schema.Prjx.ReferenceLocalcopy.True;
796                                                                 bIsWhereExpected = true;
797                                                         } catch (Exception exc) {
798                                                                 Console.WriteLine ("Error doing Assembly.LoadFrom with File: {0}\nErr Msg: {1}",
799                                                                         strRefFileName,
800                                                                         exc.Message );
801                                                         }
802                                                 }
803
804                                                 strRefFileName = Path.Combine (strBasePathMono2_0, Path.GetFileName(rf.HintPath));
805
806                                                 // Test to see if file exist in GAC location
807                                                 if(System.IO.File.Exists(strRefFileName) == true) {
808                                                         try {
809                                                                 rfOut.refto = System.Reflection.Assembly.LoadFrom(strRefFileName).FullName;
810                                                                 rfOut.type = Mfconsulting.General.Prj2Make.Schema.Prjx.ReferenceType.Gac;
811                                                                 rfOut.localcopy = Mfconsulting.General.Prj2Make.Schema.Prjx.ReferenceLocalcopy.True;
812                                                                 bIsWhereExpected = true;
813                                                         } catch (Exception exc) {
814                                                                 Console.WriteLine ("Error doing Assembly.LoadFrom with File: {0}\nErr Msg: {1}",
815                                                                         strRefFileName,
816                                                                         exc.Message );
817                                                         }
818                                                 }
819
820                                                 strRefFileName = Path.Combine (strBasePathGtkSharp, Path.GetFileName(rf.HintPath));
821
822                                                 // Test to see if file exist in GAC location
823                                                 if(System.IO.File.Exists(strRefFileName) == true) {
824                                                         try {
825                                                                 rfOut.refto = System.Reflection.Assembly.LoadFrom(strRefFileName).FullName;
826                                                                 rfOut.type = Mfconsulting.General.Prj2Make.Schema.Prjx.ReferenceType.Gac;
827                                                                 rfOut.localcopy = Mfconsulting.General.Prj2Make.Schema.Prjx.ReferenceLocalcopy.True;
828                                                                 bIsWhereExpected = true;
829                                                         } catch (Exception exc) {
830                                                                 Console.WriteLine ("Error doing Assembly.LoadFrom with File: {0}\nErr Msg: {1}",
831                                                                         strRefFileName,
832                                                                         exc.Message );
833                                                         }
834                                                 }
835                                                 
836                                                 if(bIsWhereExpected == false)
837                                                 {
838                                                         rfOut.refto = Path.GetFileName(rf.HintPath);
839                                                         rfOut.type = Mfconsulting.General.Prj2Make.Schema.Prjx.ReferenceType.Gac;
840                                                         rfOut.localcopy = Mfconsulting.General.Prj2Make.Schema.Prjx.ReferenceLocalcopy.True;
841                                                 }
842                                         }
843
844                                         // increment the iterator value
845                                         theReferences[i++] = rfOut;
846                                 }
847                                 else
848                                 {
849                                         rfOut.type = Mfconsulting.General.Prj2Make.Schema.Prjx.ReferenceType.Project;
850                                         
851                                         rfOut.refto = Path.GetFileName(rf.Name);
852                                         rfOut.localcopy = Mfconsulting.General.Prj2Make.Schema.Prjx.ReferenceLocalcopy.True;
853                                         // increment the iterator value
854                                         theReferences[i++] = rfOut;
855                                 }
856                         }
857
858                         return theReferences;
859                 }
860                 
861                 protected Mfconsulting.General.Prj2Make.Schema.Prjx.File[] GetContents(Mfconsulting.General.Prj2Make.Schema.Csproj.File[] Include)
862                 {
863                         Mfconsulting.General.Prj2Make.Schema.Prjx.File[] theFiles = null;
864                         int i = 0;
865
866                         if(Include != null && Include.Length > 0)
867                         {
868                                 theFiles = new Mfconsulting.General.Prj2Make.Schema.Prjx.File[Include.Length];
869                         }
870                         else
871                         {
872                                 return null;
873                         }
874
875                         // Iterate through the file collection of the csproj file
876                         foreach(Mfconsulting.General.Prj2Make.Schema.Csproj.File fl in Include)
877                         {
878                                 Mfconsulting.General.Prj2Make.Schema.Prjx.File flOut = new Mfconsulting.General.Prj2Make.Schema.Prjx.File();
879                                 flOut.name = String.Format(".{0}{1}", Path.DirectorySeparatorChar, fl.RelPath);
880                                 
881                                 switch(fl.SubType)
882                                 {
883                                         case "Code":
884                                                 flOut.subtype = Mfconsulting.General.Prj2Make.Schema.Prjx.FileSubtype.Code;
885                                                 break;
886                                 }
887
888                                 switch(fl.BuildAction)
889                                 {
890                                         case Mfconsulting.General.Prj2Make.Schema.Csproj.FileBuildAction.Compile:
891                                                 flOut.buildaction = Mfconsulting.General.Prj2Make.Schema.Prjx.FileBuildaction.Compile;
892                                                 break;
893                                         case Mfconsulting.General.Prj2Make.Schema.Csproj.FileBuildAction.Content:
894                                                 flOut.buildaction = Mfconsulting.General.Prj2Make.Schema.Prjx.FileBuildaction.Exclude;
895                                                 break;
896                                         case Mfconsulting.General.Prj2Make.Schema.Csproj.FileBuildAction.EmbeddedResource:
897                                                 flOut.buildaction = Mfconsulting.General.Prj2Make.Schema.Prjx.FileBuildaction.EmbedAsResource;
898                                                 break;
899                                         case Mfconsulting.General.Prj2Make.Schema.Csproj.FileBuildAction.None:
900                                                 flOut.buildaction = Mfconsulting.General.Prj2Make.Schema.Prjx.FileBuildaction.Exclude;
901                                                 break;                          
902                                 }
903                                 flOut.dependson = fl.DependentUpon;
904                                 flOut.data = "";
905
906                                 // increment the iterator value
907                                 theFiles[i++ ] = flOut;
908                         }
909
910                         return theFiles;
911                 }
912
913                 protected Configuration CreateConfigurationBlock(Config ConfigBlock, string AssemblyName, string OuputType)
914                 {
915                         Configuration ConfObj = new Configuration();
916                         CodeGeneration CodeGenObj = new CodeGeneration();
917                         Execution ExecutionObj = new Execution();
918                         Output OutputObj = new Output();
919
920                         ConfObj.runwithwarnings = "False";
921                         ConfObj.name = ConfigBlock.Name;
922
923                         // CodeGenObj member population
924                         CodeGenObj.runtime = "MsNet";
925                         CodeGenObj.compiler = "Csc";
926                         CodeGenObj.warninglevel = ConfigBlock.WarningLevel;
927                         CodeGenObj.nowarn = "";
928                         CodeGenObj.includedebuginformation = (ConfigBlock.DebugSymbols == true) ? 
929                                 CodeGenerationIncludedebuginformation.True : 
930                                 CodeGenerationIncludedebuginformation.False;
931                         
932                         CodeGenObj.optimize = (ConfigBlock.Optimize == true) ? "True" : "False";
933
934                         if (ConfigBlock.AllowUnsafeBlocks == true)
935                         {
936                                 CodeGenObj.unsafecodeallowed = CodeGenerationUnsafecodeallowed.True;
937                         }
938                         else
939                         {
940                                 CodeGenObj.unsafecodeallowed = CodeGenerationUnsafecodeallowed.False;
941                         }
942                         if (ConfigBlock.CheckForOverflowUnderflow == true)
943                         {
944                                 CodeGenObj.generateoverflowchecks = "True";
945                         }
946                         else
947                         {
948                                 CodeGenObj.generateoverflowchecks = "False";
949                         }
950                         
951                         CodeGenObj.mainclass = "";
952                         CodeGenObj.target = OuputType;
953                         CodeGenObj.generatexmldocumentation = "False";
954                         CodeGenObj.win32Icon = "";
955
956                         // ExecutionObj member population
957                         ExecutionObj.commandlineparameters = "";
958                         ExecutionObj.consolepause = "True";
959
960                         // OutputObj member population
961                         OutputObj.directory = ConfigBlock.OutputPath;
962                         OutputObj.assembly = AssemblyName;
963                         OutputObj.executeScript = "";
964                         OutputObj.executeBeforeBuild = "";
965                         OutputObj.executeAfterBuild = "";
966
967                         ConfObj.CodeGeneration = CodeGenObj;
968                         ConfObj.Execution = ExecutionObj;
969                         ConfObj.Output = OutputObj;
970
971                         return ConfObj;
972                 }
973                 
974                 protected Mfconsulting.General.Prj2Make.Schema.Cmbx.Entry[] CreateArrayOfConfEntries()
975                 {
976                         Mfconsulting.General.Prj2Make.Schema.Cmbx.Entry[] confEntry = new Mfconsulting.General.Prj2Make.Schema.Cmbx.Entry[projNameInfo.Count];
977                         // Populate the Entry objects instances
978                         int i = 0;
979                         foreach (CsprojInfo pi in projNameInfo.Values)
980                         {
981                                 Mfconsulting.General.Prj2Make.Schema.Cmbx.Entry entryObj = new Mfconsulting.General.Prj2Make.Schema.Cmbx.Entry();
982                                 entryObj.name = pi.name;
983                                 entryObj.configurationname = "Debug";
984                                 entryObj.build = "False";
985
986                                 confEntry[i++] = entryObj;
987                         }
988
989                         return confEntry;
990                 }
991         }   
992 }