public void ImportOutputProperties() { BuildPropertyGroup pg = new BuildPropertyGroup(); pg.SetProperty("foo", "fooval"); pg.SetProperty(new BuildProperty("bar", "barval", PropertyType.EnvironmentProperty)); pg.SetProperty(new BuildProperty("baz", "bazval", PropertyType.GlobalProperty)); pg.SetProperty(new BuildProperty("caz", "cazval", PropertyType.ImportedProperty)); pg.SetProperty(new BuildProperty("barb", "barbval", PropertyType.OutputProperty)); BuildPropertyGroup pgo = new BuildPropertyGroup(); pgo.SetProperty(new BuildProperty("foo", "fooout", PropertyType.OutputProperty)); pgo.SetProperty(new BuildProperty("bar", "barout", PropertyType.OutputProperty)); pgo.SetProperty(new BuildProperty("baz", "bazout", PropertyType.OutputProperty)); pgo.SetProperty(new BuildProperty("caz", "cazout", PropertyType.OutputProperty)); pgo.SetProperty(new BuildProperty("barb", "barbout", PropertyType.OutputProperty)); pgo.SetProperty(new BuildProperty("gaz", "gazout", PropertyType.OutputProperty)); pg.ImportProperties(pgo); Assertion.AssertEquals(6, pg.Count); Assertion.AssertEquals("fooout", pg["foo"].FinalValueEscaped); Assertion.AssertEquals("barout", pg["bar"].FinalValueEscaped); Assertion.AssertEquals("bazout", pg["baz"].FinalValueEscaped); Assertion.AssertEquals("cazout", pg["caz"].FinalValueEscaped); Assertion.AssertEquals("barbout", pg["barb"].FinalValueEscaped); Assertion.AssertEquals("gazout", pg["gaz"].FinalValueEscaped); pg.SetProperty(new BuildProperty("foo", "fooout2", PropertyType.OutputProperty)); pg.SetProperty(new BuildProperty("gaz", "gazout2", PropertyType.OutputProperty)); Assertion.AssertEquals("fooout2", pg["foo"].FinalValueEscaped); Assertion.AssertEquals("gazout2", pg["gaz"].FinalValueEscaped); pg.RemoveProperty("baz"); pg.RevertAllOutputProperties(); Assertion.AssertEquals(3, pg.Count); Assertion.AssertEquals("fooval", pg["foo"].FinalValueEscaped); Assertion.AssertEquals("barval", pg["bar"].FinalValueEscaped); Assertion.AssertNull(pg["baz"]); Assertion.AssertEquals("cazval", pg["caz"].FinalValueEscaped); Assertion.AssertNull(pg["barb"]); }
public void GlobalPropertiesInToolsetsAreExpandedButAreNotOverwritten() { ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" <configuration> <configSections> <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> </configSections> <msbuildToolsets> <toolset toolsVersion=""3.5""> <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v2.0.x86ret\""/> <property name=""p1"" value=""$(gp1)""/> <property name=""gp1"" value=""v2""/> <property name=""p2"" value=""$(gp1)""/> </toolset> </msbuildToolsets> </configuration>"); Engine e = new Engine(ToolsetDefinitionLocations.None); ToolsetCollection values = new ToolsetCollection(e); BuildPropertyGroup globalProperties = e.GlobalProperties; globalProperties.SetProperty("gp1", "gv1"); BuildPropertyGroup initialProperties = new BuildPropertyGroup(); initialProperties.ImportProperties(e.EnvironmentProperties); initialProperties.ImportProperties(globalProperties); string defaultToolsVersion = ToolsetReader.ReadAllToolsets ( values, new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), globalProperties, initialProperties, ToolsetDefinitionLocations.ConfigurationFile | ToolsetDefinitionLocations.Registry ); Assertion.AssertEquals("gv1", values["3.5"].BuildProperties["p1"].Value); Assertion.AssertEquals("gv1", values["3.5"].BuildProperties["p2"].Value); }
/// <summary> /// Populate ToolsetStateMap with a dictionary of (toolset version, ToolsetState) /// using information from the registry and config file, if any. /// </summary> /// <remarks>Internal for unit testing purposes only</remarks> /// <param name="locations"></param> internal void PopulateToolsetStateMap(ToolsetDefinitionLocations locations) { BuildPropertyGroup initialProperties = new BuildPropertyGroup(); initialProperties.ImportProperties(EnvironmentProperties); initialProperties.ImportProperties(GlobalProperties); string defaultVersionFromReaders = ToolsetReader.ReadAllToolsets(toolsets, GlobalProperties, initialProperties, locations); // If we got a default version from the registry or config file, we should // use that from now on. The readers guarantee that any default version they return // has a corresponding Toolset too. if (defaultVersionFromReaders != null) { this.DefaultToolsVersion = defaultVersionFromReaders; } else { // We're going to choose a hard coded default tools version of 2.0. // But don't overwrite any existing tools path for this default we're choosing. if (!toolsetStateMap.ContainsKey(Constants.defaultToolsVersion)) { string pathTo20Framework = FrameworkLocationHelper.PathToDotNetFrameworkV20; if (pathTo20Framework == null) { // We have been given no default, so we want to choose 2.0, but .NET 2.0 is not installed. // In general we do not verify that MSBuildToolsPath's point to a valid location, // so failing here would be inconsistent. The build might not even use this toolset. // Instead, synthesize what would be the path to the .NET 2.0 install location. // If the build tries to use the default toolset, the problem will be discovered then. pathTo20Framework = Path.Combine(Environment.SystemDirectory, @"Microsoft.NET\Framework\v2.0.50727"); } // There's no tools path already for 2.0, so use the path to the v2.0 .NET Framework. // If an old-fashioned caller sets BinPath property, or passed a BinPath to the constructor, // that will overwrite what we're setting here. toolsets.Add(new Toolset(Constants.defaultToolsVersion, pathTo20Framework)); } // Now update the default tools version to 2.0 DefaultToolsVersion = Constants.defaultToolsVersion; } }
public void PropertiesInToolsetsFromConfigFileAreExpandedInToolsPath() { // $(COMPUTERNAME) is just a convenient env var. $(NUMBER_OF_PROCESSORS) isn't defined on Longhorn ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" <configuration> <configSections> <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> </configSections> <msbuildToolsets> <toolset toolsVersion=""3.5""> <property name=""p1"" value=""Microsoft.NET""/> <property name=""p2"" value=""windows""/> <property name=""MSBuildBinPath"" value=""D:\windows\$(p1)\Framework\v2.0.x86ret\$(COMPUTERNAME)""/> <property name=""MSBuildToolsPath"" value=""D:\$(p2)\$(p1)\Framework\v2.0.x86ret\$(COMPUTERNAME)""/> <property name=""p3"" value=""v3$(MSBuildToolsPath)""/> </toolset> </msbuildToolsets> </configuration>"); ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); Engine e = new Engine(); BuildPropertyGroup initialProperties = new BuildPropertyGroup(); initialProperties.ImportProperties(e.EnvironmentProperties); initialProperties.ImportProperties(e.GlobalProperties); string defaultToolsVersion = ToolsetReader.ReadAllToolsets ( values, new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), new BuildPropertyGroup(), initialProperties, ToolsetDefinitionLocations.ConfigurationFile | ToolsetDefinitionLocations.Registry ); Assertion.AssertEquals("Microsoft.NET", values["3.5"].BuildProperties["p1"].Value); Assertion.AssertEquals("windows", values["3.5"].BuildProperties["p2"].Value); string expectedToolsPath = @"D:\windows\Microsoft.NET\Framework\v2.0.x86ret\" + Environment.MachineName; Assertion.AssertEquals(expectedToolsPath, values["3.5"].ToolsPath); Assertion.AssertEquals("v3" + expectedToolsPath, values["3.5"].BuildProperties["p3"].Value); }
/// <summary> /// When using the MSBuild task to build a child project, we need to figure out the set of /// global properties that the child should be built with. It is a merge of whatever /// properties the parent project was being built with, plus whatever properties were /// actually passed into the MSBuild task (in the "Properties" parameter). However, /// the slightly wrinkle is the child project may have actually been one that is /// currently loaded in the IDE, and the IDE controls what Configuration/Platform each /// project should be built with, so we have to honor that too. So, the order in which /// we look at global properties are: /// /// 1. Whatever global properties the parent project was building with. (The parent /// project is the one that called the <MSBuild< task. /// 2. If the child project was already previously loaded by the host, whatever global /// properties were sent into the child project by the host (via Project.GlobalProperties). /// 3. Whatever properties were passed into the "Properties" parameter of the <MSBuild< /// task. /// /// </summary> /// <param name="parentProjectGlobalProperties"></param> /// <param name="childProjectFile"></param> /// <param name="globalPropertiesPassedIntoTask"></param> /// <owner>RGoel</owner> /// <returns>merged PropertyGroup</returns> internal BuildPropertyGroup MergeGlobalProperties ( BuildPropertyGroup parentProjectGlobalProperties, BuildPropertyGroup postMergeProperties, string childProjectFile, IDictionary globalPropertiesPassedIntoTask ) { if (childProjectFile != null) { // The childProject can be null (if user wants us to just use the calling project as the // callee project). But if it's not null, it really shouldn't be blank, and it should // exist on disk. If it doesn't we can't get its full path. error.VerifyThrowArgument(childProjectFile.Length > 0, "EmptyProjectFileName"); // If the project file doesn't actually exist on disk, it's a failure. ErrorUtilities.VerifyThrowArgument(File.Exists(childProjectFile), "ProjectFileNotFound", childProjectFile); } // Create a new BuildPropertyGroup to represent the final set of global properties that we're going to // use for the child project. BuildPropertyGroup finalGlobalProperties = new BuildPropertyGroup(); // Start with the global properties from the parent project. if (postMergeProperties == null) { finalGlobalProperties.ImportProperties(parentProjectGlobalProperties); } else { finalGlobalProperties.ImportProperties(postMergeProperties); } // childProjectFile could be null when no Projects were passed into the MSBuild task, which // means parentProject == childProject, which means no need to import the same properties again. if (childProjectFile != null) { // Get the full path of the child project file. string childProjectFullPath = Path.GetFullPath(childProjectFile); // Find out if there's a project already loaded with the same full path. Project loadedProjectWithSameFullPath = (Project) this.projectsLoadedByHost[childProjectFullPath]; // Then ... if there is a loaded project with the same full path, merge in its global properties. // This way, we honor whatever settings the IDE has requested for this project (e.g. Configuration=Release, or whatever). if (loadedProjectWithSameFullPath != null) { finalGlobalProperties.ImportProperties(loadedProjectWithSameFullPath.GlobalProperties); } } // Finally, whatever global properties were passed into the task ... those are the final winners. if (globalPropertiesPassedIntoTask != null) { foreach (DictionaryEntry newGlobalProperty in globalPropertiesPassedIntoTask) { finalGlobalProperties.SetProperty((string) newGlobalProperty.Key, (string) newGlobalProperty.Value); } } return finalGlobalProperties; }