From 9572e2a3e3c255d96ddc4a16b7f8819227b8ba5e Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Wed, 16 Nov 2016 17:42:12 -0500 Subject: [PATCH] [xbuild] Handle a repeat build of a target, when building through .. .. `Project.Build(..)`. For example, in: ``` ``` The second invocation of `foo`, in the *same* `Project.Build(..)` call, would get skipped, but BuildTarget assumed that no previous `outputs` entry existed in the `targetOutputs` dictionary. System.Exception: MSBuild operation failed ---> System.ArgumentException: Item has already been added. Key in dictionary: 'foo' Key being added: 'foo' at System.Collections.Hashtable.Insert (System.Object key, System.Object nvalue, System.Boolean add) [0x00200] in <94fd79a3b7144c54b4cb162b50fc7761>:0 at System.Collections.Hashtable.Add (System.Object key, System.Object value) [0x00000] in <94fd79a3b7144c54b4cb162b50fc7761>:0 at Microsoft.Build.BuildEngine.Project.BuildTarget (System.String target_name, System.Collections.IDictionary targetOutputs) [0x0007e] in :0 at Microsoft.Build.BuildEngine.Project.BuildInternal (System.String[] targetNames, System.Collections.IDictionary targetOutputs, Microsoft.Build.BuildEngine.BuildSettings buildFlags) [0x00134] in :0 at Microsoft.Build.BuildEngine.Project.Build (System.String[] targetNames, System.Collections.IDictionary targetOutputs, Microsoft.Build.BuildEngine.BuildSettings buildFlags) [0x0004b] in :0 Fixes: https://bugzilla.xamarin.com/show_bug.cgi?id=44549 --- .../Microsoft.Build.BuildEngine/Project.cs | 6 +-- .../Microsoft.Build.BuildEngine/TargetTest.cs | 45 +++++++++++++++++++ 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/Project.cs b/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/Project.cs index 33aad3dea63..b4ed8562382 100644 --- a/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/Project.cs +++ b/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/Project.cs @@ -374,10 +374,8 @@ namespace Microsoft.Build.BuildEngine { return false; ITaskItem[] outputs; - if (ParentEngine.BuiltTargetsOutputByName.TryGetValue (key, out outputs)) { - if (targetOutputs != null) - targetOutputs.Add (target_name, outputs); - } + if (targetOutputs != null && ParentEngine.BuiltTargetsOutputByName.TryGetValue (key, out outputs)) + targetOutputs [target_name] = outputs; return true; } diff --git a/mcs/class/Microsoft.Build.Engine/Test/Microsoft.Build.BuildEngine/TargetTest.cs b/mcs/class/Microsoft.Build.Engine/Test/Microsoft.Build.BuildEngine/TargetTest.cs index 8f2aa2e7b28..d36ae158701 100644 --- a/mcs/class/Microsoft.Build.Engine/Test/Microsoft.Build.BuildEngine/TargetTest.cs +++ b/mcs/class/Microsoft.Build.Engine/Test/Microsoft.Build.BuildEngine/TargetTest.cs @@ -285,6 +285,51 @@ namespace MonoTests.Microsoft.Build.BuildEngine { t [0].RemoveTask (null); } + [Test] + public void TestRunTargetTwice () + { + string documentString = @" + + + + + + + + "; + + var filepath = Path.GetTempFileName (); + try { + File.WriteAllText (filepath, documentString); + + var engine = new Engine (Consts.BinPath); + var project = engine.CreateNewProject (); + project.Load (filepath); + + var logger = new TestMessageLogger (); + engine.RegisterLogger (logger); + + var result = project.Build ("Main"); + if (!result) { + logger.DumpMessages (); + Assert.Fail ("Build failed, see the logs"); + } + + Assert.AreEqual(1, logger.NormalMessageCount, "Expected number of messages"); + logger.CheckLoggedMessageHead ("Foo ran", "A1"); + + Assert.AreEqual(0, logger.NormalMessageCount, "Extra messages found"); + Assert.AreEqual(0, logger.WarningMessageCount, "Extra warning messages found"); + + Assert.AreEqual(2, logger.TargetStarted, "TargetStarted count"); + Assert.AreEqual(2, logger.TargetFinished, "TargetFinished count"); + + Assert.IsTrue (result); + } finally { + File.Delete (filepath); + } + } + [Test] public void TestTargetOutputs1 () { -- 2.25.1