X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=msvc%2Fscripts%2Fgenproj.cs;h=96337cadaaff450ce4e4e274987a19063fbedc2b;hb=43e9ddc1fcddb632fc1e661495e468a2ebdf6fec;hp=6f134efec932ec36a1d5f5432f2e35a8d557963e;hpb=44db1f2e8fafc44480d813bdad27ff48974311ea;p=mono.git diff --git a/msvc/scripts/genproj.cs b/msvc/scripts/genproj.cs index 6f134efec93..96337cadaaf 100644 --- a/msvc/scripts/genproj.cs +++ b/msvc/scripts/genproj.cs @@ -1,3 +1,16 @@ +// +// Consumes the order.xml file that contains a list of all the assemblies to build +// and produces a solution and the csproj files for it +// +// Currently this hardcodes a set of assemblies to build, the net-4.x series, but +// it can be extended to handle the command line tools. +// +// KNOWN ISSUES: +// * This fails to find matches for "System" and "System.xml" when processing the +// RabbitMQ executable, likely, because we do not process executables yet +// +// * Has not been tested in a while with the command line tools +// using System; using System.IO; using System.Collections.Generic; @@ -57,11 +70,15 @@ class SlnGenerator { public void Write (string filename) { + var fullPath = Path.GetDirectoryName (filename) + "/"; + using (var sln = new StreamWriter (filename)) { sln.WriteLine (); sln.WriteLine (header); foreach (var proj in libraries) { - sln.WriteLine (project_start, proj.library, proj.csProjFilename, proj.projectGuid); + var unixProjFile = proj.csProjFilename.Replace ("\\", "/"); + var fullProjPath = Path.GetFullPath (unixProjFile); + sln.WriteLine (project_start, proj.library, MsbuildGenerator.GetRelativePath (fullPath, fullProjPath), proj.projectGuid); sln.WriteLine (project_end); } sln.WriteLine ("Global"); @@ -190,6 +207,7 @@ class MsbuildGenerator { StringBuilder defines = new StringBuilder (); bool Optimize = true; bool want_debugging_support = false; + string main = null; Dictionary embedded_resources = new Dictionary (); List warning_as_error = new List (); List ignore_warning = new List (); @@ -198,7 +216,7 @@ class MsbuildGenerator { List references = new List (); List libs = new List (); List reference_aliases = new List (); - bool showWarnings = false; + bool showWarnings = true; // Currently unused #pragma warning disable 0219, 0414 @@ -210,7 +228,7 @@ class MsbuildGenerator { string win32IconFile; string StrongNameKeyFile; bool copyLocal = true; - Target Target = Target.Exe; + Target Target = Target.Library; string TargetExt = ".exe"; string OutputFile; string StrongNameKeyContainer; @@ -373,6 +391,9 @@ class MsbuildGenerator { return true; } case "/main": + main = value; + return true; + case "/m": case "/addmodule": case "/win32res": @@ -540,6 +561,15 @@ class MsbuildGenerator { CodePage = value; return true; + case "/publicsign": + return true; + + case "/deterministic": + return true; + + case "/runtimemetadataversion": + return true; + case "/-getresourcestrings": return true; } @@ -630,19 +660,29 @@ class MsbuildGenerator { public VsCsproj Csproj; - public VsCsproj Generate (Dictionary projects, bool showWarnings = false) + void AppendResource (StringBuilder resources, string source, string logical) + { + resources.AppendFormat (" " + NewLine, source); + resources.AppendFormat (" {0}" + NewLine, logical); + resources.AppendFormat (" " + NewLine); + } + + public VsCsproj Generate (string library_output, Dictionary projects, bool showWarnings = false) { var generatedProjFile = NativeName (Csproj.csProjFilename); //Console.WriteLine ("Generating: {0}", generatedProjFile); - string boot, flags, output_name, built_sources, response, profile; + string boot, flags, output_name, built_sources, response, profile, reskey; boot = xproject.Element ("boot").Value; flags = xproject.Element ("flags").Value; output_name = xproject.Element ("output").Value; + if (output_name.EndsWith (".exe")) + Target = Target.Exe; built_sources = xproject.Element ("built_sources").Value; response = xproject.Element ("response").Value; - //if (library.EndsWith("-build")) fx_version = "2.0"; // otherwise problem if .NET4.5 is installed, seems. (https://github.com/nikhilk/scriptsharp/issues/156) + reskey = xproject.Element ("resources").Value; + profile = xproject.Element ("profile").Value; if (string.IsNullOrEmpty (response)) { // Address the issue where entries are missing the fx_version @@ -670,29 +710,10 @@ class MsbuildGenerator { } // // Prebuild code, might be in inputs, check: - // inputs/LIBRARY-PROFILE.pre // inputs/LIBRARY.pre // - string prebuild = Load (library + ".pre"); - string prebuild_windows, prebuild_unix; - - int q = library.IndexOf ("-"); - if (q != -1) - prebuild = prebuild + Load (library.Substring (0, q) + ".pre"); - - if (prebuild.IndexOf ("@MONO@") != -1){ - prebuild_unix = prebuild.Replace ("@MONO@", "mono").Replace ("@CAT@", "cat"); - prebuild_windows = prebuild.Replace ("@MONO@", "").Replace ("@CAT@", "type"); - } else { - prebuild_unix = prebuild.Replace ("jay.exe", "jay"); - prebuild_windows = prebuild; - } - - const string condition_unix = "Condition=\" '$(OS)' != 'Windows_NT' \""; - const string condition_windows = "Condition=\" '$(OS)' == 'Windows_NT' \""; - prebuild = - " " + NewLine + prebuild_unix + NewLine + " " + NewLine + - " " + NewLine + prebuild_windows + NewLine + " " + NewLine; + string prebuild = GenerateStep (library, ".pre", "PreBuildEvent"); + string postbuild = GenerateStep (library, ".post", "PostBuildEvent"); var all_args = new Queue (); all_args.Enqueue (flags.Split ()); @@ -710,7 +731,7 @@ class MsbuildGenerator { var resp_file_full = Path.Combine (base_dir, response_file); extra_args = LoadArgs (resp_file_full); if (extra_args == null) { - Console.WriteLine ("Unable to open response file: " + resp_file_full); + Console.WriteLine ($"{library_output}: Unable to open response file: {resp_file_full}"); Environment.Exit (1); } @@ -720,13 +741,12 @@ class MsbuildGenerator { if (CSCParseOption (f [i], ref f)) continue; - Console.WriteLine ("Failure with {0}", f [i]); + Console.WriteLine ("{library_output}: Failure with {0}", f [i]); Environment.Exit (1); } } string [] source_files; - //Console.WriteLine ("Base: {0} res: {1}", base_dir, response); using (var reader = new StreamReader (NativeName (base_dir + "\\" + response))) { source_files = reader.ReadToEnd ().Split (); } @@ -774,25 +794,49 @@ class MsbuildGenerator { var refs = new StringBuilder (); - bool is_test = response.Contains ("_test_"); - if (is_test) { - // F:\src\mono\mcs\class\lib\net_2_0\nunit.framework.dll - // F:\src\mono\mcs\class\SomeProject\SomeProject_test_-net_2_0.csproj - var nunitLibPath = string.Format (@"..\lib\{0}\nunit.framework.dll", profile); - refs.Append (string.Format (" " + NewLine, nunitLibPath)); + if (response.Contains ("_test")) { + refs.Append ($@" {NewLine}"); } + // + // Generate resource referenced from the command line + // var resources = new StringBuilder (); if (embedded_resources.Count > 0) { - resources.AppendFormat (" " + NewLine); foreach (var dk in embedded_resources) { - resources.AppendFormat (" " + NewLine, dk.Key); - resources.AppendFormat (" {0}" + NewLine, dk.Value); - resources.AppendFormat (" " + NewLine); + var source = dk.Key; + if (source.EndsWith (".resources")) + source = source.Replace (".resources", ".resx"); + + // try to find a pre-built resource, and use that instead of trying to build it + if (source.EndsWith (".resx")) { + var probe_prebuilt = Path.Combine (base_dir, source.Replace (".resx", ".resources.prebuilt")); + if (File.Exists (probe_prebuilt)) { + + source = GetRelativePath (base_dir + "/", probe_prebuilt); + } + } + AppendResource (resources, source, dk.Value); + } + } + // + // Generate resources that were part of the explicit node + // + if (reskey != null && reskey != ""){ + var pairs = reskey.Split (' ', '\n', '\t'); + foreach (var pair in pairs){ + var p = pair.IndexOf (","); + if (p == -1){ + Console.Error.WriteLine ($"Found a resource without a filename: {pairs} for {Csproj.csProjFilename}"); + Environment.Exit (1); + } + AppendResource (resources, pair.Substring (p+1), pair.Substring (0, p) + ".resources"); } + } + if (resources.Length > 0){ + resources.Insert (0, " " + NewLine); resources.AppendFormat (" " + NewLine); } - if (references.Count > 0 || reference_aliases.Count > 0) { // -r:mscorlib.dll -r:System.dll @@ -805,18 +849,19 @@ class MsbuildGenerator { // System-basic // var refdistinct = references.Distinct (); - foreach (string r in refdistinct) { - var match = GetMatchingCsproj (Path.GetFileName (r), projects); + foreach (string reference in refdistinct) { + + var match = GetMatchingCsproj (library_output, reference, projects); if (match != null) { - AddProjectReference (refs, Csproj, match, r, null); + AddProjectReference (refs, Csproj, match, reference, null); } else { if (showWarnings){ - Console.WriteLine ("{0}: Could not find a matching project reference for {1}", library, Path.GetFileName (r)); + Console.WriteLine ("{0}: Could not find a matching project reference for {1}", library, Path.GetFileName (reference)); Console.WriteLine (" --> Adding reference with hintpath instead"); } - refs.Append (" " + NewLine); + refs.Append (" " + NewLine); refs.Append (" False" + NewLine); - refs.Append (" " + r + "" + NewLine); + refs.Append (" " + reference + "" + NewLine); refs.Append (" False" + NewLine); refs.Append (" " + NewLine); } @@ -826,7 +871,7 @@ class MsbuildGenerator { int index = r.IndexOf ('='); string alias = r.Substring (0, index); string assembly = r.Substring (index + 1); - var match = GetMatchingCsproj (assembly, projects, explicitPath: true); + var match = GetMatchingCsproj (library_output, assembly, projects, explicitPath: true); if (match != null) { AddProjectReference (refs, Csproj, match, r, alias); } else { @@ -850,15 +895,12 @@ class MsbuildGenerator { build_output_dir = Path.GetDirectoryName (LibraryOutput); else build_output_dir = "bin\\Debug\\" + library; - - - string postbuild_unix = string.Empty; - string postbuild_windows = string.Empty; - var postbuild = - " " + NewLine + postbuild_unix + NewLine + " " + NewLine + - " " + NewLine + postbuild_windows + NewLine + " "; - + if (build_output_dir.Contains ("-linux") || build_output_dir.Contains ("-darwin") || build_output_dir.Contains ("-win32")) + build_output_dir = build_output_dir + .Replace ("-linux", "-$(HostPlatform)") + .Replace ("-darwin", "-$(HostPlatform)") + .Replace ("-win32", "-$(HostPlatform)"); bool basic_or_build = (library.Contains ("-basic") || library.Contains ("-build")); @@ -869,15 +911,13 @@ class MsbuildGenerator { string strongNameSection = ""; if (StrongNameKeyFile != null){ strongNameSection = String.Format ( - " " + NewLine + " true" + NewLine + "{1}" + - " " + NewLine + - " " + NewLine + - " {0}" + NewLine + - " ", StrongNameKeyFile, StrongNameDelaySign ? " true" + NewLine : ""); + " {0}", + StrongNameKeyFile, StrongNameDelaySign ? " true" + NewLine : ""); } Csproj.output = template. + Replace ("@OUTPUTTYPE@", Target == Target.Library ? "Library" : "Exe"). Replace ("@SIGNATURE@", strongNameSection). Replace ("@PROJECTGUID@", Csproj.projectGuid). Replace ("@DEFINES@", defines.ToString ()). @@ -889,12 +929,14 @@ class MsbuildGenerator { Replace ("@FX_VERSION", fx_version). Replace ("@ASSEMBLYNAME@", Path.GetFileNameWithoutExtension (output_name)). Replace ("@OUTPUTDIR@", build_output_dir). + Replace ("@OUTPUTSUFFIX@", Path.GetFileName (build_output_dir)). Replace ("@DEFINECONSTANTS@", defines.ToString ()). Replace ("@DEBUG@", want_debugging_support ? "true" : "false"). Replace ("@DEBUGTYPE@", want_debugging_support ? "full" : "pdbonly"). Replace ("@REFERENCES@", refs.ToString ()). Replace ("@PREBUILD@", prebuild). Replace ("@POSTBUILD@", postbuild). + Replace ("@STARTUPOBJECT@", main == null ? "" : $"{main}"). //Replace ("@ADDITIONALLIBPATHS@", String.Format ("{0}", string.Join (",", libs.ToArray ()))). Replace ("@ADDITIONALLIBPATHS@", String.Empty). Replace ("@RESOURCES@", resources.ToString ()). @@ -909,6 +951,34 @@ class MsbuildGenerator { return Csproj; } + string GenerateStep (string library, string suffix, string eventKey) + { + string target = Load (library + suffix); + string target_windows, target_unix; + + int q = library.IndexOf ("-"); + if (q != -1) + target = target + Load (library.Substring (0, q) + suffix); + + if (target.IndexOf ("@MONO@") != -1){ + target_unix = target.Replace ("@MONO@", "mono").Replace ("@CAT@", "cat"); + target_windows = target.Replace ("@MONO@", "").Replace ("@CAT@", "type"); + } else { + target_unix = target.Replace ("jay.exe", "jay"); + target_windows = target; + } + target_unix = target_unix.Replace ("@COPY@", "cp"); + target_windows = target_unix.Replace ("@COPY@", "copy"); + + target_unix = target_unix.Replace ("\r", ""); + const string condition_unix = "Condition=\" '$(OS)' != 'Windows_NT' \""; + const string condition_windows = "Condition=\" '$(OS)' == 'Windows_NT' \""; + var result = + $" <{eventKey} {condition_unix}>\n{target_unix}\n {NewLine}" + + $" <{eventKey} {condition_windows}>{NewLine}{target_windows}{NewLine} "; + return result; + } + void AddProjectReference (StringBuilder refs, VsCsproj result, MsbuildGenerator match, string r, string alias) { refs.AppendFormat (" {1}", GetRelativePath (result.csProjFilename, match.CsprojFilename), NewLine); @@ -932,35 +1002,41 @@ class MsbuildGenerator { return ret; } - MsbuildGenerator GetMatchingCsproj (string dllReferenceName, Dictionary projects, bool explicitPath = false) + MsbuildGenerator GetMatchingCsproj (string library_output, string dllReferenceName, Dictionary projects, bool explicitPath = false) { // libDir would be "./../../class/lib/net_4_x for example // project - if (!dllReferenceName.EndsWith (".dll")) + if (!dllReferenceName.EndsWith (".dll") && !dllReferenceName.EndsWith (".exe")) dllReferenceName += ".dll"; - if (explicitPath){ - var probe = Path.GetFullPath (Path.Combine (base_dir, dllReferenceName)); - foreach (var project in projects){ - if (probe == project.Value.AbsoluteLibraryOutput) - return project.Value; - } - } + var probe = Path.GetFullPath (Path.Combine (base_dir, dllReferenceName)); + foreach (var project in projects){ + if (probe == project.Value.AbsoluteLibraryOutput) + return project.Value; + } // not explicit, search for the library in the lib path order specified foreach (var libDir in libs) { var abs = Path.GetFullPath (Path.Combine (base_dir, libDir)); foreach (var project in projects){ - var probe = Path.Combine (abs, dllReferenceName); + probe = Path.Combine (abs, dllReferenceName); if (probe == project.Value.AbsoluteLibraryOutput) return project.Value; } } - Console.WriteLine ("Did not find referenced {0} with libs={1}", dllReferenceName, String.Join (", ", libs)); + + // Last attempt, try to find the library in all the projects + foreach (var project in projects) { + if (project.Value.AbsoluteLibraryOutput.EndsWith (dllReferenceName)) + return project.Value; + + } + var ljoined = String.Join (", ", libs); + Console.WriteLine ($"{library_output}: did not find referenced {dllReferenceName} with libs={ljoined}"); foreach (var p in projects) { - Console.WriteLine (" => {0}", p.Value.AbsoluteLibraryOutput); + Console.WriteLine ("{0}", p.Value.AbsoluteLibraryOutput); } return null; } @@ -969,7 +1045,7 @@ class MsbuildGenerator { public class Driver { - static IEnumerable GetProjects (bool full = false) + static IEnumerable GetProjects (bool withTests = false) { XDocument doc = XDocument.Load ("order.xml"); foreach (XElement project in doc.Root.Elements ()) { @@ -977,18 +1053,21 @@ public class Driver { string library = project.Attribute ("library").Value; var profile = project.Element ("profile").Value; +#if false + // Skip facades for now, the tool doesn't know how to deal with them yet. + if (dir.Contains ("Facades")) + continue; + + // These are currently broken, skip until they're fixed. + if (dir.StartsWith ("mcs") || dir.Contains ("apigen")) + continue; + // // Do only class libraries for now // if (!(dir.StartsWith ("class") || dir.StartsWith ("mcs") || dir.StartsWith ("basic"))) continue; - - if (full){ - if (!library.Contains ("tests")) - yield return project; - continue; - } - +#endif // // 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). @@ -999,7 +1078,16 @@ public class Driver { // The next ones are to make debugging easier for now if (profile == "basic") continue; - if (profile != "net_4_x" || library.Contains ("tests")) + + // For now -- problem is, our resolver currently only considers the assembly name, and we ahve + // conflicing 2.0 and 2.4 versions so for now, we just skip the nunit20 versions + if (dir.Contains ("nunit20")) + continue; + + if (library.Contains ("tests") && !withTests) + continue; + + if (profile != "net_4_x") continue; yield return project; @@ -1015,12 +1103,12 @@ public class Driver { if (args.Length == 1 && args [0].ToLower ().Contains ("-h")) { Console.WriteLine ("Usage:"); - Console.WriteLine ("genproj.exe [visual_studio_release] [output_full_solutions]"); + Console.WriteLine ("genproj.exe [visual_studio_release] [output_full_solutions] [with_tests]"); Console.WriteLine ("If output_full_solutions is false, only the main System*.dll"); Console.WriteLine (" assemblies (and dependencies) is included in the solution."); Console.WriteLine ("Example:"); - Console.WriteLine ("genproj.exe 2012 false"); - Console.WriteLine ("genproj.exe with no arguments is equivalent to 'genproj.exe 2012 true'\n\n"); + Console.WriteLine ("genproj.exe 2012 false false"); + Console.WriteLine ("genproj.exe with no arguments is equivalent to 'genproj.exe 2012 true false'\n\n"); Console.WriteLine ("genproj.exe deps"); Console.WriteLine ("Generates a Makefile dependency file from the projects input"); Environment.Exit (0); @@ -1028,6 +1116,7 @@ public class Driver { var slnVersion = (args.Length > 0) ? args [0] : "2012"; bool fullSolutions = (args.Length > 1) ? bool.Parse (args [1]) : true; + bool withTests = (args.Length > 2) ? bool.Parse (args [2]) : false; // To generate makefile depenedencies var makefileDeps = (args.Length > 0 && args [0] == "deps"); @@ -1037,15 +1126,16 @@ public class Driver { var projects = new Dictionary (); var duplicates = new List (); - foreach (var project in GetProjects (makefileDeps)) { + foreach (var project in GetProjects (withTests)) { var library_output = project.Element ("library_output").Value; projects [library_output] = new MsbuildGenerator (project); } - foreach (var project in GetProjects (makefileDeps)){ + foreach (var project in GetProjects (withTests)){ var library_output = project.Element ("library_output").Value; + //Console.WriteLine ("=== {0} ===", library_output); var gen = projects [library_output]; try { - var csproj = gen.Generate (projects); + var csproj = gen.Generate (library_output, projects); var csprojFilename = csproj.csProjFilename; if (!sln_gen.ContainsProjectIdentifier (csproj.library)) { sln_gen.Add (csproj); @@ -1063,14 +1153,16 @@ public class Driver { FillSolution (four_five_sln_gen, MsbuildGenerator.profile_4_x, projects.Values, additionalFilter); - var sb = new StringBuilder (); - sb.AppendLine ("WARNING: Skipped some project references, apparent duplicates in order.xml:"); - foreach (var item in duplicates) { - sb.AppendLine (item); + if (duplicates.Count () > 0) { + var sb = new StringBuilder (); + sb.AppendLine ("WARNING: Skipped some project references, apparent duplicates in order.xml:"); + foreach (var item in duplicates) { + sb.AppendLine (item); + } + Console.WriteLine (sb.ToString ()); } - Console.WriteLine (sb.ToString ()); - WriteSolution (four_five_sln_gen, MakeSolutionName (MsbuildGenerator.profile_4_x)); + WriteSolution (four_five_sln_gen, Path.Combine ("..", "..", MakeSolutionName (MsbuildGenerator.profile_4_x))); if (makefileDeps){ const string classDirPrefix = "./../../"; @@ -1094,7 +1186,7 @@ public class Driver { // A few other optional solutions // Solutions with 'everything' and the most common libraries used in development may be of interest - //WriteSolution (sln_gen, "mcs_full.sln"); + //WriteSolution (sln_gen, "./mcs_full.sln"); //WriteSolution (small_full_sln_gen, "small_full.sln"); // The following may be useful if lacking visual studio or MonoDevelop, to bootstrap mono compiler self-hosting //WriteSolution (basic_sln_gen, "mcs_basic.sln");