/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * $URL$ * $Id$ * */ #include "msvc.h" #include #include namespace CreateProjectTool { ////////////////////////////////////////////////////////////////////////// // MSVC Provider (Base class) ////////////////////////////////////////////////////////////////////////// MSVCProvider::MSVCProvider(StringList &global_warnings, std::map &project_warnings, const int version) : ProjectProvider(global_warnings, project_warnings, version) { } void MSVCProvider::createWorkspace(const BuildSetup &setup) { UUIDMap::const_iterator svmUUID = _uuidMap.find("scummvm"); if (svmUUID == _uuidMap.end()) error("No UUID for \"scummvm\" project created"); const std::string svmProjectUUID = svmUUID->second; assert(!svmProjectUUID.empty()); std::string solutionUUID = createUUID(); std::ofstream solution((setup.outputDir + '/' + "scummvm.sln").c_str()); if (!solution) error("Could not open \"" + setup.outputDir + '/' + "scummvm.sln\" for writing"); solution << "Microsoft Visual Studio Solution File, Format Version " << _version + 1 << ".00\n"; solution << "# Visual Studio " << getVisualStudioVersion() << "\n"; solution << "Project(\"{" << solutionUUID << "}\") = \"scummvm\", \"scummvm" << getProjectExtension() << "\", \"{" << svmProjectUUID << "}\"\n"; // Project dependencies are moved to vcxproj files in Visual Studio 2010 if (_version < 10) writeReferences(solution); solution << "EndProject\n"; // Note we assume that the UUID map only includes UUIDs for enabled engines! for (UUIDMap::const_iterator i = _uuidMap.begin(); i != _uuidMap.end(); ++i) { if (i->first == "scummvm") continue; solution << "Project(\"{" << solutionUUID << "}\") = \"" << i->first << "\", \"" << i->first << getProjectExtension() << "\", \"{" << i->second << "}\"\n" << "EndProject\n"; } solution << "Global\n" "\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n" "\t\tDebug|Win32 = Debug|Win32\n" "\t\tAnalysis|Win32 = Analysis|Win32\n" "\t\tRelease|Win32 = Release|Win32\n" "\t\tDebug|x64 = Debug|x64\n" "\t\tAnalysis|x64 = Analysis|x64\n" "\t\tRelease|x64 = Release|x64\n" "\tEndGlobalSection\n" "\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n"; for (UUIDMap::const_iterator i = _uuidMap.begin(); i != _uuidMap.end(); ++i) { solution << "\t\t{" << i->second << "}.Debug|Win32.ActiveCfg = Debug|Win32\n" "\t\t{" << i->second << "}.Debug|Win32.Build.0 = Debug|Win32\n" "\t\t{" << i->second << "}.Analysis|Win32.ActiveCfg = Analysis|Win32\n" "\t\t{" << i->second << "}.Analysis|Win32.Build.0 = Analysis|Win32\n" "\t\t{" << i->second << "}.Release|Win32.ActiveCfg = Release|Win32\n" "\t\t{" << i->second << "}.Release|Win32.Build.0 = Release|Win32\n" "\t\t{" << i->second << "}.Debug|x64.ActiveCfg = Debug|x64\n" "\t\t{" << i->second << "}.Debug|x64.Build.0 = Debug|x64\n" "\t\t{" << i->second << "}.Analysis|x64.ActiveCfg = Analysis|x64\n" "\t\t{" << i->second << "}.Analysis|x64.Build.0 = Analysis|x64\n" "\t\t{" << i->second << "}.Release|x64.ActiveCfg = Release|x64\n" "\t\t{" << i->second << "}.Release|x64.Build.0 = Release|x64\n"; } solution << "\tEndGlobalSection\n" "\tGlobalSection(SolutionProperties) = preSolution\n" "\t\tHideSolutionNode = FALSE\n" "\tEndGlobalSection\n" "EndGlobal\n"; } void MSVCProvider::createOtherBuildFiles(const BuildSetup &setup) { // Create the global property file createGlobalProp(setup); // Create the configuration property files (for Debug and Release with 32 and 64bits versions) // Note: we use the debug properties for the analysis configuration createBuildProp(setup, true, false, false); createBuildProp(setup, true, true, false); createBuildProp(setup, false, false, false); createBuildProp(setup, false, false, true); createBuildProp(setup, false, true, false); createBuildProp(setup, false, true, true); } void MSVCProvider::createGlobalProp(const BuildSetup &setup) { std::ofstream properties((setup.outputDir + '/' + "ScummVM_Global" + getPropertiesExtension()).c_str()); if (!properties) error("Could not open \"" + setup.outputDir + '/' + "ScummVM_Global" + getPropertiesExtension() + "\" for writing"); outputGlobalPropFile(properties, 32, setup.defines, convertPathToWin(setup.filePrefix)); properties.close(); properties.open((setup.outputDir + '/' + "ScummVM_Global64" + getPropertiesExtension()).c_str()); if (!properties) error("Could not open \"" + setup.outputDir + '/' + "ScummVM_Global64" + getPropertiesExtension() + "\" for writing"); // HACK: We must disable the "nasm" feature for x64. To achieve that we must duplicate the feature list and // recreate a define list. FeatureList x64Features = setup.features; setFeatureBuildState("nasm", x64Features, false); StringList x64Defines = getFeatureDefines(x64Features); StringList x64EngineDefines = getEngineDefines(setup.engines); x64Defines.splice(x64Defines.end(), x64EngineDefines); outputGlobalPropFile(properties, 64, x64Defines, convertPathToWin(setup.filePrefix)); } std::string MSVCProvider::getRevisionToolCommandLine() const { std::string cmdLine = ""; cmdLine = "@echo off\n" "ECHO Generating revision number\n" "IF NOT EXIST "$(SolutionDir)../../.svn/" GOTO working_copy\n" "SubWCRev.exe "$(SolutionDir)../.." "$(SolutionDir)../../base/internal_version.h.tpl" "$(SolutionDir)../../base/internal_version.h"\n" "IF NOT %errorlevel%==0 GOTO error\n" ":working_copy\n" "ECHO Not a working copy, skipping...\n" "EXIT /B0\n" ":error\n" "ECHO SubWCRev not found, skipping...\n" "EXIT /B0"; return cmdLine; } std::string MSVCProvider::getCopyDataCommandLine(bool isWin32) const { std::string cmdLine = ""; // Copy data files and themes cmdLine = "@echo off\n" "ECHO Copying data files\n" "xcopy /F /Y "$(SolutionDir)../engine-data/*.dat" $(OutDir)\n" "xcopy /F /Y "$(SolutionDir)../engine-data/*.tbl" $(OutDir)\n" "xcopy /F /Y "$(SolutionDir)../engine-data/*.cpt" $(OutDir)\n" "xcopy /F /Y "$(SolutionDir)../engine-data/README" $(OutDir)\n" "xcopy /F /Y "$(SolutionDir)../../gui/themes/*.zip" $(OutDir)\n" "xcopy /F /Y "$(SolutionDir)../../gui/themes/translations.dat" $(OutDir)\n"; cmdLine += "xcopy /F /Y "$(SCUMMVM_LIBS)/lib/"; cmdLine += (isWin32 ? "x86" : "x64"); cmdLine += "/SDL.dll" $(OutDir)"; return cmdLine; } ////////////////////////////////////////////////////////////////////////// // Visual Studio Provider ////////////////////////////////////////////////////////////////////////// VisualStudioProvider::VisualStudioProvider(StringList &global_warnings, std::map &project_warnings, const int version) : MSVCProvider(global_warnings, project_warnings, version) { } const char *VisualStudioProvider::getProjectExtension() { return ".vcproj"; } const char *VisualStudioProvider::getPropertiesExtension() { return ".vsprops"; } int VisualStudioProvider::getVisualStudioVersion() { if (_version == 9) return 2008; if (_version == 8) return 2005; error("Unsupported version passed to createScummVMSolution"); } #define OUTPUT_CONFIGURATION_SCUMMVM(config, platform, props) { \ project << "\t\t\n" \ "\t\t\t\n" \ "\t\t\t\n" \ "\t\t\n"; \ } #define OUTPUT_CONFIGURATION_SCUMMVM_DEBUG(config, platform, props, isWin32) { \ project << "\t\t\n" \ "\t\t\t\n" \ "\t\t\t\n" \ "\t\t\t\n" \ "\t\t\t\n" \ "\t\t\n"; \ } #define OUTPUT_CONFIGURATION(config, platform, props) { \ project << "\t\t\n" \ "\t\t\t\n" \ "\t\t\n"; \ } void VisualStudioProvider::createProjectFile(const std::string &name, const std::string &uuid, const BuildSetup &setup, const std::string &moduleDir, const StringList &includeList, const StringList &excludeList) { const std::string projectFile = setup.outputDir + '/' + name + getProjectExtension(); std::ofstream project(projectFile.c_str()); if (!project) error("Could not open \"" + projectFile + "\" for writing"); project << "\n" "= 9) project << "\tTargetFrameworkVersion=\"131072\"\n"; project << "\t>\n" "\t\n" "\t\t\n" "\t\t\n" "\t\n" "\t\n"; // Check for project-specific warnings: std::map< std::string, std::list >::iterator warningsIterator = _projectWarnings.find(name); if (name == "scummvm") { std::string libraries; for (StringList::const_iterator i = setup.libraries.begin(); i != setup.libraries.end(); ++i) libraries += ' ' + *i + ".lib"; // Win32 OUTPUT_CONFIGURATION_SCUMMVM_DEBUG("Debug", "Win32", "", true); OUTPUT_CONFIGURATION_SCUMMVM_DEBUG("Analysis", "Win32", "", true); OUTPUT_CONFIGURATION_SCUMMVM("Release", "Win32", ""); // x64 // For 'x64' we must disable NASM support. Usually we would need to disable the "nasm" feature for that and // re-create the library list, BUT since NASM doesn't link any additional libraries, we can just use the // libraries list created for IA-32. If that changes in the future, we need to adjust this part! OUTPUT_CONFIGURATION_SCUMMVM_DEBUG("Debug", "x64", "64", true); OUTPUT_CONFIGURATION_SCUMMVM_DEBUG("Analysis", "x64", "64", true); OUTPUT_CONFIGURATION_SCUMMVM("Release", "x64", "64"); } else { std::string warnings = ""; if (warningsIterator != _projectWarnings.end()) for (StringList::const_iterator i = warningsIterator->second.begin(); i != warningsIterator->second.end(); ++i) warnings += *i + ';'; std::string toolConfig; toolConfig = (!warnings.empty() ? "DisableSpecificWarnings=\"" + warnings + "\"" : ""); toolConfig += (name == "tinsel" ? "DebugInformationFormat=\"3\" " : ""); toolConfig += (name == "sword25" ? "DisableLanguageExtensions=\"false\" " : ""); // Win32 OUTPUT_CONFIGURATION("Debug", "Win32", ""); OUTPUT_CONFIGURATION("Analysis", "Win32", ""); OUTPUT_CONFIGURATION("Release", "Win32", ""); OUTPUT_CONFIGURATION("Debug", "x64", "64"); OUTPUT_CONFIGURATION("Analysis", "x64", "64"); OUTPUT_CONFIGURATION("Release", "x64", "64"); } project << "\t\n" "\t\n"; std::string modulePath; if (!moduleDir.compare(0, setup.srcDir.size(), setup.srcDir)) { modulePath = moduleDir.substr(setup.srcDir.size()); if (!modulePath.empty() && modulePath.at(0) == '/') modulePath.erase(0, 1); } if (modulePath.size()) addFilesToProject(moduleDir, project, includeList, excludeList, setup.filePrefix + '/' + modulePath); else addFilesToProject(moduleDir, project, includeList, excludeList, setup.filePrefix); project << "\t\n" "\n"; } void VisualStudioProvider::writeReferences(std::ofstream &output) { output << "\tProjectSection(ProjectDependencies) = postProject\n"; for (UUIDMap::const_iterator i = _uuidMap.begin(); i != _uuidMap.end(); ++i) { if (i->first == "scummvm") continue; output << "\t\t{" << i->second << "} = {" << i->second << "}\n"; } output << "\tEndProjectSection\n"; } void VisualStudioProvider::outputGlobalPropFile(std::ofstream &properties, int bits, const StringList &defines, const std::string &prefix) { std::string warnings; for (StringList::const_iterator i = _globalWarnings.begin(); i != _globalWarnings.end(); ++i) warnings += *i + ';'; std::string definesList; for (StringList::const_iterator i = defines.begin(); i != defines.end(); ++i) { if (i != defines.begin()) definesList += ';'; definesList += *i; } properties << "\n" "\n" "\t\n" "\t\n" "\t\n" "\t\n" "\n"; properties.flush(); } void VisualStudioProvider::createBuildProp(const BuildSetup &setup, bool isRelease, bool isWin32, bool enableAnalysis) { const std::string outputType = (enableAnalysis ? "Analysis" : (isRelease ? "Release" : "Debug")); const std::string outputBitness = (isWin32 ? "32" : "64"); std::ofstream properties((setup.outputDir + '/' + "ScummVM_" + outputType + (isWin32 ? "" : "64") + getPropertiesExtension()).c_str()); if (!properties) error("Could not open \"" + setup.outputDir + '/' + "ScummVM_" + outputType + (isWin32 ? "" : "64") + getPropertiesExtension() + "\" for writing"); properties << "\n" "\n" "\t\n" "\t\n" "\t\n" "\n"; properties.flush(); properties.close(); } void VisualStudioProvider::writeFileListToProject(const FileNode &dir, std::ofstream &projectFile, const int indentation, const StringList &duplicate, const std::string &objPrefix, const std::string &filePrefix) { const std::string indentString = getIndent(indentation + 2); if (indentation) projectFile << getIndent(indentation + 1) << "\n"; for (FileNode::NodeList::const_iterator i = dir.children.begin(); i != dir.children.end(); ++i) { const FileNode *node = *i; if (!node->children.empty()) { writeFileListToProject(*node, projectFile, indentation + 1, duplicate, objPrefix + node->name + '_', filePrefix + node->name + '/'); } else { if (producesObjectFile(node->name)) { std::string name, ext; splitFilename(node->name, name, ext); const bool isDuplicate = (std::find(duplicate.begin(), duplicate.end(), name + ".o") != duplicate.end()); if (ext == "asm") { std::string objFileName = "$(IntDir)\\"; if (isDuplicate) objFileName += objPrefix; objFileName += "$(InputName).obj"; const std::string toolLine = indentString + "\t\t\n"; // NASM is not supported for x64, thus we do not need to add additional entries here :-). projectFile << indentString << "name) << "\">\n" << indentString << "\t\n" << toolLine << indentString << "\t\n" << indentString << "\t\n" << toolLine << indentString << "\t\n" << indentString << "\t\n" << toolLine << indentString << "\t\n" << indentString << "\n"; } else { if (isDuplicate) { const std::string toolLine = indentString + "\t\t\n"; projectFile << indentString << "name) << "\">\n" << indentString << "\t\n" << toolLine << indentString << "\t\n" << indentString << "\t\n" << toolLine << indentString << "\t\n" << indentString << "\t\n" << toolLine << indentString << "\t\n" << indentString << "\t\n" << toolLine << indentString << "\t\n" << indentString << "\t\n" << toolLine << indentString << "\t\n" << indentString << "\t\n" << toolLine << indentString << "\t\n" << indentString << "\n"; } else { projectFile << indentString << "name) << "\" />\n"; } } } else { projectFile << indentString << "name) << "\" />\n"; } } } if (indentation) projectFile << getIndent(indentation + 1) << "\n"; } ////////////////////////////////////////////////////////////////////////// // MSBuild Provider (Visual Studio 2010) ////////////////////////////////////////////////////////////////////////// MSBuildProvider::MSBuildProvider(StringList &global_warnings, std::map &project_warnings, const int version) : MSVCProvider(global_warnings, project_warnings, version) { } const char *MSBuildProvider::getProjectExtension() { return ".vcxproj"; } const char *MSBuildProvider::getPropertiesExtension() { return ".props"; } int MSBuildProvider::getVisualStudioVersion() { return 2010; } #define OUTPUT_CONFIGURATION_MSBUILD(config, platform) \ (project << "\t\t\n" \ "\t\t\t" << config << "\n" \ "\t\t\t" << platform << "\n" \ "\t\t\n") #define OUTPUT_CONFIGURATION_TYPE_MSBUILD(config) \ (project << "\t\n" \ "\t\t" << (name == "scummvm" ? "Application" : "StaticLibrary") << "\n" \ "\t\n") #define OUTPUT_PROPERTIES_MSBUILD(config, properties) \ (project << "\t\n" \ "\t\t\n" \ "\t\t\n" \ "\t\n") void MSBuildProvider::createProjectFile(const std::string &name, const std::string &uuid, const BuildSetup &setup, const std::string &moduleDir, const StringList &includeList, const StringList &excludeList) { const std::string projectFile = setup.outputDir + '/' + name + getProjectExtension(); std::ofstream project(projectFile.c_str()); if (!project) error("Could not open \"" + projectFile + "\" for writing"); project << "\n" "\n" "\t\n"; OUTPUT_CONFIGURATION_MSBUILD("Debug", "Win32"); OUTPUT_CONFIGURATION_MSBUILD("Debug", "x64"); OUTPUT_CONFIGURATION_MSBUILD("Analysis", "Win32"); OUTPUT_CONFIGURATION_MSBUILD("Analysis", "x64"); OUTPUT_CONFIGURATION_MSBUILD("Release", "Win32"); OUTPUT_CONFIGURATION_MSBUILD("Release", "x64"); project << "\t\n"; // Project name & Guid project << "\t\n" "\t\t{" << uuid << "}\n" "\t\t" << name << "\n" "\t\tWin32Proj\n" "\t\n"; // Shared configuration project << "\t\n"; OUTPUT_CONFIGURATION_TYPE_MSBUILD("Release|Win32"); OUTPUT_CONFIGURATION_TYPE_MSBUILD("Analysis|Win32"); OUTPUT_CONFIGURATION_TYPE_MSBUILD("Debug|Win32"); OUTPUT_CONFIGURATION_TYPE_MSBUILD("Release|x64"); OUTPUT_CONFIGURATION_TYPE_MSBUILD("Analysis|x64"); OUTPUT_CONFIGURATION_TYPE_MSBUILD("Debug|x64"); project << "\t\n" "\t\n" "\t\n"; OUTPUT_PROPERTIES_MSBUILD("Release|Win32", "ScummVM_Release.props"); OUTPUT_PROPERTIES_MSBUILD("Analysis|Win32", "ScummVM_Analysis.props"); OUTPUT_PROPERTIES_MSBUILD("Debug|Win32", "ScummVM_Debug.props"); OUTPUT_PROPERTIES_MSBUILD("Release|x64", "ScummVM_Release64.props"); OUTPUT_PROPERTIES_MSBUILD("Analysis|x64", "ScummVM_Analysis64.props"); OUTPUT_PROPERTIES_MSBUILD("Debug|x64", "ScummVM_Debug64.props"); project << "\t\n"; // Project-specific settings (analysis uses debug properties) outputProjectSettings(project, name, setup, false, true, false); outputProjectSettings(project, name, setup, false, true, true); outputProjectSettings(project, name, setup, true, true, false); outputProjectSettings(project, name, setup, false, false, false); outputProjectSettings(project, name, setup, false, false, true); outputProjectSettings(project, name, setup, true, false, false); // Files std::string modulePath; if (!moduleDir.compare(0, setup.srcDir.size(), setup.srcDir)) { modulePath = moduleDir.substr(setup.srcDir.size()); if (!modulePath.empty() && modulePath.at(0) == '/') modulePath.erase(0, 1); } if (modulePath.size()) addFilesToProject(moduleDir, project, includeList, excludeList, setup.filePrefix + '/' + modulePath); else addFilesToProject(moduleDir, project, includeList, excludeList, setup.filePrefix); // Output references for scummvm project if (name == "scummvm") writeReferences(project); project << "\t\n" "\t\n" "\t\n" "\n"; // Output filter file if necessary createFiltersFile(setup, name); } #define OUTPUT_FILTER_MSBUILD(files, action) \ if (!files.empty()) { \ filters << "\t\n"; \ for (std::list::const_iterator entry = files.begin(); entry != files.end(); ++entry) { \ if ((*entry).filter != "") { \ filters << "\t\t<" action " Include=\"" << (*entry).path << "\">\n" \ "\t\t\t" << (*entry).filter << "\n" \ "\t\t\n"; \ } else { \ filters << "\t\t<" action " Include=\"" << (*entry).path << "\" />\n"; \ } \ } \ filters << "\t\n"; \ } void MSBuildProvider::createFiltersFile(const BuildSetup &setup, const std::string &name) { // No filters => no need to create a filter file if (_filters.empty()) return; // Sort all list alphabetically _filters.sort(); _compileFiles.sort(); _includeFiles.sort(); _otherFiles.sort(); _resourceFiles.sort(); _asmFiles.sort(); const std::string filtersFile = setup.outputDir + '/' + name + getProjectExtension() + ".filters"; std::ofstream filters(filtersFile.c_str()); if (!filters) error("Could not open \"" + filtersFile + "\" for writing"); filters << "\n" "\n"; // Output the list of filters filters << "\t\n"; for (std::list::iterator filter = _filters.begin(); filter != _filters.end(); ++filter) { filters << "\t\t\n" "\t\t\t" << createUUID() << "\n" "\t\t\n"; } filters << "\t\n"; // Output files OUTPUT_FILTER_MSBUILD(_compileFiles, "ClCompile") OUTPUT_FILTER_MSBUILD(_includeFiles, "ClInclude") OUTPUT_FILTER_MSBUILD(_otherFiles, "None") OUTPUT_FILTER_MSBUILD(_resourceFiles, "ResourceCompile") OUTPUT_FILTER_MSBUILD(_asmFiles, "CustomBuild") filters << ""; } void MSBuildProvider::writeReferences(std::ofstream &output) { output << "\t\n"; for (UUIDMap::const_iterator i = _uuidMap.begin(); i != _uuidMap.end(); ++i) { if (i->first == "scummvm") continue; output << "\tfirst << ".vcxproj\">\n" "\t\t{" << i->second << "}\n" "\t\n"; } output << "\t\n"; } void MSBuildProvider::outputProjectSettings(std::ofstream &project, const std::string &name, const BuildSetup &setup, bool isRelease, bool isWin32, bool enableAnalysis) { const std::string configuration = (enableAnalysis ? "Analysis" : (isRelease ? "Release" : "Debug")); // Check for project-specific warnings: std::map::iterator warningsIterator = _projectWarnings.find(name); // Nothing to add here, move along! if (name != "scummvm" && name != "sword25" && name != "tinsel" && warningsIterator == _projectWarnings.end()) return; std::string warnings = ""; if (warningsIterator != _projectWarnings.end()) for (StringList::const_iterator i = warningsIterator->second.begin(); i != warningsIterator->second.end(); ++i) warnings += *i + ';'; project << "\t\n" "\t\t\n"; // Compile configuration if (name == "scummvm" || name == "sword25") { project << "\t\t\tfalse\n"; } else { if (name == "tinsel" && !isRelease) project << "\t\t\tProgramDatabase\n"; if (warningsIterator != _projectWarnings.end()) project << "\t\t\t" << warnings << ";%(DisableSpecificWarnings)\n"; } project << "\t\t\n"; // Link configuration for scummvm project if (name == "scummvm") { std::string libraries; for (StringList::const_iterator i = setup.libraries.begin(); i != setup.libraries.end(); ++i) libraries += *i + ".lib;"; project << "\t\t\n" "\t\t\t$(OutDir)scummvm.exe\n" "\t\t\t" << libraries << "%(AdditionalDependencies)\n" "\t\t\n"; // Only generate revision number in debug builds if (!isRelease) { project << "\t\t\n" "\t\t\tGenerate internal_version.h\n" "\t\t\t" << getRevisionToolCommandLine() << "\n" "\t\t\n"; } // Copy data files to the build folder project << "\t\t\n" "\t\t\tCopy data files to the build folder\n" "\t\t\t" << getCopyDataCommandLine(isWin32) << "\n" "\t\t\n"; } project << "\t\n"; } void MSBuildProvider::outputGlobalPropFile(std::ofstream &properties, int bits, const StringList &defines, const std::string &prefix) { std::string warnings; for (StringList::const_iterator i = _globalWarnings.begin(); i != _globalWarnings.end(); ++i) warnings += *i + ';'; std::string definesList; for (StringList::const_iterator i = defines.begin(); i != defines.end(); ++i) definesList += *i + ';'; properties << "\n" "\n" "\t\n" "\t\t<_ProjectFileVersion>10.0.30319.1\n" "\t\t<_PropertySheetDisplayName>ScummVM_Global\n" "\t\t$(SCUMMVM_LIBS)\\bin;$(ExecutablePath)\n" "\t\t$(SCUMMVM_LIBS)\\lib\\" << (bits == 32 ? "x86" : "x64") << ";$(LibraryPath)\n" "\t\t$(SCUMMVM_LIBS)\\include;$(IncludePath)\n" "\t\t$(Configuration)" << bits << "\\\n" "\t\t$(Configuration)" << bits << "/$(ProjectName)\\\n" "\t\n" "\t\n" "\t\t\n" "\t\t\ttrue\n" "\t\t\t" << warnings << ";%(DisableSpecificWarnings)\n" "\t\t\t$(SCUMMVM_LIBS)\\include;" << prefix << ";" << prefix << "\\engines;%(AdditionalIncludeDirectories)\n" "\t\t\t" << definesList << "%(PreprocessorDefinitions)\n" "\t\t\t\n" "\t\t\tfalse\n" "\t\t\tLevel4\n" "\t\t\tfalse\n" "\t\t\tDefault\n" "\t\t\n" "\t\t\n" "\t\t\t%(IgnoreSpecificDefaultLibraries)\n" "\t\t\tConsole\n" "\t\t\tWinMainCRTStartup\n" "\t\t\n" "\t\t\n" "\t\t\tHAS_INCLUDE_SET;%(PreprocessorDefinitions)\n" "\t\t\t" << prefix << ";%(AdditionalIncludeDirectories)\n" "\t\t\n" "\t\n" "\n"; properties.flush(); } void MSBuildProvider::createBuildProp(const BuildSetup &setup, bool isRelease, bool isWin32, bool enableAnalysis) { const std::string outputType = (enableAnalysis ? "Analysis" : (isRelease ? "Release" : "Debug")); const std::string outputBitness = (isWin32 ? "32" : "64"); std::ofstream properties((setup.outputDir + '/' + "ScummVM_" + outputType + (isWin32 ? "" : "64") + getPropertiesExtension()).c_str()); if (!properties) error("Could not open \"" + setup.outputDir + '/' + "ScummVM_" + outputType + (isWin32 ? "" : "64") + getPropertiesExtension() + "\" for writing"); properties << "\n" "\n" "\t\n" "\t\t\n" "\t\n" "\t\n" "\t\t<_ProjectFileVersion>10.0.30319.1\n" "\t\t<_PropertySheetDisplayName>ScummVM_" << outputType << outputBitness << "\n" "\t\t" << (isRelease ? "false" : "true") << "\n" "\t\n" "\t\n" "\t\t\n"; if (isRelease) { properties << "\t\t\ttrue\n" "\t\t\ttrue\n" "\t\t\tWIN32;RELEASE_BUILD;%(PreprocessorDefinitions)\n" "\t\t\ttrue\n" "\t\t\tfalse\n" "\t\t\t\n" "\t\t\t" << (enableAnalysis ? "true" : "false") << "\n" "\t\t\n" "\t\t\n" "\t\t\t%(IgnoreSpecificDefaultLibraries)\n" "\t\t\ttrue\n"; } else { properties << "\t\t\tDisabled\n" "\t\t\tWIN32;%(PreprocessorDefinitions)\n" "\t\t\ttrue\n" "\t\t\tEnableFastChecks\n" "\t\t\tMultiThreadedDebug\n" "\t\t\ttrue\n" "\t\t\tfalse\n" "\t\t\t" << (isWin32 ? "EditAndContinue" : "ProgramDatabase") << "\n" // For x64 format Edit and continue is not supported, thus we default to Program Database "\t\t\t" << (enableAnalysis ? "true" : "false") << "\n" "\t\t\n" "\t\t\n" "\t\t\ttrue\n" "\t\t\tlibcmt.lib;%(IgnoreSpecificDefaultLibraries)\n"; } properties << "\t\t\n" "\t\n" "\n"; properties.flush(); properties.close(); } #define OUTPUT_NASM_COMMAND_MSBUILD(config) \ projectFile << "\t\t\tnasm.exe -f win32 -g -o \"$(IntDir)" << (isDuplicate ? (*entry).prefix : "") << "%(Filename).obj\" \"%(FullPath)\"\n" \ "\t\t\t$(IntDir)" << (isDuplicate ? (*entry).prefix : "") << "%(Filename).obj;%(Outputs)\n"; #define OUPUT_OBJECT_FILENAME_MSBUILD(config, platform, prefix) \ projectFile << "\t\t$(IntDir)" << prefix << "%(Filename).obj\n" \ "\t\t$(IntDir)" << prefix << "%(Filename).xdc\n"; #define OUPUT_FILES_MSBUILD(files, action) \ if (!files.empty()) { \ projectFile << "\t\n"; \ for (std::list::const_iterator entry = files.begin(); entry != files.end(); ++entry) { \ projectFile << "\t\t<" action " Include=\"" << (*entry).path << "\" />\n"; \ } \ projectFile << "\t\n"; \ } void MSBuildProvider::writeFileListToProject(const FileNode &dir, std::ofstream &projectFile, const int, const StringList &duplicate, const std::string &objPrefix, const std::string &filePrefix) { // Reset lists _filters.clear(); _compileFiles.clear(); _includeFiles.clear(); _otherFiles.clear(); _resourceFiles.clear(); _asmFiles.clear(); // Compute the list of files _filters.push_back(""); // init filters computeFileList(dir, duplicate, objPrefix, filePrefix); _filters.pop_back(); // remove last empty filter // Output compile files if (!_compileFiles.empty()) { projectFile << "\t\n"; for (std::list::const_iterator entry = _compileFiles.begin(); entry != _compileFiles.end(); ++entry) { const bool isDuplicate = (std::find(duplicate.begin(), duplicate.end(), (*entry).name + ".o") != duplicate.end()); // Deal with duplicated file names if (isDuplicate) { projectFile << "\t\t\n"; OUPUT_OBJECT_FILENAME_MSBUILD("Debug", "Win32", (*entry).prefix) OUPUT_OBJECT_FILENAME_MSBUILD("Debug", "x64", (*entry).prefix) OUPUT_OBJECT_FILENAME_MSBUILD("Analysis", "Win32", (*entry).prefix) OUPUT_OBJECT_FILENAME_MSBUILD("Analysis", "x64", (*entry).prefix) OUPUT_OBJECT_FILENAME_MSBUILD("Release", "Win32", (*entry).prefix) OUPUT_OBJECT_FILENAME_MSBUILD("Release", "x64", (*entry).prefix) projectFile << "\t\t\n"; } else { projectFile << "\t\t\n"; } } projectFile << "\t\n"; } // Output include, other and resource files OUPUT_FILES_MSBUILD(_includeFiles, "ClInclude") OUPUT_FILES_MSBUILD(_otherFiles, "None") OUPUT_FILES_MSBUILD(_resourceFiles, "ResourceCompile") // Output asm files if (!_asmFiles.empty()) { projectFile << "\t\n"; for (std::list::const_iterator entry = _asmFiles.begin(); entry != _asmFiles.end(); ++entry) { const bool isDuplicate = (std::find(duplicate.begin(), duplicate.end(), (*entry).name + ".o") != duplicate.end()); projectFile << "\t\t\n" "\t\t\tDocument\n"; OUTPUT_NASM_COMMAND_MSBUILD("Debug") OUTPUT_NASM_COMMAND_MSBUILD("Analysis") OUTPUT_NASM_COMMAND_MSBUILD("Release") projectFile << "\t\t\n"; } projectFile << "\t\n"; } } void MSBuildProvider::computeFileList(const FileNode &dir, const StringList &duplicate, const std::string &objPrefix, const std::string &filePrefix) { for (FileNode::NodeList::const_iterator i = dir.children.begin(); i != dir.children.end(); ++i) { const FileNode *node = *i; if (!node->children.empty()) { // Update filter std::string _currentFilter = _filters.back(); _filters.back().append((_filters.back() == "" ? "" : "\\") + node->name); computeFileList(*node, duplicate, objPrefix + node->name + '_', filePrefix + node->name + '/'); // Reset filter _filters.push_back(_currentFilter); } else { // Filter files by extension std::string name, ext; splitFilename(node->name, name, ext); FileEntry entry; entry.name = name; entry.path = convertPathToWin(filePrefix + node->name); entry.filter = _filters.back(); entry.prefix = objPrefix; if (ext == "cpp" || ext == "c") _compileFiles.push_back(entry); else if (ext == "h") _includeFiles.push_back(entry); else if (ext == "rc") _resourceFiles.push_back(entry); else if (ext == "asm") _asmFiles.push_back(entry); else _otherFiles.push_back(entry); } } } } // End of CreateProjectTool namespace