Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Köplinger <alex.koeplinger@outlook.com>2018-03-24 01:56:02 +0300
committerGitHub <noreply@github.com>2018-03-24 01:56:02 +0300
commit506fc0b522fde4d71621c94cb6495c07c07f720b (patch)
tree4231feb331a3b0309173938f205c5f628ac963a2 /msvc/scripts
parent331f3d9f27e667e31ffddac26644b24e76f0e11c (diff)
[genproj] Deduplication of sources (#7810)
This implements a simple deduplication of source files in the .csproj's. A postprocessing step opens the files and grabs all ItemGroups with sources and then does an intersection. It then moves files that are common across all platforms into a separate ItemGroup.
Diffstat (limited to 'msvc/scripts')
-rw-r--r--msvc/scripts/csproj.tmpl1
-rw-r--r--msvc/scripts/genproj.cs86
2 files changed, 87 insertions, 0 deletions
diff --git a/msvc/scripts/csproj.tmpl b/msvc/scripts/csproj.tmpl
index 32f186fd228..4ca9b2be8b3 100644
--- a/msvc/scripts/csproj.tmpl
+++ b/msvc/scripts/csproj.tmpl
@@ -51,6 +51,7 @@
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+<!-- @COMMON_SOURCES@ -->
<!-- @ALL_SOURCES@ -->
<!-- @ALL_REFERENCES@ -->
diff --git a/msvc/scripts/genproj.cs b/msvc/scripts/genproj.cs
index 47d1fabccac..7efbaa446b9 100644
--- a/msvc/scripts/genproj.cs
+++ b/msvc/scripts/genproj.cs
@@ -1337,6 +1337,12 @@ public class Driver {
}
}
+ foreach (var csprojFile in projects.Values.Select (x => x.GetProjectFilename ()).Distinct ())
+ {
+ Console.WriteLine ("Deduplicating: " + csprojFile);
+ DeduplicateSources (csprojFile);
+ }
+
Func<MsbuildGenerator.VsCsproj, bool> additionalFilter;
additionalFilter = fullSolutions ? (Func<MsbuildGenerator.VsCsproj, bool>)null : IsCommonLibrary;
@@ -1382,6 +1388,86 @@ public class Driver {
//WriteSolution (build_sln_gen, "mcs_build.sln");
}
+ static void DeduplicateSources (string csprojFilename)
+ {
+ XmlDocument doc = new XmlDocument ();
+ doc.Load (csprojFilename);
+ XmlNamespaceManager mgr = new XmlNamespaceManager (doc.NameTable);
+ mgr.AddNamespace ("x", "http://schemas.microsoft.com/developer/msbuild/2003");
+
+ XmlNode root = doc.DocumentElement;
+ var allSources = new Dictionary<string, List<string>> ();
+
+ // grab all sources across all platforms
+ ProcessCompileItems (mgr, root, (source, platform) =>
+ {
+ if (!allSources.ContainsKey (platform))
+ allSources[platform] = new List<string> ();
+ allSources[platform].Add (source.Attributes["Include"].Value);
+ });
+
+ if (allSources.Count > 1)
+ {
+ // find the sources which are common across all platforms
+ var commonSources = allSources.Values.First ();
+ foreach (var l in allSources.Values.Skip (1))
+ commonSources = commonSources.Intersect (l).ToList ();
+
+ if (commonSources.Count > 0)
+ {
+ // remove common sources from the individual platforms
+ ProcessCompileItems (mgr, root, (source, platform) =>
+ {
+ var parent = source.ParentNode;
+ if (commonSources.Contains (source.Attributes["Include"].Value))
+ parent.RemoveChild (source);
+
+ if (!parent.HasChildNodes)
+ parent.ParentNode.RemoveChild (parent);
+ });
+
+ // add common sources as ItemGroup
+ XmlNode commonSourcesComment = root.SelectSingleNode ("//comment()[. = ' @COMMON_SOURCES@ ']");
+ XmlElement commonSourcesElement = doc.CreateElement ("ItemGroup", root.NamespaceURI);
+
+ foreach (var s in commonSources)
+ {
+ var c = doc.CreateElement ("Compile", root.NamespaceURI);
+ var v = doc.CreateAttribute ("Include");
+ v.Value = s;
+ c.Attributes.Append (v);
+
+ commonSourcesElement.AppendChild (c);
+ }
+ root.ReplaceChild (commonSourcesElement, commonSourcesComment);
+ }
+ }
+
+ doc.Save (csprojFilename);
+ }
+
+ static void ProcessCompileItems (XmlNamespaceManager mgr, XmlNode x, Action<XmlNode, string> action)
+ {
+ foreach (XmlNode n in x.SelectNodes("//x:ItemGroup[@Condition]", mgr))
+ {
+ if (n.Attributes.Count == 0)
+ continue;
+
+ var platform = n.Attributes["Condition"].Value;
+
+ if (!platform.Contains("$(Platform)"))
+ continue;
+
+ var compileItems = n.SelectNodes("./x:Compile[@Include]", mgr);
+
+ if (compileItems.Count == 0)
+ continue;
+
+ foreach (XmlNode source in compileItems)
+ action(source, platform);
+ }
+ }
+
// Rebases a path, assuming that execution is taking place in the "class" subdirectory,
// so it strips ../class/ from a path, which is a no-op
static string RebaseToClassDirectory (string path)