Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / msvc / scripts / genproj.cs
index 60c66680b662b862af21bb86fa01597a91e7d203..96337cadaaff450ce4e4e274987a19063fbedc2b 100644 (file)
@@ -563,7 +563,13 @@ class MsbuildGenerator {
 
                case "/publicsign":
                        return true;
-                       
+
+               case "/deterministic":
+                       return true;
+
+               case "/runtimemetadataversion":
+                       return true;
+
                case "/-getresourcestrings":
                        return true;
                }
@@ -654,12 +660,19 @@ class MsbuildGenerator {
 
        public VsCsproj Csproj;
 
+       void AppendResource (StringBuilder resources, string source, string logical)
+       {
+               resources.AppendFormat ("    <EmbeddedResource Include=\"{0}\">" + NewLine, source);
+               resources.AppendFormat ("      <LogicalName>{0}</LogicalName>" + NewLine, logical);
+               resources.AppendFormat ("    </EmbeddedResource>" + NewLine);
+       }
+       
        public VsCsproj Generate (string library_output, Dictionary<string,MsbuildGenerator> 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;
@@ -668,6 +681,7 @@ class MsbuildGenerator {
                        Target = Target.Exe;
                built_sources = xproject.Element ("built_sources").Value;
                response = xproject.Element ("response").Value;
+               reskey = xproject.Element ("resources").Value;
 
                profile = xproject.Element ("profile").Value;
                if (string.IsNullOrEmpty (response)) {
@@ -696,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 =
-                       "    <PreBuildEvent " + condition_unix + ">\n" + prebuild_unix + "\n    </PreBuildEvent>" + NewLine +
-                       "    <PreBuildEvent " + condition_windows + ">" + NewLine + prebuild_windows + NewLine + "    </PreBuildEvent>" + NewLine;
+               string prebuild = GenerateStep (library, ".pre", "PreBuildEvent");
+               string postbuild = GenerateStep (library, ".post", "PostBuildEvent");
 
                var all_args = new Queue<string []> ();
                all_args.Enqueue (flags.Split ());
@@ -752,7 +747,6 @@ class MsbuildGenerator {
                }
 
                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 ();
                }
@@ -800,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 ("    <Reference Include=\"{0}\" />" + NewLine, nunitLibPath));
+               if (response.Contains ("_test")) {
+                       refs.Append ($@"    <Reference Include=""..\lib\{profile}\nunitlite.dll"" />{NewLine}");
                }
 
+               //
+               // Generate resource referenced from the command line
+               //
                var resources = new StringBuilder ();
                if (embedded_resources.Count > 0) {
-                       resources.AppendFormat ("  <ItemGroup>" + NewLine);
                        foreach (var dk in embedded_resources) {
-                               resources.AppendFormat ("    <EmbeddedResource Include=\"{0}\">" + NewLine, dk.Key);
-                               resources.AppendFormat ("      <LogicalName>{0}</LogicalName>" + NewLine, dk.Value);
-                               resources.AppendFormat ("    </EmbeddedResource>" + 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 <resource> 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, "  <ItemGroup>" + NewLine);
                        resources.AppendFormat ("  </ItemGroup>" + NewLine);
                }
-       
 
                if (references.Count > 0 || reference_aliases.Count > 0) {
                        // -r:mscorlib.dll -r:System.dll
@@ -877,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 =  
-                       "    <PostBuildEvent " + condition_unix + ">" + NewLine + postbuild_unix + NewLine + "    </PostBuildEvent>" + NewLine +
-                       "    <PostBuildEvent " + condition_windows + ">" + NewLine + postbuild_windows + NewLine + "    </PostBuildEvent>";
-                       
+               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"));
 
@@ -896,13 +911,10 @@ class MsbuildGenerator {
                string strongNameSection = "";
                if (StrongNameKeyFile != null){
                        strongNameSection = String.Format (
-                               "  <PropertyGroup>" + NewLine +
                                "    <SignAssembly>true</SignAssembly>" + NewLine +
                                "{1}" +
-                               "  </PropertyGroup>" + NewLine +
-                               "  <PropertyGroup>" + NewLine +
-                               "    <AssemblyOriginatorKeyFile>{0}</AssemblyOriginatorKeyFile>" + NewLine +
-                               "  </PropertyGroup>", StrongNameKeyFile, StrongNameDelaySign ? "    <DelaySign>true</DelaySign>" + NewLine : "");
+                               "    <AssemblyOriginatorKeyFile>{0}</AssemblyOriginatorKeyFile>",
+                               StrongNameKeyFile, StrongNameDelaySign ? "    <DelaySign>true</DelaySign>" + NewLine : "");
                }
                Csproj.output = template.
                        Replace ("@OUTPUTTYPE@", Target == Target.Library ? "Library" : "Exe").
@@ -923,8 +935,8 @@ class MsbuildGenerator {
                        Replace ("@DEBUGTYPE@", want_debugging_support ? "full" : "pdbonly").
                        Replace ("@REFERENCES@", refs.ToString ()).
                        Replace ("@PREBUILD@", prebuild).
-                       Replace ("@STARTUPOBJECT@", main == null ? "" : $"<StartupObject>{main}</StartupObject>").
                        Replace ("@POSTBUILD@", postbuild).
+                       Replace ("@STARTUPOBJECT@", main == null ? "" : $"<StartupObject>{main}</StartupObject>").
                        //Replace ("@ADDITIONALLIBPATHS@", String.Format ("<AdditionalLibPaths>{0}</AdditionalLibPaths>", string.Join (",", libs.ToArray ()))).
                        Replace ("@ADDITIONALLIBPATHS@", String.Empty).
                        Replace ("@RESOURCES@", resources.ToString ()).
@@ -939,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    </{eventKey}>{NewLine}" +
+                       $"    <{eventKey} {condition_windows}>{NewLine}{target_windows}{NewLine}    </{eventKey}>";
+               return result;
+       }
+       
        void AddProjectReference (StringBuilder refs, VsCsproj result, MsbuildGenerator match, string r, string alias)
        {
                refs.AppendFormat ("    <ProjectReference Include=\"{0}\">{1}", GetRelativePath (result.csProjFilename, match.CsprojFilename), NewLine);
@@ -1005,7 +1045,7 @@ class MsbuildGenerator {
 
 public class Driver {
 
-       static IEnumerable<XElement> GetProjects (bool full = false)
+       static IEnumerable<XElement> GetProjects (bool withTests = false)
        {
                XDocument doc = XDocument.Load ("order.xml");
                foreach (XElement project in doc.Root.Elements ()) {
@@ -1027,12 +1067,6 @@ public class Driver {
                        //
                        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
@@ -1050,11 +1084,12 @@ public class Driver {
                        if (dir.Contains ("nunit20"))
                                continue;
                        
-#if true
-                       if (profile != "net_4_x" || library.Contains ("tests")) 
+                       if (library.Contains ("tests") && !withTests)
                                continue;
-#endif
-                       //Console.WriteLine ("Going to handle {0}", library);
+
+                       if (profile != "net_4_x")
+                               continue;
+
                        yield return project;
                }
        }
@@ -1068,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);
@@ -1081,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");
@@ -1090,11 +1126,11 @@ public class Driver {
                var projects = new Dictionary<string,MsbuildGenerator> ();
 
                var duplicates = new List<string> ();
-               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];