2 using System
.Collections
;
5 using System
.Text
.RegularExpressions
;
7 using System
.Xml
.Serialization
;
9 using MonoDevelop
.Prj2Make
.Schema
.Csproj
;
10 using MonoDevelop
.Projects
;
11 using MonoDevelop
.Projects
.Text
;
12 using MonoDevelop
.Core
;
13 using MonoDevelop
.Ide
.Gui
;
17 namespace MonoDevelop
.Prj2Make
21 public static string slash
;
22 Hashtable projNameInfo
= new Hashtable();
23 Hashtable projGuidInfo
= new Hashtable();
24 private string prjxFileName
;
25 private string m_strSlnVer
;
26 private string m_strCsprojVer
;
27 private bool m_bIsUnix
;
28 private bool m_bIsMcs
;
29 private bool m_bIsUsingLib
;
31 // Flag use to determine if the LIB variable will be used in
32 // the Makefile that prj2make generates
33 public bool IsUsingLib
35 get{ return m_bIsUsingLib; }
36 set{ m_bIsUsingLib = value; }
40 // Determines if the makefile is intended for nmake or gmake for urposes of path separator character
43 get{ return m_bIsUnix; }
44 set{ m_bIsUnix = value; }
47 // Determines if using MCS or CSC
50 get{ return m_bIsMcs; }
51 set{ m_bIsMcs = value; }
54 public string SlnVersion
56 get { return m_strSlnVer; }
57 set { m_strSlnVer = value; }
60 public string CsprojVersion
62 get { return m_strCsprojVer; }
63 set { m_strCsprojVer = value; }
66 // Shuld contain the file name
67 // of the most resent prjx generation
68 public string PrjxFileName
{
69 get { return prjxFileName; }
72 // Default constructor
77 m_bIsUsingLib
= false;
80 // Utility function to determine the sln file version
81 protected string GetSlnFileVersion(string strInSlnFile
)
83 string strVersion
= null;
84 string strInput
= null;
86 FileStream fis
= new FileStream(strInSlnFile
, FileMode
.Open
, FileAccess
.Read
, FileShare
.Read
);
87 StreamReader reader
= new StreamReader(fis
);
88 strInput
= reader
.ReadLine();
90 match
= SlnVersionRegex
.Match(strInput
);
93 strVersion
= match
.Groups
[1].Value
;
99 // Close the File Stream
105 // Utility function to determine the csproj file version
106 protected string GetCsprojFileVersion(string strInCsprojFile
)
108 string strRetVal
= null;
109 XmlDocument xmlDoc
= new XmlDocument();
111 xmlDoc
.Load(strInCsprojFile
);
112 strRetVal
= xmlDoc
.SelectSingleNode("/VisualStudioProject/CSHARP/@ProductVersion").Value
;
117 protected void ParseMsCsProj(string fname
)
119 string projectName
= System
.IO
.Path
.GetFileNameWithoutExtension (fname
);
120 string csprojPath
= System
.IO
.Path
.GetFileName (fname
);
121 string projectGuid
= "";
123 CsprojInfo pi
= new CsprojInfo (m_bIsUnix
, m_bIsMcs
, projectName
, projectGuid
, csprojPath
);
125 projNameInfo
[projectName
] = pi
;
126 projGuidInfo
[projectGuid
] = pi
;
129 protected void ParseSolution(string fname
, IProgressMonitor monitor
)
131 FileStream fis
= new FileStream(fname
,FileMode
.Open
, FileAccess
.Read
, FileShare
.Read
);
132 using (StreamReader reader
= new StreamReader(fis
)) {
135 string s
= reader
.ReadLine();
138 match
= ProjectRegex
.Match(s
);
141 string projectName
= match
.Groups
[2].Value
;
142 string csprojPath
= match
.Groups
[3].Value
;
143 string projectGuid
= match
.Groups
[4].Value
;
146 if (csprojPath
.EndsWith (".csproj") && !csprojPath
.StartsWith("http://"))
148 csprojPath
= MapPath (Path
.GetDirectoryName (fname
), csprojPath
);
149 CsprojInfo pi
= new CsprojInfo (m_bIsUnix
, m_bIsMcs
, projectName
, projectGuid
, csprojPath
);
150 projNameInfo
[projectName
] = pi
;
151 projGuidInfo
[projectGuid
] = pi
;
153 } catch (Exception ex
) {
154 Console
.WriteLine (GettextCatalog
.GetString ("Could not import project:") + csprojPath
);
155 Console
.WriteLine (ex
.ToString ());
156 monitor
.ReportError (GettextCatalog
.GetString ("Could not import project:") + csprojPath
, ex
);
161 if (s
.StartsWith("Global"))
169 public DotNetProject
CreatePrjxFromCsproj (string csprojFileName
, IProgressMonitor monitor
)
172 MonoDevelop
.Prj2Make
.Schema
.Csproj
.VisualStudioProject csprojObj
= null;
174 monitor
.BeginTask (GettextCatalog
.GetString ("Importing project: ") + csprojFileName
, 4);
176 DotNetProject prjxObj
= new DotNetProject ("C#", null, null);
178 prjxFileName
= String
.Format ("{0}.mdp",
179 Path
.Combine (Path
.GetDirectoryName (csprojFileName
),
180 Path
.GetFileNameWithoutExtension (csprojFileName
))
184 using (TextFileReader fsIn
= new TextFileReader (csprojFileName
)) {
185 XmlSerializer xmlDeSer
= new XmlSerializer (typeof(VisualStudioProject
));
186 csprojObj
= (VisualStudioProject
) xmlDeSer
.Deserialize (fsIn
);
191 // Begin prjxObj population
192 prjxObj
.FileName
= prjxFileName
;
193 prjxObj
.Name
= Path
.GetFileNameWithoutExtension(csprojFileName
);
194 prjxObj
.Description
= "";
195 prjxObj
.NewFileSearch
= NewFileSearch
.None
;
196 prjxObj
.DefaultNamespace
= csprojObj
.CSHARP
.Build
.Settings
.RootNamespace
;
198 GetContents (prjxObj
, csprojObj
.CSHARP
.Files
.Include
, prjxObj
.Files
, monitor
);
201 GetReferences (csprojObj
.CSHARP
.Build
.References
, prjxObj
.References
, monitor
);
204 prjxObj
.Configurations
.Clear ();
205 foreach (Config cblock
in csprojObj
.CSHARP
.Build
.Settings
.Config
)
207 prjxObj
.Configurations
.Add (CreateConfigurationBlock (
210 csprojObj
.CSHARP
.Build
.Settings
.AssemblyName
,
211 csprojObj
.CSHARP
.Build
.Settings
.OutputType
,
218 } catch (Exception ex
) {
219 monitor
.ReportError (GettextCatalog
.GetString ("Could not import project:") + csprojFileName
, ex
);
226 public Solution
MsSlnToCmbxHelper (string slnFileName
, IProgressMonitor monitor
)
228 Solution solution
= new Solution();
230 monitor
.BeginTask (GettextCatalog
.GetString ("Importing solution"), 2);
233 // We invoke the ParseSolution
234 // by passing the file obtained
235 ParseSolution (slnFileName
, monitor
);
237 // Create all of the prjx files form the csproj files
238 monitor
.BeginTask (null, projNameInfo
.Values
.Count
* 2);
240 foreach (CsprojInfo pi
in projNameInfo
.Values
) {
241 string mappedPath
= MapPath (Path
.GetDirectoryName (slnFileName
), pi
.csprojpath
);
242 if (mappedPath
== null) {
244 monitor
.ReportWarning (GettextCatalog
.GetString ("Project file not found: ") + pi
.csprojpath
);
247 DotNetProject prj
= CreatePrjxFromCsproj (mappedPath
, monitor
);
252 solution
.RootFolder
.Items
.Add (prj
);
259 solution
.SetLocation (Path
.GetDirectoryName (slnFileName
), Path
.GetFileNameWithoutExtension(slnFileName
));
266 monitor
.ReportError (GettextCatalog
.GetString ("The solution could not be imported."), e
);
275 protected void GetReferences (MonoDevelop
.Prj2Make
.Schema
.Csproj
.Reference
[] References
, ProjectReferenceCollection references
, IProgressMonitor monitor
)
277 if (References
== null || References
.Length
== 0)
280 monitor
.BeginTask (null, 5 + References
.Length
);
284 string strBasePathMono1_0
= GetPackageDirectory ("mono", "mono/1.0");
288 string strBasePathGtkSharp
= GetPackageDirectory ("gtk-sharp", "mono/gtk-sharp");
292 string strBasePathGtkSharp2_0
= GetPackageDirectory ("gtk-sharp-2.0", "mono/gtk-sharp-2.0");
296 string strBasePathGeckoSharp
= GetPackageDirectory ("gecko-sharp", "mono/gecko-sharp");
300 string strBasePathGeckoSharp2_0
= GetPackageDirectory ("gecko-sharp-2.0", "mono/gecko-sharp-2.0");
302 string[] monoLibs
= new string [] {
304 strBasePathGtkSharp2_0
,
306 strBasePathGeckoSharp2_0
,
307 strBasePathGeckoSharp
310 // Iterate through the reference collection of the csproj file
311 foreach (MonoDevelop
.Prj2Make
.Schema
.Csproj
.Reference rf
in References
)
315 ProjectReference rfOut
= null;
317 if (rf
.Package
!= null && rf
.Package
.Length
!= 0)
319 rfOut
= new ProjectReference (MonoDevelop
.Projects
.ReferenceType
.Project
, Path
.GetFileName (rf
.Name
));
320 rfOut
.LocalCopy
= true;
321 references
.Add (rfOut
);
323 else if (rf
.AssemblyName
!= null)
325 string rname
= rf
.AssemblyName
;
326 if (rname
== "System.XML")
327 rname
= "System.Xml";
329 string oref
= Runtime
.SystemAssemblyService
.GetAssemblyFullName (rname
);
331 monitor
.ReportWarning (GettextCatalog
.GetString ("Assembly reference could not be imported: ") + rf
.AssemblyName
);
334 rfOut
= new ProjectReference (MonoDevelop
.Projects
.ReferenceType
.Gac
, oref
);
335 rfOut
.LocalCopy
= true;
336 references
.Add (rfOut
);
338 else if (rf
.HintPath
!= null)
340 // HACK - under Unix filenames are case sensitive
341 // Under Windows there's no agreement on Xml vs XML ;-)
342 if (Path
.GetFileName (rf
.HintPath
) == "System.XML.dll")
344 ProjectReference pref
= GetMonoReferece (strBasePathMono1_0
, "System.Xml.dll");
346 references
.Add (pref
);
350 foreach (string libDir
in monoLibs
) {
351 if (libDir
== null) continue;
352 if (rf
.HintPath
== null)
354 rfOut
= GetMonoReferece (libDir
, rf
.HintPath
);
360 rfOut
= new ProjectReference (MonoDevelop
.Projects
.ReferenceType
.Gac
, Path
.GetFileName (rf
.HintPath
));
361 rfOut
.LocalCopy
= true;
363 references
.Add (rfOut
);
367 monitor
.ReportWarning (GettextCatalog
.GetString ("Assembly reference could not be imported: ") + rf
.Name
);
375 string GetPackageDirectory (string package
, string subdir
)
377 string dir
= MonoDevelop
.Prj2Make
.PkgConfigInvoker
.GetPkgVariableValue (package
, "libdir");
378 return dir
!= null ? Path
.Combine (dir
.TrimEnd(), subdir
) : null;
381 ProjectReference
GetMonoReferece (string libPath
, string reference
)
383 string strRefFileName
= Path
.Combine (libPath
, Path
.GetFileName (reference
));
385 // Test to see if file exist in GAC location
386 if (System
.IO
.File
.Exists (strRefFileName
)) {
387 ProjectReference rfOut
= new ProjectReference (MonoDevelop
.Projects
.ReferenceType
.Gac
, Runtime
.SystemAssemblyService
.GetAssemblyFullName (strRefFileName
));
388 rfOut
.LocalCopy
= true;
394 protected void GetContents (MonoDevelop
.Projects
.Project project
, MonoDevelop
.Prj2Make
.Schema
.Csproj
.File
[] Include
, ProjectFileCollection files
, IProgressMonitor monitor
)
396 if (Include
== null || Include
.Length
== 0)
399 // Iterate through the file collection of the csproj file
400 foreach(MonoDevelop
.Prj2Make
.Schema
.Csproj
.File fl
in Include
)
402 ProjectFile flOut
= new ProjectFile ();
405 if ((fl
.Link
== null) || (fl
.Link
.Length
== 0)) {
406 name
= MapPath (project
.BaseDirectory
, fl
.RelPath
);
408 name
= MapPath (null, fl
.Link
);
412 monitor
.ReportWarning (GettextCatalog
.GetString ("Can't import file: ") + fl
.RelPath
);
416 // Adding here as GetDefaultResourceIdInternal needs flOut.Project
422 flOut
.Subtype
= Subtype
.Code
;
426 switch (fl
.BuildAction
)
428 case MonoDevelop
.Prj2Make
.Schema
.Csproj
.FileBuildAction
.Compile
:
429 flOut
.BuildAction
= BuildAction
.Compile
;
431 case MonoDevelop
.Prj2Make
.Schema
.Csproj
.FileBuildAction
.Content
:
432 flOut
.BuildAction
= BuildAction
.Content
;
434 case MonoDevelop
.Prj2Make
.Schema
.Csproj
.FileBuildAction
.EmbeddedResource
:
435 flOut
.BuildAction
= BuildAction
.EmbeddedResource
;
437 case MonoDevelop
.Prj2Make
.Schema
.Csproj
.FileBuildAction
.None
:
438 flOut
.BuildAction
= BuildAction
.None
;
441 // DependentUpon is relative to flOut
442 flOut
.DependsOn
= MapPath (Path
.GetDirectoryName (flOut
.Name
), fl
.DependentUpon
);
447 protected SolutionItemConfiguration
CreateConfigurationBlock (MonoDevelop
.Projects
.DotNetProject project
, Config ConfigBlock
, string AssemblyName
, string OuputType
, IProgressMonitor monitor
)
449 DotNetProjectConfiguration confObj
= project
.CreateConfiguration (ConfigBlock
.Name
) as DotNetProjectConfiguration
;
451 confObj
.RunWithWarnings
= false;
452 confObj
.DebugMode
= ConfigBlock
.DebugSymbols
;
453 project
.CompileTarget
= (CompileTarget
) Enum
.Parse (typeof(CompileTarget
), OuputType
, true);
455 string dir
= MapPath (project
.BaseDirectory
, ConfigBlock
.OutputPath
);
457 dir
= "bin/" + ConfigBlock
.Name
;
458 monitor
.ReportWarning (string.Format (GettextCatalog
.GetString ("Output directory '{0}' can't be mapped to a local directory. The directory '{1}' will be used instead"), ConfigBlock
.OutputPath
, dir
));
460 confObj
.OutputDirectory
= dir
;
461 confObj
.OutputAssembly
= AssemblyName
;
463 CSharpCompilerParameters compilerParams
= new CSharpCompilerParameters ();
464 compilerParams
.WarningLevel
= ConfigBlock
.WarningLevel
;
465 compilerParams
.NoWarnings
= "";
466 compilerParams
.Optimize
= ConfigBlock
.Optimize
;
467 compilerParams
.DefineSymbols
= ConfigBlock
.DefineConstants
;
468 compilerParams
.UnsafeCode
= ConfigBlock
.AllowUnsafeBlocks
;
469 compilerParams
.GenerateOverflowChecks
= ConfigBlock
.CheckForOverflowUnderflow
;
474 internal static string MapPath (string basePath
, string relPath
)
476 if (relPath
== null || relPath
.Length
== 0)
479 string path
= relPath
;
480 if (Path
.DirectorySeparatorChar
!= '\\')
481 path
= path
.Replace ("\\", "/");
483 if (char.IsLetter (path
[0]) && path
.Length
> 1 && path
[1] == ':')
486 if (basePath
!= null)
487 path
= Path
.Combine (basePath
, path
);
489 if (System
.IO
.File
.Exists (path
)){
490 return Path
.GetFullPath (path
);
493 if (Path
.IsPathRooted (path
)) {
495 // Windows paths are case-insensitive. When mapping an absolute path
496 // we can try to find the correct case for the path.
498 string[] names
= path
.Substring (1).Split ('/');
501 for (int n
=0; n
<names
.Length
; n
++) {
504 if (names
[n
] == ".."){
505 part
= Path
.GetFullPath (part
+ "/..");
509 entries
= Directory
.GetFileSystemEntries (part
);
512 foreach (string e
in entries
) {
513 if (string.Compare (Path
.GetFileName (e
), names
[n
], true) == 0) {
519 // Part of the path does not exist. Can't do any more checking.
520 part
= Path
.GetFullPath (part
);
521 for (; n
< names
.Length
; n
++)
522 part
+= "/" + names
[n
];
528 return Path
.GetFullPath (part
);
530 return Path
.GetFullPath (path
);
535 static Regex projectRegex
= null;
536 internal static Regex ProjectRegex
{
538 if (projectRegex
== null)
539 projectRegex
= new Regex(@"Project\(""(\{[^}]*\})""\) = ""(.*)"", ""(.*)"", ""(\{[^{]*\})""");
544 static Regex slnVersionRegex
= null;
545 internal static Regex SlnVersionRegex
{
547 if (slnVersionRegex
== null)
548 slnVersionRegex
= new Regex (@"Microsoft Visual Studio Solution File, Format Version (\d?\d.\d\d)");
549 return slnVersionRegex
;