| | 1748 | ////////////////////////////////////////////////////////////////////////// |
| | 1749 | // MSBuild Provider (Visual Studio 2010) |
| | 1750 | ////////////////////////////////////////////////////////////////////////// |
| | 1751 | |
| | 1752 | MSBuildProvider::MSBuildProvider(const int version, std::string global_warnings, std::map<std::string, std::string> project_warnings) |
| | 1753 | : ProjectProvider(version, global_warnings, project_warnings) { |
| | 1754 | |
| | 1755 | } |
| | 1756 | |
| | 1757 | const char *MSBuildProvider::getProjectExtension() { |
| | 1758 | return ".vcxproj"; |
| | 1759 | } |
| | 1760 | |
| | 1761 | const char *MSBuildProvider::getPropertiesExtension() { |
| | 1762 | return ".props"; |
| | 1763 | } |
| | 1764 | |
| | 1765 | int MSBuildProvider::getVisualStudioVersion() { |
| | 1766 | return 2010; |
| | 1767 | } |
| | 1768 | |
| | 1769 | #define OUTPUT_CONFIGURATION_MSBUILD(config, platform) \ |
| | 1770 | project << "\t\t<ProjectConfiguration Include=\"" << config << "|" << platform << "\">\n" \ |
| | 1771 | "\t\t\t<Configuration>" << config << "</Configuration>\n" \ |
| | 1772 | "\t\t\t<Platform>" << platform << "</Platform>\n" \ |
| | 1773 | "\t\t</ProjectConfiguration>\n" |
| | 1774 | |
| | 1775 | #define OUTPUT_CONFIGURATION_TYPE_MSBUILD(config) \ |
| | 1776 | project << "\t<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='" << config << "'\" Label=\"Configuration\">\n" \ |
| | 1777 | "\t\t<ConfigurationType>" << (name == "scummvm" ? "Application" : "StaticLibrary") << "</ConfigurationType>\n" \ |
| | 1778 | "\t</PropertyGroup>\n" |
| | 1779 | |
| | 1780 | #define OUTPUT_PROPERTIES_MSBUILD(config, properties) \ |
| | 1781 | project << "\t<ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='" << config << "'\" Label=\"PropertySheets\">\n" \ |
| | 1782 | "\t\t<Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" />\n" \ |
| | 1783 | "\t\t<Import Project=\"" << properties << "\" />\n" \ |
| | 1784 | "\t</ImportGroup>\n" |
| | 1785 | |
| | 1786 | void MSBuildProvider::createProjectFile(const std::string &name, const std::string &uuid, const BuildSetup &setup, const std::string &moduleDir, |
| | 1787 | const StringList &includeList, const StringList &excludeList) { |
| | 1788 | |
| | 1789 | const std::string projectFile = setup.outputDir + '/' + name + getProjectExtension(); |
| | 1790 | std::ofstream project(projectFile.c_str()); |
| | 1791 | if (!project) |
| | 1792 | error("Could not open \"" + projectFile + "\" for writing"); |
| | 1793 | |
| | 1794 | project << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" |
| | 1795 | "<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n" |
| | 1796 | "\t<ItemGroup Label=\"ProjectConfigurations\">\n"; |
| | 1797 | |
| | 1798 | OUTPUT_CONFIGURATION_MSBUILD("Debug", "Win32"); |
| | 1799 | OUTPUT_CONFIGURATION_MSBUILD("Debug", "x64"); |
| | 1800 | OUTPUT_CONFIGURATION_MSBUILD("Release", "Win32"); |
| | 1801 | OUTPUT_CONFIGURATION_MSBUILD("Release", "x64"); |
| | 1802 | |
| | 1803 | project << "\t</ItemGroup>\n"; |
| | 1804 | |
| | 1805 | // Project name & Guid |
| | 1806 | project << "\t<PropertyGroup Label=\"Globals\">\n" |
| | 1807 | "\t\t<ProjectGuid>" << uuid << "</ProjectGuid>\n" |
| | 1808 | "\t\t<RootNamespace>" << name << "</RootNamespace>\n" |
| | 1809 | "\t\t<Keyword>Win32Proj</Keyword>\n" |
| | 1810 | "\t</PropertyGroup>\n"; |
| | 1811 | |
| | 1812 | // Shared configuration |
| | 1813 | project << "\t<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n"; |
| | 1814 | |
| | 1815 | OUTPUT_CONFIGURATION_TYPE_MSBUILD("Release|Win32"); |
| | 1816 | OUTPUT_CONFIGURATION_TYPE_MSBUILD("Debug|Win32"); |
| | 1817 | OUTPUT_CONFIGURATION_TYPE_MSBUILD("Release|x64"); |
| | 1818 | OUTPUT_CONFIGURATION_TYPE_MSBUILD("Debug|x64"); |
| | 1819 | |
| | 1820 | project << "\t<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n" |
| | 1821 | "\t<ImportGroup Label=\"ExtensionSettings\">\n" |
| | 1822 | "\t</ImportGroup>\n"; |
| | 1823 | |
| | 1824 | OUTPUT_PROPERTIES_MSBUILD("Release|Win32", "ScummVM_Release.props"); |
| | 1825 | OUTPUT_PROPERTIES_MSBUILD("Debug|Win32", "ScummVM_Debug.props"); |
| | 1826 | OUTPUT_PROPERTIES_MSBUILD("Release|x64", "ScummVM_Release64.props"); |
| | 1827 | OUTPUT_PROPERTIES_MSBUILD("Debug|x64", "ScummVM_Debug64.props"); |
| | 1828 | |
| | 1829 | project << "\t<PropertyGroup Label=\"UserMacros\" />\n"; |
| | 1830 | |
| | 1831 | // Project version number |
| | 1832 | project << "\t<PropertyGroup>\n" |
| | 1833 | "\t\t<_ProjectFileVersion>10.0.21006.1</_ProjectFileVersion>\n"; // FIXME: update temporary entry _ProjectFileVersion |
| | 1834 | |
| | 1835 | if (name == "scummvm") |
| | 1836 | project << "<ExecutablePath>$(SCUMMVM_LIBS)\\bin;$(VCInstallDir)bin;$(WindowsSdkDir)bin\\NETFX 4.0 Tools;$(WindowsSdkDir)bin;$(VSInstallDir)Common7\\Tools\\bin;$(VSInstallDir)Common7\\tools;$(VSInstallDir)Common7\\ide;$(ProgramFiles)\\HTML Help Workshop;$(FrameworkSDKDir)\\bin;$(MSBuildToolsPath32);$(VSInstallDir);$(SystemRoot)\\SysWow64;$(FxCopDir);$(PATH)</ExecutablePath>\n" |
| | 1837 | "<IncludePath>$(SCUMMVM_LIBS)\\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\\include;</IncludePath>\n" |
| | 1838 | "<LibraryPath>$(SCUMMVM_LIBS)\\lib;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\\lib</LibraryPath>\n"; |
| | 1839 | |
| | 1840 | project << "\t</PropertyGroup>\n"; |
| | 1841 | |
| | 1842 | // Project-specific settings |
| | 1843 | outputProjectSettings(project, name, setup, false, true); |
| | 1844 | outputProjectSettings(project, name, setup, true, true); |
| | 1845 | outputProjectSettings(project, name, setup, false, false); |
| | 1846 | outputProjectSettings(project, name, setup, true, false); |
| | 1847 | |
| | 1848 | // Files |
| | 1849 | std::string modulePath; |
| | 1850 | if (!moduleDir.compare(0, setup.srcDir.size(), setup.srcDir)) { |
| | 1851 | modulePath = moduleDir.substr(setup.srcDir.size()); |
| | 1852 | if (!modulePath.empty() && modulePath.at(0) == '/') |
| | 1853 | modulePath.erase(0, 1); |
| | 1854 | } |
| | 1855 | |
| | 1856 | if (modulePath.size()) |
| | 1857 | addFilesToProject(moduleDir, project, includeList, excludeList, setup.filePrefix + '/' + modulePath); |
| | 1858 | else |
| | 1859 | addFilesToProject(moduleDir, project, includeList, excludeList, setup.filePrefix); |
| | 1860 | |
| | 1861 | // Output references for scummvm project |
| | 1862 | if (name == "scummvm") |
| | 1863 | writeReferences(project); |
| | 1864 | |
| | 1865 | project << "\t<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n" |
| | 1866 | "\t<ImportGroup Label=\"ExtensionTargets\">\n" |
| | 1867 | "\t</ImportGroup>\n" |
| | 1868 | "</Project>\n"; |
| | 1869 | |
| | 1870 | // Output filter file if necessary |
| | 1871 | createFiltersFile(setup, name); |
| | 1872 | } |
| | 1873 | |
| | 1874 | #define OUTPUT_FILTER_MSBUILD(files, action) \ |
| | 1875 | if (!files.empty()) { \ |
| | 1876 | filters << "\t<ItemGroup>\n"; \ |
| | 1877 | for (std::list<FileEntry>::const_iterator entry = files.begin(); entry != files.end(); ++entry) { \ |
| | 1878 | if ((*entry).filter != "") { \ |
| | 1879 | filters << "\t\t<" action " Include=\"" << (*entry).path << "\">\n" \ |
| | 1880 | "\t\t\t<Filter>" << (*entry).filter << "</Filter>\n" \ |
| | 1881 | "\t\t</" action ">\n"; \ |
| | 1882 | } else { \ |
| | 1883 | filters << "\t\t<" action " Include=\"" << (*entry).path << "\" />\n"; \ |
| | 1884 | } \ |
| | 1885 | } \ |
| | 1886 | filters << "\t</ItemGroup>\n"; \ |
| | 1887 | } |
| | 1888 | |
| | 1889 | void MSBuildProvider::createFiltersFile(const BuildSetup &setup, const std::string &name) { |
| | 1890 | // No filters => no need to create a filter file |
| | 1891 | if (_filters.empty()) |
| | 1892 | return; |
| | 1893 | |
| | 1894 | // Sort all list alphabetically |
| | 1895 | _filters.sort(); |
| | 1896 | _compileFiles.sort(); |
| | 1897 | _includeFiles.sort(); |
| | 1898 | _otherFiles.sort(); |
| | 1899 | _resourceFiles.sort(); |
| | 1900 | _asmFiles.sort(); |
| | 1901 | |
| | 1902 | const std::string filtersFile = setup.outputDir + '/' + name + getProjectExtension() + ".filters"; |
| | 1903 | std::ofstream filters(filtersFile.c_str()); |
| | 1904 | if (!filters) |
| | 1905 | error("Could not open \"" + filtersFile + "\" for writing"); |
| | 1906 | |
| | 1907 | filters << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" |
| | 1908 | "<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"; |
| | 1909 | |
| | 1910 | // Output the list of filters |
| | 1911 | filters << "\t<ItemGroup>\n"; |
| | 1912 | for (std::list<std::string>::iterator filter = _filters.begin(); filter != _filters.end(); ++filter) { |
| | 1913 | filters << "\t\t<Filter Include=\"" << *filter << "\">\n" |
| | 1914 | "\t\t\t<UniqueIdentifier>" << createUUID() << "</UniqueIdentifier>\n" |
| | 1915 | "\t\t</Filter>\n"; |
| | 1916 | } |
| | 1917 | filters << "\t</ItemGroup>\n"; |
| | 1918 | |
| | 1919 | // Output files |
| | 1920 | OUTPUT_FILTER_MSBUILD(_compileFiles, "ClCompile") |
| | 1921 | OUTPUT_FILTER_MSBUILD(_includeFiles, "ClInclude") |
| | 1922 | OUTPUT_FILTER_MSBUILD(_otherFiles, "None") |
| | 1923 | OUTPUT_FILTER_MSBUILD(_resourceFiles, "ResourceCompile") |
| | 1924 | OUTPUT_FILTER_MSBUILD(_asmFiles, "CustomBuild") |
| | 1925 | |
| | 1926 | filters << "</Project>"; |
| | 1927 | } |
| | 1928 | |
| | 1929 | void MSBuildProvider::writeReferences(std::ofstream &output) { |
| | 1930 | output << "\t<ItemGroup>\n"; |
| | 1931 | |
| | 1932 | for (UUIDMap::const_iterator i = _uuidMap.begin(); i != _uuidMap.end(); ++i) { |
| | 1933 | if (i->first == "scummvm") |
| | 1934 | continue; |
| | 1935 | |
| | 1936 | output << "\t<ProjectReference Include=\"" << i->first << ".vcxproj\">\n" |
| | 1937 | "\t\t<Project>{" << i->second << "}</Project>\n" |
| | 1938 | "\t</ProjectReference>\n"; |
| | 1939 | } |
| | 1940 | |
| | 1941 | output << "\t</ItemGroup>\n"; |
| | 1942 | } |
| | 1943 | |
| | 1944 | void MSBuildProvider::outputProjectSettings(std::ofstream &project, const std::string &name, const BuildSetup &setup, bool isRelease, bool isWin32) { |
| | 1945 | |
| | 1946 | // Check for project-specific warnings: |
| | 1947 | std::map<std::string, std::string>::iterator warnings = _projectWarnings.find(name); |
| | 1948 | |
| | 1949 | // Nothing to add here, move along! |
| | 1950 | if (name != "scummvm" && name != "tinsel" && warnings == _projectWarnings.end()) |
| | 1951 | return; |
| | 1952 | |
| | 1953 | project << "\t<ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='" << (isRelease ? "Release" : "Debug") << "|" << (isWin32 ? "Win32" : "x64") << "'\">\n" |
| | 1954 | "\t\t<ClCompile>\n"; |
| | 1955 | |
| | 1956 | // Compile configuration |
| | 1957 | if (name == "scummvm") { |
| | 1958 | project << "\t\t\t<DisableLanguageExtensions>false</DisableLanguageExtensions>\n"; |
| | 1959 | } else { |
| | 1960 | if (name == "tinsel" && !isRelease) |
| | 1961 | project << "\t\t\t<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\n"; |
| | 1962 | |
| | 1963 | if (warnings != _projectWarnings.end()) |
| | 1964 | project << "\t\t\t<DisableSpecificWarnings>" << warnings->second << ";%(DisableSpecificWarnings)</DisableSpecificWarnings>\n"; |
| | 1965 | } |
| | 1966 | |
| | 1967 | project << "\t\t</ClCompile>\n"; |
| | 1968 | |
| | 1969 | // Link configuration for scummvm project |
| | 1970 | if (name == "scummvm") { |
| | 1971 | std::string libraries; |
| | 1972 | |
| | 1973 | for (StringList::const_iterator i = setup.libraries.begin(); i != setup.libraries.end(); ++i) |
| | 1974 | libraries += *i + ';'; |
| | 1975 | |
| | 1976 | project << "\t\t<Link>\n" |
| | 1977 | "\t\t\t<OutputFile>$(OutDir)scummvm.exe</OutputFile>\n" |
| | 1978 | "\t\t\t<AdditionalDependencies>" << libraries << "%(AdditionalDependencies)</AdditionalDependencies>\n" |
| | 1979 | "\t\t</Link>\n"; |
| | 1980 | } |
| | 1981 | |
| | 1982 | project << "\t</ItemDefinitionGroup>\n"; |
| | 1983 | } |
| | 1984 | |
| | 1985 | void MSBuildProvider::outputGlobalPropFile(std::ofstream &properties, int bits, const std::string &defines, const std::string &prefix) { |
| | 1986 | // FIXME: update temporary entries _ProjectFileVersion & _PropertySheetDisplayName |
| | 1987 | properties << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" |
| | 1988 | "<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n" |
| | 1989 | "<PropertyGroup>\n" |
| | 1990 | "<_ProjectFileVersion>10.0.21006.1</_ProjectFileVersion>\n" |
| | 1991 | "<_PropertySheetDisplayName>ScummVM_Global</_PropertySheetDisplayName>\n" |
| | 1992 | "<OutDir>$(Configuration)" << bits << "\\</OutDir>\n" |
| | 1993 | "<IntDir>$(Configuration)" << bits << "/$(ProjectName)\\</IntDir>\n" |
| | 1994 | "</PropertyGroup>\n" |
| | 1995 | "<ItemDefinitionGroup>\n" |
| | 1996 | "<ClCompile>\n" |
| | 1997 | "<DisableLanguageExtensions>true</DisableLanguageExtensions>\n" |
| | 1998 | "<DisableSpecificWarnings>" << _globalWarnings << ";%(DisableSpecificWarnings)</DisableSpecificWarnings>\n" |
| | 1999 | "<AdditionalIncludeDirectories>" << prefix << ";" << prefix << "\\engines;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n" |
| | 2000 | "<PreprocessorDefinitions>" << defines << ";%(PreprocessorDefinitions)</PreprocessorDefinitions>\n" |
| | 2001 | "<ExceptionHandling>\n" |
| | 2002 | "</ExceptionHandling>\n" |
| | 2003 | "<RuntimeTypeInfo>false</RuntimeTypeInfo>\n" |
| | 2004 | "<WarningLevel>Level4</WarningLevel>\n" |
| | 2005 | "<TreatWarningAsError>false</TreatWarningAsError>\n" |
| | 2006 | "<CompileAs>Default</CompileAs>\n" |
| | 2007 | "</ClCompile>\n" |
| | 2008 | "<Link>\n" |
| | 2009 | "<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\n" |
| | 2010 | "<SubSystem>Console</SubSystem>\n" |
| | 2011 | "<EntryPointSymbol>WinMainCRTStartup</EntryPointSymbol>\n" |
| | 2012 | "</Link>\n" |
| | 2013 | "<ResourceCompile>\n" |
| | 2014 | "<PreprocessorDefinitions>HAS_INCLUDE_SET;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n" |
| | 2015 | "<AdditionalIncludeDirectories>" << prefix << ";%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n" |
| | 2016 | "</ResourceCompile>\n" |
| | 2017 | "</ItemDefinitionGroup>\n" |
| | 2018 | "</Project>\n"; |
| | 2019 | |
| | 2020 | properties.flush(); |
| | 2021 | } |
| | 2022 | |
| | 2023 | void MSBuildProvider::createBuildProp(const BuildSetup &setup, bool isRelease, bool isWin32) { |
| | 2024 | const std::string outputType = (isRelease ? "Release" : "Debug"); |
| | 2025 | const std::string outputBitness = (isWin32 ? "32" : "64"); |
| | 2026 | |
| | 2027 | std::ofstream properties((setup.outputDir + '/' + "ScummVM_" + outputType + (isWin32 ? "" : "64") + getPropertiesExtension()).c_str()); |
| | 2028 | if (!properties) |
| | 2029 | error("Could not open \"" + setup.outputDir + '/' + "ScummVM_" + outputType + (isWin32 ? "" : "64") + getPropertiesExtension() + "\" for writing"); |
| | 2030 | |
| | 2031 | // FIXME: update temporary entries _ProjectFileVersion & _PropertySheetDisplayName |
| | 2032 | properties << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" |
| | 2033 | "<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n" |
| | 2034 | "\t<ImportGroup Label=\"PropertySheets\">\n" |
| | 2035 | "\t\t<Import Project=\"ScummVM_Global" << (isWin32 ? "" : "64") << ".props\" />\n" |
| | 2036 | "\t</ImportGroup>\n" |
| | 2037 | "\t<PropertyGroup>\n" |
| | 2038 | "\t\t<_ProjectFileVersion>10.0.21006.1</_ProjectFileVersion>\n" |
| | 2039 | "\t\t<_PropertySheetDisplayName>ScummVM_" << outputType << outputBitness << "</_PropertySheetDisplayName>\n" |
| | 2040 | "\t\t<LinkIncremental>" << (isRelease ? "false" : "true") << "</LinkIncremental>\n" |
| | 2041 | "\t</PropertyGroup>\n" |
| | 2042 | "\t<ItemDefinitionGroup>\n" |
| | 2043 | "\t\t<ClCompile>\n"; |
| | 2044 | |
| | 2045 | if (isRelease) { |
| | 2046 | properties << "\t\t\t<IntrinsicFunctions>true</IntrinsicFunctions>\n" |
| | 2047 | "\t\t\t<WholeProgramOptimization>true</WholeProgramOptimization>\n" |
| | 2048 | "\t\t\t<PreprocessorDefinitions>WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n" |
| | 2049 | "\t\t\t<StringPooling>true</StringPooling>\n" |
| | 2050 | "\t\t\t<BufferSecurityCheck>false</BufferSecurityCheck>\n" |
| | 2051 | "\t\t\t<DebugInformationFormat></DebugInformationFormat>\n" |
| | 2052 | "\t\t</ClCompile>\n" |
| | 2053 | "\t\t<Link>\n" |
| | 2054 | "\t\t\t<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\n" |
| | 2055 | "\t\t\t<SetChecksum>true</SetChecksum>\n"; |
| | 2056 | } else { |
| | 2057 | properties << "\t\t\t<Optimization>Disabled</Optimization>\n" |
| | 2058 | "\t\t\t<PreprocessorDefinitions>WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n" |
| | 2059 | "\t\t\t<MinimalRebuild>true</MinimalRebuild>\n" |
| | 2060 | "\t\t\t<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n" |
| | 2061 | "\t\t\t<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n" |
| | 2062 | "\t\t\t<FunctionLevelLinking>true</FunctionLevelLinking>\n" |
| | 2063 | "\t\t\t<TreatWarningAsError>false</TreatWarningAsError>\n" |
| | 2064 | "\t\t\t<DebugInformationFormat>" << (isWin32 ? "EditAndContinue" : "ProgramDatabase") << "</DebugInformationFormat>\n" // For x64 format Edit and continue is not supported, thus we default to Program Database |
| | 2065 | "\t\t</ClCompile>\n" |
| | 2066 | "\t\t<Link>\n" |
| | 2067 | "\t\t\t<GenerateDebugInformation>true</GenerateDebugInformation>\n" |
| | 2068 | "\t\t\t<IgnoreSpecificDefaultLibraries>libcmt.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\n"; |
| | 2069 | } |
| | 2070 | |
| | 2071 | properties << "\t\t</Link>\n" |
| | 2072 | "\t</ItemDefinitionGroup>\n" |
| | 2073 | "</Project>\n"; |
| | 2074 | |
| | 2075 | properties.flush(); |
| | 2076 | properties.close(); |
| | 2077 | } |
| | 2078 | |
| | 2079 | #define OUTPUT_NASM_COMMAND_MSBUILD(config) \ |
| | 2080 | projectFile << "\t\t\t<Command Condition=\"'$(Configuration)|$(Platform)'=='" << config << "|Win32'\">nasm.exe -f win32 -g -o \"$(IntDir)" << (isDuplicate ? (*entry).prefix : "") << "%(FileName).obj\" \"%(FullPath)\"</Command>\n" \ |
| | 2081 | "\t\t\t<Outputs Condition=\"'$(Configuration)|$(Platform)'=='" << config << "|Win32'\">$(IntDir)" << (isDuplicate ? (*entry).prefix : "") << "%(FileName).obj;%(Outputs)</Outputs>\n"; |
| | 2082 | |
| | 2083 | #define OUPUT_OBJECT_FILENAME_MSBUILD(config, platform, prefix) \ |
| | 2084 | projectFile << "\t\t<ObjectFileName Condition=\"'$(Configuration)|$(Platform)'=='" << config << "|" << platform << "'\">$(IntDir)" << prefix << "%(FileName).obj</ObjectFileName>\n" \ |
| | 2085 | "\t\t<XMLDocumentationFileName Condition=\"'$(Configuration)|$(Platform)'=='" << config << "|" << platform << "'\">$(IntDir)" << prefix << "%(FileName).xdc</XMLDocumentationFileName>\n"; |
| | 2086 | |
| | 2087 | #define OUPUT_FILES_MSBUILD(files, action) \ |
| | 2088 | if (!files.empty()) { \ |
| | 2089 | projectFile << "\t<ItemGroup>\n"; \ |
| | 2090 | for (std::list<FileEntry>::const_iterator entry = files.begin(); entry != files.end(); ++entry) { \ |
| | 2091 | projectFile << "\t\t<" action " Include=\"" << (*entry).path << "\" />\n"; \ |
| | 2092 | } \ |
| | 2093 | projectFile << "\t</ItemGroup>\n"; \ |
| | 2094 | } |
| | 2095 | |
| | 2096 | void MSBuildProvider::writeFileListToProject(const FileNode &dir, std::ofstream &projectFile, const int, const StringList &duplicate, |
| | 2097 | const std::string &objPrefix, const std::string &filePrefix) { |
| | 2098 | |
| | 2099 | // Reset lists |
| | 2100 | _filters.clear(); |
| | 2101 | _compileFiles.clear(); |
| | 2102 | _includeFiles.clear(); |
| | 2103 | _otherFiles.clear(); |
| | 2104 | _resourceFiles.clear(); |
| | 2105 | _asmFiles.clear(); |
| | 2106 | |
| | 2107 | // Compute the list of files |
| | 2108 | _filters.push_back(""); // init filters |
| | 2109 | computeFileList(dir, duplicate, objPrefix, filePrefix); |
| | 2110 | _filters.pop_back(); // remove last empty filter |
| | 2111 | |
| | 2112 | // Output compile files |
| | 2113 | if (!_compileFiles.empty()) { |
| | 2114 | projectFile << "\t<ItemGroup>\n"; |
| | 2115 | for (std::list<FileEntry>::const_iterator entry = _compileFiles.begin(); entry != _compileFiles.end(); ++entry) { |
| | 2116 | const bool isDuplicate = (std::find(duplicate.begin(), duplicate.end(), (*entry).name + ".o") != duplicate.end()); |
| | 2117 | |
| | 2118 | // Deal with duplicated file names |
| | 2119 | if (isDuplicate) { |
| | 2120 | projectFile << "\t\t<ClCompile Include=\"" << (*entry).path << "\">\n"; |
| | 2121 | OUPUT_OBJECT_FILENAME_MSBUILD("Debug", "Win32", (*entry).prefix) |
| | 2122 | OUPUT_OBJECT_FILENAME_MSBUILD("Debug", "x64", (*entry).prefix) |
| | 2123 | OUPUT_OBJECT_FILENAME_MSBUILD("Release", "Win32", (*entry).prefix) |
| | 2124 | OUPUT_OBJECT_FILENAME_MSBUILD("Release", "x64", (*entry).prefix) |
| | 2125 | projectFile << "\t\t</ClCompile>\n"; |
| | 2126 | } else { |
| | 2127 | projectFile << "\t\t<ClCompile Include=\"" << (*entry).path << "\" />\n"; |
| | 2128 | } |
| | 2129 | } |
| | 2130 | projectFile << "\t</ItemGroup>\n"; |
| | 2131 | } |
| | 2132 | |
| | 2133 | // Output include, other and resource files |
| | 2134 | OUPUT_FILES_MSBUILD(_includeFiles, "ClInclude") |
| | 2135 | OUPUT_FILES_MSBUILD(_otherFiles, "None") |
| | 2136 | OUPUT_FILES_MSBUILD(_resourceFiles, "ResourceCompile") |
| | 2137 | |
| | 2138 | // Output asm files |
| | 2139 | if (!_asmFiles.empty()) { |
| | 2140 | projectFile << "\t<ItemGroup>\n"; |
| | 2141 | for (std::list<FileEntry>::const_iterator entry = _asmFiles.begin(); entry != _asmFiles.end(); ++entry) { |
| | 2142 | |
| | 2143 | const bool isDuplicate = (std::find(duplicate.begin(), duplicate.end(), (*entry).name + ".o") != duplicate.end()); |
| | 2144 | |
| | 2145 | projectFile << "\t\t<CustomBuild Include=\"" << (*entry).path << "\">\n" |
| | 2146 | "\t\t\t<FileType>Document</FileType>\n"; |
| | 2147 | |
| | 2148 | OUTPUT_NASM_COMMAND_MSBUILD("Debug") |
| | 2149 | OUTPUT_NASM_COMMAND_MSBUILD("Release") |
| | 2150 | |
| | 2151 | projectFile << "\t\t</CustomBuild>\n"; |
| | 2152 | } |
| | 2153 | projectFile << "\t</ItemGroup>\n"; |
| | 2154 | } |
| | 2155 | } |
| | 2156 | |
| | 2157 | void MSBuildProvider::computeFileList(const FileNode &dir, const StringList &duplicate, const std::string &objPrefix, const std::string &filePrefix) { |
| | 2158 | |
| | 2159 | for (FileNode::NodeList::const_iterator i = dir.children.begin(); i != dir.children.end(); ++i) { |
| | 2160 | const FileNode *node = *i; |
| | 2161 | |
| | 2162 | if (!node->children.empty()) { |
| | 2163 | // Update filter |
| | 2164 | std::string _currentFilter = _filters.back(); |
| | 2165 | _filters.back().append((_filters.back() == "" ? "" : "\\") + node->name); |
| | 2166 | |
| | 2167 | computeFileList(*node, duplicate, objPrefix + node->name + '_', filePrefix + node->name + '/'); |
| | 2168 | |
| | 2169 | // Reset filter |
| | 2170 | _filters.push_back(_currentFilter); |
| | 2171 | } else { |
| | 2172 | // Filter files by extension |
| | 2173 | std::string name, ext; |
| | 2174 | splitFilename(node->name, name, ext); |
| | 2175 | |
| | 2176 | FileEntry entry; |
| | 2177 | entry.name = name; |
| | 2178 | entry.path = convertPathToWin(filePrefix + node->name); |
| | 2179 | entry.filter = _filters.back(); |
| | 2180 | entry.prefix = objPrefix; |
| | 2181 | |
| | 2182 | if (ext == "cpp" || ext == "c") { |
| | 2183 | _compileFiles.push_back(entry); |
| | 2184 | } else if (ext == "h") { |
| | 2185 | _includeFiles.push_back(entry); |
| | 2186 | } else if (ext == "rc") { |
| | 2187 | _resourceFiles.push_back(entry); |
| | 2188 | } else if (ext == "asm") { |
| | 2189 | _asmFiles.push_back(entry); |
| | 2190 | } else { |
| | 2191 | _otherFiles.push_back(entry); |
| | 2192 | } |
| | 2193 | } |
| | 2194 | } |
| | 2195 | } |
| | 2196 | |