Do not use --stacktrace
[mono.git] / mcs / tools / prj2make / MdPrjHelper.cs
1 using System;\r
2 using System.Collections;\r
3 using System.IO;\r
4 using System.Text;\r
5 using System.Text.RegularExpressions;\r
6 using System.Xml;\r
7 using System.Xml.Serialization;\r
8 using System.Diagnostics;\r
9 \r
10 namespace Mfconsulting.General.Prj2Make\r
11 {\r
12     public class CmbxMaker\r
13     {\r
14                 public static string slash;\r
15                 static Hashtable projNameInfo = new Hashtable();\r
16                 static Hashtable projGuidInfo = new Hashtable();\r
17                 private Mfconsulting.General.Prj2Make.Schema.Cmbx.Combine m_cmbObject;\r
18                 private bool m_bIsUnix;\r
19                 private bool m_bIsMcs;\r
20                 private bool m_bIsUsingLib;\r
21  \r
22                 // Flag use to determine if the LIB variable will be used in\r
23                 // the Makefile that prj2make generates\r
24                 public bool IsUsingLib\r
25                 {\r
26                         get{ return m_bIsUsingLib; }\r
27                         set{ m_bIsUsingLib = value; }\r
28                 }\r
29 \r
30                 // Determines if the makefile is intended for nmake or gmake for urposes of path separator character\r
31                 public bool IsUnix\r
32                 {\r
33                         get{ return m_bIsUnix; }\r
34                         set{ m_bIsUnix = value; }\r
35                 }\r
36 \r
37                 // Determines if using MCS or CSC\r
38                 public bool IsMcs\r
39                 {\r
40                         get{ return m_bIsMcs; }\r
41                         set{ m_bIsMcs = value; }\r
42                 }\r
43 \r
44         public Mfconsulting.General.Prj2Make.Schema.Cmbx.Combine Solucion {\r
45                 get { return m_cmbObject; }\r
46         }\r
47 \r
48                 public CmbxMaker()\r
49                 {\r
50                         m_bIsUnix = false;\r
51                         m_bIsMcs = false;\r
52                         m_bIsUsingLib = false;\r
53                 }\r
54     \r
55                 // Combine desirialization \r
56                 protected Mfconsulting.General.Prj2Make.Schema.Cmbx.Combine LoadCmbFromFile (string strIn)\r
57                 {\r
58                         FileStream fs = new FileStream (strIn, FileMode.Open);\r
59             \r
60                         XmlSerializer xmlSer = new XmlSerializer (typeof(Mfconsulting.General.Prj2Make.Schema.Cmbx.Combine));\r
61                         Mfconsulting.General.Prj2Make.Schema.Cmbx.Combine cmbObj = (Mfconsulting.General.Prj2Make.Schema.Cmbx.Combine) xmlSer.Deserialize (fs);\r
62             \r
63                         fs.Close();\r
64             \r
65                         return (cmbObj);\r
66                 }\r
67 \r
68                 protected void ParseMdCsProj(string fname)\r
69         {\r
70                 string projectName;\r
71                 \r
72             PrjxInfo pi = new PrjxInfo(m_bIsUnix, m_bIsMcs, fname);\r
73             projectName = pi.name;            \r
74                         projNameInfo[projectName] = pi;            \r
75         }\r
76         \r
77         protected void ParseCombine(string fname)\r
78         {\r
79                 string CombineFilePath = fname;\r
80                 \r
81                 // convert backslashes to slashes               \r
82                 CombineFilePath = CombineFilePath.Replace("\\", "/");\r
83     \r
84                 // loads the file in order to deserialize and\r
85                 // build the object graph\r
86                 try {\r
87                         m_cmbObject = LoadCmbFromFile (CombineFilePath);\r
88                         } catch (Exception exc) {\r
89                         \r
90                                 Console.WriteLine (\r
91                                         String.Format ("Could not load the file {0}\nException: {1}",\r
92                                                 CombineFilePath,\r
93                                                 exc.Message)\r
94                                         );\r
95                                 return;                 \r
96                         }\r
97 \r
98                 foreach(Mfconsulting.General.Prj2Make.Schema.Cmbx.Entry ent in m_cmbObject.Entries)\r
99                 {\r
100                                 string projectName = System.IO.Path.GetFileNameWithoutExtension(ent.filename);\r
101                                 string csprojPath = ent.filename;\r
102     \r
103                                 if (csprojPath.EndsWith(".prjx"))\r
104                                 {\r
105                                         PrjxInfo pi = new PrjxInfo(m_bIsUnix, m_bIsMcs, csprojPath);\r
106     \r
107                                         projNameInfo[projectName] = pi;\r
108                                 }    \r
109                 }\r
110         }\r
111     \r
112         public string MdCmbxHelper(bool isUnixMode, bool isMcsMode, bool isSln, string slnFile)\r
113         {\r
114                 bool noCommonTargets = false;\r
115                 bool noProjectTargets = false;\r
116                 bool noFlags = false;\r
117                         int nPos = -1;\r
118                 StringBuilder MakefileBuilder = new StringBuilder();\r
119 \r
120                         m_bIsUnix = isUnixMode;\r
121                         m_bIsMcs =  isMcsMode;\r
122 \r
123                         if(m_bIsUnix == true && m_bIsMcs == true)\r
124                         {\r
125                                 m_bIsUsingLib = true;\r
126                         }\r
127     \r
128                 if (m_bIsUnix)\r
129                 {\r
130                         slash = "/";\r
131                 }\r
132                 else\r
133                 {\r
134                         slash = "\\";\r
135                 }\r
136     \r
137                 try\r
138                 {\r
139                         string d = Path.GetDirectoryName(slnFile);\r
140                         \r
141                         if (d != "")\r
142                                 Directory.SetCurrentDirectory(d);\r
143 \r
144                         if (isSln == true) {\r
145                                         // We invoke the ParseSolution \r
146                                         // by passing the file obtained\r
147                                         ParseCombine (slnFile);\r
148                         } else {\r
149     \r
150                                         // We invoke the ParseMsCsProj \r
151                                         // by passing the file obtained \r
152                                         ParseMdCsProj (slnFile);\r
153                         }\r
154         \r
155                         if (!noFlags)\r
156                         {\r
157                         if (m_bIsUnix) // gmake\r
158                         {\r
159                                         MakefileBuilder.Append("ifndef TARGET\n");\r
160                                         MakefileBuilder.Append("\tTARGET=./bin/Debug\n");                                       \r
161                                         MakefileBuilder.Append("else\n");\r
162                                         MakefileBuilder.Append("\tTARGET=./bin/$(TARGET)\n");\r
163                                         MakefileBuilder.Append("endif\n\n");\r
164                                         \r
165                                         if (m_bIsMcs == false)\r
166                                         {\r
167                                                 MakefileBuilder.Append("MCS=csc\n");\r
168                                                 MakefileBuilder.Append("MCSFLAGS=-nologo\n\n");\r
169                                                 MakefileBuilder.Append("ifdef (RELEASE)\n");\r
170                                                 MakefileBuilder.Append("\tMCSFLAGS=$(MCSFLAGS) -optimize+ -d:TRACE\n");\r
171                                                 MakefileBuilder.Append("else\n");\r
172                                                 MakefileBuilder.Append("\tMCSFLAGS=$(MCSFLAGS) -debug+ -d:TRACE,DEBUG\n");\r
173                                                 MakefileBuilder.Append("endif\n");\r
174                                         }\r
175                                         else\r
176                                         {\r
177                                                 MakefileBuilder.Append("MCS=mcs\n");\r
178                                                 MakefileBuilder.Append("ifndef (RELEASE)\n");\r
179                                                 MakefileBuilder.Append("\tMCSFLAGS=-debug \n");\r
180                                                 MakefileBuilder.Append("endif\n");\r
181                                                         // Define and add the information used in the -lib: arguments passed to the\r
182                                                         // compiler to assist in finding non-fullyqualified assembly references.\r
183                                                         if(m_bIsUsingLib == true)\r
184                                                         {\r
185                                                                 string strlibDir = PkgConfigInvoker.GetPkgVariableValue("mono", "libdir");\r
186 \r
187                                                                 if (strlibDir == null)\r
188                                                                 {\r
189                                                                         strlibDir = "/usr/lib";\r
190                                                                 }\r
191 \r
192                                                                 MakefileBuilder.AppendFormat("\nLIBS=-lib:{0} -lib:{1}\n\n", \r
193                                                                         Path.Combine(strlibDir.TrimEnd(), "mono/1.0"),\r
194                                                                         Path.Combine(strlibDir.TrimEnd(), "mono/gtk-sharp")\r
195                                                                         );\r
196                                                         }\r
197                                         }                       \r
198                         }\r
199                         else // nmake\r
200                         {\r
201                                         MakefileBuilder.Append("!if !defined (TARGET)\n");\r
202                                         MakefileBuilder.Append("TARGET=.\\bin\\Debug\n");                                       \r
203                                         MakefileBuilder.Append("!else\n");\r
204                                         MakefileBuilder.Append("TARGET=.\\bin\\$(TARGET)\n");\r
205                                         MakefileBuilder.Append("!endif\n\n");\r
206                                         \r
207                                         if (m_bIsMcs == false)\r
208                                         {\r
209                                                 MakefileBuilder.Append("MCS=csc\n");\r
210                                                 MakefileBuilder.Append("MCSFLAGS=-nologo\n\n");\r
211                                                 MakefileBuilder.Append("!if !defined(RELEASE)\n");\r
212                                                 MakefileBuilder.Append("MCSFLAGS=$(MCSFLAGS) -optimize+ -d:TRACE\n");\r
213                                                 MakefileBuilder.Append("!else\n");\r
214                                                 MakefileBuilder.Append("MCSFLAGS=$(MCSFLAGS) -debug+ -d:TRACE,DEBUG\n");\r
215                                                 MakefileBuilder.Append("!endif\n");\r
216                                         }\r
217                                         else\r
218                                         {\r
219                                                 MakefileBuilder.Append("MCS=mcs\n");\r
220                                                 MakefileBuilder.Append("!if !defined(RELEASE)\n");\r
221                                                 MakefileBuilder.Append("MCSFLAGS=-debug \n");\r
222                                                 MakefileBuilder.Append("!endif\n");\r
223                                         }                               \r
224                         }\r
225     \r
226                                 MakefileBuilder.Append("\n");\r
227                         }\r
228                         else\r
229                         {\r
230                                 MakefileBuilder.Append("!if !defined(MCS)\n");\r
231                                 MakefileBuilder.Append("!error You must provide MCS when making\n");\r
232                                 MakefileBuilder.Append("!endif\n\n");\r
233                         }\r
234     \r
235                         foreach (PrjxInfo prjI in projNameInfo.Values)\r
236                         {\r
237                                 MakefileBuilder.AppendFormat("{0}=$(TARGET){1}{2}\n", prjI.makename_ext, slash, prjI.assembly_name);\r
238                                 MakefileBuilder.AppendFormat("{0}_PDB=$(TARGET){1}{2}\n", prjI.makename, slash, prjI.assembly_name.Replace(".dll",".pdb"));\r
239                                 MakefileBuilder.AppendFormat("{0}_SRC={1}\n", prjI.makename, prjI.src);\r
240                                 MakefileBuilder.AppendFormat("{0}_RES={1}\n\n", prjI.makename, prjI.res);\r
241                         }\r
242 \r
243     \r
244                         foreach (PrjxInfo pi in projNameInfo.Values)\r
245                         {\r
246                                 string refs = "";\r
247                                 string deps = "";\r
248                                 \r
249                                 foreach (Mfconsulting.General.Prj2Make.Schema.Prjx.Reference rf in pi.Proyecto.References)\r
250                                 {\r
251                                                 if (refs != "")\r
252                                                         refs += " ";\r
253    \r
254                                                 string assemblyName = rf.refto;\r
255    \r
256                                                 // HACK - under Unix filenames are case sensitive\r
257                                                 // Under Windows there's no agreement on Xml vs XML ;-)                                                 \r
258                                                 if (0 == String.Compare(assemblyName, "System.Xml", true))\r
259                                                 {\r
260                                                         assemblyName = "System.Xml";\r
261                                                 }\r
262 \r
263                                                 // Check to see if there is a coma in the\r
264                                                 // reference. This could indicate a GAC\r
265                                                 // style reference\r
266                                                 nPos = assemblyName.IndexOf(',');\r
267                                                 if(nPos == -1)\r
268                                                 {\r
269                                                         if (System.IO.Path.GetExtension(assemblyName).ToUpper().CompareTo(".DLL") == 0) \r
270                                                         {\r
271                                                                 refs += "-r:" + assemblyName;\r
272                                                         } \r
273                                                         else \r
274                                                         {\r
275                                                                 refs += "-r:" + assemblyName + ".dll";\r
276                                                         }\r
277                                                 }\r
278                                                 else\r
279                                                 {\r
280                                                         refs += "-r:" + assemblyName.Substring(0, nPos) + ".dll";\r
281                                                 }\r
282                                 }\r
283     \r
284                                 MakefileBuilder.AppendFormat("$({0}): $({1}_SRC) {2}\n", pi.makename_ext, pi.makename, deps);\r
285                 \r
286                         if (isUnixMode)\r
287                         {\r
288                                         MakefileBuilder.Append("\t-mkdir -p $(TARGET)\n");\r
289                         }\r
290                         else\r
291                         {\r
292                                         MakefileBuilder.Append("\t-md $(TARGET)\n");\r
293                         }\r
294                         \r
295                                         MakefileBuilder.Append("\t$(MCS) $(MCSFLAGS)");\r
296 \r
297                                         // Test to see if any configuratino has the Allow unsafe blocks on\r
298                                         if(pi.AllowUnsafeCode == true ) {\r
299                                                 MakefileBuilder.Append(" -unsafe");\r
300                                         }\r
301 \r
302                                         // Test for LIBS usage\r
303                                         if(m_bIsUsingLib == true) {\r
304                                         MakefileBuilder.Append(" $(LIBS)");\r
305                                         }\r
306 \r
307                                         MakefileBuilder.AppendFormat(" {2}{3} -out:$({0}) $({1}_RES) $({1}_SRC)\n", \r
308                                                         pi.makename_ext, pi.makename, refs, pi.switches);\r
309                                                                         \r
310                                         MakefileBuilder.Append("\n");\r
311                         }\r
312     \r
313                         if (!noCommonTargets)\r
314                         {\r
315                                 MakefileBuilder.Append("\n");\r
316                                 MakefileBuilder.Append("# common targets\n\n");\r
317                                 MakefileBuilder.Append("all:\t");\r
318     \r
319                                 bool first = true;\r
320     \r
321                                 foreach (PrjxInfo pi in projNameInfo.Values)\r
322                                 {\r
323                                         if (!first)\r
324                                         {\r
325                                                 MakefileBuilder.Append(" \\\n\t");\r
326                                         }\r
327                                         MakefileBuilder.AppendFormat("$({0})", pi.makename_ext);\r
328                                         first = false;\r
329                                 }\r
330                                 MakefileBuilder.Append("\n\n");\r
331     \r
332                                 MakefileBuilder.Append("clean:\n");\r
333     \r
334                                 foreach (PrjxInfo pi in projNameInfo.Values)\r
335                                 {\r
336                                         if (isUnixMode)\r
337                                         {\r
338                                                 MakefileBuilder.AppendFormat("\t-rm -f \"$({0})\" 2> /dev/null\n", pi.makename_ext);\r
339                                                 MakefileBuilder.AppendFormat("\t-rm -f \"$({0}_PDB)\" 2> /dev/null\n", pi.makename);\r
340                                         }\r
341                                         else\r
342                                         {\r
343                                                 MakefileBuilder.AppendFormat("\t-del \"$({0})\" 2> nul\n", pi.makename_ext);\r
344                                                 MakefileBuilder.AppendFormat("\t-del \"$({0}_PDB)\" 2> nul\n", pi.makename);\r
345                                         }\r
346                                 }\r
347                                 MakefileBuilder.Append("\n");\r
348                         }\r
349     \r
350                         if (!noProjectTargets)\r
351                         {\r
352                                 MakefileBuilder.Append("\n");\r
353                                 MakefileBuilder.Append("# project names as targets\n\n");\r
354                                 foreach (PrjxInfo pi in projNameInfo.Values)\r
355                                 {\r
356                                         MakefileBuilder.AppendFormat("{0}: $({1})\n", pi.name, pi.makename_ext);\r
357                                 }\r
358                         }\r
359                 }\r
360                 catch (Exception e)\r
361                 {\r
362                         Console.WriteLine("EXCEPTION: {0}\n", e);\r
363                         return "";\r
364                 }\r
365                 \r
366                         return MakefileBuilder.ToString();\r
367         }\r
368     }    \r
369 }\r