Add initial solution generation support. This generates a solution with all mcs assem...
[mono.git] / msvc / scripts / genproj.cs
1 using System;
2 using System.IO;
3 using System.Collections.Generic;
4 using System.Text;
5 using System.Globalization;
6 using System.Xml.Linq;
7
8 public enum Target {
9         Library, Exe, Module, WinExe
10 }
11
12 public enum LanguageVersion
13 {
14         ISO_1           = 1,
15         Default_MCS     = 2,
16         ISO_2           = 3,
17         LINQ            = 4,
18         Future          = 5,
19         Default         = LINQ
20 }
21
22 class SlnGenerator {
23         const string header = "Microsoft Visual Studio Solution File, Format Version 10.00\n" +
24                 "# Visual Studio 2008";
25
26         const string project_start = "Project(\"{{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}}\") = \"{0}\", \"{1}\", \"{{{2}}}\"";
27         const string project_end = "EndProject";
28
29         Dictionary<string, string> libraries = new Dictionary<string, string> ();
30
31         public void Add (string library)
32         {
33                 try {
34                         libraries.Add (library, Guid.NewGuid ().ToString ().ToUpper ());
35                 }
36                 catch (Exception ex) {
37                         Console.WriteLine (ex);
38                 }
39         }
40
41         public void Write (string filename)
42         {
43                 using (var sln = new StreamWriter (filename)) {
44                         sln.WriteLine ();
45                         sln.WriteLine (header);
46                         foreach (var library in libraries) {
47                                 var library_name = Path.GetFileNameWithoutExtension (library.Key);
48                                 sln.WriteLine (project_start, library_name, library.Key, library.Value);
49                                 sln.WriteLine (project_end);
50                         }
51                         sln.WriteLine ("Global");
52
53                         sln.WriteLine ("\tGlobalSection(SolutionConfigurationPlatforms) = preSolution");
54                         sln.WriteLine ("\t\tDebug|Any CPU = Debug|Any CPU");
55                         sln.WriteLine ("\t\tRelease|Any CPU = Release|Any CPU");
56                         sln.WriteLine ("\tEndGlobalSection");
57                         
58                         sln.WriteLine ("\tGlobalSection(ProjectConfigurationPlatforms) = postSolution");
59                         foreach (var library in libraries) {
60                                 sln.WriteLine ("\t\t{{{0}}}.Debug|Any CPU.ActiveCfg = Debug|Any CPU", library.Value);
61                                 sln.WriteLine ("\t\t{{{0}}}.Debug|Any CPU.Build.0 = Debug|Any CPU", library.Value);
62                                 sln.WriteLine ("\t\t{{{0}}}.Release|Any CPU.ActiveCfg = Release|Any CPU", library.Value);
63                                 sln.WriteLine ("\t\t{{{0}}}.Release|Any CPU.Build.0 = Release|Any CPU", library.Value);
64                         }
65                         sln.WriteLine ("\tEndGlobalSection");
66                                 
67                         sln.WriteLine ("\tGlobalSection(SolutionProperties) = preSolution");
68                         sln.WriteLine ("\t\tHideSolutionNode = FALSE");
69                         sln.WriteLine ("\tEndGlobalSection");
70
71                         sln.WriteLine ("EndGlobal");
72                 }
73         }
74 }
75
76 class MsbuildGenerator {
77         static void Usage ()
78         {
79                 Console.WriteLine ("Invalid argument");
80         }
81
82         static string template;
83         static MsbuildGenerator ()
84         {
85                 using (var input = new StreamReader ("csproj.tmpl")){
86                         template = input.ReadToEnd ();
87                 }
88         }
89
90         // The directory as specified in order.xml
91         string dir;
92
93         //
94         // Our base directory, this is relative to our exectution point mono/msvc/scripts
95         string base_dir;
96
97         string mcs_topdir;
98
99         // Class directory, relative to 
100         string class_dir;
101         
102         public MsbuildGenerator (string dir)
103         {
104                 this.dir = dir;
105                 
106                 if (dir == "mcs"){
107                         mcs_topdir = "..\\";
108                         class_dir = "..\\class\\";
109                         base_dir = "..\\..\\..\\mcs\\mcs";
110                 } else {
111                         mcs_topdir = "..\\";
112                         
113                         foreach (char c in dir){
114                                 if (c == '/')
115                                         mcs_topdir = "..\\" + mcs_topdir;
116                         }
117                         class_dir = mcs_topdir.Substring (3);
118                         
119                         base_dir = "..\\..\\..\\mcs\\" + dir;
120                 }
121         }
122         
123         // Currently used
124         bool Unsafe = false;
125         StringBuilder defines = new StringBuilder ();
126         bool StdLib = true;
127
128         // Currently unused
129         Target Target = Target.Exe;
130         string TargetExt = ".exe";
131         string OutputFile;
132         bool Optimize = true;
133         bool VerifyClsCompliance = true;
134
135         string win32IconFile;
136         bool want_debugging_support = false;
137         bool Checked = false;
138         bool WarningsAreErrors;
139         Dictionary<string,string> embedded_resources = new Dictionary<string,string> ();
140         List<string> references = new List<string> ();
141         List<string> reference_aliases = new List<string> ();
142         List<string> warning_as_error = new List<string> ();
143         int WarningLevel = 4;
144         List<int> ignore_warning = new List<int> ();
145         bool load_default_config = true;
146         string StrongNameKeyFile;
147         string StrongNameKeyContainer;
148         bool StrongNameDelaySign = false;
149         LanguageVersion Version = LanguageVersion.Default;
150         string CodePage;
151
152         readonly char[] argument_value_separator = new char [] { ';', ',' };
153
154         //
155         // This parses the -arg and /arg options to the compiler, even if the strings
156         // in the following text use "/arg" on the strings.
157         //
158         bool CSCParseOption (string option, ref string [] args)
159         {
160                 int idx = option.IndexOf (':');
161                 string arg, value;
162
163                 if (idx == -1){
164                         arg = option;
165                         value = "";
166                 } else {
167                         arg = option.Substring (0, idx);
168
169                         value = option.Substring (idx + 1);
170                 }
171
172                 switch (arg.ToLower (CultureInfo.InvariantCulture)){
173                 case "/nologo":
174                         return true;
175
176                 case "/t":
177                 case "/target":
178                         switch (value){
179                         case "exe":
180                                 Target = Target.Exe;
181                                 break;
182
183                         case "winexe":
184                                 Target = Target.WinExe;
185                                 break;
186
187                         case "library":
188                                 Target = Target.Library;
189                                 TargetExt = ".dll";
190                                 break;
191
192                         case "module":
193                                 Target = Target.Module;
194                                 TargetExt = ".netmodule";
195                                 break;
196
197                         default:
198                                 return false;
199                         }
200                         return true;
201
202                 case "/out":
203                         if (value.Length == 0){
204                                 Usage ();
205                                 Environment.Exit (1);
206                         }
207                         OutputFile = value;
208                         return true;
209
210                 case "/o":
211                 case "/o+":
212                 case "/optimize":
213                 case "/optimize+":
214                         Optimize = true;
215                         return true;
216
217                 case "/o-":
218                 case "/optimize-":
219                         Optimize = false;
220                         return true;
221
222                 case "/incremental":
223                 case "/incremental+":
224                 case "/incremental-":
225                         // nothing.
226                         return true;
227
228                 case "/d":
229                 case "/define": {
230                         if (value.Length == 0){
231                                 Usage ();
232                                 Environment.Exit (1);
233                         }
234
235                         foreach (string d in value.Split (argument_value_separator)){
236                                 if (defines.Length != 0)
237                                         defines.Append (";");
238                                 defines.Append (d);
239                         }
240
241                         return true;
242                 }
243
244                 case "/bugreport":
245                         //
246                         // We should collect data, runtime, etc and store in the file specified
247                         //
248                         return true;
249                 case "/linkres":
250                 case "/linkresource":
251                 case "/res":
252                 case "/resource":
253                         bool embeded = arg [1] == 'r' || arg [1] == 'R';
254                         string[] s = value.Split (argument_value_separator);
255                         switch (s.Length) {
256                         case 1:
257                                 if (s[0].Length == 0)
258                                         goto default;
259                                 embedded_resources [s[0]] = Path.GetFileName (s[0]);
260                                 break;
261                         case 2:
262                                 embedded_resources [s [0]] = s [1];
263                                 break;
264                         case 3:
265                                 Console.WriteLine ("Does not support this method yet: {0}", arg);
266                                 Environment.Exit (1);
267                                 break;
268                         default:
269                                 Console.WriteLine ("Wrong number of arguments for option `{0}'", option);
270                                 Environment.Exit (1);
271                                 break;
272                                 
273                         }
274
275                         return true;
276                                 
277                 case "/recurse":
278                         Console.WriteLine ("/recurse not supported");
279                         Environment.Exit (1);
280                         return true;
281
282                 case "/r":
283                 case "/reference": {
284                         if (value.Length == 0){
285                                 Console.WriteLine ("-reference requires an argument");
286                                 Environment.Exit (1);
287                         }
288
289                         string[] refs = value.Split (argument_value_separator);
290                         foreach (string r in refs){
291                                 string val = r;
292                                 int index = val.IndexOf ('=');
293                                 if (index > -1) {
294                                         reference_aliases.Add (r);
295                                         continue;
296                                 }
297
298                                 if (val.Length != 0)
299                                         references.Add (val);
300                         }
301                         return true;
302                 }
303                 case "/main":
304                 case "/m":
305                 case "/addmodule": 
306                 case "/win32res":
307                 case "/doc": 
308                 case "/lib": 
309                 {
310                         Console.WriteLine ("{0} = not supported", arg);
311                         throw new Exception ();
312                 }
313                 case "/win32icon": {
314                         win32IconFile = value;
315                         return true;
316                 }
317                 case "/debug-":
318                         want_debugging_support = false;
319                         return true;
320                                 
321                 case "/debug":
322                 case "/debug+":
323                         want_debugging_support = true;
324                         return true;
325
326                 case "/checked":
327                 case "/checked+":
328                         Checked = true;
329                         return true;
330
331                 case "/checked-":
332                         Checked = false;
333                         return true;
334
335                 case "/clscheck":
336                 case "/clscheck+":
337                         return true;
338
339                 case "/clscheck-":
340                         VerifyClsCompliance = false;
341                         return true;
342
343                 case "/unsafe":
344                 case "/unsafe+":
345                         Unsafe = true;
346                         return true;
347
348                 case "/unsafe-":
349                         Unsafe = false;
350                         return true;
351
352                 case "/warnaserror":
353                 case "/warnaserror+":
354                         if (value.Length == 0) {
355                                 WarningsAreErrors = true;
356                         } else {
357                                 foreach (string wid in value.Split (argument_value_separator))
358                                         warning_as_error.Add (wid);
359                         }
360                         return true;
361
362                 case "/warnaserror-":
363                         if (value.Length == 0) {
364                                 WarningsAreErrors = false;
365                         } else {
366                                 foreach (string wid in value.Split (argument_value_separator))
367                                         warning_as_error.Remove (wid);
368                         }
369                         return true;
370
371                 case "/warn":
372                         WarningLevel = Int32.Parse (value);
373                         return true;
374
375                 case "/nowarn": {
376                         string [] warns;
377
378                         if (value.Length == 0){
379                                 Console.WriteLine ("/nowarn requires an argument");
380                                 Environment.Exit (1);
381                         }
382
383                         warns = value.Split (argument_value_separator);
384                         foreach (string wc in warns){
385                                 try {
386                                         if (wc.Trim ().Length == 0)
387                                                 continue;
388
389                                         int warn = Int32.Parse (wc);
390                                         if (warn < 1) {
391                                                 throw new ArgumentOutOfRangeException("warn");
392                                         }
393                                         ignore_warning.Add (warn);
394                                 } catch {
395                                         Console.WriteLine (String.Format("`{0}' is not a valid warning number", wc));
396                                         Environment.Exit (1);
397                                 }
398                         }
399                         return true;
400                 }
401
402                 case "/noconfig":
403                         load_default_config = false;
404                         return true;
405
406                 case "/nostdlib":
407                 case "/nostdlib+":
408                         StdLib = false;
409                         return true;
410
411                 case "/nostdlib-":
412                         StdLib = true;
413                         return true;
414
415                 case "/fullpaths":
416                         return true;
417
418                 case "/keyfile":
419                         if (value == String.Empty) {
420                                 Console.WriteLine ("{0} requires an argument", arg);
421                                 Environment.Exit (1);
422                         }
423                         StrongNameKeyFile = value;
424                         return true;
425                 case "/keycontainer":
426                         if (value == String.Empty) {
427                                 Console.WriteLine ("{0} requires an argument", arg);
428                                 Environment.Exit (1);
429                         }
430                         StrongNameKeyContainer = value;
431                         return true;
432                 case "/delaysign+":
433                         StrongNameDelaySign = true;
434                         return true;
435                 case "/delaysign-":
436                         StrongNameDelaySign = false;
437                         return true;
438
439                 case "/langversion":
440                         switch (value.ToLower (CultureInfo.InvariantCulture)) {
441                         case "iso-1":
442                                 Version = LanguageVersion.ISO_1;
443                                 return true;
444                                         
445                         case "default":
446                                 Version = LanguageVersion.Default;
447                                 return true;
448                         case "iso-2":
449                                 Version = LanguageVersion.ISO_2;
450                                 return true;
451                         case "future":
452                                 Version = LanguageVersion.Future;
453                                 return true;
454                         }
455                         Console.WriteLine ("Invalid option `{0}' for /langversion. It must be either `ISO-1', `ISO-2' or `Default'", value);
456                         Environment.Exit (1);
457                         return true;
458                         
459                 case "/codepage":
460                         CodePage = value;
461                         return true;
462                 }
463
464                 return false;
465         }
466
467         static string [] LoadArgs (string file)
468         {
469                 StreamReader f;
470                 var args = new List<string> ();
471                 string line;
472                 try {
473                         f = new StreamReader (file);
474                 } catch {
475                         return null;
476                 }
477                 
478                 StringBuilder sb = new StringBuilder ();
479                 
480                 while ((line = f.ReadLine ()) != null){
481                         int t = line.Length;
482                         
483                         for (int i = 0; i < t; i++){
484                                 char c = line [i];
485                                 
486                                 if (c == '"' || c == '\''){
487                                         char end = c;
488                                         
489                                         for (i++; i < t; i++){
490                                                 c = line [i];
491                                                 
492                                                 if (c == end)
493                                                         break;
494                                                 sb.Append (c);
495                                         }
496                                 } else if (c == ' '){
497                                         if (sb.Length > 0){
498                                                 args.Add (sb.ToString ());
499                                                 sb.Length = 0;
500                                         }
501                                 } else
502                                         sb.Append (c);
503                         }
504                         if (sb.Length > 0){
505                                 args.Add (sb.ToString ());
506                                 sb.Length = 0;
507                         }
508                 }
509                 
510                 string [] ret_value = new string [args.Count];
511                 args.CopyTo (ret_value, 0);
512                 
513                 return ret_value;
514         }
515
516         static string Load (string f)
517         {
518                 if (File.Exists (f)){
519                         using (var sr = new StreamReader (f)){
520                                 return sr.ReadToEnd ();
521                         }
522                 } else
523                         return "";
524         }
525         
526         public string Generate (XElement xproject)
527         {
528                 string library = xproject.Attribute ("library").Value;
529                 string boot, mcs, flags, output_name, built_sources, library_output, response;
530
531                 boot  = xproject.Element ("boot").Value;
532                 mcs   = xproject.Element ("mcs").Value;
533                 flags = xproject.Element ("flags").Value;
534                 output_name =xproject.Element ("output").Value;
535                 built_sources = xproject.Element ("built_sources").Value;
536                 library_output = xproject.Element ("library_output").Value;
537                 response = xproject.Element ("response").Value;
538
539                 //
540                 // Prebuild code, might be in inputs, check:
541                 //  inputs/LIBRARY-PROFILE.pre
542                 //  inputs/LIBRARY.pre
543                 //
544                 string prebuild = Load (library + ".pre");
545
546                 int q = library.IndexOf ("-");
547                 if (q != -1)
548                         prebuild = prebuild + Load (library.Substring (0, q) + ".pre");
549                         
550                 var all_args = new Queue<string []> ();
551                 all_args.Enqueue (flags.Split ());
552                 while (all_args.Count > 0){
553                         string [] f = all_args.Dequeue ();
554                         
555                         for (int i = 0; i < f.Length; i++){
556                                 if (f [i][0] == '-')
557                                         f [i] = "/" + f [i].Substring (1);
558                                 
559                                 if (f [i][0] == '@') {
560                                         string [] extra_args;
561                                         string response_file = f [i].Substring (1);
562                                         
563                                         extra_args = LoadArgs (base_dir + "\\" + response_file);
564                                         if (extra_args == null) {
565                                                 Console.WriteLine ("Unable to open response file: " + response_file);
566                                                 Environment.Exit (1);
567                                         }
568
569                                         all_args.Enqueue (extra_args);
570                                         continue;
571                                 }
572                                 
573                                 if (CSCParseOption (f [i], ref f))
574                                         continue;
575                                 Console.WriteLine ("Failure with {0}", f [i]);
576                                 Environment.Exit (1);
577                         }
578                 }
579                 
580                 string [] source_files;
581                 using (var reader = new StreamReader (base_dir + "\\" + response)){
582                         source_files  = reader.ReadToEnd ().Split ();
583                 }
584                 StringBuilder sources = new StringBuilder ();
585                 foreach (string s in source_files){
586                         if (s.Length == 0)
587                                 continue;
588                         sources.Append (String.Format ("   <Compile Include=\"{0}\" />\n", s.Replace ("/", "\\")));
589                 }
590                 foreach (string s in built_sources.Split ()){
591                         if (s.Length == 0)
592                                 continue;
593                         
594                         sources.Append (String.Format ("   <Compile Include=\"{0}\" />\n", s.Replace ("/", "\\")));
595                 }
596                 
597                 //
598                 // Compute the csc command that we need to use
599                 //
600                 // The mcs string is formatted like this:
601                 // MONO_PATH=./../../class/lib/basic: /cvs/mono/runtime/mono-wrapper ./../../class/lib/basic/mcs.exe
602                 //
603                 // The first block is a set of MONO_PATHs, the last part is the compiler
604                 //
605                 if (mcs.StartsWith ("MONO_PATH="))
606                         mcs = mcs.Substring (10);
607                 
608                 var compiler = mcs.Substring (mcs.LastIndexOf (' ') + 1);
609                 if (compiler.EndsWith ("class/lib/basic/mcs.exe"))
610                         compiler = "basic";
611                 else if (compiler.EndsWith ("class/lib/net_1_1_bootstrap/mcs.exe"))
612                         compiler = "net_1_1_bootstrap";
613                 else if (compiler.EndsWith ("class/lib/net_1_1/mcs.exe"))
614                         compiler = "net_1_1";
615                 else if (compiler.EndsWith ("class/lib/net_2_0_bootstrap/gmcs.exe"))
616                         compiler = "net_2_0_bootstrap";
617                 else if (compiler.EndsWith ("mcs/gmcs.exe"))
618                         compiler = "gmcs";
619                 else if (compiler.EndsWith ("class/lib/net_2_1_bootstrap/smcs.exe"))
620                         compiler = "net_2_1_bootstrap";
621                 else if (compiler.EndsWith ("class/lib/net_2_1_raw/smcs.exe"))
622                         compiler = "net_2_1_raw";
623                 else {
624                         Console.WriteLine ("Can not determine compiler from {0}", compiler);
625                         Environment.Exit (1);
626                 }
627
628                 var mono_paths = mcs.Substring (0, mcs.IndexOf (' ')).Split (new char [] {':'});
629                 for (int i = 0; i < mono_paths.Length; i++){
630                         int p = mono_paths [i].LastIndexOf ('/');
631                         if (p != -1)
632                                 mono_paths [i] = mono_paths [i].Substring (p + 1);
633                 }
634                 
635                 var encoded_mono_paths = string.Join ("-", mono_paths).Replace ("--", "-");
636                 var encoded_mp_compiler = (encoded_mono_paths + "-" + compiler).Replace ("--", "-");
637                 
638                 string csc_tool_path = mcs_topdir + "..\\mono\\msvc\\scripts\\" + encoded_mp_compiler;
639                 if (!Directory.Exists (encoded_mp_compiler)){
640                         Console.WriteLine ("Created {0}", encoded_mp_compiler);
641                         Directory.CreateDirectory (encoded_mp_compiler);
642                 }
643                 if (!File.Exists (Path.Combine (encoded_mp_compiler, "csc.exe"))){
644                         File.Copy ("monowrap.exe", Path.Combine (encoded_mp_compiler, "csc.exe"));
645                         File.Copy ("monowrap.pdb", Path.Combine (encoded_mp_compiler, "csc.pdb"));
646                 }
647                 
648                 var refs = new StringBuilder ();
649                 //
650                 // mcs is different that csc in this regard, somehow with -noconfig we still import System and System.XML
651                 //
652                 if (dir == "mcs" && !load_default_config){
653                         references.Add ("System.dll");
654                         references.Add ("System.Xml.dll");
655                 }
656                 
657                 if (references.Count > 0 || reference_aliases.Count > 0){
658                         refs.Append ("<ItemGroup>\n");
659                         string last = mono_paths [0].Substring (mono_paths [0].LastIndexOf ('/') + 1);
660                         
661                         string hint_path = class_dir + "\\lib\\" + last;
662
663                         foreach (string r in references){
664                                 refs.Append ("    <Reference Include=\"" + r + "\">\n");
665                                 refs.Append ("      <SpecificVersion>False</SpecificVersion>\n");
666                                 refs.Append ("      <HintPath>" + hint_path + "\\" + r + "</HintPath>\n");
667                                 refs.Append ("    </Reference>\n");
668                         }
669
670                         foreach (string r in reference_aliases){
671                                 int index = r.IndexOf ('=');
672                                 string alias = r.Substring (0, index);
673                                 string assembly = r.Substring (index + 1);
674
675                                 refs.Append ("    <Reference Include=\"" + assembly + "\">\n");
676                                 refs.Append ("      <SpecificVersion>False</SpecificVersion>\n");
677                                 refs.Append ("      <HintPath>" + hint_path + "\\" + r + "</HintPath>\n");
678                                 refs.Append ("      <Aliases>" + alias + "</Aliases>\n");
679                                 refs.Append ("    </Reference>\n");
680                         }
681                         
682                         refs.Append ("  </ItemGroup>\n");
683                 }
684
685                 try {
686                         Path.GetDirectoryName (library_output);
687                 } catch {
688                         Console.WriteLine ("Error in path: {0} while processing {1}", library_output, library);
689                 }
690                 
691                 //
692                 // Replace the template values
693                 //
694                 string output = template.
695                         Replace ("@DEFINES@", defines.ToString ()).
696                         Replace ("@NOSTDLIB@", StdLib ? "" : "<NoStdLib>true</NoStdLib>").
697                         Replace ("@ALLOWUNSAFE@", Unsafe ? "<AllowUnsafeBlocks>true</AllowUnsafeBlocks>" : "").
698                         Replace ("@ASSEMBLYNAME@", Path.GetFileNameWithoutExtension (output_name)).
699                         Replace ("@OUTPUTDIR@", Path.GetDirectoryName (library_output)).
700                         Replace ("@DEFINECONSTANTS@", defines.ToString ()).
701                         Replace ("@CSCTOOLPATH@", csc_tool_path).
702                         Replace ("@DEBUG@", want_debugging_support ? "true" : "false").
703                         Replace ("@DEBUGTYPE@", want_debugging_support ? "full" : "pdbonly").
704                         Replace ("@REFERENCES@", refs.ToString ()).
705                         Replace ("@PREBUILD@", prebuild).
706                         Replace ("@SOURCES@", sources.ToString ());
707
708
709                 string ofile = "..\\..\\..\\mcs\\" + dir + "\\" + library + ".csproj";
710                 ofile = ofile.Replace ('/', '\\');
711                 //Console.WriteLine ("Generated {0}", ofile.Replace ("\\", "/"));
712                 using (var o = new StreamWriter (ofile)){
713                         o.WriteLine (output);
714                 }
715
716                 return ofile;
717         }
718         
719 }
720
721 public class Driver {
722         
723         static void Main (string [] args)
724         {
725                 if (!File.Exists ("genproj.cs") || !File.Exists ("monowrap.cs")){
726                         Console.WriteLine ("This command should be ran from mono/msvc/scripts");
727                         Environment.Exit (1);
728                 }
729
730         var sln_gen = new SlnGenerator ();
731                 XDocument doc = XDocument.Load ("order.xml");
732                 foreach (XElement project in doc.Root.Elements ()){
733                         string dir = project.Attribute ("dir").Value;
734                         string library = project.Attribute ("library").Value;
735
736                         //
737                         // Do only class libraries for now
738                         //
739                         if (!(dir.StartsWith ("class") || dir.StartsWith ("mcs")))
740                                 continue;
741
742                         //
743                         // Do not do 2.1, it is not working yet
744                         // Do not do basic, as there is no point (requires a system mcs to be installed).
745                         //
746                         if (library.Contains ("net_2_1") || library.Contains ("-basic"))
747                                 continue;
748                         
749                         var gen = new MsbuildGenerator (dir);
750                         try {
751                                 sln_gen.Add (gen.Generate (project));
752                         } catch (Exception e) {
753                                 Console.WriteLine ("Error in {0}\n{1}", dir, e);
754                         }
755                 }
756         sln_gen.Write ("mcs_full.sln");
757     }
758
759 }