Merge branch 'master' of github.com:mono/mono
[mono.git] / msvc / scripts / genproj.cs
index 5c6b5f63a3135ea32eb2671e905d1126e5f1c83b..6c1f5e66163f80342c7ef44231efcf2626f9d69c 100644 (file)
@@ -3,6 +3,8 @@ using System.IO;
 using System.Collections.Generic;
 using System.Text;
 using System.Globalization;
+using System.Xml.Linq;
+using System.Linq;
 
 public enum Target {
        Library, Exe, Module, WinExe
@@ -18,6 +20,60 @@ public enum LanguageVersion
        Default         = LINQ
 }
 
+class SlnGenerator {
+       const string header = "Microsoft Visual Studio Solution File, Format Version 10.00\n" +
+               "# Visual Studio 2008";
+
+       const string project_start = "Project(\"{{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}}\") = \"{0}\", \"{1}\", \"{{{2}}}\"";
+       const string project_end = "EndProject";
+
+       Dictionary<string, string> libraries = new Dictionary<string, string> ();
+
+       public void Add (string library)
+       {
+               try {
+                       libraries.Add (library, Guid.NewGuid ().ToString ().ToUpper ());
+               }
+               catch (Exception ex) {
+                       Console.WriteLine (ex);
+               }
+       }
+
+       public void Write (string filename)
+       {
+               using (var sln = new StreamWriter (filename)) {
+                       sln.WriteLine ();
+                       sln.WriteLine (header);
+                       foreach (var library in libraries) {
+                               var library_name = Path.GetFileNameWithoutExtension (library.Key);
+                               sln.WriteLine (project_start, library_name, library.Key, library.Value);
+                               sln.WriteLine (project_end);
+                       }
+                       sln.WriteLine ("Global");
+
+                       sln.WriteLine ("\tGlobalSection(SolutionConfigurationPlatforms) = preSolution");
+                       sln.WriteLine ("\t\tDebug|Any CPU = Debug|Any CPU");
+                       sln.WriteLine ("\t\tRelease|Any CPU = Release|Any CPU");
+                       sln.WriteLine ("\tEndGlobalSection");
+                       
+                       sln.WriteLine ("\tGlobalSection(ProjectConfigurationPlatforms) = postSolution");
+                       foreach (var library in libraries) {
+                               sln.WriteLine ("\t\t{{{0}}}.Debug|Any CPU.ActiveCfg = Debug|Any CPU", library.Value);
+                               sln.WriteLine ("\t\t{{{0}}}.Debug|Any CPU.Build.0 = Debug|Any CPU", library.Value);
+                               sln.WriteLine ("\t\t{{{0}}}.Release|Any CPU.ActiveCfg = Release|Any CPU", library.Value);
+                               sln.WriteLine ("\t\t{{{0}}}.Release|Any CPU.Build.0 = Release|Any CPU", library.Value);
+                       }
+                       sln.WriteLine ("\tEndGlobalSection");
+                               
+                       sln.WriteLine ("\tGlobalSection(SolutionProperties) = preSolution");
+                       sln.WriteLine ("\t\tHideSolutionNode = FALSE");
+                       sln.WriteLine ("\tEndGlobalSection");
+
+                       sln.WriteLine ("EndGlobal");
+               }
+       }
+}
+
 class MsbuildGenerator {
        static void Usage ()
        {
@@ -31,24 +87,38 @@ class MsbuildGenerator {
                        template = input.ReadToEnd ();
                }
        }
+
+       // The directory as specified in order.xml
+       string dir;
+
+       //
+       // Our base directory, this is relative to our exectution point mono/msvc/scripts
+       string base_dir;
+
+       string mcs_topdir;
+
+       // Class directory, relative to 
+       string class_dir;
        
-       string base_dir, dir;
-       string config_file;
-       string mcs_topdir, class_dir;
-       
-       public MsbuildGenerator (string dir, string config_file)
+       public MsbuildGenerator (string dir)
        {
-               mcs_topdir = "";
+               this.dir = dir;
                
-               foreach (char c in dir){
-                       if (c == '/')
-                               mcs_topdir = "..\\" + mcs_topdir;
+               if (dir == "mcs"){
+                       mcs_topdir = "..\\";
+                       class_dir = "..\\class\\";
+                       base_dir = "..\\..\\mcs\\mcs";
+               } else {
+                       mcs_topdir = "..\\";
+                       
+                       foreach (char c in dir){
+                               if (c == '/')
+                                       mcs_topdir = "..\\" + mcs_topdir;
+                       }
+                       class_dir = mcs_topdir.Substring (3);
+                       
+                       base_dir = "..\\..\\mcs\\" + dir;
                }
-               class_dir = mcs_topdir.Substring (3);
-               
-               this.dir = dir;
-               base_dir = "..\\..\\..\\mcs\\" + dir;
-               this.config_file = config_file;
        }
        
        // Currently used
@@ -69,6 +139,7 @@ class MsbuildGenerator {
        bool WarningsAreErrors;
        Dictionary<string,string> embedded_resources = new Dictionary<string,string> ();
        List<string> references = new List<string> ();
+       List<string> libs = new List<string> ();
        List<string> reference_aliases = new List<string> ();
        List<string> warning_as_error = new List<string> ();
        int WarningLevel = 4;
@@ -236,11 +307,15 @@ class MsbuildGenerator {
                case "/addmodule": 
                case "/win32res":
                case "/doc": 
-               case "/lib": 
                {
                        Console.WriteLine ("{0} = not supported", arg);
                        throw new Exception ();
                }
+               case "/lib":
+               {
+                       libs.Add (value);
+                       return true;
+               }
                case "/win32icon": {
                        win32IconFile = value;
                        return true;
@@ -290,6 +365,10 @@ class MsbuildGenerator {
                        }
                        return true;
 
+               case "/-runtime":
+                       Console.WriteLine ("Warning ignoring /runtime:v4");
+                       return true;
+                       
                case "/warnaserror-":
                        if (value.Length == 0) {
                                WarningsAreErrors = false;
@@ -392,6 +471,7 @@ class MsbuildGenerator {
                        return true;
                }
 
+               Console.WriteLine ("Failing with : {0}", arg);
                return false;
        }
 
@@ -443,28 +523,51 @@ class MsbuildGenerator {
                
                return ret_value;
        }
+
+       static string Load (string f)
+       {
+               var native = NativeName (f);
+                       
+               if (File.Exists (native)){
+                       using (var sr = new StreamReader (native)){
+                               return sr.ReadToEnd ();
+                       }
+               } else
+                       return "";
+       }
+
+       public static string NativeName (string path)
+       {
+               if (System.IO.Path.DirectorySeparatorChar == '/')
+                       return path.Replace ("\\", "/");
+               else
+                       return path.Replace ("/", "\\");
+       }
        
-       public void Generate ()
+       public string Generate (XElement xproject)
        {
+               string library = xproject.Attribute ("library").Value;
                string boot, mcs, flags, output_name, built_sources, library_output, response;
 
-               using (var par = new StreamReader (Path.Combine ("inputs", config_file))){
-                       boot = par.ReadLine ();
-                       mcs = par.ReadLine ();
-                       flags = par.ReadLine ();
-                       output_name = par.ReadLine ();
-                       built_sources = par.ReadLine ();
-                       library_output = par.ReadLine ();
-                       response = par.ReadLine ();
-               }
-               string prefile = Path.Combine ("inputs", config_file.Replace (".input", ".pre"));
-               string prebuild = "";
-               if (File.Exists (prefile)){
-                       using (var pre = new StreamReader (prefile)){
-                               prebuild = pre.ReadToEnd ();
-                       }
-               }
+               boot  = xproject.Element ("boot").Value;
+               mcs   = xproject.Element ("mcs").Value;
+               flags = xproject.Element ("flags").Value;
+               output_name =xproject.Element ("output").Value;
+               built_sources = xproject.Element ("built_sources").Value;
+               library_output = xproject.Element ("library_output").Value;
+               response = xproject.Element ("response").Value;
 
+               //
+               // Prebuild code, might be in inputs, check:
+               //  inputs/LIBRARY-PROFILE.pre
+               //  inputs/LIBRARY.pre
+               //
+               string prebuild = Load (library + ".pre");
+
+               int q = library.IndexOf ("-");
+               if (q != -1)
+                       prebuild = prebuild + Load (library.Substring (0, q) + ".pre");
+                       
                var all_args = new Queue<string []> ();
                all_args.Enqueue (flags.Split ());
                while (all_args.Count > 0){
@@ -496,47 +599,23 @@ class MsbuildGenerator {
                }
                
                string [] source_files;
-               using (var reader = new StreamReader (base_dir + "\\" + response)){
+               Console.WriteLine ("Base: {0} res: {1}", base_dir, response);
+               using (var reader = new StreamReader (NativeName (base_dir + "\\" + response))){
                        source_files  = reader.ReadToEnd ().Split ();
                }
                StringBuilder sources = new StringBuilder ();
                foreach (string s in source_files){
                        if (s.Length == 0)
                                continue;
-                       sources.Append (String.Format ("   <Compile Include=\"{0}\" />\n", s));
+                       sources.Append (String.Format ("   <Compile Include=\"{0}\" />\n", s.Replace ("/", "\\")));
                }
-               
-               //
-               // Compute the csc command that we need to use
-               //
-               // The mcs string is formatted like this:
-               // MONO_PATH=./../../class/lib/basic: /cvs/mono/runtime/mono-wrapper ./../../class/lib/basic/mcs.exe
-               //
-               // The first block is a set of MONO_PATHs, the last part is the compiler
-               //
-               if (mcs.StartsWith ("MONO_PATH="))
-                       mcs = mcs.Substring (10);
-               
-               var compiler = mcs.Substring (mcs.LastIndexOf (' ') + 1);
-               if (compiler.EndsWith ("class/lib/basic/mcs.exe"))
-                       compiler = "basic";
-               else if (compiler.EndsWith ("class/lib/net_1_1_bootstrap/mcs.exe"))
-                       compiler = "net_1_1_bootstrap";
-               else if (compiler.EndsWith ("class/lib/net_1_1/mcs.exe"))
-                       compiler = "net_1_1";
-               else if (compiler.EndsWith ("class/lib/net_2_0_bootstrap/gmcs.exe"))
-                       compiler = "net_2_0_bootstrap";
-               else if (compiler.EndsWith ("mcs/gmcs.exe"))
-                       compiler = "gmcs";
-               else if (compiler.EndsWith ("class/lib/net_2_1_bootstrap/smcs.exe"))
-                       compiler = "net_2_1_bootstrap";
-               else if (compiler.EndsWith ("class/lib/net_2_1_raw/smcs.exe"))
-                       compiler = "net_2_1_raw";
-               else {
-                       Console.WriteLine ("Can not determine compiler from {0}", compiler);
-                       Environment.Exit (1);
+               foreach (string s in built_sources.Split ()){
+                       if (s.Length == 0)
+                               continue;
+                       
+                       sources.Append (String.Format ("   <Compile Include=\"{0}\" />\n", s.Replace ("/", "\\")));
                }
-
+               
                var mono_paths = mcs.Substring (0, mcs.IndexOf (' ')).Split (new char [] {':'});
                for (int i = 0; i < mono_paths.Length; i++){
                        int p = mono_paths [i].LastIndexOf ('/');
@@ -545,18 +624,22 @@ class MsbuildGenerator {
                }
                
                var encoded_mono_paths = string.Join ("-", mono_paths).Replace ("--", "-");
-
-               string csc_tool_path = mcs_topdir + "\\..\\mono\\msvc\\scripts\\" + encoded_mono_paths + "-" + compiler;
-               csc_tool_path = csc_tool_path.Replace ("--", "-");
-
+               
                var refs = new StringBuilder ();
+               //
+               // mcs is different that csc in this regard, somehow with -noconfig we still import System and System.XML
+               //
+               if (dir == "mcs" && !load_default_config){
+                       references.Add ("System.dll");
+                       references.Add ("System.Xml.dll");
+               }
                
                if (references.Count > 0 || reference_aliases.Count > 0){
                        refs.Append ("<ItemGroup>\n");
                        string last = mono_paths [0].Substring (mono_paths [0].LastIndexOf ('/') + 1);
                        
                        string hint_path = class_dir + "\\lib\\" + last;
-                       
+
                        foreach (string r in references){
                                refs.Append ("    <Reference Include=\"" + r + "\">\n");
                                refs.Append ("      <SpecificVersion>False</SpecificVersion>\n");
@@ -575,32 +658,56 @@ class MsbuildGenerator {
                                refs.Append ("      <Aliases>" + alias + "</Aliases>\n");
                                refs.Append ("    </Reference>\n");
                        }
-
+                       
                        refs.Append ("  </ItemGroup>\n");
                }
+
+               var resources = new StringBuilder ();
+               if (embedded_resources.Count > 0){
+                       resources.AppendFormat ("  <ItemGroup>\n");
+                       foreach (var dk in embedded_resources){
+                               resources.AppendFormat ("    <EmbeddedResource Include=\"{0}\">\n", dk.Key);
+                               resources.AppendFormat ("       <LogicalName>{0}</LogicalName>\n", dk.Value);
+                               resources.AppendFormat ("    </EmbeddedResource>\n");
+                       }
+                       resources.AppendFormat ("  </ItemGroup>\n");
+               }
+               
+               try {
+                       Path.GetDirectoryName (library_output);
+               } catch {
+                       Console.WriteLine ("Error in path: {0} while processing {1}", library_output, library);
+               }
                
                //
                // Replace the template values
                //
                string output = template.
                        Replace ("@DEFINES@", defines.ToString ()).
+                       Replace ("@DISABLEDWARNINGS@", string.Join (",", (from i in ignore_warning select i.ToString ()).ToArray ())).
                        Replace ("@NOSTDLIB@", StdLib ? "" : "<NoStdLib>true</NoStdLib>").
                        Replace ("@ALLOWUNSAFE@", Unsafe ? "<AllowUnsafeBlocks>true</AllowUnsafeBlocks>" : "").
                        Replace ("@ASSEMBLYNAME@", Path.GetFileNameWithoutExtension (output_name)).
                        Replace ("@OUTPUTDIR@", Path.GetDirectoryName (library_output)).
                        Replace ("@DEFINECONSTANTS@", defines.ToString ()).
-                       Replace ("@CSCTOOLPATH@", csc_tool_path).
                        Replace ("@DEBUG@", want_debugging_support ? "true" : "false").
+                       Replace ("@DEBUGTYPE@", want_debugging_support ? "full" : "pdbonly").
                        Replace ("@REFERENCES@", refs.ToString ()).
                        Replace ("@PREBUILD@", prebuild).
+                       Replace ("@ADDITIONALLIBPATHS@", String.Format ("<AdditionalLibPaths>{0}</AdditionalLibPaths>", string.Join (",", libs.ToArray ()))).
+                       Replace ("@RESOURCES@", resources.ToString ()).
+                       Replace ("@OPTIMIZE@", Optimize ? "true" : "false").
                        Replace ("@SOURCES@", sources.ToString ());
 
 
-               string ofile = "..\\..\\..\\mcs\\" + dir + "\\" + config_file.Replace ("input", "csproj");
-               Console.WriteLine ("Generated {0}", ofile.Replace ("\\", "/"));
+               string ofile = "..\\..\\mcs\\" + dir + "\\" + library + ".csproj";
+               ofile = ofile.Replace ('\\', '/');
+               //Console.WriteLine ("Generated {0}", ofile.Replace ("\\", "/"));
                using (var o = new StreamWriter (ofile)){
                        o.WriteLine (output);
                }
+
+               return ofile;
        }
        
 }
@@ -609,27 +716,39 @@ public class Driver {
        
        static void Main (string [] args)
        {
-               if (!Directory.Exists ("inputs") || !File.Exists ("monowrap.cs")){
+               if (!File.Exists ("genproj.cs")){
                        Console.WriteLine ("This command should be ran from mono/msvc/scripts");
                        Environment.Exit (1);
                }
-               
-               using (var s = new StreamReader ("order")){
-                       string line;
 
-                       while ((line = s.ReadLine ()) != null){
-                               string [] lp = line.Split (new char [] { ':' });
-                               if (!lp [0].StartsWith ("class"))
-                                       continue;
+               var sln_gen = new SlnGenerator ();
+               XDocument doc = XDocument.Load ("order.xml");
+               foreach (XElement project in doc.Root.Elements ()){
+                       string dir = project.Attribute ("dir").Value;
+                       string library = project.Attribute ("library").Value;
 
-                               var gen = new MsbuildGenerator (lp [0], lp [1]);
-                               try {
-                                       gen.Generate ();
-                               } catch (Exception e) {
-                                       Console.WriteLine ("Error in {0}\n{1}", line, e);
-                               }
+                       //
+                       // Do only class libraries for now
+                       //
+                       if (!(dir.StartsWith ("class") || dir.StartsWith ("mcs")))
+                               continue;
+
+                       //
+                       // Do not do 2.1, it is not working yet
+                       // Do not do basic, as there is no point (requires a system mcs to be installed).
+                       //
+                       if (library.Contains ("moonlight") || library.Contains ("-basic") || library.EndsWith ("bootstrap"))
+                               continue;
+                       
+                       var gen = new MsbuildGenerator (dir);
+                       try {
+                               //sln_gen.Add (gen.Generate (project));
+                               gen.Generate (project);
+                       } catch (Exception e) {
+                               Console.WriteLine ("Error in {0}\n{1}", dir, e);
                        }
                }
-       }
+               sln_gen.Write ("mcs_full.sln");
+    }
 
-}
\ No newline at end of file
+}