コード例 #1
0
        /// <summary>
        /// Generates project files for Visual Studio: '.vcxproj' and '.vcxproj.filter'.
        /// </summary>
        /// <param name="project">Parsed project object.</param>
        /// <returns>Path to Visual Studio '.vcxproj file'.</returns>
        public sealed override string GenerateProjectFiles(Project project)
        {
            var vcxProjPath = Path.Combine(base.GenerateProjectFiles(project), project.Name) + ".vcxproj";

            try
            {
                // For build tools the best was is to load a GUID from project files: this causes exceptions
                // in Visual Studio when reloading of solution, and all opened tabs would be terminated.
                project.Misc.GUID = QueryGuidFromProject(vcxProjPath);
            }
            catch (Exception)
            {
                project.Misc.GUID = CreateMsBuildGuid();
            }

            // ==========================================================================================
            // Generating VCXPROJ files.
            // ==========================================================================================
            using (var vcxProj = new XmlTextWriter(vcxProjPath, null)
            {
                Formatting = Formatting.Indented, Indentation = 1, IndentChar = '\t'
            })
            {
                vcxProj.WriteStartDocument();
                vcxProj.WriteComment("Generated by GoddamnBuildSystem. Please, do not edit this file manually.");
                vcxProj./**/ WriteStartElement("Project", c_MsBuild2003Namespace);
                vcxProj./**//**/ WriteAttributeString("ToolsVersion", c_ToolsVersion);
                vcxProj./**//**/ WriteAttributeString("DefaultTargets", "Build");

                // ------------------------------------------------------------------------------------------
                // Defining list of configurations.
                // ------------------------------------------------------------------------------------------
                vcxProj.WriteStartElement("ItemGroup");
                vcxProj./**/ WriteAttributeString("Label", "ProjectConfigurations");
                foreach (var platform in TargetInfo.EnumerateAllPlatforms())
                {
                    var platformString = ConvertPlatformToMsBuildPlatform(platform);
                    foreach (var configuration in TargetInfo.EnumerateAllConfigurations())
                    {
                        var configurationName = string.Concat(configuration, platform);
                        vcxProj./**/ WriteStartElement("ProjectConfiguration");
                        vcxProj./**//**/ WriteAttributeString("Include", configurationName + '|' + platformString);
                        vcxProj./**//**/ WriteElementString("Configuration", configurationName);
                        vcxProj./**//**/ WriteElementString("Platform", platformString);
                        vcxProj./**/ WriteEndElement();
                    }
                }
                vcxProj.WriteEndElement();

                // ------------------------------------------------------------------------------------------
                // Defining list of source files.
                // ------------------------------------------------------------------------------------------
                foreach (var platform in TargetInfo.EnumerateAllPlatforms())
                {
                    var platformString = ConvertPlatformToMsBuildPlatform(platform);
                    foreach (var configuration in TargetInfo.EnumerateAllConfigurations())
                    {
                        var configurationName = string.Concat(configuration, platform);
                        vcxProj.WriteStartElement("ItemGroup");
                        vcxProj.WriteAttributeStringFormat("Condition", @"'$(Configuration)|$(Platform)'=='{0}|{1}'", configurationName, platformString);
                        foreach (var projectSource in project.Files[platform, configuration])
                        {
                            vcxProj.WriteStartElement(ConvertFileTypeToVcxProjElement(projectSource.FileType));
                            vcxProj.WriteAttributeString("Include", projectSource.FilePath);
                            vcxProj.WriteEndElement();
                        }
                        vcxProj.WriteEndElement();
                    }
                }

                // ------------------------------------------------------------------------------------------
                // Overriding global project properties.
                // ------------------------------------------------------------------------------------------
                vcxProj.WriteStartElement("PropertyGroup");
                vcxProj./**/ WriteElementString("ProjectGuid", project.Misc.GUID);
                vcxProj./**/ WriteElementString("RootNamespace", project.Name);
                vcxProj./**/ WriteElementString("MinimumVisualStudioVersion", "14.0");
                vcxProj.WriteEndElement();
                foreach (var platform in TargetInfo.EnumerateAllPlatforms())
                {
                    var platformString = ConvertPlatformToMsBuildPlatform(platform);
                    foreach (var configuration in TargetInfo.EnumerateAllConfigurations())
                    {
                        var configurationName = string.Concat(configuration, platform);
                        vcxProj.WriteStartElement("PropertyGroup");
                        vcxProj./**/ WriteAttributeStringFormat("Condition", "'$(Configuration)|$(Platform)'=='{0}|{1}'", configurationName, platformString);
                        vcxProj./**/ WriteAttributeString("Label", "Globals");
                        vcxProj./**/ WriteElementString("WindowsTargetPlatformVersion", "10.0.16299.0");
                        if (platform == TargetPlatform.XboxOne)
                        {
                            vcxProj./**/ WriteElementString("AppContainerApplication", "true");
                            vcxProj./**/ WriteElementString("ApplicationType", "Windows Store");
                            vcxProj./**/ WriteElementString("WindowsTargetPlatformVersion", "10.0.16299.0");
                            vcxProj./**/ WriteElementString("WindowsTargetPlatformMinVersion", "10.0.10586.0");
                            vcxProj./**/ WriteElementString("ApplicationTypeRevision", "10");
                        }
                        vcxProj.WriteEndElement();
                    }
                }

                // ------------------------------------------------------------------------------------------
                // Overriding main configuration properties.
                // ------------------------------------------------------------------------------------------
                foreach (var platform in TargetInfo.EnumerateAllPlatforms())
                {
                    var platformString  = ConvertPlatformToMsBuildPlatform(platform);
                    var platformToolset = "v141";

                    foreach (var configuration in TargetInfo.EnumerateAllConfigurations())
                    {
                        var configurationName = string.Concat(configuration, platform);
                        vcxProj.WriteStartElement("PropertyGroup");
                        vcxProj./**/ WriteAttributeStringFormat("Condition", "'$(Configuration)|$(Platform)'=='{0}|{1}'", configurationName, platformString);
                        vcxProj./**/ WriteAttributeString("Label", "Configuration");
                        vcxProj./**/ WriteElementString("PlatformToolset", platformToolset);
                        if (IsPlatformNativelySupported(platform))
                        {
                            vcxProj./**/ WriteElementString("ConfigurationType", project.BuildType[platform, configuration].ToString());
                            vcxProj./**/ WriteElementString("CharacterSet", "Unicode");
                        }
                        else
                        {
                            vcxProj./**/ WriteElementString("ConfigurationType", "Makefile");
                        }
                        vcxProj.WriteEndElement();
                    }
                }

                vcxProj.WriteStartElement("Import");
                vcxProj./**/ WriteAttributeString("Project", @"$(VCTargetsPath)\Microsoft.Cpp.Default.props");
                vcxProj.WriteEndElement();
                vcxProj.WriteStartElement("Import");
                vcxProj./**/ WriteAttributeString("Project", @"$(VCTargetsPath)\Microsoft.Cpp.props");
                vcxProj.WriteEndElement();
                vcxProj.WriteStartElement("ImportGroup");
                vcxProj./**/ WriteAttributeString("Label", "ExtensionSettings");
                vcxProj./**/ WriteStartElement("Import");
                vcxProj./**//**/ WriteAttributeString("Project", @"$(VCTargetsPath)\BuildCustomizations\masm.props");
                vcxProj./**/ WriteEndElement();
                vcxProj.WriteEndElement();
                vcxProj.WriteStartElement("PropertyGroup");
                vcxProj./**/ WriteAttributeString("Label", "UserMacros");
                vcxProj.WriteEndElement();
                vcxProj.WriteStartElement("PropertyGroup");
                vcxProj./**/ WriteElementString("NMakeForcedIncludes", "$(NMakeForcedIncludes)");
                vcxProj./**/ WriteElementString("NMakeAssemblySearchPath", "$(NMakeAssemblySearchPath)");
                vcxProj./**/ WriteElementString("NMakeForcedUsingAssemblies", "$(NMakeForcedUsingAssemblies)");
                vcxProj.WriteEndElement();

                // ------------------------------------------------------------------------------------------
                // Overriding VC++ compiler and linker properties OR NMake commands..
                // ------------------------------------------------------------------------------------------
                foreach (var platform in TargetInfo.EnumerateAllPlatforms())
                {
                    var platformInfo   = TargetPlatformInfo.Get(platform);
                    var platformString = ConvertPlatformToMsBuildPlatform(platform);

                    // Building list of header directories.
                    var includePathes          = project.GenerateIncludePaths(platform, TargetConfiguration.Debug);
                    var standardLibrariesPaths = platformInfo.GenerateStandardIncludePaths();
                    if (string.IsNullOrEmpty(standardLibrariesPaths))
                    {
                        standardLibrariesPaths = "$(NMakeIncludeSearchPath)";
                    }

                    foreach (var configuration in TargetInfo.EnumerateAllConfigurations())
                    {
                        var configurationInfo = TargetConfigurationInfo.Get(configuration);

                        // Defining macros..
                        //var macros = project.GenerateMacros(platform, configuration);
                        //var standardMacros = platformInfo.GenerateStandardMacrosList();
                        //if (string.IsNullOrEmpty(standardMacros))
                        //{
                        //    standardMacros = "$(NMakePreprocessorDefinitions)";
                        //}

                        // Collecting linked libraries..
                        var linkedLibraries         = project.GenerateLinkedLibrariesPaths(platform, configuration);
                        var standardLinkedLibraries = platformInfo.GenerateStandardLinkedLibrariesPaths();
                        if (string.IsNullOrEmpty(standardLinkedLibraries))
                        {
                            standardLinkedLibraries = "";
                        }
                        standardLinkedLibraries += "%(AdditionalDependencies)";

                        var configurationName = string.Concat(configuration, platform);
                        var outputPath        = project.OutputPath[platform, configuration];

                        vcxProj.WriteStartElement("ImportGroup");
                        vcxProj./**/ WriteAttributeStringFormat("Condition", "'$(Configuration)|$(Platform)'=='{0}|{1}'", configurationName, platformString);
                        vcxProj./**/ WriteAttributeString("Label", "PropertySheets");
                        vcxProj./**/ WriteStartElement("Import");
                        vcxProj./**//**/ WriteAttributeString("Project", @"$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props");
                        vcxProj./**//**/ WriteAttributeString("Condition", @"exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')");
                        vcxProj./**//**/ WriteAttributeString("Label", "LocalAppDataPlatform");
                        vcxProj./**/ WriteEndElement();
                        vcxProj.WriteEndElement();

                        if (IsPlatformNativelySupported(platform))
                        {
                            // ------------------------------------------------------------------------------------------
                            // Defining VC++ compiler and linker properties.
                            // ------------------------------------------------------------------------------------------

                            // Include paths..
                            vcxProj.WriteStartElement("PropertyGroup");
                            vcxProj./**/ WriteAttributeStringFormat("Condition", "'$(Configuration)|$(Platform)'=='{0}|{1}'", configurationName, platformString);
                            vcxProj./**/ WriteElementString("IncludePath", includePathes + "$(IncludePath)");
                            vcxProj./**/ WriteElementString("OutDir", Path.GetDirectoryName(outputPath) + Path.DirectorySeparatorChar);
                            vcxProj./**/ WriteElementString("TargetName", Path.GetFileNameWithoutExtension(outputPath));
                            vcxProj.WriteEndElement();

                            // Compiler properties..
                            vcxProj.WriteStartElement("ItemDefinitionGroup");
                            vcxProj./**/ WriteAttributeStringFormat("Condition", "'$(Configuration)|$(Platform)'=='{0}|{1}'", configurationName, platformString);
                            vcxProj./**/ WriteStartElement("ClCompile");
                            vcxProj./**//**/ WriteElementString("FavorSizeOrSpeed", "Speed");
                            vcxProj./**//**/ WriteElementString("PrecompiledHeader", "NotUsing");
                            vcxProj./**//**/ WriteElementString("CallingConvention", "FastCall");
                            vcxProj./**//**/ WriteElementString("WarningLevel", "Level" + TargetCppCompilerInformation.WarningLevel);
                            vcxProj./**//**/ WriteElementString("TreatWarningAsError", TargetCppCompilerInformation.WarningsAreErrors.ToString());
                            //vcxProj./**//**/WriteElementString("PreprocessorDefinitions", macros + "%(PreprocessorDefinition)");
                            vcxProj./**//**/ WriteElementString("Optimization", configurationInfo.Optimize ? "Full" : "Disabled");
                            if (configurationInfo.IsDebug)
                            {
                                vcxProj.WriteElementString("RuntimeLibrary", "MultiThreadedDebugDLL");
                            }
                            if (!platformInfo.RequiresRtti)
                            {
                                vcxProj.WriteElementString("RuntimeTypeInfo", "false");
                            }
                            if (!platformInfo.RequiresExceptions)
                            {
                                //vcxProj.WriteElementString("ExceptionHandling", "false");
                            }
                            vcxProj./**/ WriteEndElement(); // </ VC++ COMPILER PROPERTIES

                            // Linker properties.
                            vcxProj./**/ WriteStartElement("Link");
                            vcxProj./**//**/ WriteElementString("AdditionalDependencies", linkedLibraries + standardLinkedLibraries);
                            vcxProj./**//**/ WriteElementString("GenerateDebugInformation", configurationInfo.GenerateDebugInformation.ToString().ToLowerInvariant());
                            if (project.BuildType[platform, configuration] == ProjectBuildType.DynamicLibrary)
                            {
                                vcxProj./**//**/ WriteElementString("ImportLibrary", project.ImportLibraryOutputPath[platform, configuration]);
                            }
                            vcxProj./**/ WriteEndElement();
                            vcxProj.WriteEndElement();
                        }
                        else
                        {
                            // ------------------------------------------------------------------------------------------
                            // Defining NMake properties..
                            // ------------------------------------------------------------------------------------------

                            var nmakeCommand =
                                $"\"{System.Reflection.Assembly.GetExecutingAssembly().Location}\" --compile-project \"{project.Source}\" {platform} {configuration} ";
                            vcxProj.WriteStartElement("PropertyGroup");
                            vcxProj./**/ WriteAttributeStringFormat("Condition", "'$(Configuration)|$(Platform)'=='{0}|{1}'", configurationName, platformString);
                            vcxProj./**/ WriteElementString("OutDir", Path.GetDirectoryName(outputPath) + Path.DirectorySeparatorChar);
                            vcxProj./**/ WriteElementString("NMakeOutput", outputPath);
                            //vcxProj./**/WriteElementString("NMakePreprocessorDefinitions", macros + standardMacros + ";GD_PLATFORNOT_WINDOWS=1");
                            vcxProj./**/ WriteElementString("NMakeIncludeSearchPath", includePathes + standardLibrariesPaths);
                            vcxProj./**/ WriteElementString("NMakeBuildCommandLine", nmakeCommand);
                            vcxProj./**/ WriteElementString("NMakeReBuildCommandLine", nmakeCommand + "Rebuild");
                            vcxProj./**/ WriteElementString("NMakeCleanCommandLine", nmakeCommand + "Clean");
                            vcxProj.WriteEndElement();
                        }
                    }
                }

                vcxProj.WriteStartElement("Import");
                vcxProj./**/ WriteAttributeString("Project", @"$(VCTargetsPath)\Microsoft.Cpp.targets");
                vcxProj.WriteEndElement();
                vcxProj.WriteStartElement("ImportGroup");
                vcxProj./**/ WriteAttributeString("Label", "ExtensionSettings");
                vcxProj./**/ WriteStartElement("Import");
                vcxProj./**//**/ WriteAttributeString("Project", @"$(VCTargetsPath)\BuildCustomizations\masm.targets");
                vcxProj./**/ WriteEndElement();
                vcxProj.WriteEndElement();

                vcxProj./**/ WriteEndElement();
                vcxProj.WriteEndDocument();
            }

            // ==========================================================================================
            // Generating VCPROJ.FILTERS files.
            // ==========================================================================================
            var vcxProjFiltersPath = vcxProjPath + ".filters";

            using (var vcxProjFilters = new XmlTextWriter(vcxProjFiltersPath, null)
            {
                Formatting = Formatting.Indented, Indentation = 1, IndentChar = '\t'
            })
            {
                vcxProjFilters.WriteStartDocument();
                vcxProjFilters./**/ WriteStartElement("Project", c_MsBuild2003Namespace);
                vcxProjFilters./**/ WriteAttributeString("ToolsVersion", c_ToolsFiltersVersion);

                var projectFoldersCache = new HashSet <string>();
                foreach (var projectSourceFile in project.Files[TargetPlatform.Any, TargetConfiguration.Any])
                {
                    var    projectSourceFileDirectory = Path.GetDirectoryName(projectSourceFile.FilePath);
                    string projectSourceFilter;

                    // Checking if this source can have a filter: it is located in project directory and it not in it's root.
                    // We also add "Source" to each filter to separate configuration and source files.
                    if (projectSourceFileDirectory != null && projectSourceFileDirectory.StartsWith(project.SourcesFilterOrigin, StringComparison.InvariantCultureIgnoreCase) &&
                        projectSourceFileDirectory.Length > project.SourcesFilterOrigin.Length + 1)
                    {
                        projectSourceFilter = "Source\\" + projectSourceFileDirectory.Substring(project.SourcesFilterOrigin.Length + 1);
                        var projectSourceFilterIter = projectSourceFilter;
                        while (!projectFoldersCache.Contains(projectSourceFilterIter) && !string.IsNullOrEmpty(projectSourceFilterIter))
                        {
                            // ------------------------------------------------------------------------------------------
                            // Defining group of filters.
                            // ------------------------------------------------------------------------------------------
                            vcxProjFilters.WriteStartElement("ItemGroup");
                            vcxProjFilters./**/ WriteStartElement("Filter");
                            vcxProjFilters./**//**/ WriteAttributeString("Include", projectSourceFilterIter);
                            vcxProjFilters./**//**/ WriteElementString("UniqueIdentifier", CreateMsBuildGuid());
                            vcxProjFilters./**/ WriteEndElement();
                            vcxProjFilters.WriteEndElement();

                            projectFoldersCache.Add(projectSourceFilterIter);
                            projectSourceFilterIter = Path.GetDirectoryName(projectSourceFilterIter);
                        }
                    }
                    else
                    {
                        projectSourceFilter = "Source";
                    }

                    // ------------------------------------------------------------------------------------------
                    // Defining source's filters.
                    // ------------------------------------------------------------------------------------------
                    vcxProjFilters.WriteStartElement("ItemGroup");
                    vcxProjFilters./**/ WriteStartElement(ConvertFileTypeToVcxProjElement(projectSourceFile.FileType));
                    vcxProjFilters./**//**/ WriteAttributeString("Include", projectSourceFile.FilePath);
                    vcxProjFilters./**//**/ WriteElementString("Filter", projectSourceFilter);
                    vcxProjFilters./**/ WriteEndElement();
                    vcxProjFilters.WriteEndElement();
                }

                vcxProjFilters./**/ WriteEndElement();
                vcxProjFilters.WriteEndDocument();
            }

            return(vcxProjPath);
        }