using System.Collections.Generic;
using System.Text;
using System.Globalization;
+using System.Xml.Linq;
public enum Target {
Library, Exe, Module, WinExe
Default = LINQ
}
-class MsbuildGenerator {
- static string read ()
+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)
{
- return Console.ReadLine ();
+ try {
+ libraries.Add (library, Guid.NewGuid ().ToString ().ToUpper ());
+ }
+ catch (Exception ex) {
+ Console.WriteLine (ex);
+ }
}
- // Currently used
- static bool Unsafe = false;
- static StringBuilder defines = new StringBuilder ();
- static bool StdLib = true;
+ 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");
- // Currently unused
- static Target Target = Target.Exe;
- static string TargetExt = ".exe";
- static string OutputFile;
- static bool Optimize = true;
- static bool VerifyClsCompliance = true;
-
- static string win32IconFile;
- static bool want_debugging_support = false;
- static bool Checked = false;
- static bool WarningsAreErrors;
- static Dictionary<string,string> embedded_resources = new Dictionary<string,string> ();
- static List<string> references = new List<string> ();
- static List<string> warning_as_error = new List<string> ();
- static int WarningLevel = 4;
- static List<int> ignore_warning = new List<int> ();
- static bool load_default_config = true;
- static string StrongNameKeyFile;
- static string StrongNameKeyContainer;
- static bool StrongNameDelaySign = false;
- static LanguageVersion Version = LanguageVersion.Default;
- static string CodePage;
-
- static readonly char[] argument_value_separator = new char [] { ';', ',' };
+ 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 ()
{
Console.WriteLine ("Invalid argument");
}
+
+ static string template;
+ static MsbuildGenerator ()
+ {
+ using (var input = new StreamReader ("csproj.tmpl")){
+ 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;
+
+ public MsbuildGenerator (string dir)
+ {
+ this.dir = dir;
+
+ 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;
+ }
+ }
+ // Currently used
+ bool Unsafe = false;
+ StringBuilder defines = new StringBuilder ();
+ bool StdLib = true;
+
+ // Currently unused
+ Target Target = Target.Exe;
+ string TargetExt = ".exe";
+ string OutputFile;
+ bool Optimize = true;
+ bool VerifyClsCompliance = true;
+
+ string win32IconFile;
+ bool want_debugging_support = false;
+ bool Checked = false;
+ bool WarningsAreErrors;
+ Dictionary<string,string> embedded_resources = new Dictionary<string,string> ();
+ List<string> references = new List<string> ();
+ List<string> reference_aliases = new List<string> ();
+ List<string> warning_as_error = new List<string> ();
+ int WarningLevel = 4;
+ List<int> ignore_warning = new List<int> ();
+ bool load_default_config = true;
+ string StrongNameKeyFile;
+ string StrongNameKeyContainer;
+ bool StrongNameDelaySign = false;
+ LanguageVersion Version = LanguageVersion.Default;
+ string CodePage;
+
+ readonly char[] argument_value_separator = new char [] { ';', ',' };
+
//
// This parses the -arg and /arg options to the compiler, even if the strings
// in the following text use "/arg" on the strings.
//
- static bool CSCParseOption (string option, ref string [] args)
+ bool CSCParseOption (string option, ref string [] args)
{
int idx = option.IndexOf (':');
string arg, value;
string val = r;
int index = val.IndexOf ('=');
if (index > -1) {
- Console.WriteLine ("/reference = not supported");
- Environment.Exit (1);
- //string alias = r.Substring (0, index);
- //string assembly = r.Substring (index + 1);
- //AddExternAlias (alias, assembly);
- //return true;
+ reference_aliases.Add (r);
+ continue;
}
if (val.Length != 0)
case "/doc":
case "/lib":
{
- Console.WriteLine ("{0} = not supported", option);
- Environment.Exit (1);
- return true;
+ Console.WriteLine ("{0} = not supported", arg);
+ throw new Exception ();
}
case "/win32icon": {
win32IconFile = value;
return false;
}
- static string FindMcsRoot ()
+ static string [] LoadArgs (string file)
{
- string p = Path.GetFullPath (".");
- string steps = "";
-
- while (p != Path.GetPathRoot (p)){
- if (Directory.Exists (Path.Combine (p, "jay")) &&
- Directory.Exists (Path.Combine (p, "ilasm")))
- return steps;
-
- p = Path.GetFullPath (Path.Combine (p, ".."));
- steps = Path.Combine (steps, "..");
+ StreamReader f;
+ var args = new List<string> ();
+ string line;
+ try {
+ f = new StreamReader (file);
+ } catch {
+ return null;
}
- Console.WriteLine ("Can not detect the root of MCS");
- Environment.Exit (1);
- return null;
+
+ StringBuilder sb = new StringBuilder ();
+
+ while ((line = f.ReadLine ()) != null){
+ int t = line.Length;
+
+ for (int i = 0; i < t; i++){
+ char c = line [i];
+
+ if (c == '"' || c == '\''){
+ char end = c;
+
+ for (i++; i < t; i++){
+ c = line [i];
+
+ if (c == end)
+ break;
+ sb.Append (c);
+ }
+ } else if (c == ' '){
+ if (sb.Length > 0){
+ args.Add (sb.ToString ());
+ sb.Length = 0;
+ }
+ } else
+ sb.Append (c);
+ }
+ if (sb.Length > 0){
+ args.Add (sb.ToString ());
+ sb.Length = 0;
+ }
+ }
+
+ string [] ret_value = new string [args.Count];
+ args.CopyTo (ret_value, 0);
+
+ return ret_value;
}
- static string FindClassRoot ()
+ static string Load (string f)
{
- string p = Path.GetFullPath (".");
- string steps = "";
-
- while (p != Path.GetPathRoot (p)){
- if (Directory.Exists (Path.Combine (p, "corlib")) &&
- Directory.Exists (Path.Combine (p, "Managed.Windows.Forms")))
- return steps;
-
- p = Path.GetFullPath (Path.Combine (p, ".."));
- steps = Path.Combine (steps, "..");
- }
- Console.WriteLine ("Can not detect the mcs/class directory");
- Environment.Exit (1);
- return null;
+ if (File.Exists (f)){
+ using (var sr = new StreamReader (f)){
+ return sr.ReadToEnd ();
+ }
+ } else
+ return "";
}
-
- static void Main (string [] args)
+
+ public string Generate (XElement xproject)
{
- if (args.Length != 2){
- Console.WriteLine ("You must specify the template file and the output file");
- return;
- }
-
+ string library = xproject.Attribute ("library").Value;
string boot, mcs, flags, output_name, built_sources, library_output, response;
- boot = read ();
- mcs = read ();
- flags = read ();
- output_name = read ();
- built_sources = read ();
- library_output = read ();
- response = read ();
+ 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;
- string [] f = flags.Split ();
- for (int i = 0; i < f.Length; i++){
- if (f [i][0] == '-')
- f [i] = "/" + f [i].Substring (1);
+ //
+ // Prebuild code, might be in inputs, check:
+ // inputs/LIBRARY-PROFILE.pre
+ // inputs/LIBRARY.pre
+ //
+ string prebuild = Load (library + ".pre");
- if (CSCParseOption (f [i], ref f))
- continue;
- Console.WriteLine ("Failure with {0}", f [i]);
- Environment.Exit (1);
- }
+ 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){
+ string [] f = all_args.Dequeue ();
+
+ for (int i = 0; i < f.Length; i++){
+ if (f [i][0] == '-')
+ f [i] = "/" + f [i].Substring (1);
+
+ if (f [i][0] == '@') {
+ string [] extra_args;
+ string response_file = f [i].Substring (1);
+
+ extra_args = LoadArgs (base_dir + "\\" + response_file);
+ if (extra_args == null) {
+ Console.WriteLine ("Unable to open response file: " + response_file);
+ Environment.Exit (1);
+ }
+ all_args.Enqueue (extra_args);
+ continue;
+ }
+
+ if (CSCParseOption (f [i], ref f))
+ continue;
+ Console.WriteLine ("Failure with {0}", f [i]);
+ Environment.Exit (1);
+ }
+ }
+
string [] source_files;
- using (var reader = new StreamReader (response)){
+ using (var reader = new StreamReader (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 ("/", "\\")));
+ }
+ foreach (string s in built_sources.Split ()){
+ if (s.Length == 0)
+ continue;
+
+ sources.Append (String.Format (" <Compile Include=\"{0}\" />\n", s.Replace ("/", "\\")));
}
- var input = new StreamReader (args [0]);
- string template = input.ReadToEnd ();
-
//
// Compute the csc command that we need to use
//
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";
+ if (compiler.EndsWith ("class/lib/basic/gmcs.exe"))
+ compiler = "gmcs";
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 if (compiler.EndsWith ("class/lib/moonlight_bootstrap/smcs.exe"))
+ compiler = "moonlight_bootstrap";
+ else if (compiler.EndsWith ("class/lib/moonlight_raw/smcs.exe"))
+ compiler = "moonlight_raw";
+ else if (compiler.EndsWith ("class/lib/net_4_0_bootstrap/dmcs.exe"))
+ compiler = "net_4_0_bootstrap";
+ else if (compiler.EndsWith ("class/lib/net_4_0/dmcs.exe"))
+ compiler = "dmcs";
else {
Console.WriteLine ("Can not determine compiler from {0}", compiler);
Environment.Exit (1);
}
var encoded_mono_paths = string.Join ("-", mono_paths).Replace ("--", "-");
-
- Console.WriteLine ("The root is at {0}", FindMcsRoot ());
- string csc_tool_path = FindMcsRoot ().Replace ("/", "\\") + "\\..\\mono\\msvc\\scripts\\" + encoded_mono_paths + "-" + compiler;
- csc_tool_path = csc_tool_path.Replace ("--", "-");
-
+ var encoded_mp_compiler = (encoded_mono_paths + "-" + compiler).Replace ("--", "-");
+
+ string csc_tool_path = mcs_topdir + "..\\mono\\msvc\\scripts\\" + encoded_mp_compiler;
+ if (!Directory.Exists (encoded_mp_compiler)){
+ Console.WriteLine ("Created {0}", encoded_mp_compiler);
+ Directory.CreateDirectory (encoded_mp_compiler);
+ }
+ if (!File.Exists (Path.Combine (encoded_mp_compiler, "csc.exe"))){
+ File.Copy ("monowrap.exe", Path.Combine (encoded_mp_compiler, "csc.exe"));
+ File.Copy ("monowrap.pdb", Path.Combine (encoded_mp_compiler, "csc.pdb"));
+ }
+
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){
+ if (references.Count > 0 || reference_aliases.Count > 0){
refs.Append ("<ItemGroup>\n");
- string class_root = FindClassRoot ();
string last = mono_paths [0].Substring (mono_paths [0].LastIndexOf ('/') + 1);
- string hint_path = FindClassRoot () + "\\lib\\" + last;
-
+ string hint_path = class_dir + "\\lib\\" + last;
+
foreach (string r in references){
refs.Append (" <Reference Include=\"" + r + "\">\n");
refs.Append (" <SpecificVersion>False</SpecificVersion>\n");
refs.Append (" <HintPath>" + hint_path + "\\" + r + "</HintPath>\n");
refs.Append (" </Reference>\n");
}
+
+ foreach (string r in reference_aliases){
+ int index = r.IndexOf ('=');
+ string alias = r.Substring (0, index);
+ string assembly = r.Substring (index + 1);
+
+ refs.Append (" <Reference Include=\"" + assembly + "\">\n");
+ refs.Append (" <SpecificVersion>False</SpecificVersion>\n");
+ refs.Append (" <HintPath>" + hint_path + "\\" + r + "</HintPath>\n");
+ refs.Append (" <Aliases>" + alias + "</Aliases>\n");
+ refs.Append (" </Reference>\n");
+ }
refs.Append (" </ItemGroup>\n");
}
+
+ try {
+ Path.GetDirectoryName (library_output);
+ } catch {
+ Console.WriteLine ("Error in path: {0} while processing {1}", library_output, library);
+ }
//
// Replace the template values
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 ("@SOURCES@", sources.ToString ());
- using (var o = new StreamWriter (args [1])){
+
+ 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;
}
-}
\ No newline at end of file
+
+}
+
+public class Driver {
+
+ static void Main (string [] args)
+ {
+ if (!File.Exists ("genproj.cs") || !File.Exists ("monowrap.cs")){
+ Console.WriteLine ("This command should be ran from mono/msvc/scripts");
+ Environment.Exit (1);
+ }
+
+ 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;
+
+ //
+ // 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"))
+ continue;
+
+ var gen = new MsbuildGenerator (dir);
+ try {
+ sln_gen.Add (gen.Generate (project));
+ } catch (Exception e) {
+ Console.WriteLine ("Error in {0}\n{1}", dir, e);
+ }
+ }
+ sln_gen.Write ("mcs_full.sln");
+ }
+
+}