public void ExpandExtensionsPathFallback()
        {
            string extnTargetsFileContentTemplate = @"
                <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' >
                    <Target Name='FromExtn'>
                        <Message Text='Running FromExtn'/>
                    </Target>
                    <Import Project='$(MSBuildExtensionsPath)\\foo\\extn.proj' Condition=""Exists('$(MSBuildExtensionsPath)\foo\extn.proj')"" />
                </Project>";

            var configFileContents = @"
                 <configuration>
                   <configSections>
                     <section name=""msbuildToolsets"" type=""Microsoft.Build.Evaluation.ToolsetConfigurationSection, Microsoft.Build"" />
                   </configSections>
                   <msbuildToolsets default=""14.1"">
                     <toolset toolsVersion=""14.1"">
                       <property name=""MSBuildToolsPath"" value="".""/>
                       <property name=""MSBuildBinPath"" value="".""/>
                       <projectImportSearchPaths>
                         <searchPaths os=""" + NativeMethodsShared.GetOSNameForExtensionsPath() + @""">
                           <property name=""MSBuildExtensionsPath"" value=""$(FallbackExpandDir1)"" />
                         </searchPaths>
                       </projectImportSearchPaths>
                      </toolset>
                   </msbuildToolsets>
                 </configuration>";

            string extnDir1        = null;
            string mainProjectPath = null;

            try
            {
                extnDir1 = GetNewExtensionsPathAndCreateFile("extensions1", Path.Combine("foo", "extn.proj"),
                                                             extnTargetsFileContentTemplate);

                mainProjectPath = ObjectModelHelpers.CreateFileInTempProjectDirectory("main.proj",
                                                                                      GetMainTargetFileContent());

                ToolsetConfigurationReaderTestHelper.WriteConfigFile(configFileContents);
                var reader = GetStandardConfigurationReader();

                var projectCollection = new ProjectCollection(new Dictionary <string, string> {
                    ["FallbackExpandDir1"] = extnDir1
                });

                projectCollection.ResetToolsetsForTests(reader);
                var logger = new MockLogger();
                projectCollection.RegisterLogger(logger);

                var project = projectCollection.LoadProject(mainProjectPath);
                Assert.True(project.Build("Main"));
                logger.AssertLogContains("Running FromExtn");
            }
            finally
            {
                FileUtilities.DeleteNoThrow(mainProjectPath);
                FileUtilities.DeleteDirectoryNoThrow(extnDir1, true);
            }
        }
        public void FallbackImportWithFileNotFoundWhenPropertyNotDefined()
        {
            // Import something from $(UndefinedProperty)
            string mainTargetsFileContent = @"
               <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' >
                   <Import Project='$(UndefinedProperty)\filenotfound.props' />
                   <Target Name='Main' DependsOnTargets='FromExtn' />
               </Project>";

            string extnDir1        = null;
            string mainProjectPath = null;

            try
            {
                // The path to "extensions1" fallback should exist, but the file doens't need to
                extnDir1 = GetNewExtensionsPathAndCreateFile("extensions1", Path.Combine("file.props"), string.Empty);

                // Implement fallback for UndefinedProperty, but don't define the property.
                var configFileContents = @"
                <configuration>
                  <configSections>
                    <section name=""msbuildToolsets"" type=""Microsoft.Build.Evaluation.ToolsetConfigurationSection, Microsoft.Build, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"" />
                  </configSections>
                  <msbuildToolsets default=""" + toolsVersionToUse + @""">
                    <toolset toolsVersion=""" + toolsVersionToUse + @""">
                      <property name=""MSBuildToolsPath"" value="".""/>
                      <property name=""MSBuildBinPath"" value="".""/>
                      <projectImportSearchPaths>
                        <searchPaths os=""" + NativeMethodsShared.GetOSNameForExtensionsPath() + @""">
                          <property name=""UndefinedProperty"" value=""" + extnDir1 + @""" />
                        </searchPaths>
                      </projectImportSearchPaths>
                     </toolset>
                  </msbuildToolsets>
                </configuration>";

                mainProjectPath = ObjectModelHelpers.CreateFileInTempProjectDirectory("main.proj", mainTargetsFileContent);

                ToolsetConfigurationReaderTestHelper.WriteConfigFile(configFileContents);
                var reader = GetStandardConfigurationReader();

                var projectCollection = new ProjectCollection(new Dictionary <string, string> {
                    ["FallbackExpandDir1"] = extnDir1
                });

                projectCollection.ResetToolsetsForTests(reader);
                var logger = new MockLogger();
                projectCollection.RegisterLogger(logger);

                Assert.Throws <InvalidProjectFileException>(() => projectCollection.LoadProject(mainProjectPath));
                logger.AssertLogContains(@"MSB4226: The imported project """ + Path.Combine("$(UndefinedProperty)", "filenotfound.props")
                                         + @""" was not found. Also, tried to find");
            }
            finally
            {
                FileUtilities.DeleteNoThrow(mainProjectPath);
                FileUtilities.DeleteDirectoryNoThrow(extnDir1, true);
            }
        }
        private ToolsetConfigurationReader WriteConfigFileAndGetReader(string extnPathPropertyName, params string[] extnDirs)
        {
            string combinedExtnDirs = extnDirs != null?String.Join(";", extnDirs) : String.Empty;

            ToolsetConfigurationReaderTestHelper.WriteConfigFile(@"
                 <configuration>
                   <configSections>
                     <section name=""msbuildToolsets"" type=""Microsoft.Build.Evaluation.ToolsetConfigurationSection, Microsoft.Build"" />
                   </configSections>
                   <msbuildToolsets default=""14.1"">
                     <toolset toolsVersion=""14.1"">
                       <property name=""MSBuildToolsPath"" value=""."" />
                       <property name=""MSBuildBinPath"" value=""."" />
                       <projectImportSearchPaths>
                         <searchPaths os=""" + NativeMethodsShared.GetOSNameForExtensionsPath() + @""">
                           <property name=""" + extnPathPropertyName + @""" value=""" + combinedExtnDirs + @""" />
                         </searchPaths>
                       </projectImportSearchPaths>
                      </toolset>
                   </msbuildToolsets>
                 </configuration>");

            return(GetStandardConfigurationReader());
        }
        public void ImportFromExtensionsPathAnd32And64()
        {
            string extnTargetsFileContentTemplate = @"
                <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' >
                    <Target Name='FromExtn{0}' DependsOnTargets='{1}'>
                        <Message Text='Running FromExtn{0}'/>
                    </Target>
                    {2}
                </Project>
                ";

            var configFileContents = @"
                 <configuration>
                   <configSections>
                     <section name=""msbuildToolsets"" type=""Microsoft.Build.Evaluation.ToolsetConfigurationSection, Microsoft.Build"" />
                   </configSections>
                   <msbuildToolsets default=""14.1"">
                     <toolset toolsVersion=""14.1"">
                       <property name=""MSBuildToolsPath"" value="".""/>
                       <property name=""MSBuildBinPath"" value=""" + /*v4Folder*/ "." + @"""/>
                       <projectImportSearchPaths>
                         <searchPaths os=""" + NativeMethodsShared.GetOSNameForExtensionsPath() + @""">
                           <property name=""MSBuildExtensionsPath"" value=""{0}"" />
                           <property name=""MSBuildExtensionsPath32"" value=""{1}"" />
                           <property name=""MSBuildExtensionsPath64"" value=""{2}"" />
                         </searchPaths>
                       </projectImportSearchPaths>
                      </toolset>
                   </msbuildToolsets>
                 </configuration>";

            string extnDir1 = null, extnDir2 = null, extnDir3 = null;
            string mainProjectPath = null;

            try {
                extnDir1 = GetNewExtensionsPathAndCreateFile("extensions1", Path.Combine("foo", "extn.proj"),
                                                             String.Format(extnTargetsFileContentTemplate, String.Empty, "FromExtn2", "<Import Project='$(MSBuildExtensionsPath32)\\bar\\extn2.proj' />"));
                extnDir2 = GetNewExtensionsPathAndCreateFile("extensions2", Path.Combine("bar", "extn2.proj"),
                                                             String.Format(extnTargetsFileContentTemplate, 2, "FromExtn3", "<Import Project='$(MSBuildExtensionsPath64)\\xyz\\extn3.proj' />"));
                extnDir3 = GetNewExtensionsPathAndCreateFile("extensions3", Path.Combine("xyz", "extn3.proj"),
                                                             String.Format(extnTargetsFileContentTemplate, 3, String.Empty, String.Empty));

                mainProjectPath = ObjectModelHelpers.CreateFileInTempProjectDirectory("main.proj", GetMainTargetFileContent());

                var configFilePath = ToolsetConfigurationReaderTestHelper.WriteConfigFile(String.Format(configFileContents, extnDir1, extnDir2, extnDir3));
                var reader         = GetStandardConfigurationReader();

                var projColln = new ProjectCollection();
                projColln.ResetToolsetsForTests(reader);
                var logger = new MockLogger();
                projColln.RegisterLogger(logger);

                var project = projColln.LoadProject(mainProjectPath);
                Assert.True(project.Build("Main"));
                logger.AssertLogContains("Running FromExtn3");
                logger.AssertLogContains("Running FromExtn2");
                logger.AssertLogContains("Running FromExtn");
            } finally {
                if (mainProjectPath != null)
                {
                    FileUtilities.DeleteNoThrow(mainProjectPath);
                }
                if (extnDir1 != null)
                {
                    FileUtilities.DeleteDirectoryNoThrow(extnDir1, recursive: true);
                }
                if (extnDir2 != null)
                {
                    FileUtilities.DeleteDirectoryNoThrow(extnDir2, recursive: true);
                }
                if (extnDir3 != null)
                {
                    FileUtilities.DeleteDirectoryNoThrow(extnDir3, recursive: true);
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Reads the settings for a specified tools version
        /// </summary>
        private Toolset ReadToolset
        (
            ToolsetPropertyDefinition toolsVersion,
            PropertyDictionary <ProjectPropertyInstance> globalProperties,
            PropertyDictionary <ProjectPropertyInstance> initialProperties,
            bool accumulateProperties
        )
        {
            // Initial properties is the set of properties we're going to use to expand property expressions like $(foo)
            // in the values we read out of the registry or config file. We'll add to it as we pick up properties (including binpath)
            // from the registry or config file, so that properties there can be referenced in values below them.
            // After processing all the properties, we don't need initialProperties anymore.
            string toolsPath = null;
            string binPath   = null;
            PropertyDictionary <ProjectPropertyInstance> properties = new PropertyDictionary <ProjectPropertyInstance>();

            IEnumerable <ToolsetPropertyDefinition> rawProperties = GetPropertyDefinitions(toolsVersion.Name);

            Expander <ProjectPropertyInstance, ProjectItemInstance> expander = new Expander <ProjectPropertyInstance, ProjectItemInstance>(initialProperties, FileSystems.Default);

            foreach (ToolsetPropertyDefinition property in rawProperties)
            {
                EvaluateAndSetProperty(property, properties, globalProperties, initialProperties, accumulateProperties, ref toolsPath, ref binPath, ref expander);
            }

            Dictionary <string, SubToolset> subToolsets        = new Dictionary <string, SubToolset>(StringComparer.OrdinalIgnoreCase);
            IEnumerable <string>            subToolsetVersions = GetSubToolsetVersions(toolsVersion.Name);

            foreach (string subToolsetVersion in subToolsetVersions)
            {
                string subToolsetToolsPath = null;
                string subToolsetBinPath   = null;
                IEnumerable <ToolsetPropertyDefinition>      rawSubToolsetProperties = GetSubToolsetPropertyDefinitions(toolsVersion.Name, subToolsetVersion);
                PropertyDictionary <ProjectPropertyInstance> subToolsetProperties    = new PropertyDictionary <ProjectPropertyInstance>();

                // If we have a sub-toolset, any values defined here will override the toolset properties.
                foreach (ToolsetPropertyDefinition property in rawSubToolsetProperties)
                {
                    EvaluateAndSetProperty(property, subToolsetProperties, globalProperties, initialProperties, false /* do not ever accumulate sub-toolset properties */, ref subToolsetToolsPath, ref subToolsetBinPath, ref expander);
                }

                if (subToolsetToolsPath != null || subToolsetBinPath != null)
                {
                    InvalidToolsetDefinitionException.Throw("MSBuildToolsPathNotSupportedInSubToolsets", toolsVersion.Name, toolsVersion.Source.LocationString, subToolsetVersion);
                }

                subToolsets[subToolsetVersion] = new SubToolset(subToolsetVersion, subToolsetProperties);
            }

            // All tools versions must specify a value for MSBuildToolsPath (or MSBuildBinPath)
            if (String.IsNullOrEmpty(toolsPath) && String.IsNullOrEmpty(binPath))
            {
                return(null);
            }

            // If both MSBuildBinPath and MSBuildToolsPath are present, they must be the same
            if (toolsPath != null && binPath != null && !toolsPath.Equals(binPath, StringComparison.OrdinalIgnoreCase))
            {
                InvalidToolsetDefinitionException.Throw("ConflictingValuesOfMSBuildToolsPath", toolsVersion.Name, toolsVersion.Source.LocationString);
            }

            AppendStandardProperties(properties, globalProperties, toolsVersion.Name, null, toolsPath);
            Toolset toolset = null;

            try
            {
                var importSearchPathsTable = GetProjectImportSearchPathsTable(toolsVersion.Name, NativeMethodsShared.GetOSNameForExtensionsPath());
                toolset = new Toolset(toolsVersion.Name, toolsPath == null ? binPath : toolsPath, properties, _environmentProperties, globalProperties, subToolsets, MSBuildOverrideTasksPath, DefaultOverrideToolsVersion, importSearchPathsTable);
            }
            catch (ArgumentException e)
            {
                InvalidToolsetDefinitionException.Throw("ErrorCreatingToolset", toolsVersion.Name, e.Message);
            }

            return(toolset);
        }
        public void FallbackImportWithIndirectReference()
        {
            string mainTargetsFileContent = @"
               <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' >
                   <PropertyGroup>
                       <VSToolsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v99</VSToolsPath>
                   </PropertyGroup>
                   <Import Project='$(VSToolsPath)\DNX\Microsoft.DNX.Props' Condition=""Exists('$(VSToolsPath)\DNX\Microsoft.DNX.Props')"" />
                   <Target Name='Main' DependsOnTargets='FromExtn' />
               </Project>";

            string extnTargetsFileContentTemplate = @"
               <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' >
                   <Target Name='FromExtn'>
                       <Message Text='Running FromExtn'/>
                   </Target>
               </Project>";

            var configFileContents = @"
                <configuration>
                  <configSections>
                    <section name=""msbuildToolsets"" type=""net.r_eg.IeXod.Evaluation.ToolsetConfigurationSection, net.r_eg.IeXod"" />
                  </configSections>
                  <msbuildToolsets default=""" + toolsVersionToUse + @""">
                    <toolset toolsVersion=""" + toolsVersionToUse + @""">
                      <property name=""MSBuildToolsPath"" value="".""/>
                      <property name=""MSBuildBinPath"" value="".""/>
                      <projectImportSearchPaths>
                        <searchPaths os=""" + NativeMethodsShared.GetOSNameForExtensionsPath() + @""">
                          <property name=""MSBuildExtensionsPath"" value=""$(FallbackExpandDir1)"" />
                          <property name=""VSToolsPath"" value=""$(FallbackExpandDir1)\Microsoft\VisualStudio\v99"" />
                        </searchPaths>
                      </projectImportSearchPaths>
                     </toolset>
                  </msbuildToolsets>
                </configuration>";

            string extnDir1        = null;
            string mainProjectPath = null;

            try
            {
                extnDir1 = GetNewExtensionsPathAndCreateFile("extensions1", Path.Combine("Microsoft", "VisualStudio", "v99", "DNX", "Microsoft.DNX.Props"),
                                                             extnTargetsFileContentTemplate);

                mainProjectPath = ObjectModelHelpers.CreateFileInTempProjectDirectory("main.proj", mainTargetsFileContent);

                ToolsetConfigurationReaderTestHelper.WriteConfigFile(configFileContents);
                var reader = GetStandardConfigurationReader();

                var projectCollection = new ProjectCollection(new Dictionary <string, string> {
                    ["FallbackExpandDir1"] = extnDir1
                });

                projectCollection.ResetToolsetsForTests(reader);
                var logger = new MockLogger();
                projectCollection.RegisterLogger(logger);

                var project = projectCollection.LoadProject(mainProjectPath);
                Assert.True(project.Build("Main"));
                logger.AssertLogContains("Running FromExtn");
            }
            finally
            {
                FileUtilities.DeleteNoThrow(mainProjectPath);
                FileUtilities.DeleteDirectoryNoThrow(extnDir1, true);
            }
        }