| 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 | |