Fix the IR class of OP_NEWARR to be of the array type and not element's.
[mono-project.git] / msvc / scripts / genproj.cs
blob53123b6b7e878bf4ab959ce0457b9fcfa5bdce94
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 using System.Linq;
9 public enum Target {
10 Library, Exe, Module, WinExe
13 public enum LanguageVersion
15 ISO_1 = 1,
16 Default_MCS = 2,
17 ISO_2 = 3,
18 LINQ = 4,
19 Future = 5,
20 Default = LINQ
23 class SlnGenerator {
24 const string header = "Microsoft Visual Studio Solution File, Format Version 10.00\n" +
25 "# Visual Studio 2008";
27 const string project_start = "Project(\"{{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}}\") = \"{0}\", \"{1}\", \"{{{2}}}\"";
28 const string project_end = "EndProject";
30 Dictionary<string, string> libraries = new Dictionary<string, string> ();
32 public void Add (string library)
34 try {
35 libraries.Add (library, Guid.NewGuid ().ToString ().ToUpper ());
37 catch (Exception ex) {
38 Console.WriteLine (ex);
42 public void Write (string filename)
44 using (var sln = new StreamWriter (filename)) {
45 sln.WriteLine ();
46 sln.WriteLine (header);
47 foreach (var library in libraries) {
48 var library_name = Path.GetFileNameWithoutExtension (library.Key);
49 sln.WriteLine (project_start, library_name, library.Key, library.Value);
50 sln.WriteLine (project_end);
52 sln.WriteLine ("Global");
54 sln.WriteLine ("\tGlobalSection(SolutionConfigurationPlatforms) = preSolution");
55 sln.WriteLine ("\t\tDebug|Any CPU = Debug|Any CPU");
56 sln.WriteLine ("\t\tRelease|Any CPU = Release|Any CPU");
57 sln.WriteLine ("\tEndGlobalSection");
59 sln.WriteLine ("\tGlobalSection(ProjectConfigurationPlatforms) = postSolution");
60 foreach (var library in libraries) {
61 sln.WriteLine ("\t\t{{{0}}}.Debug|Any CPU.ActiveCfg = Debug|Any CPU", library.Value);
62 sln.WriteLine ("\t\t{{{0}}}.Debug|Any CPU.Build.0 = Debug|Any CPU", library.Value);
63 sln.WriteLine ("\t\t{{{0}}}.Release|Any CPU.ActiveCfg = Release|Any CPU", library.Value);
64 sln.WriteLine ("\t\t{{{0}}}.Release|Any CPU.Build.0 = Release|Any CPU", library.Value);
66 sln.WriteLine ("\tEndGlobalSection");
68 sln.WriteLine ("\tGlobalSection(SolutionProperties) = preSolution");
69 sln.WriteLine ("\t\tHideSolutionNode = FALSE");
70 sln.WriteLine ("\tEndGlobalSection");
72 sln.WriteLine ("EndGlobal");
77 class MsbuildGenerator {
78 static void Usage ()
80 Console.WriteLine ("Invalid argument");
83 static string template;
84 static MsbuildGenerator ()
86 using (var input = new StreamReader ("csproj.tmpl")){
87 template = input.ReadToEnd ();
91 // The directory as specified in order.xml
92 string dir;
95 // Our base directory, this is relative to our exectution point mono/msvc/scripts
96 string base_dir;
98 string mcs_topdir;
100 // Class directory, relative to
101 string class_dir;
103 public MsbuildGenerator (string dir)
105 this.dir = dir;
107 if (dir == "mcs"){
108 mcs_topdir = "..\\";
109 class_dir = "..\\class\\";
110 base_dir = "..\\..\\mcs\\mcs";
111 } else {
112 mcs_topdir = "..\\";
114 foreach (char c in dir){
115 if (c == '/')
116 mcs_topdir = "..//" + mcs_topdir;
118 class_dir = mcs_topdir.Substring (3);
120 base_dir = Path.Combine ("..", "..", "mcs", dir);
124 // Currently used
125 bool Unsafe = false;
126 StringBuilder defines = new StringBuilder ();
127 bool StdLib = true;
129 // Currently unused
130 Target Target = Target.Exe;
131 string TargetExt = ".exe";
132 string OutputFile;
133 bool Optimize = true;
134 bool VerifyClsCompliance = true;
136 string win32IconFile;
137 bool want_debugging_support = false;
138 bool Checked = false;
139 bool WarningsAreErrors;
140 Dictionary<string,string> embedded_resources = new Dictionary<string,string> ();
141 List<string> references = new List<string> ();
142 List<string> libs = new List<string> ();
143 List<string> reference_aliases = new List<string> ();
144 List<string> warning_as_error = new List<string> ();
145 int WarningLevel = 4;
146 List<int> ignore_warning = new List<int> ();
147 bool load_default_config = true;
148 string StrongNameKeyFile;
149 string StrongNameKeyContainer;
150 bool StrongNameDelaySign = false;
151 LanguageVersion Version = LanguageVersion.Default;
152 string CodePage;
154 readonly char[] argument_value_separator = new char [] { ';', ',' };
157 // This parses the -arg and /arg options to the compiler, even if the strings
158 // in the following text use "/arg" on the strings.
160 bool CSCParseOption (string option, ref string [] args)
162 int idx = option.IndexOf (':');
163 string arg, value;
165 if (idx == -1){
166 arg = option;
167 value = "";
168 } else {
169 arg = option.Substring (0, idx);
171 value = option.Substring (idx + 1);
174 switch (arg.ToLower (CultureInfo.InvariantCulture)){
175 case "/nologo":
176 return true;
178 case "/t":
179 case "/target":
180 switch (value){
181 case "exe":
182 Target = Target.Exe;
183 break;
185 case "winexe":
186 Target = Target.WinExe;
187 break;
189 case "library":
190 Target = Target.Library;
191 TargetExt = ".dll";
192 break;
194 case "module":
195 Target = Target.Module;
196 TargetExt = ".netmodule";
197 break;
199 default:
200 return false;
202 return true;
204 case "/out":
205 if (value.Length == 0){
206 Usage ();
207 Environment.Exit (1);
209 OutputFile = value;
210 return true;
212 case "/o":
213 case "/o+":
214 case "/optimize":
215 case "/optimize+":
216 Optimize = true;
217 return true;
219 case "/o-":
220 case "/optimize-":
221 Optimize = false;
222 return true;
224 case "/incremental":
225 case "/incremental+":
226 case "/incremental-":
227 // nothing.
228 return true;
230 case "/d":
231 case "/define": {
232 if (value.Length == 0){
233 Usage ();
234 Environment.Exit (1);
237 foreach (string d in value.Split (argument_value_separator)){
238 if (defines.Length != 0)
239 defines.Append (";");
240 defines.Append (d);
243 return true;
246 case "/bugreport":
248 // We should collect data, runtime, etc and store in the file specified
250 return true;
251 case "/linkres":
252 case "/linkresource":
253 case "/res":
254 case "/resource":
255 bool embeded = arg [1] == 'r' || arg [1] == 'R';
256 string[] s = value.Split (argument_value_separator);
257 switch (s.Length) {
258 case 1:
259 if (s[0].Length == 0)
260 goto default;
261 embedded_resources [s[0]] = Path.GetFileName (s[0]);
262 break;
263 case 2:
264 embedded_resources [s [0]] = s [1];
265 break;
266 case 3:
267 Console.WriteLine ("Does not support this method yet: {0}", arg);
268 Environment.Exit (1);
269 break;
270 default:
271 Console.WriteLine ("Wrong number of arguments for option `{0}'", option);
272 Environment.Exit (1);
273 break;
277 return true;
279 case "/recurse":
280 Console.WriteLine ("/recurse not supported");
281 Environment.Exit (1);
282 return true;
284 case "/r":
285 case "/reference": {
286 if (value.Length == 0){
287 Console.WriteLine ("-reference requires an argument");
288 Environment.Exit (1);
291 string[] refs = value.Split (argument_value_separator);
292 foreach (string r in refs){
293 string val = r;
294 int index = val.IndexOf ('=');
295 if (index > -1) {
296 reference_aliases.Add (r);
297 continue;
300 if (val.Length != 0)
301 references.Add (val);
303 return true;
305 case "/main":
306 case "/m":
307 case "/addmodule":
308 case "/win32res":
309 case "/doc":
311 Console.WriteLine ("{0} = not supported", arg);
312 throw new Exception ();
314 case "/lib":
316 libs.Add (value);
317 return true;
319 case "/win32icon": {
320 win32IconFile = value;
321 return true;
323 case "/debug-":
324 want_debugging_support = false;
325 return true;
327 case "/debug":
328 case "/debug+":
329 want_debugging_support = true;
330 return true;
332 case "/checked":
333 case "/checked+":
334 Checked = true;
335 return true;
337 case "/checked-":
338 Checked = false;
339 return true;
341 case "/clscheck":
342 case "/clscheck+":
343 return true;
345 case "/clscheck-":
346 VerifyClsCompliance = false;
347 return true;
349 case "/unsafe":
350 case "/unsafe+":
351 Unsafe = true;
352 return true;
354 case "/unsafe-":
355 Unsafe = false;
356 return true;
358 case "/warnaserror":
359 case "/warnaserror+":
360 if (value.Length == 0) {
361 WarningsAreErrors = true;
362 } else {
363 foreach (string wid in value.Split (argument_value_separator))
364 warning_as_error.Add (wid);
366 return true;
368 case "/-runtime":
369 Console.WriteLine ("Warning ignoring /runtime:v4");
370 return true;
372 case "/warnaserror-":
373 if (value.Length == 0) {
374 WarningsAreErrors = false;
375 } else {
376 foreach (string wid in value.Split (argument_value_separator))
377 warning_as_error.Remove (wid);
379 return true;
381 case "/warn":
382 WarningLevel = Int32.Parse (value);
383 return true;
385 case "/nowarn": {
386 string [] warns;
388 if (value.Length == 0){
389 Console.WriteLine ("/nowarn requires an argument");
390 Environment.Exit (1);
393 warns = value.Split (argument_value_separator);
394 foreach (string wc in warns){
395 try {
396 if (wc.Trim ().Length == 0)
397 continue;
399 int warn = Int32.Parse (wc);
400 if (warn < 1) {
401 throw new ArgumentOutOfRangeException("warn");
403 ignore_warning.Add (warn);
404 } catch {
405 Console.WriteLine (String.Format("`{0}' is not a valid warning number", wc));
406 Environment.Exit (1);
409 return true;
412 case "/noconfig":
413 load_default_config = false;
414 return true;
416 case "/nostdlib":
417 case "/nostdlib+":
418 StdLib = false;
419 return true;
421 case "/nostdlib-":
422 StdLib = true;
423 return true;
425 case "/fullpaths":
426 return true;
428 case "/keyfile":
429 if (value == String.Empty) {
430 Console.WriteLine ("{0} requires an argument", arg);
431 Environment.Exit (1);
433 StrongNameKeyFile = value;
434 return true;
435 case "/keycontainer":
436 if (value == String.Empty) {
437 Console.WriteLine ("{0} requires an argument", arg);
438 Environment.Exit (1);
440 StrongNameKeyContainer = value;
441 return true;
442 case "/delaysign+":
443 StrongNameDelaySign = true;
444 return true;
445 case "/delaysign-":
446 StrongNameDelaySign = false;
447 return true;
449 case "/langversion":
450 switch (value.ToLower (CultureInfo.InvariantCulture)) {
451 case "iso-1":
452 Version = LanguageVersion.ISO_1;
453 return true;
455 case "default":
456 Version = LanguageVersion.Default;
457 return true;
458 case "iso-2":
459 Version = LanguageVersion.ISO_2;
460 return true;
461 case "future":
462 Version = LanguageVersion.Future;
463 return true;
465 Console.WriteLine ("Invalid option `{0}' for /langversion. It must be either `ISO-1', `ISO-2' or `Default'", value);
466 Environment.Exit (1);
467 return true;
469 case "/codepage":
470 CodePage = value;
471 return true;
474 Console.WriteLine ("Failing with : {0}", arg);
475 return false;
478 static string [] LoadArgs (string file)
480 StreamReader f;
481 var args = new List<string> ();
482 string line;
483 try {
484 f = new StreamReader (file);
485 } catch {
486 return null;
489 StringBuilder sb = new StringBuilder ();
491 while ((line = f.ReadLine ()) != null){
492 int t = line.Length;
494 for (int i = 0; i < t; i++){
495 char c = line [i];
497 if (c == '"' || c == '\''){
498 char end = c;
500 for (i++; i < t; i++){
501 c = line [i];
503 if (c == end)
504 break;
505 sb.Append (c);
507 } else if (c == ' '){
508 if (sb.Length > 0){
509 args.Add (sb.ToString ());
510 sb.Length = 0;
512 } else
513 sb.Append (c);
515 if (sb.Length > 0){
516 args.Add (sb.ToString ());
517 sb.Length = 0;
521 string [] ret_value = new string [args.Count];
522 args.CopyTo (ret_value, 0);
524 return ret_value;
527 static string Load (string f)
529 var native = NativeName (f);
531 if (File.Exists (native)){
532 using (var sr = new StreamReader (native)){
533 return sr.ReadToEnd ();
535 } else
536 return "";
539 public static string NativeName (string path)
541 if (System.IO.Path.DirectorySeparatorChar == '/')
542 return path.Replace ("\\", "/");
543 else
544 return path.Replace ("/", "\\");
547 public string Generate (XElement xproject)
549 string library = xproject.Attribute ("library").Value;
550 string boot, mcs, flags, output_name, built_sources, library_output, response, fx_version;
552 boot = xproject.Element ("boot").Value;
553 mcs = xproject.Element ("mcs").Value;
554 flags = xproject.Element ("flags").Value;
555 output_name =xproject.Element ("output").Value;
556 built_sources = xproject.Element ("built_sources").Value;
557 library_output = xproject.Element ("library_output").Value;
558 response = xproject.Element ("response").Value;
559 fx_version = xproject.Element ("fx_version").Value;
562 // Prebuild code, might be in inputs, check:
563 // inputs/LIBRARY-PROFILE.pre
564 // inputs/LIBRARY.pre
566 string prebuild = Load (library + ".pre");
568 int q = library.IndexOf ("-");
569 if (q != -1)
570 prebuild = prebuild + Load (library.Substring (0, q) + ".pre");
572 var all_args = new Queue<string []> ();
573 all_args.Enqueue (flags.Split ());
574 while (all_args.Count > 0){
575 string [] f = all_args.Dequeue ();
577 for (int i = 0; i < f.Length; i++){
578 if (f [i][0] == '-')
579 f [i] = "/" + f [i].Substring (1);
581 if (f [i][0] == '@') {
582 string [] extra_args;
583 string response_file = f [i].Substring (1);
585 var resp_file_full = Path.Combine (base_dir, response_file);
586 extra_args = LoadArgs (resp_file_full);
587 if (extra_args == null) {
588 Console.WriteLine ("Unable to open response file: " + resp_file_full);
589 Environment.Exit (1);
592 all_args.Enqueue (extra_args);
593 continue;
596 if (CSCParseOption (f [i], ref f))
597 continue;
598 Console.WriteLine ("Failure with {0}", f [i]);
599 Environment.Exit (1);
603 string [] source_files;
604 Console.WriteLine ("Base: {0} res: {1}", base_dir, response);
605 using (var reader = new StreamReader (NativeName (base_dir + "\\" + response))){
606 source_files = reader.ReadToEnd ().Split ();
608 StringBuilder sources = new StringBuilder ();
609 foreach (string s in source_files){
610 if (s.Length == 0)
611 continue;
613 string src = s.Replace ("/", "\\");
614 if (src.StartsWith (@"Test\..\"))
615 src = src.Substring (8, src.Length - 8);
617 sources.Append (String.Format (" <Compile Include=\"{0}\" />\n", src));
619 foreach (string s in built_sources.Split ()){
620 if (s.Length == 0)
621 continue;
623 string src = s.Replace ("/", "\\");
624 if (src.StartsWith (@"Test\..\"))
625 src = src.Substring (8, src.Length - 8);
627 sources.Append (String.Format (" <Compile Include=\"{0}\" />\n", src));
630 var mono_paths = mcs.Substring (0, mcs.IndexOf (' ')).Split (new char [] {':'});
631 for (int i = 0; i < mono_paths.Length; i++){
632 int p = mono_paths [i].LastIndexOf ('/');
633 if (p != -1)
634 mono_paths [i] = mono_paths [i].Substring (p + 1);
637 var encoded_mono_paths = string.Join ("-", mono_paths).Replace ("--", "-");
639 var refs = new StringBuilder ();
641 if (references.Count > 0 || reference_aliases.Count > 0){
642 string last = mono_paths [0].Substring (mono_paths [0].LastIndexOf ('/') + 1);
644 string hint_path = class_dir + "\\lib\\" + last;
646 foreach (string r in references){
647 refs.Append (" <Reference Include=\"" + r + "\">\n");
648 refs.Append (" <SpecificVersion>False</SpecificVersion>\n");
649 refs.Append (" <HintPath>" + r + "</HintPath>\n");
650 refs.Append (" </Reference>\n");
653 foreach (string r in reference_aliases){
654 int index = r.IndexOf ('=');
655 string alias = r.Substring (0, index);
656 string assembly = r.Substring (index + 1);
658 refs.Append (" <Reference Include=\"" + assembly + "\">\n");
659 refs.Append (" <SpecificVersion>False</SpecificVersion>\n");
660 refs.Append (" <HintPath>" + r + "</HintPath>\n");
661 refs.Append (" <Aliases>" + alias + "</Aliases>\n");
662 refs.Append (" </Reference>\n");
666 bool is_test = response.Contains ("_test_");
667 if (is_test) {
668 refs.Append (" <Reference Include=\"nunit.framework\" />\n");
671 var resources = new StringBuilder ();
672 if (embedded_resources.Count > 0){
673 resources.AppendFormat (" <ItemGroup>\n");
674 foreach (var dk in embedded_resources){
675 resources.AppendFormat (" <EmbeddedResource Include=\"{0}\">\n", dk.Key);
676 resources.AppendFormat (" <LogicalName>{0}</LogicalName>\n", dk.Value);
677 resources.AppendFormat (" </EmbeddedResource>\n");
679 resources.AppendFormat (" </ItemGroup>\n");
682 try {
683 library_output = Path.GetDirectoryName (library_output);
684 if (string.IsNullOrEmpty (library_output))
685 library_output = @".\";
686 } catch {
687 Console.WriteLine ("Error in path: {0} while processing {1}", library_output, library);
691 // Replace the template values
693 string output = template.
694 Replace ("@DEFINES@", defines.ToString ()).
695 Replace ("@DISABLEDWARNINGS@", string.Join (",", (from i in ignore_warning select i.ToString ()).ToArray ())).
696 Replace ("@NOSTDLIB@", StdLib ? "" : "<NoStdLib>true</NoStdLib>").
697 Replace ("@ALLOWUNSAFE@", Unsafe ? "<AllowUnsafeBlocks>true</AllowUnsafeBlocks>" : "").
698 Replace ("@FX_VERSION", fx_version).
699 Replace ("@ASSEMBLYNAME@", Path.GetFileNameWithoutExtension (output_name)).
700 Replace ("@OUTPUTDIR@", library_output).
701 Replace ("@DEFINECONSTANTS@", defines.ToString ()).
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 ("@ADDITIONALLIBPATHS@", String.Format ("<AdditionalLibPaths>{0}</AdditionalLibPaths>", string.Join (",", libs.ToArray ()))).
707 Replace ("@RESOURCES@", resources.ToString ()).
708 Replace ("@OPTIMIZE@", Optimize ? "true" : "false").
709 Replace ("@SOURCES@", sources.ToString ());
712 string ofile = "..\\..\\mcs\\" + dir + "\\" + library + ".csproj";
713 ofile = ofile.Replace ('\\', '/');
714 //Console.WriteLine ("Generated {0}", ofile.Replace ("\\", "/"));
715 using (var o = new StreamWriter (ofile)){
716 o.WriteLine (output);
719 return ofile;
724 public class Driver {
726 static void Main (string [] args)
728 if (!File.Exists ("genproj.cs")){
729 Console.WriteLine ("This command should be ran from mono/msvc/scripts");
730 Environment.Exit (1);
733 var sln_gen = new SlnGenerator ();
734 XDocument doc = XDocument.Load ("order.xml");
735 foreach (XElement project in doc.Root.Elements ()){
736 string dir = project.Attribute ("dir").Value;
737 string library = project.Attribute ("library").Value;
740 // Do only class libraries for now
742 if (!(dir.StartsWith ("class") || dir.StartsWith ("mcs")))
743 continue;
746 // Do not do 2.1, it is not working yet
747 // Do not do basic, as there is no point (requires a system mcs to be installed).
749 if (library.Contains ("moonlight") || library.Contains ("-basic") || library.EndsWith ("bootstrap"))
750 continue;
752 var gen = new MsbuildGenerator (dir);
753 try {
754 //sln_gen.Add (gen.Generate (project));
755 gen.Generate (project);
756 } catch (Exception e) {
757 Console.WriteLine ("Error in {0}\n{1}", dir, e);
760 sln_gen.Write ("mcs_full.sln");