3 using System
.Collections
.Generic
;
5 using System
.Globalization
;
10 Library
, Exe
, Module
, WinExe
13 public enum LanguageVersion
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
)
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
)) {
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
{
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
95 // Our base directory, this is relative to our exectution point mono/msvc/scripts
100 // Class directory, relative to
103 public MsbuildGenerator (string dir
)
109 class_dir
= "..\\class\\";
110 base_dir
= "..\\..\\mcs\\mcs";
114 foreach (char c
in dir
){
116 mcs_topdir
= "..//" + mcs_topdir
;
118 class_dir
= mcs_topdir
.Substring (3);
120 base_dir
= Path
.Combine ("..", "..", "mcs", dir
);
126 StringBuilder defines
= new StringBuilder ();
130 Target Target
= Target
.Exe
;
131 string TargetExt
= ".exe";
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
;
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 (':');
169 arg
= option
.Substring (0, idx
);
171 value = option
.Substring (idx
+ 1);
174 switch (arg
.ToLower (CultureInfo
.InvariantCulture
)){
186 Target
= Target
.WinExe
;
190 Target
= Target
.Library
;
195 Target
= Target
.Module
;
196 TargetExt
= ".netmodule";
205 if (value.Length
== 0){
207 Environment
.Exit (1);
225 case "/incremental+":
226 case "/incremental-":
232 if (value.Length
== 0){
234 Environment
.Exit (1);
237 foreach (string d
in value.Split (argument_value_separator
)){
238 if (defines
.Length
!= 0)
239 defines
.Append (";");
248 // We should collect data, runtime, etc and store in the file specified
252 case "/linkresource":
255 bool embeded
= arg
[1] == 'r' || arg
[1] == 'R';
256 string[] s
= value.Split (argument_value_separator
);
259 if (s
[0].Length
== 0)
261 embedded_resources
[s
[0]] = Path
.GetFileName (s
[0]);
264 embedded_resources
[s
[0]] = s
[1];
267 Console
.WriteLine ("Does not support this method yet: {0}", arg
);
268 Environment
.Exit (1);
271 Console
.WriteLine ("Wrong number of arguments for option `{0}'", option
);
272 Environment
.Exit (1);
280 Console
.WriteLine ("/recurse not supported");
281 Environment
.Exit (1);
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
){
294 int index
= val
.IndexOf ('=');
296 reference_aliases
.Add (r
);
301 references
.Add (val
);
311 Console
.WriteLine ("{0} = not supported", arg
);
312 throw new Exception ();
320 win32IconFile
= value;
324 want_debugging_support
= false;
329 want_debugging_support
= true;
346 VerifyClsCompliance
= false;
359 case "/warnaserror+":
360 if (value.Length
== 0) {
361 WarningsAreErrors
= true;
363 foreach (string wid
in value.Split (argument_value_separator
))
364 warning_as_error
.Add (wid
);
369 Console
.WriteLine ("Warning ignoring /runtime:v4");
372 case "/warnaserror-":
373 if (value.Length
== 0) {
374 WarningsAreErrors
= false;
376 foreach (string wid
in value.Split (argument_value_separator
))
377 warning_as_error
.Remove (wid
);
382 WarningLevel
= Int32
.Parse (value);
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
){
396 if (wc
.Trim ().Length
== 0)
399 int warn
= Int32
.Parse (wc
);
401 throw new ArgumentOutOfRangeException("warn");
403 ignore_warning
.Add (warn
);
405 Console
.WriteLine (String
.Format("`{0}' is not a valid warning number", wc
));
406 Environment
.Exit (1);
413 load_default_config
= false;
429 if (value == String
.Empty
) {
430 Console
.WriteLine ("{0} requires an argument", arg
);
431 Environment
.Exit (1);
433 StrongNameKeyFile
= value;
435 case "/keycontainer":
436 if (value == String
.Empty
) {
437 Console
.WriteLine ("{0} requires an argument", arg
);
438 Environment
.Exit (1);
440 StrongNameKeyContainer
= value;
443 StrongNameDelaySign
= true;
446 StrongNameDelaySign
= false;
450 switch (value.ToLower (CultureInfo
.InvariantCulture
)) {
452 Version
= LanguageVersion
.ISO_1
;
456 Version
= LanguageVersion
.Default
;
459 Version
= LanguageVersion
.ISO_2
;
462 Version
= LanguageVersion
.Future
;
465 Console
.WriteLine ("Invalid option `{0}' for /langversion. It must be either `ISO-1', `ISO-2' or `Default'", value);
466 Environment
.Exit (1);
474 Console
.WriteLine ("Failing with : {0}", arg
);
478 static string [] LoadArgs (string file
)
481 var args
= new List
<string> ();
484 f
= new StreamReader (file
);
489 StringBuilder sb
= new StringBuilder ();
491 while ((line
= f
.ReadLine ()) != null){
494 for (int i
= 0; i
< t
; i
++){
497 if (c
== '"' || c
== '\''){
500 for (i
++; i
< t
; i
++){
507 } else if (c
== ' '){
509 args
.Add (sb
.ToString ());
516 args
.Add (sb
.ToString ());
521 string [] ret_value
= new string [args
.Count
];
522 args
.CopyTo (ret_value
, 0);
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 ();
539 public static string NativeName (string path
)
541 if (System
.IO
.Path
.DirectorySeparatorChar
== '/')
542 return path
.Replace ("\\", "/");
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 ("-");
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
++){
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
);
596 if (CSCParseOption (f
[i
], ref f
))
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
){
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 ()){
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 ('/');
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_");
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");
683 library_output
= Path
.GetDirectoryName (library_output
);
684 if (string.IsNullOrEmpty (library_output
))
685 library_output
= @".\";
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
);
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")))
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"))
752 var gen
= new MsbuildGenerator (dir
);
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");