Ticket #9137: TOOLS - Add create_project tool.patch

File TOOLS - Add create_project tool.patch, 134.0 KB (added by Templier, 9 years ago)

4 - Add create_project tool

  • new file tools/create_project/codeblocks.cpp

    # HG changeset patch
    # User Julien <littleboy@users.sf.net>
    # Parent e24b1c8ca9425663ae80cc825fe59bf7f37acc44
    TOOLS: Add create_project tool
    
    diff -r e24b1c8ca942 tools/create_project/codeblocks.cpp
    - +  
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11 *
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL$
     22 * $Id$
     23 *
     24 */
     25
     26#include "codeblocks.h"
     27
     28#include <fstream>
     29
     30namespace CreateProjectTool {
     31
     32CodeBlocksProvider::CodeBlocksProvider(StringList &global_warnings, std::map<std::string, StringList> &project_warnings, const int version)
     33        : ProjectProvider(global_warnings, project_warnings, version) {
     34}
     35
     36void CodeBlocksProvider::createWorkspace(const BuildSetup &setup) {
     37        std::ofstream workspace((setup.outputDir + '/' + "scummvm.workspace").c_str());
     38        if (!workspace)
     39                error("Could not open \"" + setup.outputDir + '/' + "scummvm.workspace\" for writing");
     40
     41        workspace << "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\n"
     42                     "<CodeBlocks_workspace_file>\n";
     43
     44        workspace << "\t<Workspace title=\"ScummVM\">\n";
     45
     46        writeReferences(workspace);
     47
     48        // Note we assume that the UUID map only includes UUIDs for enabled engines!
     49        for (UUIDMap::const_iterator i = _uuidMap.begin(); i != _uuidMap.end(); ++i) {
     50                if (i->first == "scummvm")
     51                        continue;
     52
     53                workspace << "\t\t<Project filename=\"" << i->first << ".cbp\" />\n";
     54        }
     55
     56        workspace << "\t</Workspace>\n"
     57                     "</CodeBlocks_workspace_file>";
     58}
     59
     60void CodeBlocksProvider::createProjectFile(const std::string &name, const std::string &, const BuildSetup &setup, const std::string &moduleDir,
     61                                           const StringList &includeList, const StringList &excludeList) {
     62
     63        const std::string projectFile = setup.outputDir + '/' + name + getProjectExtension();
     64        std::ofstream project(projectFile.c_str());
     65        if (!project)
     66                error("Could not open \"" + projectFile + "\" for writing");
     67
     68        project << "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\n"
     69                   "<CodeBlocks_project_file>\n"
     70                   "\t<FileVersion major=\"1\" minor=\"6\" />\n"
     71                   "\t<Project>\n"
     72                   "\t\t<Option title=\"" << name << "\" />\n"
     73                   "\t\t<Option pch_mode=\"2\" />\n"
     74                   "\t\t<Option compiler=\"gcc\" />\n"
     75                   "\t\t<Build>\n";
     76
     77        if (name == "scummvm") {
     78                std::string libraries;
     79
     80                for (StringList::const_iterator i = setup.libraries.begin(); i != setup.libraries.end(); ++i)
     81                        libraries += *i + ".a;";
     82
     83                project << "\t\t\t<Target title=\"default\">\n"
     84                           "\t\t\t\t<Option output=\"scummvm\\scummvm\" prefix_auto=\"1\" extension_auto=\"1\" />\n"
     85                           "\t\t\t\t<Option object_output=\"scummvm\" />\n"
     86                           "\t\t\t\t<Option external_deps=\"" << libraries /* + list of engines scummvm\engines\name\name.a */ << "\" />\n"
     87                           "\t\t\t\t<Option type=\"1\" />\n"
     88                           "\t\t\t\t<Option compiler=\"gcc\" />\n"
     89                           "\t\t\t\t<Option parameters=\"-d 8 --debugflags=parser\" />\n"
     90                           "\t\t\t\t<Option projectIncludeDirsRelation=\"2\" />\n";
     91
     92                //////////////////////////////////////////////////////////////////////////
     93                // Compiler
     94                project << "\t\t\t\t<Compiler>\n";
     95
     96                writeWarnings(name, project);
     97                writeDefines(setup.defines, project);
     98
     99                project << "\t\t\t\t\t<Add directory=\"..\\..\" />\n"
     100                           "\t\t\t\t\t<Add directory=\"..\\..\\engines\" />\n"
     101                           "\t\t\t\t\t<Add directory=\"..\\..\\common\" />\n"
     102                           "\t\t\t\t\t<Add directory=\"$(SCUMMVM_LIBS)\\include\" />\n"
     103                           "\t\t\t\t</Compiler>\n";
     104
     105                //////////////////////////////////////////////////////////////////////////
     106                // Linker
     107                project << "\t\t\t\t<Linker>\n";
     108
     109                for (StringList::const_iterator i = setup.libraries.begin(); i != setup.libraries.end(); ++i)
     110                        project << "\t\t\t\t\t<Add library=\"" << *i << ".a\" />\n";
     111
     112                for (UUIDMap::const_iterator i = _uuidMap.begin(); i != _uuidMap.end(); ++i) {
     113                        if (i->first == "scummvm")
     114                                continue;
     115
     116                        project << "\t\t\t\t\t<Add library=\"scummvm\\engines\\" << i->first << "\\lib" << i->first << ".a\" />\n";
     117                }
     118
     119                project << "\t\t\t\t\t<Add directory=\"$(SCUMMVM_LIBS)\\lib\" />\n"
     120                           "\t\t\t\t</Linker>\n";
     121
     122                //////////////////////////////////////////////////////////////////////////
     123                // Resource compiler
     124                project << "\t\t\t\t<ResourceCompiler>\n"
     125                           "\t\t\t\t\t<Add directory=\"..\\..\\dists\" />\n"
     126                           "\t\t\t\t\t<Add directory=\"..\\..\\..\\scummvm\" />\n"
     127                           "\t\t\t\t</ResourceCompiler>\n"
     128                           "\t\t\t</Target>\n"
     129                           "\t\t</Build>\n";
     130
     131
     132
     133        } else {
     134                project << "\t\t\t<Target title=\"default\">\n"
     135                           "\t\t\t\t<Option output=\"scummvm\\engines\\" << name << "\\lib" << name << "\" prefix_auto=\"1\" extension_auto=\"1\" />\n"
     136                           "\t\t\t\t<Option working_dir=\"\" />\n"
     137                           "\t\t\t\t<Option object_output=\"scummvm\" />\n"
     138                           "\t\t\t\t<Option type=\"2\" />\n"
     139                           "\t\t\t\t<Option compiler=\"gcc\" />\n"
     140                           "\t\t\t\t<Option createDefFile=\"1\" />\n"
     141                           "\t\t\t\t<Compiler>\n";
     142
     143                writeWarnings(name, project);
     144                writeDefines(setup.defines, project);
     145
     146                project << "\t\t\t\t\t<Add option=\"-g\" />\n"
     147                           "\t\t\t\t\t<Add directory=\"..\\..\\engines\" />\n"
     148                           "\t\t\t\t\t<Add directory=\"..\\..\\..\\scummvm\" />\n"
     149                           "\t\t\t\t</Compiler>\n"
     150                           "\t\t\t</Target>\n"
     151                           "\t\t</Build>\n";
     152        }
     153
     154        std::string modulePath;
     155        if (!moduleDir.compare(0, setup.srcDir.size(), setup.srcDir)) {
     156                modulePath = moduleDir.substr(setup.srcDir.size());
     157                if (!modulePath.empty() && modulePath.at(0) == '/')
     158                        modulePath.erase(0, 1);
     159        }
     160
     161        if (modulePath.size())
     162                addFilesToProject(moduleDir, project, includeList, excludeList, setup.filePrefix + '/' + modulePath);
     163        else
     164                addFilesToProject(moduleDir, project, includeList, excludeList, setup.filePrefix);
     165
     166
     167        project << "\t\t<Extensions>\n"
     168                   "\t\t\t<code_completion />\n"
     169                   "\t\t\t<debugger />\n"
     170                   "\t\t</Extensions>\n"
     171                   "\t</Project>\n"
     172                   "</CodeBlocks_project_file>";
     173
     174}
     175
     176void CodeBlocksProvider::writeWarnings(const std::string &name, std::ofstream &output) const {
     177
     178        // Global warnings
     179        for (StringList::const_iterator i = _globalWarnings.begin(); i != _globalWarnings.end(); ++i)
     180                output << "\t\t\t\t\t<Add option=\"" << *i << "\" />\n";
     181
     182        // Check for project-specific warnings:
     183        std::map<std::string, StringList>::iterator warningsIterator = _projectWarnings.find(name);
     184        if (warningsIterator != _projectWarnings.end())
     185                for (StringList::const_iterator i = warningsIterator->second.begin(); i != warningsIterator->second.end(); ++i)
     186                        output << "\t\t\t\t\t<Add option=\"" << *i << "\" />\n";
     187
     188}
     189
     190void CodeBlocksProvider::writeDefines(const StringList &defines, std::ofstream &output) const {
     191        for (StringList::const_iterator i = defines.begin(); i != defines.end(); ++i)
     192                output << "\t\t\t\t\t<Add option=\"-D" << *i << "\" />\n";
     193}
     194
     195void CodeBlocksProvider::writeFileListToProject(const FileNode &dir, std::ofstream &projectFile, const int indentation,
     196                                                const StringList &duplicate, const std::string &objPrefix, const std::string &filePrefix) {
     197
     198        for (FileNode::NodeList::const_iterator i = dir.children.begin(); i != dir.children.end(); ++i) {
     199                const FileNode *node = *i;
     200
     201                if (!node->children.empty()) {
     202                        writeFileListToProject(*node, projectFile, indentation + 1, duplicate, objPrefix + node->name + '_', filePrefix + node->name + '/');
     203                } else {
     204                        std::string name, ext;
     205                        splitFilename(node->name, name, ext);
     206
     207                        if (ext == "rc") {
     208                                projectFile << "\t\t<Unit filename=\"" << convertPathToWin(filePrefix + node->name) << "\">\n"
     209                                               "\t\t\t<Option compilerVar=\"WINDRES\" />\n"
     210                                               "\t\t</Unit>\n";
     211
     212                        } else {
     213                                projectFile << "\t\t<Unit filename=\"" << convertPathToWin(filePrefix + node->name) << "\" />\n";
     214                        }
     215                }
     216        }
     217}
     218
     219void CodeBlocksProvider::writeReferences(std::ofstream &output) {
     220        output << "\t\t<Project filename=\"scummvm.cbp\" active=\"1\">\n";
     221
     222        for (UUIDMap::const_iterator i = _uuidMap.begin(); i != _uuidMap.end(); ++i) {
     223                if (i->first == "scummvm")
     224                        continue;
     225
     226                output << "\t\t\t<Depends filename=\"" << i->first << ".cbp\" />\n";
     227        }
     228
     229        output << "\t\t</Project>\n";
     230}
     231
     232const char *CodeBlocksProvider::getProjectExtension() {
     233        return ".cbp";
     234}
     235
     236
     237} // End of CreateProjectTool namespace
  • new file tools/create_project/codeblocks.h

    diff -r e24b1c8ca942 tools/create_project/codeblocks.h
    - +  
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11 *
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL$
     22 * $Id$
     23 *
     24 */
     25
     26#ifndef TOOLS_CREATE_PROJECT_CODEBLOCKS_H
     27#define TOOLS_CREATE_PROJECT_CODEBLOCKS_H
     28
     29#include "create_project.h"
     30
     31namespace CreateProjectTool {
     32
     33class CodeBlocksProvider : public ProjectProvider {
     34public:
     35        CodeBlocksProvider(StringList &global_warnings, std::map<std::string, StringList> &project_warnings, const int version = 0);
     36
     37protected:
     38
     39        void createWorkspace(const BuildSetup &setup);
     40
     41        void createOtherBuildFiles(const BuildSetup &) {}
     42
     43        void createProjectFile(const std::string &name, const std::string &uuid, const BuildSetup &setup, const std::string &moduleDir,
     44                               const StringList &includeList, const StringList &excludeList);
     45
     46        void writeFileListToProject(const FileNode &dir, std::ofstream &projectFile, const int indentation,
     47                                    const StringList &duplicate, const std::string &objPrefix, const std::string &filePrefix);
     48
     49        void writeReferences(std::ofstream &output);
     50
     51        const char *getProjectExtension();
     52
     53private:
     54        void writeWarnings(const std::string &name, std::ofstream &output) const;
     55        void writeDefines(const StringList &defines, std::ofstream &output) const;
     56};
     57
     58} // End of CreateProjectTool namespace
     59
     60#endif // TOOLS_CREATE_PROJECT_CODEBLOCKS_H
  • new file tools/create_project/create_project.cpp

    diff -r e24b1c8ca942 tools/create_project/create_project.cpp
    - +  
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11 *
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL$
     22 * $Id$
     23 *
     24 */
     25
     26#include "create_project.h"
     27#include "codeblocks.h"
     28#include "msvc.h"
     29
     30#include <fstream>
     31#include <iostream>
     32
     33#include <stack>
     34#include <algorithm>
     35#include <iomanip>
     36
     37#include <cstring>
     38#include <cstdlib>
     39#include <ctime>
     40
     41#if defined(_WIN32) || defined(WIN32)
     42#include <windows.h>
     43#else
     44#include <sstream>
     45#include <sys/param.h>
     46#include <sys/stat.h>
     47#include <dirent.h>
     48#endif
     49
     50namespace {
     51/**
     52 * Converts the given path to only use slashes as
     53 * delimiters.
     54 * This means that for example the path:
     55 *  foo/bar\test.txt
     56 * will be converted to:
     57 *  foo/bar/test.txt
     58 *
     59 * @param path Path string.
     60 * @return Converted path.
     61 */
     62std::string unifyPath(const std::string &path);
     63
     64/**
     65 * Returns the last path component.
     66 *
     67 * @param path Path string.
     68 * @return Last path component.
     69 */
     70std::string getLastPathComponent(const std::string &path);
     71
     72/**
     73 * Display the help text for the program.
     74 *
     75 * @param exe Name of the executable.
     76 */
     77void displayHelp(const char *exe);
     78
     79/**
     80 * Structure for describing an FSNode. This is a very minimalistic
     81 * description, which includes everything we need.
     82 * It only contains the name of the node and whether it is a directory
     83 * or not.
     84 */
     85struct FSNode {
     86        FSNode() : name(), isDirectory(false) {}
     87        FSNode(const std::string &n, bool iD) : name(n), isDirectory(iD) {}
     88
     89        std::string name; ///< Name of the file system node
     90        bool isDirectory; ///< Whether it is a directory or not
     91};
     92
     93typedef std::list<FSNode> FileList;
     94} // End of anonymous namespace
     95
     96enum ProjectType {
     97        kProjectNone,
     98        kProjectCodeBlocks,
     99        kProjectMSVC
     100};
     101
     102int main(int argc, char *argv[]) {
     103#if !(defined(_WIN32) || defined(WIN32))
     104        // Initialize random number generator for UUID creation
     105        std::srand(std::time(0));
     106#endif
     107
     108        if (argc < 2) {
     109                displayHelp(argv[0]);
     110                return -1;
     111        }
     112
     113        const std::string srcDir = argv[1];
     114
     115        BuildSetup setup;
     116        setup.srcDir = unifyPath(srcDir);
     117
     118        if (setup.srcDir.at(setup.srcDir.size() - 1) == '/')
     119                setup.srcDir.erase(setup.srcDir.size() - 1);
     120
     121        setup.filePrefix = setup.srcDir;
     122        setup.outputDir = '.';
     123
     124        setup.engines = parseConfigure(setup.srcDir);
     125
     126        if (setup.engines.empty()) {
     127                std::cout << "WARNING: No engines found in configure file or configure file missing in \"" << setup.srcDir << "\"\n";
     128                return 0;
     129        }
     130
     131        setup.features = getAllFeatures();
     132
     133        ProjectType projectType = kProjectNone;
     134        int msvcVersion = 9;
     135
     136        // Parse command line arguments
     137        using std::cout;
     138        for (int i = 2; i < argc; ++i) {
     139                if (!std::strcmp(argv[i], "--list-engines")) {
     140                        cout << " The following enables are available in the ScummVM source distribution\n"
     141                                " located at \"" << srcDir << "\":\n";
     142
     143                        cout << "   state  |       name      |     description\n\n";
     144                        cout.setf(std::ios_base::left, std::ios_base::adjustfield);
     145                        for (EngineDescList::const_iterator j = setup.engines.begin(); j != setup.engines.end(); ++j)
     146                                cout << ' ' << (j->enable ? " enabled" : "disabled") << " | " << std::setw((std::streamsize)15) << j->name << std::setw((std::streamsize)0) << " | " << j->desc << "\n";
     147                        cout.setf(std::ios_base::right, std::ios_base::adjustfield);
     148
     149                        return 0;
     150
     151                } else if (!std::strcmp(argv[i], "--codeblocks")) {
     152                        if (projectType != kProjectNone) {
     153                                std::cerr << "ERROR: You cannot pass more than one project type!\n";
     154                                return -1;
     155                        }
     156
     157                        projectType = kProjectCodeBlocks;
     158
     159                } else if (!std::strcmp(argv[i], "--msvc")) {
     160                        if (projectType != kProjectNone) {
     161                                std::cerr << "ERROR: You cannot pass more than one project type!\n";
     162                                return -1;
     163                        }
     164
     165                        projectType = kProjectMSVC;
     166
     167                } else if (!std::strcmp(argv[i], "--msvc-version")) {
     168                        if (i + 1 >= argc) {
     169                                std::cerr << "ERROR: Missing \"version\" parameter for \"--msvc-version\"!\n";
     170                                return -1;
     171                        }
     172
     173                        msvcVersion = atoi(argv[++i]);
     174
     175                        if (msvcVersion != 8 && msvcVersion != 9 && msvcVersion != 10) {
     176                                std::cerr << "ERROR: Unsupported version: \"" << msvcVersion << "\" passed to \"--msvc-version\"!\n";
     177                                return -1;
     178                        }
     179                } else if (!strncmp(argv[i], "--enable-", 9)) {
     180                        const char *name = &argv[i][9];
     181                        if (!*name) {
     182                                std::cerr << "ERROR: Invalid command \"" << argv[i] << "\"\n";
     183                                return -1;
     184                        }
     185
     186                        if (!std::strcmp(name, "all-engines")) {
     187                                for (EngineDescList::iterator j = setup.engines.begin(); j != setup.engines.end(); ++j)
     188                                        j->enable = true;
     189                        } else if (!setEngineBuildState(name, setup.engines, true)) {
     190                                // If none found, we'll try the features list
     191                                if (!setFeatureBuildState(name, setup.features, true)) {
     192                                        std::cerr << "ERROR: \"" << name << "\" is neither an engine nor a feature!\n";
     193                                        return -1;
     194                                }
     195                        }
     196                } else if (!strncmp(argv[i], "--disable-", 10)) {
     197                        const char *name = &argv[i][10];
     198                        if (!*name) {
     199                                std::cerr << "ERROR: Invalid command \"" << argv[i] << "\"\n";
     200                                return -1;
     201                        }
     202
     203                        if (!std::strcmp(name, "all-engines")) {
     204                                for (EngineDescList::iterator j = setup.engines.begin(); j != setup.engines.end(); ++j)
     205                                        j->enable = false;
     206                        } else if (!setEngineBuildState(name, setup.engines, false)) {
     207                                // If none found, we'll try the features list
     208                                if (!setFeatureBuildState(name, setup.features, false)) {
     209                                        std::cerr << "ERROR: \"" << name << "\" is neither an engine nor a feature!\n";
     210                                        return -1;
     211                                }
     212                        }
     213                } else if (!std::strcmp(argv[i], "--file-prefix")) {
     214                        if (i + 1 >= argc) {
     215                                std::cerr << "ERROR: Missing \"prefix\" parameter for \"--file-prefix\"!\n";
     216                                return -1;
     217                        }
     218
     219                        setup.filePrefix = unifyPath(argv[++i]);
     220                        if (setup.filePrefix.at(setup.filePrefix.size() - 1) == '/')
     221                                setup.filePrefix.erase(setup.filePrefix.size() - 1);
     222                } else if (!std::strcmp(argv[i], "--output-dir")) {
     223                        if (i + 1 >= argc) {
     224                                std::cerr << "ERROR: Missing \"path\" parameter for \"--output-dirx\"!\n";
     225                                return -1;
     226                        }
     227
     228                        setup.outputDir = unifyPath(argv[++i]);
     229                        if (setup.outputDir.at(setup.outputDir.size() - 1) == '/')
     230                                setup.outputDir.erase(setup.outputDir.size() - 1);
     231                } else {
     232                        std::cerr << "ERROR: Unknown parameter \"" << argv[i] << "\"\n";
     233                        return -1;
     234                }
     235        }
     236
     237        // Print status
     238        cout << "Enabled engines:\n\n";
     239        for (EngineDescList::const_iterator i = setup.engines.begin(); i != setup.engines.end(); ++i) {
     240                if (i->enable)
     241                        cout << "    " << i->desc << '\n';
     242        }
     243
     244        cout << "\nDisabled engines:\n\n";
     245        for (EngineDescList::const_iterator i = setup.engines.begin(); i != setup.engines.end(); ++i) {
     246                if (!i->enable)
     247                        cout << "    " << i->desc << '\n';
     248        }
     249
     250        cout << "\nEnabled features:\n\n";
     251        for (FeatureList::const_iterator i = setup.features.begin(); i != setup.features.end(); ++i) {
     252                if (i->enable)
     253                        cout << "    " << i->description << '\n';
     254        }
     255
     256        cout << "\nDisabled features:\n\n";
     257        for (FeatureList::const_iterator i = setup.features.begin(); i != setup.features.end(); ++i) {
     258                if (!i->enable)
     259                        cout << "    " << i->description << '\n';
     260        }
     261
     262        // Creation...
     263        setup.defines = getEngineDefines(setup.engines);
     264        StringList featureDefines = getFeatureDefines(setup.features);
     265        setup.defines.splice(setup.defines.begin(), featureDefines);
     266
     267        setup.libraries = getFeatureLibraries(setup.features);
     268
     269        setup.libraries.push_back("winmm");
     270        setup.libraries.push_back("sdl");
     271
     272// Initialize global & project-specific warnings
     273#define SET_GLOBAL_WARNINGS(...) \
     274        { \
     275                std::string global[PP_NARG(__VA_ARGS__)] = { __VA_ARGS__ }; \
     276                globalWarnings.assign(global, global + (sizeof(global) / sizeof(global[0]))); \
     277        }
     278
     279#define SET_WARNINGS(name, ...) \
     280        { \
     281                std::string project[PP_NARG(__VA_ARGS__)] = { __VA_ARGS__ }; \
     282                projectWarnings[name].assign(project, project + (sizeof(project) / sizeof(project[0]))); \
     283        }
     284
     285        // List of global warnings and map of project-specific warnings
     286        StringList globalWarnings;
     287        std::map<std::string, StringList> projectWarnings;
     288
     289        CreateProjectTool::ProjectProvider *provider = NULL;
     290
     291        switch (projectType) {
     292        default:
     293        case kProjectNone:
     294                std::cerr << "ERROR: No project type has been specified!\n";
     295                return -1;
     296
     297        case kProjectCodeBlocks:
     298                ////////////////////////////////////////////////////////////////////////////
     299                // Code::Blocks is using GCC behind the scenes, so we need to pass a list
     300                // of options to enable or disable warnings
     301                ////////////////////////////////////////////////////////////////////////////
     302                //
     303                // -Wall
     304                //   enable all warnings
     305                //
     306                // -Wno-long-long -Wno-multichar -Wno-unknown-pragmas -Wno-reorder
     307                //   disable annoying and not-so-useful warnings
     308                //
     309                // -Wpointer-arith -Wcast-qual -Wcast-align
     310                // -Wshadow -Wimplicit -Wnon-virtual-dtor -Wwrite-strings
     311                //   enable even more warnings...
     312                //
     313                // -fno-rtti -fno-exceptions -fcheck-new
     314                //   disable RTTI and exceptions, and enable checking of pointers returned
     315                //   by "new"
     316                //
     317                ////////////////////////////////////////////////////////////////////////////
     318
     319                SET_GLOBAL_WARNINGS("-Wall", "-Wno-long-long", "-Wno-multichar", "-Wno-unknown-pragmas", "-Wno-reorder",
     320                                    "-Wpointer-arith", "-Wcast-qual", "-Wcast-align", "-Wshadow", "-Wimplicit",
     321                                    "-Wnon-virtual-dtor", "-Wwrite-strings", "-fno-rtti", "-fno-exceptions", "-fcheck-new");
     322
     323                provider = new CreateProjectTool::CodeBlocksProvider(globalWarnings, projectWarnings);
     324
     325                break;
     326
     327        case kProjectMSVC:
     328                ////////////////////////////////////////////////////////////////////////////
     329                // For Visual Studio, all warnings are on by default in the project files,
     330                // so we pass a list of warnings to disable globally or per-project
     331                //
     332                // Tracker reference:
     333                // https://sourceforge.net/tracker/?func=detail&aid=2909981&group_id=37116&atid=418822
     334                ////////////////////////////////////////////////////////////////////////////
     335                //
     336                // 4068 (unknown pragma)
     337                //   only used in scumm engine to mark code sections
     338                //
     339                // 4100 (unreferenced formal parameter)
     340                //
     341                // 4103 (alignment changed after including header, may be due to missing #pragma pack(pop))
     342                //   used by pack-start / pack-end
     343                //
     344                // 4127 (conditional expression is constant)
     345                //   used in a lot of engines
     346                //
     347                // 4244 ('conversion' conversion from 'type1' to 'type2', possible loss of data)
     348                //   throws tons and tons of warnings, most of them false positives
     349                //
     350                // 4250 ('class1' : inherits 'class2::member' via dominance)
     351                //   two or more members have the same name. Should be harmless
     352                //
     353                // 4310 (cast truncates constant value)
     354                //   used in some engines
     355                //
     356                // 4351 (new behavior: elements of array 'array' will be default initialized)
     357                //   a change in behavior in Visual Studio 2005. We want the new behavior, so it can be disabled
     358                //
     359                // 4512 ('class' : assignment operator could not be generated)
     360                //   some classes use const items and the default assignment operator cannot be generated
     361                //
     362                // 4702 (unreachable code)
     363                //   mostly thrown after error() calls (marked as NORETURN)
     364                //
     365                // 4706 (assignment within conditional expression)
     366                //   used in a lot of engines
     367                //
     368                // 4800 ('type' : forcing value to bool 'true' or 'false' (performance warning))
     369                //
     370                // 4996 ('function': was declared deprecated)
     371                //   disabling it removes all the non-standard unsafe functions warnings (strcpy_s, etc.)
     372                //
     373                ////////////////////////////////////////////////////////////////////////////
     374                //
     375                // 4189 (local variable is initialized but not referenced)
     376                //   false positive in lure engine
     377                //
     378                // 4355 ('this' : used in base member initializer list)
     379                //   only disabled for specific engines where it is used in a safe way
     380                //
     381                // 4510 ('class' : default constructor could not be generated)
     382                //
     383                // 4511 ('class' : copy constructor could not be generated)
     384                //
     385                // 4610 (object 'class' can never be instantiated - user-defined constructor required)
     386                //   "correct" but harmless (as is 4510)
     387                //
     388                ////////////////////////////////////////////////////////////////////////////
     389
     390                SET_GLOBAL_WARNINGS("4068", "4100", "4103", "4127", "4244", "4250", "4310", "4351", "4512", "4702", "4706", "4800", "4996");
     391                SET_WARNINGS("agi", "4510", "4610");
     392                SET_WARNINGS("agos", "4511");
     393                SET_WARNINGS("lure", "4189", "4355");
     394                SET_WARNINGS("kyra", "4355");
     395                SET_WARNINGS("m4", "4355");
     396
     397                if (msvcVersion == 8 || msvcVersion == 9)
     398                        provider = new CreateProjectTool::VisualStudioProvider(globalWarnings, projectWarnings, msvcVersion);
     399                else
     400                        provider = new CreateProjectTool::MSBuildProvider(globalWarnings, projectWarnings, msvcVersion);
     401
     402                break;
     403        }
     404
     405        provider->createProject(setup);
     406
     407        delete provider;
     408}
     409
     410namespace {
     411std::string unifyPath(const std::string &path) {
     412        std::string result = path;
     413        std::replace(result.begin(), result.end(), '\\', '/');
     414        return result;
     415}
     416
     417std::string getLastPathComponent(const std::string &path) {
     418        std::string::size_type pos = path.find_last_of('/');
     419        if (pos == std::string::npos)
     420                return path;
     421        else
     422                return path.substr(pos + 1);
     423}
     424
     425void displayHelp(const char *exe) {
     426        using std::cout;
     427
     428        cout << "Usage:\n"
     429             << exe << " path\\to\\source [optional options]\n"
     430             << "\n"
     431             << " Creates project files for the ScummVM source located at \"path\\to\\source\".\n"
     432                " The project files will be created in the directory where tool is run from and\n"
     433                " will include \"path\\to\\source\" for relative file paths, thus be sure that you\n"
     434                " pass a relative file path like \"..\\..\\trunk\".\n"
     435                "\n"
     436                " Additionally there are the following switches for changing various settings:\n"
     437                "\n"
     438                "Project specific settings:\n"
     439                " --codeblock              build Code::Blocks project files\n"
     440                " --msvc                   build Visual Studio project files\n"
     441                " --file-prefix prefix     allow overwriting of relative file prefix in the\n"
     442                "                          MSVC project files. By default the prefix is the\n"
     443                "                          \"path\\to\\source\" argument\n"
     444                " --output-dir path        overwrite path, where the project files are placed\n"
     445                "                          By default this is \".\", i.e. the current working\n"
     446                "                          directory\n"
     447                "\n"
     448                "MSVC specific settings:\n"
     449                " --msvc-version version   set the targeted MSVC version. Possible values:\n"
     450                "                           8 stands for \"Visual Studio 2005\"\n"
     451                "                           9 stands for \"Visual Studio 2008\"\n"
     452                "                           10 stands for \"Visual Studio 2010\"\n"
     453                "                           The default is \"9\", thus \"Visual Studio 2008\"\n"
     454                "\n"
     455                "ScummVM engine settings:\n"
     456                " --list-engines           list all available engines and their default state\n"
     457                " --enable-engine          enable building of the engine with the name \"engine\"\n"
     458                " --disable-engine         disable building of the engine with the name \"engine\"\n"
     459                " --enable-all-engines     enable building of all engines\n"
     460                " --disable-all-engines    disable building of all engines\n"
     461                "\n"
     462                "ScummVM optional feature settings:\n"
     463                " --enable-name            enable inclusion of the feature \"name\"\n"
     464                " --disable-name           disable inclusion of the feature \"name\"\n"
     465                "\n"
     466                " There are the following features available:\n"
     467                "\n";
     468
     469        cout << "   state  |       name      |     description\n\n";
     470        const FeatureList features = getAllFeatures();
     471        cout.setf(std::ios_base::left, std::ios_base::adjustfield);
     472        for (FeatureList::const_iterator i = features.begin(); i != features.end(); ++i)
     473                cout << ' ' << (i->enable ? " enabled" : "disabled") << " | " << std::setw((std::streamsize)15) << i->name << std::setw((std::streamsize)0) << " | " << i->description << '\n';
     474        cout.setf(std::ios_base::right, std::ios_base::adjustfield);
     475}
     476
     477typedef StringList TokenList;
     478
     479/**
     480 * Takes a given input line and creates a list of tokens out of it.
     481 *
     482 * A token in this context is separated by whitespaces. A special case
     483 * are quotation marks though. A string inside quotation marks is treated
     484 * as single token, even when it contains whitespaces.
     485 *
     486 * Thus for example the input:
     487 * foo bar "1 2 3 4" ScummVM
     488 * will create a list with the following entries:
     489 * "foo", "bar", "1 2 3 4", "ScummVM"
     490 * As you can see the quotation marks will get *removed* too.
     491 *
     492 * @param input The text to be tokenized.
     493 * @return A list of tokens.
     494 */
     495TokenList tokenize(const std::string &input);
     496
     497/**
     498 * Try to parse a given line and create an engine definition
     499 * out of the result.
     500 *
     501 * This may take *any* input line, when the line is not used
     502 * to define an engine the result of the function will be "false".
     503 *
     504 * Note that the contents of "engine" are undefined, when this
     505 * function returns "false".
     506 *
     507 * @param line Text input line.
     508 * @param engine Reference to an object, where the engine information
     509 *               is to be stored in.
     510 * @return "true", when parsing succeeded, "false" otherwise.
     511 */
     512bool parseEngine(const std::string &line, EngineDesc &engine);
     513} // End of anonymous namespace
     514
     515EngineDescList parseConfigure(const std::string &srcDir) {
     516        std::string configureFile = srcDir + "/configure";
     517
     518        std::ifstream configure(configureFile.c_str());
     519        if (!configure)
     520                return EngineDescList();
     521
     522        std::string line;
     523        EngineDescList engines;
     524
     525        for (;;) {
     526                std::getline(configure, line);
     527                if (configure.eof())
     528                        break;
     529
     530                if (configure.fail())
     531                        error("Failed while reading from " + configureFile);
     532
     533                EngineDesc desc;
     534                if (parseEngine(line, desc))
     535                        engines.push_back(desc);
     536        }
     537
     538        return engines;
     539}
     540
     541bool isSubEngine(const std::string &name, const EngineDescList &engines) {
     542        for (EngineDescList::const_iterator i = engines.begin(); i != engines.end(); ++i) {
     543                if (std::find(i->subEngines.begin(), i->subEngines.end(), name) != i->subEngines.end())
     544                        return true;
     545        }
     546
     547        return false;
     548}
     549
     550bool setEngineBuildState(const std::string &name, EngineDescList &engines, bool enable) {
     551        if (enable && isSubEngine(name, engines)) {
     552                // When we enable a sub engine, we need to assure that the parent is also enabled,
     553                // thus we enable both sub engine and parent over here.
     554                EngineDescList::iterator engine = std::find(engines.begin(), engines.end(), name);
     555                if (engine != engines.end()) {
     556                        engine->enable = enable;
     557
     558                        for (engine = engines.begin(); engine != engines.end(); ++engine) {
     559                                if (std::find(engine->subEngines.begin(), engine->subEngines.end(), name) != engine->subEngines.end()) {
     560                                        engine->enable = true;
     561                                        break;
     562                                }
     563                        }
     564
     565                        return true;
     566                }
     567        } else {
     568                EngineDescList::iterator engine = std::find(engines.begin(), engines.end(), name);
     569                if (engine != engines.end()) {
     570                        engine->enable = enable;
     571
     572                        // When we disable an einge, we also need to disable all the sub engines.
     573                        if (!enable && !engine->subEngines.empty()) {
     574                                for (StringList::const_iterator j = engine->subEngines.begin(); j != engine->subEngines.end(); ++j) {
     575                                        EngineDescList::iterator subEngine = std::find(engines.begin(), engines.end(), *j);
     576                                        if (subEngine != engines.end())
     577                                                subEngine->enable = false;
     578                                }
     579                        }
     580
     581                        return true;
     582                }
     583        }
     584
     585        return false;
     586}
     587
     588StringList getEngineDefines(const EngineDescList &engines) {
     589        StringList result;
     590
     591        for (EngineDescList::const_iterator i = engines.begin(); i != engines.end(); ++i) {
     592                if (i->enable) {
     593                        std::string define = "ENABLE_" + i->name;
     594                        std::transform(define.begin(), define.end(), define.begin(), toupper);
     595                        result.push_back(define);
     596                }
     597        }
     598
     599        return result;
     600}
     601
     602namespace {
     603bool parseEngine(const std::string &line, EngineDesc &engine) {
     604        // Format:
     605        // add_engine engine_name "Readable Description" enable_default ["SubEngineList"]
     606        TokenList tokens = tokenize(line);
     607
     608        if (tokens.size() < 4)
     609                return false;
     610
     611        TokenList::const_iterator token = tokens.begin();
     612
     613        if (*token != "add_engine")
     614                return false;
     615        ++token;
     616
     617        engine.name = *token; ++token;
     618        engine.desc = *token; ++token;
     619        engine.enable = (*token == "yes"); ++token;
     620        if (token != tokens.end())
     621                engine.subEngines = tokenize(*token);
     622
     623        return true;
     624}
     625
     626TokenList tokenize(const std::string &input) {
     627        TokenList result;
     628
     629        std::string::size_type sIdx = input.find_first_not_of(" \t");
     630        std::string::size_type nIdx = std::string::npos;
     631
     632        if (sIdx == std::string::npos)
     633                return result;
     634
     635        do {
     636                if (input.at(sIdx) == '\"') {
     637                        ++sIdx;
     638                        nIdx = input.find_first_of('\"', sIdx);
     639                } else {
     640                        nIdx = input.find_first_of(' ', sIdx);
     641                }
     642
     643                if (nIdx != std::string::npos) {
     644                        result.push_back(input.substr(sIdx, nIdx - sIdx));
     645                        sIdx = input.find_first_not_of(" \t", nIdx + 1);
     646                } else {
     647                        result.push_back(input.substr(sIdx));
     648                        break;
     649                }
     650        } while (sIdx != std::string::npos);
     651
     652        return result;
     653}
     654} // End of anonymous namespace
     655
     656namespace {
     657const Feature s_features[] = {
     658        // Libraries
     659        {    "libz",        "USE_ZLIB", "zlib", true, "zlib (compression) support" },
     660        {     "mad",         "USE_MAD", "libmad", true, "libmad (MP3) support" },
     661        {  "vorbis",      "USE_VORBIS", "libvorbisfile_static libvorbis_static libogg_static", true, "Ogg Vorbis support" },
     662        {    "flac",        "USE_FLAC", "libFLAC_static", true, "FLAC support" },
     663        {   "png",           "USE_PNG", "libpng", true, "libpng support" },
     664        {   "theora",  "USE_THEORADEC", "libtheora_static", true, "Theora decoding support" },
     665        {   "mpeg2",       "USE_MPEG2", "libmpeg2", false, "mpeg2 codec for cutscenes" },
     666
     667        // ScummVM feature flags
     668        {     "scalers",     "USE_SCALERS", "", true, "Scalers" },
     669        {   "hqscalers",  "USE_HQ_SCALERS", "", true, "HQ scalers" },
     670        {       "16bit",   "USE_RGB_COLOR", "", true, "16bit color support" },
     671        {     "mt32emu",     "USE_MT32EMU", "", true, "integrated MT-32 emulator" },
     672        {        "nasm",        "USE_NASM", "", true, "IA-32 assembly support" }, // This feature is special in the regard, that it needs additional handling.
     673        { "translation", "USE_TRANSLATION", "", true, "Translation support" },
     674        {  "langdetect",  "USE_DETECTLANG", "", true, "System language detection support" } // This feature actually depends on "translation", there
     675                                                                                            // is just no current way of properly detecting this...
     676};
     677} // End of anonymous namespace
     678
     679FeatureList getAllFeatures() {
     680        const size_t featureCount = sizeof(s_features) / sizeof(s_features[0]);
     681
     682        FeatureList features;
     683        for (size_t i = 0; i < featureCount; ++i)
     684                features.push_back(s_features[i]);
     685
     686        return features;
     687}
     688
     689StringList getFeatureDefines(const FeatureList &features) {
     690        StringList defines;
     691
     692        for (FeatureList::const_iterator i = features.begin(); i != features.end(); ++i) {
     693                if (i->enable && i->define && i->define[0])
     694                        defines.push_back(i->define);
     695        }
     696
     697        return defines;
     698}
     699
     700StringList getFeatureLibraries(const FeatureList &features) {
     701        StringList libraries;
     702
     703        for (FeatureList::const_iterator i = features.begin(); i != features.end(); ++i) {
     704                if (i->enable && i->libraries && i->libraries[0]) {
     705                        StringList fLibraries = tokenize(i->libraries);
     706                        libraries.splice(libraries.end(), fLibraries);
     707                }
     708        }
     709
     710        return libraries;
     711}
     712
     713bool setFeatureBuildState(const std::string &name, FeatureList &features, bool enable) {
     714        FeatureList::iterator i = std::find(features.begin(), features.end(), name);
     715        if (i != features.end()) {
     716                i->enable = enable;
     717                return true;
     718        } else {
     719                return false;
     720        }
     721}
     722
     723namespace CreateProjectTool {
     724
     725//////////////////////////////////////////////////////////////////////////
     726// Utilities
     727//////////////////////////////////////////////////////////////////////////
     728
     729std::string convertPathToWin(const std::string &path) {
     730        std::string result = path;
     731        std::replace(result.begin(), result.end(), '/', '\\');
     732        return result;
     733}
     734
     735std::string getIndent(const int indentation) {
     736        std::string result;
     737        for (int i = 0; i < indentation; ++i)
     738                result += '\t';
     739        return result;
     740}
     741
     742void splitFilename(const std::string &fileName, std::string &name, std::string &ext) {
     743        const std::string::size_type dot = fileName.find_last_of('.');
     744        name = (dot == std::string::npos) ? fileName : fileName.substr(0, dot);
     745        ext = (dot == std::string::npos) ? std::string() : fileName.substr(dot + 1);
     746}
     747
     748bool producesObjectFile(const std::string &fileName) {
     749        std::string n, ext;
     750        splitFilename(fileName, n, ext);
     751
     752        if (ext == "cpp" || ext == "c" || ext == "asm")
     753                return true;
     754        else
     755                return false;
     756}
     757
     758/**
     759 * Checks whether the give file in the specified directory is present in the given
     760 * file list.
     761 *
     762 * This function does as special match against the file list. It will not take file
     763 * extensions into consideration, when the extension of a file in the specified
     764 * directory is one of "h", "cpp", "c" or "asm".
     765 *
     766 * @param dir Parent directory of the file.
     767 * @param fileName File name to match.
     768 * @param fileList List of files to match against.
     769 * @return "true" when the file is in the list, "false" otherwise.
     770 */
     771bool isInList(const std::string &dir, const std::string &fileName, const StringList &fileList) {
     772        std::string compareName, extensionName;
     773        splitFilename(fileName, compareName, extensionName);
     774
     775        if (!extensionName.empty())
     776                compareName += '.';
     777
     778        for (StringList::const_iterator i = fileList.begin(); i != fileList.end(); ++i) {
     779                if (i->compare(0, dir.size(), dir))
     780                        continue;
     781
     782                // When no comparison name is given, we try to match whether a subset of
     783                // the given directory should be included. To do that we must assure that
     784                // the first character after the substring, having the same size as dir, must
     785                // be a path delimiter.
     786                if (compareName.empty()) {
     787                        if (i->size() >= dir.size() + 1 && i->at(dir.size()) == '/')
     788                                return true;
     789                        else
     790                                continue;
     791                }
     792
     793                const std::string lastPathComponent = getLastPathComponent(*i);
     794                if (!producesObjectFile(fileName) && extensionName != "h") {
     795                        if (fileName == lastPathComponent)
     796                                return true;
     797                } else {
     798                        if (!lastPathComponent.compare(0, compareName.size(), compareName))
     799                                return true;
     800                }
     801        }
     802
     803        return false;
     804}
     805
     806/**
     807 * A strict weak compare predicate for sorting a list of
     808 * "FileNode *" entries.
     809 *
     810 * It will sort directory nodes before file nodes.
     811 *
     812 * @param l Left-hand operand.
     813 * @param r Right-hand operand.
     814 * @return "true" if and only if l should be sorted before r.
     815 */
     816bool compareNodes(const FileNode *l, const FileNode *r) {
     817        if (!l) {
     818                return false;
     819        } else if (!r) {
     820                return true;
     821        } else {
     822                if (l->children.empty() && !r->children.empty()) {
     823                        return false;
     824                } else if (!l->children.empty() && r->children.empty()) {
     825                        return true;
     826                } else {
     827                        return l->name < r->name;
     828                }
     829        }
     830}
     831
     832/**
     833 * Returns a list of all files and directories in the specified
     834 * path.
     835 *
     836 * @param dir Directory which should be listed.
     837 * @return List of all children.
     838 */
     839FileList listDirectory(const std::string &dir) {
     840        FileList result;
     841#if defined(_WIN32) || defined(WIN32)
     842        WIN32_FIND_DATA fileInformation;
     843        HANDLE fileHandle = FindFirstFile((dir + "/*").c_str(), &fileInformation);
     844
     845        if (fileHandle == INVALID_HANDLE_VALUE)
     846                return result;
     847
     848        do {
     849                if (fileInformation.cFileName[0] == '.')
     850                        continue;
     851
     852                result.push_back(FSNode(fileInformation.cFileName, (fileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0));
     853        } while (FindNextFile(fileHandle, &fileInformation) == TRUE);
     854
     855        FindClose(fileHandle);
     856#else
     857        DIR *dirp = opendir(dir.c_str());
     858        struct dirent *dp = NULL;
     859
     860        if (dirp == NULL)
     861                return result;
     862
     863        while ((dp = readdir(dirp)) != NULL) {
     864                if (dp->d_name[0] == '.')
     865                        continue;
     866
     867                struct stat st;
     868                if (stat((dir + '/' + dp->d_name).c_str(), &st))
     869                        continue;
     870
     871                result.push_back(FSNode(dp->d_name, S_ISDIR(st.st_mode)));
     872        }
     873
     874        closedir(dirp);
     875#endif
     876        return result;
     877}
     878
     879/**
     880 * Scans the specified directory against files, which should be included
     881 * in the project files. It will not include files present in the exclude list.
     882 *
     883 * @param dir Directory in which to search for files.
     884 * @param includeList Files to include in the project.
     885 * @param excludeList Files to exclude from the project.
     886 * @return Returns a file node for the specific directory.
     887 */
     888FileNode *scanFiles(const std::string &dir, const StringList &includeList, const StringList &excludeList) {
     889        FileList files = listDirectory(dir);
     890
     891        if (files.empty())
     892                return 0;
     893
     894        FileNode *result = new FileNode(dir);
     895        assert(result);
     896
     897        for (FileList::const_iterator i = files.begin(); i != files.end(); ++i) {
     898                if (i->isDirectory) {
     899                        const std::string subDirName = dir + '/' + i->name;
     900                        if (!isInList(subDirName, std::string(), includeList))
     901                                continue;
     902
     903                        FileNode *subDir = scanFiles(subDirName, includeList, excludeList);
     904
     905                        if (subDir) {
     906                                subDir->name = i->name;
     907                                result->children.push_back(subDir);
     908                        }
     909                        continue;
     910                }
     911
     912                if (isInList(dir, i->name, excludeList))
     913                        continue;
     914
     915                std::string name, ext;
     916                splitFilename(i->name, name, ext);
     917
     918                if (ext != "h") {
     919                        if (!isInList(dir, i->name, includeList))
     920                                continue;
     921                }
     922
     923                FileNode *child = new FileNode(i->name);
     924                assert(child);
     925                result->children.push_back(child);
     926        }
     927
     928        if (result->children.empty()) {
     929                delete result;
     930                return 0;
     931        } else {
     932                result->children.sort(compareNodes);
     933                return result;
     934        }
     935}
     936
     937//////////////////////////////////////////////////////////////////////////
     938// Project Provider methods
     939//////////////////////////////////////////////////////////////////////////
     940ProjectProvider::ProjectProvider(StringList &global_warnings, std::map<std::string, StringList> &project_warnings, const int version)
     941        : _version(version), _globalWarnings(global_warnings), _projectWarnings(project_warnings) {
     942}
     943
     944void ProjectProvider::createProject(const BuildSetup &setup) {
     945        _uuidMap = createUUIDMap(setup);
     946
     947        // We also need to add the UUID of the main project file.
     948        const std::string svmUUID = _uuidMap["scummvm"] = createUUID();
     949
     950        // Create Solution/Workspace file
     951        createWorkspace(setup);
     952
     953        StringList in, ex;
     954
     955        // Create engine project files
     956        for (UUIDMap::const_iterator i = _uuidMap.begin(); i != _uuidMap.end(); ++i) {
     957                if (i->first == "scummvm")
     958                        continue;
     959
     960                in.clear(); ex.clear();
     961                const std::string moduleDir = setup.srcDir + "/engines/" + i->first;
     962
     963                createModuleList(moduleDir, setup.defines, in, ex);
     964                createProjectFile(i->first, i->second, setup, moduleDir, in, ex);
     965        }
     966
     967        // Last but not least create the main ScummVM project file.
     968        in.clear(); ex.clear();
     969
     970        // File list for the ScummVM project file
     971        createModuleList(setup.srcDir + "/backends", setup.defines, in, ex);
     972        createModuleList(setup.srcDir + "/backends/platform/sdl", setup.defines, in, ex);
     973        createModuleList(setup.srcDir + "/base", setup.defines, in, ex);
     974        createModuleList(setup.srcDir + "/common", setup.defines, in, ex);
     975        createModuleList(setup.srcDir + "/engines", setup.defines, in, ex);
     976        createModuleList(setup.srcDir + "/graphics", setup.defines, in, ex);
     977        createModuleList(setup.srcDir + "/gui", setup.defines, in, ex);
     978        createModuleList(setup.srcDir + "/sound", setup.defines, in, ex);
     979        createModuleList(setup.srcDir + "/sound/softsynth/mt32", setup.defines, in, ex);
     980
     981        // Resource files
     982        in.push_back(setup.srcDir + "/icons/scummvm.ico");
     983        in.push_back(setup.srcDir + "/dists/scummvm.rc");
     984
     985        // Various text files
     986        in.push_back(setup.srcDir + "/AUTHORS");
     987        in.push_back(setup.srcDir + "/COPYING");
     988        in.push_back(setup.srcDir + "/COPYING.LGPL");
     989        in.push_back(setup.srcDir + "/COPYRIGHT");
     990        in.push_back(setup.srcDir + "/NEWS");
     991        in.push_back(setup.srcDir + "/README");
     992        in.push_back(setup.srcDir + "/TODO");
     993
     994        // Create the scummvm project file.
     995        createProjectFile("scummvm", svmUUID, setup, setup.srcDir, in, ex);
     996
     997        // Create other misc. build files
     998        createOtherBuildFiles(setup);
     999}
     1000
     1001ProjectProvider::UUIDMap ProjectProvider::createUUIDMap(const BuildSetup &setup) const {
     1002        UUIDMap result;
     1003
     1004        for (EngineDescList::const_iterator i = setup.engines.begin(); i != setup.engines.end(); ++i) {
     1005                if (!i->enable || isSubEngine(i->name, setup.engines))
     1006                        continue;
     1007
     1008                result[i->name] = createUUID();
     1009        }
     1010
     1011        return result;
     1012}
     1013
     1014std::string ProjectProvider::createUUID() const {
     1015#if defined(_WIN32) || defined(WIN32)
     1016        UUID uuid;
     1017        if (UuidCreate(&uuid) != RPC_S_OK)
     1018                error("UuidCreate failed");
     1019
     1020        unsigned char *string = 0;
     1021        if (UuidToStringA(&uuid, &string) != RPC_S_OK)
     1022                error("UuidToStringA failed");
     1023
     1024        std::string result = std::string((char *)string);
     1025        std::transform(result.begin(), result.end(), result.begin(), toupper);
     1026        RpcStringFreeA(&string);
     1027        return result;
     1028#else
     1029        unsigned char uuid[16];
     1030
     1031        for (int i = 0; i < 16; ++i)
     1032                uuid[i] = (unsigned char)((std::rand() / (double)(RAND_MAX)) * 0xFF);
     1033
     1034        uuid[8] &= 0xBF; uuid[8] |= 0x80;
     1035        uuid[6] &= 0x4F; uuid[6] |= 0x40;
     1036
     1037        std::stringstream uuidString;
     1038        uuidString << std::hex << std::uppercase << std::setfill('0');
     1039        for (int i = 0; i < 16; ++i) {
     1040                uuidString << std::setw(2) << (int)uuid[i];
     1041                if (i == 3 || i == 5 || i == 7 || i == 9) {
     1042                        uuidString << std::setw(0) << '-';
     1043                }
     1044        }
     1045
     1046        return uuidString.str();
     1047#endif
     1048}
     1049
     1050void ProjectProvider::addFilesToProject(const std::string &dir, std::ofstream &projectFile,
     1051                                        const StringList &includeList, const StringList &excludeList,
     1052                                        const std::string &filePrefix) {
     1053        // Check for duplicate object file names
     1054        StringList duplicate;
     1055
     1056        for (StringList::const_iterator i = includeList.begin(); i != includeList.end(); ++i) {
     1057                const std::string fileName = getLastPathComponent(*i);
     1058
     1059                // Leave out non object file names.
     1060                if (fileName.size() < 2 || fileName.compare(fileName.size() - 2, 2, ".o"))
     1061                        continue;
     1062
     1063                // Check whether an duplicate has been found yet
     1064                if (std::find(duplicate.begin(), duplicate.end(), fileName) != duplicate.end())
     1065                        continue;
     1066
     1067                // Search for duplicates
     1068                StringList::const_iterator j = i; ++j;
     1069                for (; j != includeList.end(); ++j) {
     1070                        if (fileName == getLastPathComponent(*j)) {
     1071                                duplicate.push_back(fileName);
     1072                                break;
     1073                        }
     1074                }
     1075        }
     1076
     1077        FileNode *files = scanFiles(dir, includeList, excludeList);
     1078
     1079        writeFileListToProject(*files, projectFile, 0, duplicate, std::string(), filePrefix + '/');
     1080
     1081        delete files;
     1082}
     1083
     1084void ProjectProvider::createModuleList(const std::string &moduleDir, const StringList &defines, StringList &includeList, StringList &excludeList) const {
     1085        const std::string moduleMkFile = moduleDir + "/module.mk";
     1086        std::ifstream moduleMk(moduleMkFile.c_str());
     1087        if (!moduleMk)
     1088                error(moduleMkFile + " is not present");
     1089
     1090        includeList.push_back(moduleMkFile);
     1091
     1092        std::stack<bool> shouldInclude;
     1093        shouldInclude.push(true);
     1094
     1095        bool hadModule = false;
     1096        std::string line;
     1097        for (;;) {
     1098                std::getline(moduleMk, line);
     1099
     1100                if (moduleMk.eof())
     1101                        break;
     1102
     1103                if (moduleMk.fail())
     1104                        error("Failed while reading from " + moduleMkFile);
     1105
     1106                TokenList tokens = tokenize(line);
     1107                if (tokens.empty())
     1108                        continue;
     1109
     1110                TokenList::const_iterator i = tokens.begin();
     1111                if (*i == "MODULE") {
     1112                        if (hadModule)
     1113                                error("More than one MODULE definition in " + moduleMkFile);
     1114                        // Format: "MODULE := path/to/module"
     1115                        if (tokens.size() < 3)
     1116                                error("Malformed MODULE definition in " + moduleMkFile);
     1117                        ++i;
     1118                        if (*i != ":=")
     1119                                error("Malformed MODULE definition in " + moduleMkFile);
     1120                        ++i;
     1121
     1122                        std::string moduleRoot = unifyPath(*i);
     1123                        if (moduleDir.compare(moduleDir.size() - moduleRoot.size(), moduleRoot.size(), moduleRoot))
     1124                                error("MODULE root " + moduleRoot + " does not match base dir " + moduleDir);
     1125
     1126                        hadModule = true;
     1127                } else if (*i == "MODULE_OBJS") {
     1128                        if (tokens.size() < 3)
     1129                                error("Malformed MODULE_OBJS definition in " + moduleMkFile);
     1130                        ++i;
     1131
     1132                        // This is not exactly correct, for example an ":=" would usually overwrite
     1133                        // all already added files, but since we do only save the files inside
     1134                        // includeList or excludeList currently, we couldn't handle such a case easily.
     1135                        // (includeList and excludeList should always preserve their entries, not added
     1136                        // by this function, thus we can't just clear them on ":=" or "=").
     1137                        // But hopefully our module.mk files will never do such things anyway.
     1138                        if (*i != ":=" && *i != "+=" && *i != "=")
     1139                                error("Malformed MODULE_OBJS definition in " + moduleMkFile);
     1140
     1141                        ++i;
     1142
     1143                        while (i != tokens.end()) {
     1144                                if (*i == "\\") {
     1145                                        std::getline(moduleMk, line);
     1146                                        tokens = tokenize(line);
     1147                                        i = tokens.begin();
     1148                                } else {
     1149                                        if (shouldInclude.top())
     1150                                                includeList.push_back(moduleDir + "/" + unifyPath(*i));
     1151                                        else
     1152                                                excludeList.push_back(moduleDir + "/" + unifyPath(*i));
     1153                                        ++i;
     1154                                }
     1155                        }
     1156                } else if (*i == "ifdef") {
     1157                        if (tokens.size() < 2)
     1158                                error("Malformed ifdef in " + moduleMkFile);
     1159                        ++i;
     1160
     1161                        if (std::find(defines.begin(), defines.end(), *i) == defines.end())
     1162                                shouldInclude.push(false);
     1163                        else
     1164                                shouldInclude.push(true);
     1165                } else if (*i == "ifndef") {
     1166                        if (tokens.size() < 2)
     1167                                error("Malformed ifndef in " + moduleMkFile);
     1168                        ++i;
     1169
     1170                        if (std::find(defines.begin(), defines.end(), *i) == defines.end())
     1171                                shouldInclude.push(true);
     1172                        else
     1173                                shouldInclude.push(false);
     1174                } else if (*i == "else") {
     1175                        shouldInclude.top() = !shouldInclude.top();
     1176                } else if (*i == "endif") {
     1177                        if (shouldInclude.size() <= 1)
     1178                                error("endif without ifdef found in " + moduleMkFile);
     1179                        shouldInclude.pop();
     1180                } else if (*i == "elif") {
     1181                        error("Unsupported operation 'elif' in " + moduleMkFile);
     1182                } else if (*i == "ifeq") {
     1183                        //XXX
     1184                        shouldInclude.push(false);
     1185                }
     1186        }
     1187
     1188        if (shouldInclude.size() != 1)
     1189                error("Malformed file " + moduleMkFile);
     1190}
     1191
     1192} // End of anonymous namespace
     1193
     1194void error(const std::string &message) {
     1195        std::cerr << "ERROR: " << message << "!" << std::endl;
     1196        std::exit(-1);
     1197}
  • new file tools/create_project/create_project.h

    diff -r e24b1c8ca942 tools/create_project/create_project.h
    - +  
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11 *
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL$
     22 * $Id$
     23 *
     24 */
     25
     26#ifndef TOOLS_CREATE_PROJECT_H
     27#define TOOLS_CREATE_PROJECT_H
     28
     29#include <map>
     30#include <list>
     31#include <string>
     32
     33#include <cassert>
     34
     35// The PP_NARG macro returns the number of arguments that have been passed to it.
     36#define PP_NARG(...) \
     37         PP_NARG_(__VA_ARGS__,PP_RSEQ_N())
     38#define PP_NARG_(...) \
     39         PP_ARG_N(__VA_ARGS__)
     40#define PP_ARG_N( \
     41          _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
     42         _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
     43         _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
     44         _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
     45         _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
     46         _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
     47         _61,_62,_63,N,...) N
     48#define PP_RSEQ_N() \
     49         63,62,61,60,                   \
     50         59,58,57,56,55,54,53,52,51,50, \
     51         49,48,47,46,45,44,43,42,41,40, \
     52         39,38,37,36,35,34,33,32,31,30, \
     53         29,28,27,26,25,24,23,22,21,20, \
     54         19,18,17,16,15,14,13,12,11,10, \
     55         9,8,7,6,5,4,3,2,1,0
     56
     57#define SET_VALUES(list, ...) \
     58        { \
     59                std::string values[PP_NARG(__VA_ARGS__)] = { __VA_ARGS__ }; \
     60                list.assign(values, values + (sizeof(values) / sizeof(values[0]))); \
     61        }
     62
     63typedef std::list<std::string> StringList;
     64
     65/**
     66 * Structure to describe a game engine to be built into ScummVM.
     67 *
     68 * We do get the game engines available by parsing the "configure"
     69 * script of our source distribution. See "parseConfigure" for more
     70 * information on that.
     71 * @see parseConfigure
     72 */
     73struct EngineDesc {
     74        /**
     75         * The name of the engine. We use this to determine the directory
     76         * the engine is in and to create the define, which needs to be
     77         * set to enable the engine.
     78         */
     79        std::string name;
     80
     81        /**
     82         * A human readable description of the engine. We will use this
     83         * to display a description of the engine to the user in the list
     84         * of which engines are built and which are disabled.
     85         */
     86        std::string desc;
     87
     88        /**
     89         * Whether the engine should be included in the build or not.
     90         */
     91        bool enable;
     92
     93        /**
     94         * A list of all available sub engine names. Sub engines are engines
     95         * which are built on top of an existing engines and can be only
     96         * enabled when the parten engine is enabled.
     97         */
     98        StringList subEngines;
     99
     100        bool operator==(const std::string &n) const {
     101                return (name == n);
     102        }
     103};
     104
     105typedef std::list<EngineDesc> EngineDescList;
     106
     107/**
     108 * This function parses the ScummVM configure file and creates a list
     109 * of available engines.
     110 *
     111 * It will also automatically setup the default build state (enabled
     112 * or disabled) to the state specified in the "configure" file.
     113 *
     114 * @param srcDir Path to the root of the ScummVM source.
     115 * @return List of available engines.
     116 */
     117EngineDescList parseConfigure(const std::string &srcDir);
     118
     119/**
     120 * Checks whether the specified engine is a sub engine. To determine this
     121 * there is a fully setup engine list needed.
     122 *
     123 * @param name Name of the engine to check.
     124 * @param engines List of engines.
     125 * @return "true", when the engine is a sub engine, "false" otherwise.
     126 */
     127bool isSubEngine(const std::string &name, const EngineDescList &engines);
     128
     129/**
     130 * Enables or disables the specified engine in the engines list.
     131 *
     132 * This function also disables all sub engines of an engine, when it is
     133 * to be disabled.
     134 * Also this function does enable the parent of a sub engine, when a
     135 * sub engine is to be enabled.
     136 *
     137 * @param name Name of the engine to be enabled or disabled.
     138 * @param engines The list of engines, which should be operated on.
     139 * @param enable Whether the engine should be enabled or disabled.
     140 * @return "true", when it succeeded, "false" otherwise.
     141 */
     142bool setEngineBuildState(const std::string &name, EngineDescList &engines, bool enable);
     143
     144/**
     145 * Returns a list of all defines, according to the engine list passed.
     146 *
     147 * @param features The list of engines, which should be operated on. (this may contain engines, which are *not* enabled!)
     148 */
     149StringList getEngineDefines(const EngineDescList &engines);
     150
     151/**
     152 * Structure to define a given feature, usually an external library,
     153 * used to build ScummVM.
     154 */
     155struct Feature {
     156        const char *name;        ///< Name of the feature
     157        const char *define;      ///< Define of the feature
     158
     159        const char *libraries;   ///< Libraries, which need to be linked, for the feature
     160
     161        bool enable;             ///< Whether the feature is enabled or not
     162
     163        const char *description; ///< Human readable description of the feature
     164
     165        bool operator==(const std::string &n) const {
     166                return (name == n);
     167        }
     168};
     169typedef std::list<Feature> FeatureList;
     170
     171/**
     172 * Creates a list of all features available for MSVC.
     173 *
     174 * @return A list including all features available.
     175 */
     176FeatureList getAllFeatures();
     177
     178/**
     179 * Returns a list of all defines, according to the feature set
     180 * passed.
     181 *
     182 * @param features List of features for the build (this may contain features, which are *not* enabled!)
     183 */
     184StringList getFeatureDefines(const FeatureList &features);
     185
     186/**
     187 * Returns a list of all external library files, according to the
     188 * feature set passed.
     189 *
     190 * @param features List of features for the build (this may contain features, which are *not* enabled!)
     191 */
     192StringList getFeatureLibraries(const FeatureList &features);
     193
     194/**
     195 * Sets the state of a given feature. This can be used to
     196 * either include or exclude an feature.
     197 *
     198 * @param name Name of the feature.
     199 * @param features List of features to operate on.
     200 * @param enable Whether the feature should be enabled or disabled.
     201 * @return "true", when it succeeded, "false" otherwise.
     202 */
     203bool setFeatureBuildState(const std::string &name, FeatureList &features, bool enable);
     204
     205/**
     206 * Structure to describe a MSVC build setup.
     207 *
     208 * This includes various information about which engines to
     209 * enable, which features should be built into ScummVM.
     210 * It also contains the path to the ScummVM souce root.
     211 */
     212struct BuildSetup {
     213        std::string srcDir;     ///< Path to the ScummVM sources.
     214        std::string filePrefix; ///< Prefix for the relative path arguments in the project files.
     215        std::string outputDir;  ///< Path where to put the MSVC project files.
     216
     217        EngineDescList engines; ///< Engine list for the build (this may contain engines, which are *not* enabled!).
     218        FeatureList features;   ///< Feature list for the build (this may contain features, which are *not* enabled!).
     219
     220        StringList defines;   ///< List of all defines for the build.
     221        StringList libraries; ///< List of all external libraries required for the build.
     222};
     223
     224/**
     225 * Quits the program with the specified error message.
     226 *
     227 * @param message The error message to print to stderr.
     228 */
     229#if defined(__GNUC__)
     230        #define NORETURN_POST __attribute__((__noreturn__))
     231#elif defined(_MSC_VER)
     232        #define NORETURN_PRE __declspec(noreturn)
     233#endif
     234
     235#ifndef NORETURN_PRE
     236#define NORETURN_PRE
     237#endif
     238
     239#ifndef NORETURN_POST
     240#define NORETURN_POST
     241#endif
     242void NORETURN_PRE error(const std::string &message) NORETURN_POST;
     243
     244namespace CreateProjectTool {
     245
     246/**
     247 * Gets a proper sequence of \t characters for the given
     248 * indentation level.
     249 *
     250 * For example with an indentation level of 2 this will
     251 * produce:
     252 *  \t\t
     253 *
     254 * @param indentation The indentation level
     255 * @return Sequence of \t characters.
     256 */
     257std::string getIndent(const int indentation);
     258
     259/**
     260 * Converts the given path to only use backslashes.
     261 * This means that for example the path:
     262 *  foo/bar\test.txt
     263 * will be converted to:
     264 *  foo\bar\test.txt
     265 *
     266 * @param path Path string.
     267 * @return Converted path.
     268 */
     269std::string convertPathToWin(const std::string &path);
     270
     271/**
     272 * Splits a file name into name and extension.
     273 * The file name must be only the filename, no
     274 * additional path name.
     275 *
     276 * @param fileName Filename to split
     277 * @param name Reference to a string, where to store the name.
     278 * @param ext Reference to a string, where to store the extension.
     279 */
     280void splitFilename(const std::string &fileName, std::string &name, std::string &ext);
     281
     282/**
     283 * Checks whether the given file will produce an object file or not.
     284 *
     285 * @param fileName Name of the file.
     286 * @return "true" when it will produce a file, "false" otherwise.
     287 */
     288bool producesObjectFile(const std::string &fileName);
     289
     290/**
     291 * Structure representing a file tree. This contains two
     292 * members: name and children. "name" holds the name of
     293 * the node. "children" does contain all the node's children.
     294 * When the list "children" is empty, the node is a file entry,
     295 * otherwise it's a directory.
     296 */
     297struct FileNode {
     298        typedef std::list<FileNode *> NodeList;
     299
     300        explicit FileNode(const std::string &n) : name(n), children() {}
     301
     302        ~FileNode() {
     303                for (NodeList::iterator i = children.begin(); i != children.end(); ++i)
     304                        delete *i;
     305        }
     306
     307        std::string name;  ///< Name of the node
     308        NodeList children; ///< List of children for the node
     309};
     310
     311class ProjectProvider {
     312public:
     313        typedef std::map<std::string, std::string> UUIDMap;
     314
     315        /**
     316         * Instantiate new ProjectProvider class
     317         *
     318         * @param global_warnings List of warnings that apply to all projects
     319         * @param project_warnings List of project-specific warnings
     320         * @param version Target project version.
     321         */
     322        ProjectProvider(StringList &global_warnings, std::map<std::string, StringList> &project_warnings, const int version = 0);
     323        virtual ~ProjectProvider() {}
     324
     325        /**
     326         * Creates all build files
     327         *
     328         * @param setup Description of the desired build setup.
     329         */
     330        void createProject(const BuildSetup &setup);
     331
     332protected:
     333        const int _version;                                      ///< Target project version
     334        StringList &_globalWarnings;                             ///< Global warnings
     335        std::map<std::string, StringList> &_projectWarnings;     ///< Per-project warnings
     336
     337        UUIDMap _uuidMap;                                        ///< List of (project name, UUID) pairs
     338
     339        /**
     340         *  Create workspace/solution file
     341         *
     342         * @param setup Description of the desired build setup.
     343         */
     344        virtual void createWorkspace(const BuildSetup &setup) = 0;
     345
     346        /**
     347         *  Create other files (such as build properties)
     348         *
     349         * @param setup Description of the desired build setup.
     350         */
     351        virtual void createOtherBuildFiles(const BuildSetup &setup) = 0;
     352
     353        /**
     354         * Create a project file for the specified list of files.
     355         *
     356         * @param name Name of the project file.
     357         * @param uuid UUID of the project file.
     358         * @param setup Description of the desired build.
     359         * @param moduleDir Path to the module.
     360         * @param includeList Files to include (must have "moduleDir" as prefix).
     361         * @param excludeList Files to exclude (must have "moduleDir" as prefix).
     362         */
     363        virtual void createProjectFile(const std::string &name, const std::string &uuid, const BuildSetup &setup, const std::string &moduleDir,
     364                                       const StringList &includeList, const StringList &excludeList) = 0;
     365
     366        /**
     367         * Writes file entries for the specified directory node into
     368         * the given project file. It will also take care of duplicate
     369         * object files.
     370         *
     371         * @param dir Directory node.
     372         * @param projectFile File stream to write to.
     373         * @param indentation Indentation level to use.
     374         * @param duplicate List of duplicate object file names.
     375         * @param objPrefix Prefix to use for object files, which would name clash.
     376         * @param filePrefix Generic prefix to all files of the node.
     377         */
     378        virtual void writeFileListToProject(const FileNode &dir, std::ofstream &projectFile, const int indentation,
     379                                            const StringList &duplicate, const std::string &objPrefix, const std::string &filePrefix) = 0;
     380
     381        /**
     382         * Output a list of project references to the file stream
     383         *
     384         * @param output File stream to write to.
     385         */
     386        virtual void writeReferences(std::ofstream &) {};
     387
     388        /**
     389         * Get the file extension for project files
     390         */
     391        virtual const char *getProjectExtension() { return ""; }
     392
     393        /**
     394         * Adds files of the specified directory recursively to given project file.
     395         *
     396         * @param dir Path to the directory.
     397         * @param projectFile Output stream object, where all data should be written to.
     398         * @param includeList Files to include (must have a relative directory as prefix).
     399         * @param excludeList Files to exclude (must have a relative directory as prefix).
     400         * @param filePrefix Prefix to use for relative path arguments.
     401         */
     402        void addFilesToProject(const std::string &dir, std::ofstream &projectFile,
     403                               const StringList &includeList, const StringList &excludeList,
     404                               const std::string &filePrefix);
     405
     406        /**
     407         * Creates a list of files of the specified module. This also
     408         * creates a list of files, which should not be included.
     409         * All filenames will have "moduleDir" as prefix.
     410         *
     411         * @param moduleDir Path to the module.
     412         * @param defines List of set defines.
     413         * @param includeList Reference to a list, where included files should be added.
     414         * @param excludeList Reference to a list, where excluded files should be added.
     415         */
     416        void createModuleList(const std::string &moduleDir, const StringList &defines, StringList &includeList, StringList &excludeList) const;
     417
     418        /**
     419         * Creates an UUID for every enabled engine of the
     420         * passed build description.
     421         *
     422         * @param setup Description of the desired build.
     423         * @return A map, which includes UUIDs for all enabled engines.
     424         */
     425        UUIDMap createUUIDMap(const BuildSetup &setup) const;
     426
     427        /**
     428         * Creates an UUID and returns it in string representation.
     429         *
     430         * @return A new UUID as string.
     431         */
     432        std::string createUUID() const;
     433};
     434
     435} // End of CreateProjectTool namespace
     436
     437#endif // TOOLS_CREATE_PROJECT_H
  • new file tools/create_project/module.mk

    diff -r e24b1c8ca942 tools/create_project/module.mk
    - +  
     1# $URL$
     2# $Id$
     3
     4MODULE := tools/create_project
     5
     6MODULE_OBJS := \
     7        create_project.o \
     8        codeblocks.o \
     9        msvc.o
     10
     11# Set the name of the executable
     12TOOL_EXECUTABLE := create_project
     13
     14# Include common rules
     15include $(srcdir)/rules.mk
     16
     17# Silence variadic macros warning for C++
     18CXXFLAGS := $(CXXFLAGS) -Wno-variadic-macros
  • new file tools/create_project/msvc.cpp

    diff -r e24b1c8ca942 tools/create_project/msvc.cpp
    - +  
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11 *
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL$
     22 * $Id$
     23 *
     24 */
     25
     26#include "msvc.h"
     27
     28#include <fstream>
     29
     30#include <algorithm>
     31
     32namespace CreateProjectTool {
     33
     34//////////////////////////////////////////////////////////////////////////
     35// MSVC Provider (Base class)
     36//////////////////////////////////////////////////////////////////////////
     37MSVCProvider::MSVCProvider(StringList &global_warnings, std::map<std::string, StringList> &project_warnings, const int version)
     38        : ProjectProvider(global_warnings, project_warnings, version) {
     39}
     40
     41void MSVCProvider::createWorkspace(const BuildSetup &setup) {
     42        UUIDMap::const_iterator svmUUID = _uuidMap.find("scummvm");
     43        if (svmUUID == _uuidMap.end())
     44                error("No UUID for \"scummvm\" project created");
     45
     46        const std::string svmProjectUUID = svmUUID->second;
     47        assert(!svmProjectUUID.empty());
     48
     49        std::string solutionUUID = createUUID();
     50
     51        std::ofstream solution((setup.outputDir + '/' + "scummvm.sln").c_str());
     52        if (!solution)
     53                error("Could not open \"" + setup.outputDir + '/' + "scummvm.sln\" for writing");
     54
     55        solution << "Microsoft Visual Studio Solution File, Format Version " << _version + 1 << ".00\n";
     56        solution << "# Visual Studio " << getVisualStudioVersion() << "\n";
     57
     58        solution << "Project(\"{" << solutionUUID << "}\") = \"scummvm\", \"scummvm" << getProjectExtension() << "\", \"{" << svmProjectUUID << "}\"\n";
     59
     60        // Project dependencies are moved to vcxproj files in Visual Studio 2010
     61        if (_version < 10)
     62                writeReferences(solution);
     63
     64        solution << "EndProject\n";
     65
     66        // Note we assume that the UUID map only includes UUIDs for enabled engines!
     67        for (UUIDMap::const_iterator i = _uuidMap.begin(); i != _uuidMap.end(); ++i) {
     68                if (i->first == "scummvm")
     69                        continue;
     70
     71                solution << "Project(\"{" << solutionUUID << "}\") = \"" << i->first << "\", \"" << i->first << getProjectExtension() << "\", \"{" << i->second << "}\"\n"
     72                         << "EndProject\n";
     73        }
     74
     75        solution << "Global\n"
     76                    "\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n"
     77                    "\t\tDebug|Win32 = Debug|Win32\n"
     78                    "\t\tRelease|Win32 = Release|Win32\n"
     79                     "\t\tDebug|x64 = Debug|x64\n"
     80                    "\t\tRelease|x64 = Release|x64\n"
     81                    "\tEndGlobalSection\n"
     82                    "\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n";
     83
     84        for (UUIDMap::const_iterator i = _uuidMap.begin(); i != _uuidMap.end(); ++i) {
     85                solution << "\t\t{" << i->second << "}.Debug|Win32.ActiveCfg = Debug|Win32\n"
     86                         << "\t\t{" << i->second << "}.Debug|Win32.Build.0 = Debug|Win32\n"
     87                         << "\t\t{" << i->second << "}.Release|Win32.ActiveCfg = Release|Win32\n"
     88                         << "\t\t{" << i->second << "}.Release|Win32.Build.0 = Release|Win32\n"
     89                         << "\t\t{" << i->second << "}.Debug|x64.ActiveCfg = Debug|x64\n"
     90                         << "\t\t{" << i->second << "}.Debug|x64.Build.0 = Debug|x64\n"
     91                         << "\t\t{" << i->second << "}.Release|x64.ActiveCfg = Release|x64\n"
     92                         << "\t\t{" << i->second << "}.Release|x64.Build.0 = Release|x64\n";
     93        }
     94
     95        solution << "\tEndGlobalSection\n"
     96                    "\tGlobalSection(SolutionProperties) = preSolution\n"
     97                    "\t\tHideSolutionNode = FALSE\n"
     98                    "\tEndGlobalSection\n"
     99                    "EndGlobal\n";
     100}
     101
     102void MSVCProvider::createOtherBuildFiles(const BuildSetup &setup) {
     103        // Create the global property file
     104        createGlobalProp(setup);
     105
     106        // Create the configuration property files (for Debug and Release with 32 and 64bits versions)
     107        createBuildProp(setup, true, false);
     108        createBuildProp(setup, true, true);
     109        createBuildProp(setup, false, false);
     110        createBuildProp(setup, false, true);
     111}
     112
     113void MSVCProvider::createGlobalProp(const BuildSetup &setup) {
     114        std::ofstream properties((setup.outputDir + '/' + "ScummVM_Global" + getPropertiesExtension()).c_str());
     115        if (!properties)
     116                error("Could not open \"" + setup.outputDir + '/' + "ScummVM_Global" + getPropertiesExtension() + "\" for writing");
     117
     118        outputGlobalPropFile(properties, 32, setup.defines, convertPathToWin(setup.filePrefix));
     119        properties.close();
     120
     121        properties.open((setup.outputDir + '/' + "ScummVM_Global64" + getPropertiesExtension()).c_str());
     122        if (!properties)
     123                error("Could not open \"" + setup.outputDir + '/' + "ScummVM_Global64" + getPropertiesExtension() + "\" for writing");
     124
     125        // HACK: We must disable the "nasm" feature for x64. To achieve that we must duplicate the feature list and
     126        // recreate a define list.
     127        FeatureList x64Features = setup.features;
     128        setFeatureBuildState("nasm", x64Features, false);
     129        StringList x64Defines = getFeatureDefines(x64Features);
     130        StringList x64EngineDefines = getEngineDefines(setup.engines);
     131        x64Defines.splice(x64Defines.end(), x64EngineDefines);
     132
     133        outputGlobalPropFile(properties, 64, x64Defines, convertPathToWin(setup.filePrefix));
     134}
     135
     136std::string MSVCProvider::getRevisionToolCommandLine() const {
     137        std::string cmdLine = "";
     138
     139        cmdLine = "@echo off\n"
     140                  "ECHO Generating revision number\n"
     141                  "IF NOT EXIST &quot;$(SolutionDir)../../.svn/&quot; GOTO working_copy\n"
     142                  "SubWCRev.exe &quot;$(SolutionDir)../..&quot; &quot;$(SolutionDir)../../base/internal_version.h.tpl&quot; &quot;$(SolutionDir)../../base/internal_version.h&quot;\n"
     143                  "IF NOT %errorlevel%==0 GOTO error\n"
     144                  ":working_copy\n"
     145                  "ECHO Not a working copy, skipping...\n"
     146                  "EXIT /B0\n"
     147                  ":error\n"
     148                  "ECHO SubWCRev not found, skipping...\n"
     149                  "EXIT /B0";
     150
     151        return cmdLine;
     152}
     153
     154std::string MSVCProvider::getCopyDataCommandLine(bool isWin32) const {
     155        std::string cmdLine = "";
     156
     157        // Copy data files and themes
     158        cmdLine = "@echo off\n"
     159                  "ECHO Copying data files\n"
     160                  "xcopy /F /Y &quot;$(SolutionDir)../engine-data/*.dat&quot; $(OutDir)\n"
     161                  "xcopy /F /Y &quot;$(SolutionDir)../engine-data/*.tbl&quot; $(OutDir)\n"
     162                  "xcopy /F /Y &quot;$(SolutionDir)../engine-data/*.cpt&quot; $(OutDir)\n"
     163                  "xcopy /F /Y &quot;$(SolutionDir)../engine-data/README&quot; $(OutDir)\n"
     164                  "xcopy /F /Y &quot;$(SolutionDir)../../gui/themes/*.zip&quot; $(OutDir)\n"
     165                  "xcopy /F /Y &quot;$(SolutionDir)../../gui/themes/translations.dat&quot; $(OutDir)\n";
     166
     167        cmdLine += "xcopy /F /Y &quot;$(SCUMMVM_LIBS)/lib/";
     168        cmdLine += (isWin32 ? "x86" : "x64");
     169        cmdLine += "/SDL.dll&quot; $(OutDir)";
     170
     171        return cmdLine;
     172}
     173
     174//////////////////////////////////////////////////////////////////////////
     175// Visual Studio Provider
     176//////////////////////////////////////////////////////////////////////////
     177
     178VisualStudioProvider::VisualStudioProvider(StringList &global_warnings, std::map<std::string, StringList> &project_warnings, const int version)
     179        : MSVCProvider(global_warnings, project_warnings, version) {
     180}
     181
     182const char *VisualStudioProvider::getProjectExtension() {
     183        return ".vcproj";
     184}
     185
     186const char *VisualStudioProvider::getPropertiesExtension() {
     187        return ".vsprops";
     188}
     189
     190int VisualStudioProvider::getVisualStudioVersion() {
     191        if (_version == 9)
     192                return 2008;
     193
     194        if (_version == 8)
     195                return 2005;
     196
     197        error("Unsupported version passed to createScummVMSolution");
     198}
     199
     200void VisualStudioProvider::createProjectFile(const std::string &name, const std::string &uuid, const BuildSetup &setup, const std::string &moduleDir,
     201                                             const StringList &includeList, const StringList &excludeList) {
     202        const std::string projectFile = setup.outputDir + '/' + name + getProjectExtension();
     203        std::ofstream project(projectFile.c_str());
     204        if (!project)
     205                error("Could not open \"" + projectFile + "\" for writing");
     206
     207        project << "<?xml version=\"1.0\" encoding=\"windows-1252\"?>\n"
     208                   "<VisualStudioProject\n"
     209                   "\tProjectType=\"Visual C++\"\n"
     210                   "\tVersion=\"" << _version << ".00\"\n"
     211                   "\tName=\"" << name << "\"\n"
     212                   "\tProjectGUID=\"{" << uuid << "}\"\n"
     213                   "\tRootNamespace=\"" << name << "\"\n"
     214                   "\tKeyword=\"Win32Proj\"\n";
     215
     216        if (_version >= 9)
     217                project << "\tTargetFrameworkVersion=\"131072\"\n";
     218
     219        project << "\t>\n"
     220                   "\t<Platforms>\n"
     221                   "\t\t<Platform Name=\"Win32\" />\n"
     222                   "\t\t<Platform Name=\"x64\" />\n"
     223                   "\t</Platforms>\n"
     224                   "\t<Configurations>\n";
     225
     226        // Check for project-specific warnings:
     227        std::map< std::string, std::list<std::string> >::iterator warningsIterator = _projectWarnings.find(name);
     228
     229        if (name == "scummvm") {
     230                std::string libraries;
     231
     232                for (StringList::const_iterator i = setup.libraries.begin(); i != setup.libraries.end(); ++i)
     233                        libraries += ' ' + *i + ".lib";
     234
     235                // Win32
     236                project << "\t\t<Configuration Name=\"Debug|Win32\" ConfigurationType=\"1\" InheritedPropertySheets=\".\\ScummVM_Debug.vsprops\">\n"
     237                           "\t\t\t<Tool\tName=\"VCCLCompilerTool\" DisableLanguageExtensions=\"false\" />\n"
     238                           "\t\t\t<Tool\tName=\"VCLinkerTool\" OutputFile=\"$(OutDir)/scummvm.exe\"\n"
     239                           "\t\t\t\tAdditionalDependencies=\"" << libraries << "\"\n"
     240                           "\t\t\t/>\n"
     241                           "\t\t\t<Tool\tName=\"VCPreBuildEventTool\"\n"
     242                           "\t\t\t\tCommandLine=\"" << getRevisionToolCommandLine() << "\"\n"
     243                           "\t\t\t/>\n"
     244                           "\t\t\t<Tool\tName=\"VCPostBuildEventTool\"\n"
     245                           "\t\t\t\tCommandLine=\"" << getCopyDataCommandLine(true) << "\"\n"
     246                           "\t\t\t/>\n"
     247                           "\t\t</Configuration>\n"
     248                           "\t\t<Configuration Name=\"Release|Win32\" ConfigurationType=\"1\" InheritedPropertySheets=\".\\ScummVM_Release.vsprops\">\n"
     249                           "\t\t\t<Tool\tName=\"VCCLCompilerTool\" DisableLanguageExtensions=\"false\" />\n"
     250                           "\t\t\t<Tool\tName=\"VCLinkerTool\" OutputFile=\"$(OutDir)/scummvm.exe\"\n"
     251                           "\t\t\t\tAdditionalDependencies=\"" << libraries << "\"\n"
     252                           "\t\t\t/>\n"
     253                           "\t\t</Configuration>\n";
     254
     255                // x64
     256                // For 'x64' we must disable NASM support. Usually we would need to disable the "nasm" feature for that and
     257                // re-create the library list, BUT since NASM doesn't link any additional libraries, we can just use the
     258                // libraries list created for IA-32. If that changes in the future, we need to adjust this part!
     259                project << "\t\t<Configuration Name=\"Debug|x64\" ConfigurationType=\"1\" InheritedPropertySheets=\".\\ScummVM_Debug64.vsprops\">\n"
     260                           "\t\t\t<Tool\tName=\"VCCLCompilerTool\" DisableLanguageExtensions=\"false\" />\n"
     261                           "\t\t\t<Tool\tName=\"VCLinkerTool\" OutputFile=\"$(OutDir)/scummvm.exe\"\n"
     262                           "\t\t\t\tAdditionalDependencies=\"" << libraries << "\"\n"
     263                           "\t\t\t/>\n"
     264                           "\t\t\t<Tool\tName=\"VCPreBuildEventTool\"\n"
     265                           "\t\t\t\tCommandLine=\"" << getRevisionToolCommandLine() << "\"\n"
     266                           "\t\t\t/>\n"
     267                           "\t\t\t<Tool\tName=\"VCPostBuildEventTool\"\n"
     268                           "\t\t\t\tCommandLine=\"" << getCopyDataCommandLine(false) << "\"\n"
     269                           "\t\t\t/>\n"
     270                           "\t\t</Configuration>\n"
     271                           "\t\t<Configuration Name=\"Release|x64\" ConfigurationType=\"1\" InheritedPropertySheets=\".\\ScummVM_Release64.vsprops\">\n"
     272                           "\t\t\t<Tool\tName=\"VCCLCompilerTool\" DisableLanguageExtensions=\"false\" />\n"
     273                           "\t\t\t<Tool\tName=\"VCLinkerTool\" OutputFile=\"$(OutDir)/scummvm.exe\"\n"
     274                           "\t\t\t\tAdditionalDependencies=\"" << libraries << "\"\n"
     275                           "\t\t\t/>\n"
     276                           "\t\t</Configuration>\n";
     277        } else {
     278                std::string warnings = "";
     279                if (warningsIterator != _projectWarnings.end())
     280                        for (StringList::const_iterator i = warningsIterator->second.begin(); i != warningsIterator->second.end(); ++i)
     281                                warnings +=  *i + ';';
     282
     283                std::string toolConfig;
     284                toolConfig  = (!warnings.empty() ? "DisableSpecificWarnings=\"" + warnings + "\"" : "");
     285                toolConfig += (name == "tinsel" ? "DebugInformationFormat=\"3\" " : "");
     286                toolConfig += (name == "sword25" ? "DisableLanguageExtensions=\"false\" " : "");
     287
     288                // Win32
     289                project << "\t\t<Configuration Name=\"Debug|Win32\" ConfigurationType=\"4\" InheritedPropertySheets=\".\\ScummVM_Debug.vsprops\">\n"
     290                           "\t\t\t<Tool Name=\"VCCLCompilerTool\" "<< toolConfig << "/>\n"
     291                           "\t\t</Configuration>\n"
     292
     293                           "\t\t<Configuration Name=\"Release|Win32\" ConfigurationType=\"4\" InheritedPropertySheets=\".\\ScummVM_Release.vsprops\">\n"
     294                           "\t\t\t<Tool Name=\"VCCLCompilerTool\" " << toolConfig << " />\n"
     295                           "\t\t</Configuration>\n";
     296                // x64
     297                project << "\t\t<Configuration Name=\"Debug|x64\" ConfigurationType=\"4\" InheritedPropertySheets=\".\\ScummVM_Debug64.vsprops\">\n"
     298                           "\t\t\t<Tool Name=\"VCCLCompilerTool\" " << toolConfig << " />\n"
     299                           "\t\t</Configuration>\n"
     300                           "\t\t<Configuration Name=\"Release|x64\" ConfigurationType=\"4\" InheritedPropertySheets=\".\\ScummVM_Release64.vsprops\">\n"
     301                           "\t\t\t<Tool Name=\"VCCLCompilerTool\" " << toolConfig << " />\n"
     302                           "\t\t</Configuration>\n";
     303        }
     304
     305        project << "\t</Configurations>\n"
     306                   "\t<Files>\n";
     307
     308        std::string modulePath;
     309        if (!moduleDir.compare(0, setup.srcDir.size(), setup.srcDir)) {
     310                modulePath = moduleDir.substr(setup.srcDir.size());
     311                if (!modulePath.empty() && modulePath.at(0) == '/')
     312                        modulePath.erase(0, 1);
     313        }
     314
     315        if (modulePath.size())
     316                addFilesToProject(moduleDir, project, includeList, excludeList, setup.filePrefix + '/' + modulePath);
     317        else
     318                addFilesToProject(moduleDir, project, includeList, excludeList, setup.filePrefix);
     319
     320        project << "\t</Files>\n"
     321                   "</VisualStudioProject>\n";
     322}
     323
     324void VisualStudioProvider::writeReferences(std::ofstream &output) {
     325        output << "\tProjectSection(ProjectDependencies) = postProject\n";
     326
     327        for (UUIDMap::const_iterator i = _uuidMap.begin(); i != _uuidMap.end(); ++i) {
     328                if (i->first == "scummvm")
     329                        continue;
     330
     331                output << "\t\t{" << i->second << "} = {" << i->second << "}\n";
     332        }
     333
     334        output << "\tEndProjectSection\n";
     335}
     336
     337void VisualStudioProvider::outputGlobalPropFile(std::ofstream &properties, int bits, const StringList &defines, const std::string &prefix) {
     338        std::string warnings;
     339        for (StringList::const_iterator i = _globalWarnings.begin(); i != _globalWarnings.end(); ++i)
     340                warnings +=  *i + ';';
     341
     342        std::string definesList;
     343        for (StringList::const_iterator i = defines.begin(); i != defines.end(); ++i) {
     344                if (i != defines.begin())
     345                        definesList += ';';
     346                definesList += *i;
     347        }
     348
     349        properties << "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>\n"
     350                      "<VisualStudioPropertySheet\n"
     351                      "\tProjectType=\"Visual C++\"\n"
     352                      "\tVersion=\"8.00\"\n"
     353                      "\tName=\"ScummVM_Global\"\n"
     354                      "\tOutputDirectory=\"$(ConfigurationName)" << bits << "\"\n"
     355                      "\tIntermediateDirectory=\"$(ConfigurationName)" << bits << "/$(ProjectName)\"\n"
     356                      "\t>\n"
     357                      "\t<Tool\n"
     358                      "\t\tName=\"VCCLCompilerTool\"\n"
     359                      "\t\tDisableLanguageExtensions=\"true\"\n"
     360                      "\t\tDisableSpecificWarnings=\"" << warnings << "\"\n"
     361                      "\t\tAdditionalIncludeDirectories=\"" << prefix << ";" << prefix << "\\engines;$(SCUMMVM_LIBS)\\include\"\n"
     362                      "\t\tPreprocessorDefinitions=\"" << definesList << "\"\n"
     363                      "\t\tExceptionHandling=\"0\"\n"
     364                      "\t\tRuntimeTypeInfo=\"false\"\n"
     365                      "\t\tWarningLevel=\"4\"\n"
     366                      "\t\tWarnAsError=\"false\"\n"
     367                      "\t\tCompileAs=\"0\"\n"
     368                      "\t\t/>\n"
     369                      "\t<Tool\n"
     370                      "\t\tName=\"VCLibrarianTool\"\n"
     371                      "\t\tIgnoreDefaultLibraryNames=\"\"\n"
     372                      "\t/>\n"
     373                      "\t<Tool\n"
     374                      "\t\tName=\"VCLinkerTool\"\n"
     375                      "\t\tIgnoreDefaultLibraryNames=\"\"\n"
     376                      "\t\tSubSystem=\"1\"\n"
     377                      "\t\tEntryPointSymbol=\"WinMainCRTStartup\"\n"
     378                      "\t/>\n"
     379                      "\t<Tool\n"
     380                      "\t\tName=\"VCResourceCompilerTool\"\n"
     381                      "\t\tPreprocessorDefinitions=\"HAS_INCLUDE_SET\"\n"
     382                      "\t\tAdditionalIncludeDirectories=\"$(SCUMMVM_LIBS)\\lib\\" << (bits == 32 ? "x86" : "x64") << "\"\n"
     383                      "\t/>\n"
     384                      "</VisualStudioPropertySheet>\n";
     385
     386        properties.flush();
     387}
     388
     389void VisualStudioProvider::createBuildProp(const BuildSetup &setup, bool isRelease, bool isWin32) {
     390        const std::string outputType = (isRelease ? "Release" : "Debug");
     391        const std::string outputBitness = (isWin32 ? "32" : "64");
     392
     393        std::ofstream properties((setup.outputDir + '/' + "ScummVM_" + outputType + (isWin32 ? "" : "64") + getPropertiesExtension()).c_str());
     394        if (!properties)
     395                error("Could not open \"" + setup.outputDir + '/' + "ScummVM_" + outputType + (isWin32 ? "" : "64") + getPropertiesExtension() + "\" for writing");
     396
     397        properties << "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>\n"
     398                      "<VisualStudioPropertySheet\n"
     399                      "\tProjectType=\"Visual C++\"\n"
     400                      "\tVersion=\"8.00\"\n"
     401                      "\tName=\"ScummVM_" << outputType << outputBitness << "\"\n"
     402                      "\tInheritedPropertySheets=\".\\ScummVM_Global" << (isWin32 ? "" : "64") << ".vsprops\"\n"
     403                      "\t>\n"
     404                      "\t<Tool\n"
     405                      "\t\tName=\"VCCLCompilerTool\"\n";
     406
     407        if (isRelease) {
     408                properties << "\t\tEnableIntrinsicFunctions=\"true\"\n"
     409                              "\t\tWholeProgramOptimization=\"true\"\n"
     410                              "\t\tPreprocessorDefinitions=\"WIN32;RELEASE_BUILD\"\n"
     411                              "\t\tStringPooling=\"true\"\n"
     412                              "\t\tBufferSecurityCheck=\"false\"\n"
     413                              "\t\tDebugInformationFormat=\"0\"\n"
     414                              "\t/>\n"
     415                              "\t<Tool\n"
     416                              "\t\tName=\"VCLinkerTool\"\n"
     417                              "\t\tLinkIncremental=\"1\"\n"
     418                              "\t\tIgnoreDefaultLibraryNames=\"\"\n"
     419                              "\t\tSetChecksum=\"true\"\n";
     420        } else {
     421                properties << "\t\tOptimization=\"0\"\n"
     422                              "\t\tPreprocessorDefinitions=\"WIN32\"\n"
     423                              "\t\tMinimalRebuild=\"true\"\n"
     424                              "\t\tBasicRuntimeChecks=\"3\"\n"
     425                              "\t\tRuntimeLibrary=\"1\"\n"
     426                              "\t\tEnableFunctionLevelLinking=\"true\"\n"
     427                              "\t\tWarnAsError=\"false\"\n"
     428                              "\t\tDebugInformationFormat=\"" << (isWin32 ? "4" : "3") << "\"\n"        // For x64 format "4" (Edit and continue) is not supported, thus we default to "3"
     429                              "\t/>\n"
     430                              "\t<Tool\n"
     431                              "\t\tName=\"VCLinkerTool\"\n"
     432                              "\t\tLinkIncremental=\"2\"\n"
     433                              "\t\tGenerateDebugInformation=\"true\"\n"
     434                              "\t\tIgnoreDefaultLibraryNames=\"libcmt.lib\"\n";
     435        }
     436
     437        properties << "\t/>\n"
     438                      "</VisualStudioPropertySheet>\n";
     439
     440        properties.flush();
     441        properties.close();
     442}
     443
     444void VisualStudioProvider::writeFileListToProject(const FileNode &dir, std::ofstream &projectFile, const int indentation,
     445                                                  const StringList &duplicate, const std::string &objPrefix, const std::string &filePrefix) {
     446        const std::string indentString = getIndent(indentation + 2);
     447
     448        if (indentation)
     449                projectFile << getIndent(indentation + 1) << "<Filter\tName=\"" << dir.name << "\">\n";
     450
     451        for (FileNode::NodeList::const_iterator i = dir.children.begin(); i != dir.children.end(); ++i) {
     452                const FileNode *node = *i;
     453
     454                if (!node->children.empty()) {
     455                        writeFileListToProject(*node, projectFile, indentation + 1, duplicate, objPrefix + node->name + '_', filePrefix + node->name + '/');
     456                } else {
     457                        if (producesObjectFile(node->name)) {
     458                                std::string name, ext;
     459                                splitFilename(node->name, name, ext);
     460                                const bool isDuplicate = (std::find(duplicate.begin(), duplicate.end(), name + ".o") != duplicate.end());
     461
     462                                if (ext == "asm") {
     463                                        std::string objFileName = "$(IntDir)\\";
     464                                        if (isDuplicate)
     465                                                objFileName += objPrefix;
     466                                        objFileName += "$(InputName).obj";
     467
     468                                        const std::string toolLine = indentString + "\t\t<Tool Name=\"VCCustomBuildTool\" CommandLine=\"nasm.exe -f win32 -g -o &quot;" + objFileName + "&quot; &quot;$(InputPath)&quot;&#x0D;&#x0A;\" Outputs=\"" + objFileName + "\" />\n";
     469
     470                                        // NASM is not supported for x64, thus we do not need to add additional entries here :-).
     471                                        projectFile << indentString << "<File RelativePath=\"" << convertPathToWin(filePrefix + node->name) << "\">\n"
     472                                                    << indentString << "\t<FileConfiguration Name=\"Debug|Win32\">\n"
     473                                                    << toolLine
     474                                                    << indentString << "\t</FileConfiguration>\n"
     475                                                    << indentString << "\t<FileConfiguration Name=\"Release|Win32\">\n"
     476                                                    << toolLine
     477                                                    << indentString << "\t</FileConfiguration>\n"
     478                                                    << indentString << "</File>\n";
     479                                } else {
     480                                        if (isDuplicate) {
     481                                                const std::string toolLine = indentString + "\t\t<Tool Name=\"VCCLCompilerTool\" ObjectFile=\"$(IntDir)\\" + objPrefix + "$(InputName).obj\" XMLDocumentationFileName=\"$(IntDir)\\" + objPrefix + "$(InputName).xdc\" />\n";
     482
     483                                                projectFile << indentString << "<File RelativePath=\"" << convertPathToWin(filePrefix + node->name) << "\">\n"
     484                                                            << indentString << "\t<FileConfiguration Name=\"Debug|Win32\">\n"
     485                                                            << toolLine
     486                                                            << indentString << "\t</FileConfiguration>\n"
     487                                                            << indentString << "\t<FileConfiguration Name=\"Release|Win32\">\n"
     488                                                            << toolLine
     489                                                            << indentString << "\t</FileConfiguration>\n"
     490                                                            << indentString << "\t<FileConfiguration Name=\"Debug|x64\">\n"
     491                                                            << toolLine
     492                                                            << indentString << "\t</FileConfiguration>\n"
     493                                                            << indentString << "\t<FileConfiguration Name=\"Release|x64\">\n"
     494                                                            << toolLine
     495                                                            << indentString << "\t</FileConfiguration>\n"
     496                                                            << indentString << "</File>\n";
     497                                        } else {
     498                                                projectFile << indentString << "<File RelativePath=\"" << convertPathToWin(filePrefix + node->name) << "\" />\n";
     499                                        }
     500                                }
     501                        } else {
     502                                projectFile << indentString << "<File RelativePath=\"" << convertPathToWin(filePrefix + node->name) << "\" />\n";
     503                        }
     504                }
     505        }
     506
     507        if (indentation)
     508                projectFile << getIndent(indentation + 1) << "</Filter>\n";
     509}
     510
     511//////////////////////////////////////////////////////////////////////////
     512// MSBuild Provider (Visual Studio 2010)
     513//////////////////////////////////////////////////////////////////////////
     514
     515MSBuildProvider::MSBuildProvider(StringList &global_warnings, std::map<std::string, StringList> &project_warnings, const int version)
     516        : MSVCProvider(global_warnings, project_warnings, version) {
     517
     518}
     519
     520const char *MSBuildProvider::getProjectExtension() {
     521        return ".vcxproj";
     522}
     523
     524const char *MSBuildProvider::getPropertiesExtension() {
     525        return ".props";
     526}
     527
     528int MSBuildProvider::getVisualStudioVersion() {
     529        return 2010;
     530}
     531
     532#define OUTPUT_CONFIGURATION_MSBUILD(config, platform) \
     533        (project << "\t\t<ProjectConfiguration Include=\"" << config << "|" << platform << "\">\n" \
     534                   "\t\t\t<Configuration>" << config << "</Configuration>\n" \
     535                   "\t\t\t<Platform>" << platform << "</Platform>\n" \
     536                   "\t\t</ProjectConfiguration>\n")
     537
     538#define OUTPUT_CONFIGURATION_TYPE_MSBUILD(config) \
     539        (project << "\t<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='" << config << "'\" Label=\"Configuration\">\n" \
     540                   "\t\t<ConfigurationType>" << (name == "scummvm" ? "Application" : "StaticLibrary") << "</ConfigurationType>\n" \
     541                   "\t</PropertyGroup>\n")
     542
     543#define OUTPUT_PROPERTIES_MSBUILD(config, properties) \
     544        (project << "\t<ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='" << config << "'\" Label=\"PropertySheets\">\n" \
     545                   "\t\t<Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n" \
     546                   "\t\t<Import Project=\"" << properties << "\" />\n" \
     547                   "\t</ImportGroup>\n")
     548
     549void MSBuildProvider::createProjectFile(const std::string &name, const std::string &uuid, const BuildSetup &setup, const std::string &moduleDir,
     550                                        const StringList &includeList, const StringList &excludeList) {
     551        const std::string projectFile = setup.outputDir + '/' + name + getProjectExtension();
     552        std::ofstream project(projectFile.c_str());
     553        if (!project)
     554                error("Could not open \"" + projectFile + "\" for writing");
     555
     556        project << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
     557                   "<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"
     558                   "\t<ItemGroup Label=\"ProjectConfigurations\">\n";
     559
     560        OUTPUT_CONFIGURATION_MSBUILD("Debug", "Win32");
     561        OUTPUT_CONFIGURATION_MSBUILD("Debug", "x64");
     562        OUTPUT_CONFIGURATION_MSBUILD("Release", "Win32");
     563        OUTPUT_CONFIGURATION_MSBUILD("Release", "x64");
     564
     565        project << "\t</ItemGroup>\n";
     566
     567        // Project name & Guid
     568        project << "\t<PropertyGroup Label=\"Globals\">\n"
     569                   "\t\t<ProjectGuid>{" << uuid << "}</ProjectGuid>\n"
     570                   "\t\t<RootNamespace>" << name << "</RootNamespace>\n"
     571                   "\t\t<Keyword>Win32Proj</Keyword>\n"
     572                   "\t</PropertyGroup>\n";
     573
     574        // Shared configuration
     575        project << "\t<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n";
     576
     577        OUTPUT_CONFIGURATION_TYPE_MSBUILD("Release|Win32");
     578        OUTPUT_CONFIGURATION_TYPE_MSBUILD("Debug|Win32");
     579        OUTPUT_CONFIGURATION_TYPE_MSBUILD("Release|x64");
     580        OUTPUT_CONFIGURATION_TYPE_MSBUILD("Debug|x64");
     581
     582        project << "\t<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n"
     583                   "\t<ImportGroup Label=\"ExtensionSettings\">\n"
     584                   "\t</ImportGroup>\n";
     585
     586        OUTPUT_PROPERTIES_MSBUILD("Release|Win32", "ScummVM_Release.props");
     587        OUTPUT_PROPERTIES_MSBUILD("Debug|Win32", "ScummVM_Debug.props");
     588        OUTPUT_PROPERTIES_MSBUILD("Release|x64", "ScummVM_Release64.props");
     589        OUTPUT_PROPERTIES_MSBUILD("Debug|x64", "ScummVM_Debug64.props");
     590
     591        project << "\t<PropertyGroup Label=\"UserMacros\" />\n";
     592
     593        // Project-specific settings
     594        outputProjectSettings(project, name, setup, false, true);
     595        outputProjectSettings(project, name, setup, true, true);
     596        outputProjectSettings(project, name, setup, false, false);
     597        outputProjectSettings(project, name, setup, true, false);
     598
     599        // Files
     600        std::string modulePath;
     601        if (!moduleDir.compare(0, setup.srcDir.size(), setup.srcDir)) {
     602                modulePath = moduleDir.substr(setup.srcDir.size());
     603                if (!modulePath.empty() && modulePath.at(0) == '/')
     604                        modulePath.erase(0, 1);
     605        }
     606
     607        if (modulePath.size())
     608                addFilesToProject(moduleDir, project, includeList, excludeList, setup.filePrefix + '/' + modulePath);
     609        else
     610                addFilesToProject(moduleDir, project, includeList, excludeList, setup.filePrefix);
     611
     612        // Output references for scummvm project
     613        if (name == "scummvm")
     614                writeReferences(project);
     615
     616        project << "\t<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n"
     617                   "\t<ImportGroup Label=\"ExtensionTargets\">\n"
     618                   "\t</ImportGroup>\n"
     619                   "</Project>\n";
     620
     621        // Output filter file if necessary
     622        createFiltersFile(setup, name);
     623}
     624
     625#define OUTPUT_FILTER_MSBUILD(files, action) \
     626        if (!files.empty()) { \
     627                filters << "\t<ItemGroup>\n"; \
     628                for (std::list<FileEntry>::const_iterator entry = files.begin(); entry != files.end(); ++entry) { \
     629                        if ((*entry).filter != "") { \
     630                                filters << "\t\t<" action " Include=\"" << (*entry).path << "\">\n" \
     631                                           "\t\t\t<Filter>" << (*entry).filter << "</Filter>\n" \
     632                                           "\t\t</" action ">\n"; \
     633                        } else { \
     634                                filters << "\t\t<" action " Include=\"" << (*entry).path << "\" />\n"; \
     635                        } \
     636                } \
     637                filters << "\t</ItemGroup>\n"; \
     638        }
     639
     640void MSBuildProvider::createFiltersFile(const BuildSetup &setup, const std::string &name) {
     641        // No filters => no need to create a filter file
     642        if (_filters.empty())
     643                return;
     644
     645        // Sort all list alphabetically
     646        _filters.sort();
     647        _compileFiles.sort();
     648        _includeFiles.sort();
     649        _otherFiles.sort();
     650        _resourceFiles.sort();
     651        _asmFiles.sort();
     652
     653        const std::string filtersFile = setup.outputDir + '/' + name + getProjectExtension() + ".filters";
     654        std::ofstream filters(filtersFile.c_str());
     655        if (!filters)
     656                error("Could not open \"" + filtersFile + "\" for writing");
     657
     658        filters << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
     659                   "<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n";
     660
     661        // Output the list of filters
     662        filters << "\t<ItemGroup>\n";
     663        for (std::list<std::string>::iterator filter = _filters.begin(); filter != _filters.end(); ++filter) {
     664                filters << "\t\t<Filter Include=\"" << *filter << "\">\n"
     665                           "\t\t\t<UniqueIdentifier>" << createUUID() << "</UniqueIdentifier>\n"
     666                           "\t\t</Filter>\n";
     667        }
     668        filters << "\t</ItemGroup>\n";
     669
     670        // Output files
     671        OUTPUT_FILTER_MSBUILD(_compileFiles, "ClCompile")
     672        OUTPUT_FILTER_MSBUILD(_includeFiles, "ClInclude")
     673        OUTPUT_FILTER_MSBUILD(_otherFiles, "None")
     674        OUTPUT_FILTER_MSBUILD(_resourceFiles, "ResourceCompile")
     675        OUTPUT_FILTER_MSBUILD(_asmFiles, "CustomBuild")
     676
     677        filters << "</Project>";
     678}
     679
     680void MSBuildProvider::writeReferences(std::ofstream &output) {
     681        output << "\t<ItemGroup>\n";
     682
     683        for (UUIDMap::const_iterator i = _uuidMap.begin(); i != _uuidMap.end(); ++i) {
     684                if (i->first == "scummvm")
     685                        continue;
     686
     687                output << "\t<ProjectReference Include=\"" << i->first << ".vcxproj\">\n"
     688                          "\t\t<Project>{" << i->second << "}</Project>\n"
     689                          "\t</ProjectReference>\n";
     690        }
     691
     692        output << "\t</ItemGroup>\n";
     693}
     694
     695void MSBuildProvider::outputProjectSettings(std::ofstream &project, const std::string &name, const BuildSetup &setup, bool isRelease, bool isWin32) {
     696        // Check for project-specific warnings:
     697        std::map<std::string, StringList>::iterator warningsIterator = _projectWarnings.find(name);
     698
     699        // Nothing to add here, move along!
     700        if (name != "scummvm" && name != "sword25" && name != "tinsel" && warningsIterator == _projectWarnings.end())
     701                return;
     702
     703        std::string warnings = "";
     704        if (warningsIterator != _projectWarnings.end())
     705                for (StringList::const_iterator i = warningsIterator->second.begin(); i != warningsIterator->second.end(); ++i)
     706                        warnings +=  *i + ';';
     707
     708        project << "\t<ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='" << (isRelease ? "Release" : "Debug") << "|" << (isWin32 ? "Win32" : "x64") << "'\">\n"
     709                   "\t\t<ClCompile>\n";
     710
     711        // Compile configuration
     712        if (name == "scummvm" || name == "sword25") {
     713                project << "\t\t\t<DisableLanguageExtensions>false</DisableLanguageExtensions>\n";
     714        } else {
     715                if (name == "tinsel" && !isRelease)
     716                        project << "\t\t\t<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\n";
     717
     718                if (warningsIterator != _projectWarnings.end())
     719                        project << "\t\t\t<DisableSpecificWarnings>" << warnings << ";%(DisableSpecificWarnings)</DisableSpecificWarnings>\n";
     720        }
     721
     722        project << "\t\t</ClCompile>\n";
     723
     724        // Link configuration for scummvm project
     725        if (name == "scummvm") {
     726                std::string libraries;
     727
     728                for (StringList::const_iterator i = setup.libraries.begin(); i != setup.libraries.end(); ++i)
     729                        libraries += *i + ".lib;";
     730
     731                project << "\t\t<Link>\n"
     732                           "\t\t\t<OutputFile>$(OutDir)scummvm.exe</OutputFile>\n"
     733                           "\t\t\t<AdditionalDependencies>" << libraries << "%(AdditionalDependencies)</AdditionalDependencies>\n"
     734                           "\t\t</Link>\n";
     735
     736                // Only generate revision number in debug builds
     737                if (!isRelease) {
     738                        project << "\t\t<PreBuildEvent>\n"
     739                                   "\t\t\t<Message>Generate internal_version.h</Message>\n"
     740                                   "\t\t\t<Command>" << getRevisionToolCommandLine() << "</Command>\n"
     741                                   "\t\t</PreBuildEvent>\n";
     742                }
     743
     744                // Copy data files to the build folder
     745                project << "\t\t<PostBuildEvent>\n"
     746                           "\t\t\t<Message>Copy data files to the build folder</Message>\n"
     747                       "\t\t\t<Command>" << getCopyDataCommandLine(isWin32) << "</Command>\n"
     748                           "\t\t</PostBuildEvent>\n";
     749        }
     750
     751        project << "\t</ItemDefinitionGroup>\n";
     752}
     753
     754void MSBuildProvider::outputGlobalPropFile(std::ofstream &properties, int bits, const StringList &defines, const std::string &prefix) {
     755
     756        std::string warnings;
     757        for (StringList::const_iterator i = _globalWarnings.begin(); i != _globalWarnings.end(); ++i)
     758                warnings +=  *i + ';';
     759
     760        std::string definesList;
     761        for (StringList::const_iterator i = defines.begin(); i != defines.end(); ++i)
     762                definesList += *i + ';';
     763
     764        properties << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
     765                      "<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"
     766                      "\t<PropertyGroup>\n"
     767                      "\t\t<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\n"
     768                      "\t\t<_PropertySheetDisplayName>ScummVM_Global</_PropertySheetDisplayName>\n"
     769                      "\t\t<ExecutablePath>$(SCUMMVM_LIBS)\\bin;$(ExecutablePath)</ExecutablePath>\n"
     770                      "\t\t<LibraryPath>$(SCUMMVM_LIBS)\\lib\\" << (bits == 32 ? "x86" : "x64") << ";$(LibraryPath)</LibraryPath>\n"
     771                      "\t\t<IncludePath>$(SCUMMVM_LIBS)\\include;$(IncludePath)</IncludePath>\n"
     772                      "\t\t<OutDir>$(Configuration)" << bits << "\\</OutDir>\n"
     773                      "\t\t<IntDir>$(Configuration)" << bits << "/$(ProjectName)\\</IntDir>\n"
     774                      "\t</PropertyGroup>\n"
     775                      "\t<ItemDefinitionGroup>\n"
     776                      "\t\t<ClCompile>\n"
     777                      "\t\t\t<DisableLanguageExtensions>true</DisableLanguageExtensions>\n"
     778                      "\t\t\t<DisableSpecificWarnings>" << warnings << ";%(DisableSpecificWarnings)</DisableSpecificWarnings>\n"
     779                      "\t\t\t<AdditionalIncludeDirectories>$(SCUMMVM_LIBS)\\include;" << prefix << ";" << prefix << "\\engines;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n"
     780                      "\t\t\t<PreprocessorDefinitions>" << definesList << "%(PreprocessorDefinitions)</PreprocessorDefinitions>\n"
     781                      "\t\t\t<ExceptionHandling></ExceptionHandling>\n"
     782                      "\t\t\t<RuntimeTypeInfo>false</RuntimeTypeInfo>\n"
     783                      "\t\t\t<WarningLevel>Level4</WarningLevel>\n"
     784                      "\t\t\t<TreatWarningAsError>false</TreatWarningAsError>\n"
     785                      "\t\t\t<CompileAs>Default</CompileAs>\n"
     786                      "\t\t</ClCompile>\n"
     787                      "\t\t<Link>\n"
     788                      "\t\t\t<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\n"
     789                      "\t\t\t<SubSystem>Console</SubSystem>\n"
     790                      "\t\t\t<EntryPointSymbol>WinMainCRTStartup</EntryPointSymbol>\n"
     791                      "\t\t</Link>\n"
     792                      "\t\t<ResourceCompile>\n"
     793                      "\t\t\t<PreprocessorDefinitions>HAS_INCLUDE_SET;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n"
     794                      "\t\t\t<AdditionalIncludeDirectories>" << prefix << ";%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n"
     795                      "\t\t</ResourceCompile>\n"
     796                      "\t</ItemDefinitionGroup>\n"
     797                      "</Project>\n";
     798
     799        properties.flush();
     800}
     801
     802void MSBuildProvider::createBuildProp(const BuildSetup &setup, bool isRelease, bool isWin32) {
     803        const std::string outputType = (isRelease ? "Release" : "Debug");
     804        const std::string outputBitness = (isWin32 ? "32" : "64");
     805
     806        std::ofstream properties((setup.outputDir + '/' + "ScummVM_" + outputType + (isWin32 ? "" : "64") + getPropertiesExtension()).c_str());
     807        if (!properties)
     808                error("Could not open \"" + setup.outputDir + '/' + "ScummVM_" + outputType + (isWin32 ? "" : "64") + getPropertiesExtension() + "\" for writing");
     809
     810        properties << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
     811                      "<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"
     812                      "\t<ImportGroup Label=\"PropertySheets\">\n"
     813                      "\t\t<Import Project=\"ScummVM_Global" << (isWin32 ? "" : "64") << ".props\" />\n"
     814                      "\t</ImportGroup>\n"
     815                      "\t<PropertyGroup>\n"
     816                      "\t\t<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\n"
     817                      "\t\t<_PropertySheetDisplayName>ScummVM_" << outputType << outputBitness << "</_PropertySheetDisplayName>\n"
     818                      "\t\t<LinkIncremental>" << (isRelease ? "false" : "true") << "</LinkIncremental>\n"
     819                      "\t</PropertyGroup>\n"
     820                      "\t<ItemDefinitionGroup>\n"
     821                      "\t\t<ClCompile>\n";
     822
     823        if (isRelease) {
     824                properties << "\t\t\t<IntrinsicFunctions>true</IntrinsicFunctions>\n"
     825                              "\t\t\t<WholeProgramOptimization>true</WholeProgramOptimization>\n"
     826                              "\t\t\t<PreprocessorDefinitions>WIN32;RELEASE_BUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n"
     827                              "\t\t\t<StringPooling>true</StringPooling>\n"
     828                              "\t\t\t<BufferSecurityCheck>false</BufferSecurityCheck>\n"
     829                              "\t\t\t<DebugInformationFormat></DebugInformationFormat>\n"
     830                              "\t\t</ClCompile>\n"
     831                              "\t\t<Link>\n"
     832                              "\t\t\t<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\n"
     833                              "\t\t\t<SetChecksum>true</SetChecksum>\n";
     834        } else {
     835                properties << "\t\t\t<Optimization>Disabled</Optimization>\n"
     836                              "\t\t\t<PreprocessorDefinitions>WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n"
     837                              "\t\t\t<MinimalRebuild>true</MinimalRebuild>\n"
     838                              "\t\t\t<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n"
     839                              "\t\t\t<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n"
     840                              "\t\t\t<FunctionLevelLinking>true</FunctionLevelLinking>\n"
     841                              "\t\t\t<TreatWarningAsError>false</TreatWarningAsError>\n"
     842                              "\t\t\t<DebugInformationFormat>" << (isWin32 ? "EditAndContinue" : "ProgramDatabase") << "</DebugInformationFormat>\n" // For x64 format Edit and continue is not supported, thus we default to Program Database
     843                              "\t\t</ClCompile>\n"
     844                              "\t\t<Link>\n"
     845                              "\t\t\t<GenerateDebugInformation>true</GenerateDebugInformation>\n"
     846                              "\t\t\t<IgnoreSpecificDefaultLibraries>libcmt.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\n";
     847        }
     848
     849        properties << "\t\t</Link>\n"
     850                      "\t</ItemDefinitionGroup>\n"
     851                      "</Project>\n";
     852
     853        properties.flush();
     854        properties.close();
     855}
     856
     857#define OUTPUT_NASM_COMMAND_MSBUILD(config) \
     858        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" \
     859                       "\t\t\t<Outputs Condition=\"'$(Configuration)|$(Platform)'=='" << config << "|Win32'\">$(IntDir)" << (isDuplicate ? (*entry).prefix : "") << "%(Filename).obj;%(Outputs)</Outputs>\n";
     860
     861#define OUPUT_OBJECT_FILENAME_MSBUILD(config, platform, prefix) \
     862        projectFile << "\t\t<ObjectFileName Condition=\"'$(Configuration)|$(Platform)'=='" << config << "|" << platform << "'\">$(IntDir)" << prefix << "%(Filename).obj</ObjectFileName>\n" \
     863                       "\t\t<XMLDocumentationFileName Condition=\"'$(Configuration)|$(Platform)'=='" << config << "|" << platform << "'\">$(IntDir)" << prefix << "%(Filename).xdc</XMLDocumentationFileName>\n";
     864
     865#define OUPUT_FILES_MSBUILD(files, action) \
     866        if (!files.empty()) { \
     867                projectFile << "\t<ItemGroup>\n"; \
     868                for (std::list<FileEntry>::const_iterator entry = files.begin(); entry != files.end(); ++entry) { \
     869                        projectFile << "\t\t<" action " Include=\"" << (*entry).path << "\" />\n"; \
     870                } \
     871                projectFile << "\t</ItemGroup>\n"; \
     872        }
     873
     874void MSBuildProvider::writeFileListToProject(const FileNode &dir, std::ofstream &projectFile, const int, const StringList &duplicate,
     875                                             const std::string &objPrefix, const std::string &filePrefix) {
     876        // Reset lists
     877        _filters.clear();
     878        _compileFiles.clear();
     879        _includeFiles.clear();
     880        _otherFiles.clear();
     881        _resourceFiles.clear();
     882        _asmFiles.clear();
     883
     884        // Compute the list of files
     885        _filters.push_back(""); // init filters
     886        computeFileList(dir, duplicate, objPrefix, filePrefix);
     887        _filters.pop_back();    // remove last empty filter
     888
     889        // Output compile files
     890        if (!_compileFiles.empty()) {
     891                projectFile << "\t<ItemGroup>\n";
     892                for (std::list<FileEntry>::const_iterator entry = _compileFiles.begin(); entry != _compileFiles.end(); ++entry) {
     893                        const bool isDuplicate = (std::find(duplicate.begin(), duplicate.end(), (*entry).name + ".o") != duplicate.end());
     894
     895                        // Deal with duplicated file names
     896                        if (isDuplicate) {
     897                                projectFile << "\t\t<ClCompile Include=\"" << (*entry).path << "\">\n";
     898                                OUPUT_OBJECT_FILENAME_MSBUILD("Debug", "Win32", (*entry).prefix)
     899                                OUPUT_OBJECT_FILENAME_MSBUILD("Debug", "x64", (*entry).prefix)
     900                                OUPUT_OBJECT_FILENAME_MSBUILD("Release", "Win32", (*entry).prefix)
     901                                OUPUT_OBJECT_FILENAME_MSBUILD("Release", "x64", (*entry).prefix)
     902                                projectFile << "\t\t</ClCompile>\n";
     903                        } else {
     904                                projectFile << "\t\t<ClCompile Include=\"" << (*entry).path << "\" />\n";
     905                        }
     906                }
     907                projectFile << "\t</ItemGroup>\n";
     908        }
     909
     910        // Output include, other and resource files
     911        OUPUT_FILES_MSBUILD(_includeFiles, "ClInclude")
     912        OUPUT_FILES_MSBUILD(_otherFiles, "None")
     913        OUPUT_FILES_MSBUILD(_resourceFiles, "ResourceCompile")
     914
     915        // Output asm files
     916        if (!_asmFiles.empty()) {
     917                projectFile << "\t<ItemGroup>\n";
     918                for (std::list<FileEntry>::const_iterator entry = _asmFiles.begin(); entry != _asmFiles.end(); ++entry) {
     919
     920                        const bool isDuplicate = (std::find(duplicate.begin(), duplicate.end(), (*entry).name + ".o") != duplicate.end());
     921
     922                        projectFile << "\t\t<CustomBuild Include=\"" << (*entry).path << "\">\n"
     923                                       "\t\t\t<FileType>Document</FileType>\n";
     924
     925                        OUTPUT_NASM_COMMAND_MSBUILD("Debug")
     926                        OUTPUT_NASM_COMMAND_MSBUILD("Release")
     927
     928                        projectFile << "\t\t</CustomBuild>\n";
     929                }
     930                projectFile << "\t</ItemGroup>\n";
     931        }
     932}
     933
     934void MSBuildProvider::computeFileList(const FileNode &dir, const StringList &duplicate, const std::string &objPrefix, const std::string &filePrefix) {
     935        for (FileNode::NodeList::const_iterator i = dir.children.begin(); i != dir.children.end(); ++i) {
     936                const FileNode *node = *i;
     937
     938                if (!node->children.empty()) {
     939                        // Update filter
     940                        std::string _currentFilter = _filters.back();
     941                        _filters.back().append((_filters.back() == "" ? "" : "\\") + node->name);
     942
     943                        computeFileList(*node, duplicate, objPrefix + node->name + '_', filePrefix + node->name + '/');
     944
     945                        // Reset filter
     946                        _filters.push_back(_currentFilter);
     947                } else {
     948                        // Filter files by extension
     949                        std::string name, ext;
     950                        splitFilename(node->name, name, ext);
     951
     952                        FileEntry entry;
     953                        entry.name = name;
     954                        entry.path = convertPathToWin(filePrefix + node->name);
     955                        entry.filter = _filters.back();
     956                        entry.prefix = objPrefix;
     957
     958                        if (ext == "cpp" || ext == "c")
     959                                _compileFiles.push_back(entry);
     960                        else if (ext == "h")
     961                                _includeFiles.push_back(entry);
     962                        else if (ext == "rc")
     963                                _resourceFiles.push_back(entry);
     964                        else if (ext == "asm")
     965                                _asmFiles.push_back(entry);
     966                        else
     967                                _otherFiles.push_back(entry);
     968                }
     969        }
     970}
     971
     972} // End of CreateProjectTool namespace
  • new file tools/create_project/msvc.h

    diff -r e24b1c8ca942 tools/create_project/msvc.h
    - +  
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11 *
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL$
     22 * $Id$
     23 *
     24 */
     25
     26#ifndef TOOLS_CREATE_PROJECT_MSVC_H
     27#define TOOLS_CREATE_PROJECT_MSVC_H
     28
     29#include "create_project.h"
     30
     31namespace CreateProjectTool {
     32
     33class MSVCProvider : public ProjectProvider {
     34public:
     35        MSVCProvider(StringList &global_warnings, std::map<std::string, StringList> &project_warnings, const int version);
     36
     37protected:
     38
     39        void createWorkspace(const BuildSetup &setup);
     40
     41        void createOtherBuildFiles(const BuildSetup &setup);
     42
     43        /**
     44         * Create the global project properties.
     45         *
     46         * @param setup Description of the desired build setup.
     47         */
     48        void createGlobalProp(const BuildSetup &setup);
     49
     50        /**
     51         * Outputs a property file based on the input parameters.
     52         *
     53         * It can be easily used to create different global properties files
     54         * for a 64 bit and a 32 bit version. It will also take care that the
     55         * two platform configurations will output their files into different
     56         * directories.
     57         *
     58         * @param properties File stream in which to write the property settings.
     59         * @param bits Number of bits the platform supports.
     60         * @param defines Defines the platform needs to have set.
     61         * @param prefix File prefix, used to add additional include paths.
     62         */
     63        virtual void outputGlobalPropFile(std::ofstream &properties, int bits, const StringList &defines, const std::string &prefix) = 0;
     64
     65        /**
     66         * Generates the project properties for debug and release settings.
     67         *
     68         * @param setup Description of the desired build setup.
     69         * @param isRelease Type of property file
     70         * @param isWin32 Bitness of property file
     71         */
     72        virtual void createBuildProp(const BuildSetup &setup, bool isRelease, bool isWin32) = 0;
     73
     74        /**
     75         * Get the file extension for property files
     76         */
     77        virtual const char *getPropertiesExtension() = 0;
     78
     79        /**
     80         * Get the Visual Studio version (used by the VS shell extension to launch the correct VS version)
     81         */
     82        virtual int getVisualStudioVersion() = 0;
     83
     84        /**
     85         * Get the command line for the revision tool (shared between all Visual Studio based providers)
     86         */
     87        std::string getRevisionToolCommandLine() const;
     88
     89        /**
     90         * Get the command line for copying data files to the build directory
     91         *
     92         * @param isWin32 Bitness of property file
     93         */
     94        std::string getCopyDataCommandLine(bool isWin32) const;
     95};
     96
     97class VisualStudioProvider : public MSVCProvider {
     98public:
     99        VisualStudioProvider(StringList &global_warnings, std::map<std::string, StringList> &project_warnings, const int version);
     100
     101protected:
     102        void createProjectFile(const std::string &name, const std::string &uuid, const BuildSetup &setup, const std::string &moduleDir,
     103                               const StringList &includeList, const StringList &excludeList);
     104
     105        void writeFileListToProject(const FileNode &dir, std::ofstream &projectFile, const int indentation,
     106                                    const StringList &duplicate, const std::string &objPrefix, const std::string &filePrefix);
     107
     108        void writeReferences(std::ofstream &output);
     109
     110        void outputGlobalPropFile(std::ofstream &properties, int bits, const StringList &defines, const std::string &prefix);
     111
     112        void createBuildProp(const BuildSetup &setup, bool isRelease, bool isWin32);
     113
     114        const char *getProjectExtension();
     115        const char *getPropertiesExtension();
     116        int getVisualStudioVersion();
     117};
     118
     119class MSBuildProvider : public MSVCProvider {
     120public:
     121        MSBuildProvider(StringList &global_warnings, std::map<std::string, StringList> &project_warnings, const int version);
     122
     123protected:
     124        void createProjectFile(const std::string &name, const std::string &uuid, const BuildSetup &setup, const std::string &moduleDir,
     125                               const StringList &includeList, const StringList &excludeList);
     126
     127        void outputProjectSettings(std::ofstream &project, const std::string &name, const BuildSetup &setup, bool isRelease, bool isWin32);
     128
     129        void writeFileListToProject(const FileNode &dir, std::ofstream &projectFile, const int indentation,
     130                                    const StringList &duplicate, const std::string &objPrefix, const std::string &filePrefix);
     131
     132        void writeReferences(std::ofstream &output);
     133
     134        void outputGlobalPropFile(std::ofstream &properties, int bits, const StringList &defines, const std::string &prefix);
     135
     136        void createBuildProp(const BuildSetup &setup, bool isRelease, bool isWin32);
     137
     138        const char *getProjectExtension();
     139        const char *getPropertiesExtension();
     140        int getVisualStudioVersion();
     141
     142private:
     143        struct FileEntry {
     144                std::string name;
     145                std::string path;
     146                std::string filter;
     147                std::string prefix;
     148
     149                bool operator<(const FileEntry& rhs) const {
     150                        return path.compare(rhs.path) == -1;   // Not exactly right for alphabetical order, but good enough
     151                }
     152        };
     153        typedef std::list<FileEntry> FileEntries;
     154
     155        std::list<std::string> _filters; // list of filters (we need to create a GUID for each filter id)
     156        FileEntries _compileFiles;
     157        FileEntries _includeFiles;
     158        FileEntries _otherFiles;
     159        FileEntries _asmFiles;
     160        FileEntries _resourceFiles;
     161
     162        void computeFileList(const FileNode &dir, const StringList &duplicate, const std::string &objPrefix, const std::string &filePrefix);
     163        void createFiltersFile(const BuildSetup &setup, const std::string &name);
     164};
     165
     166} // End of CreateProjectTool namespace
     167
     168#endif // TOOLS_CREATE_PROJECT_MSVC_H
  • new file tools/create_project/msvc10/create_project.sln

    diff -r e24b1c8ca942 tools/create_project/msvc10/create_project.sln
    - +  
     1
     2Microsoft Visual Studio Solution File, Format Version 11.00
     3# Visual Studio 2010
     4Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "create_project", "create_project.vcxproj", "{CF177559-077D-4A08-AABE-BE0FD35F6C63}"
     5EndProject
     6Global
     7        GlobalSection(SolutionConfigurationPlatforms) = preSolution
     8                Debug|Win32 = Debug|Win32
     9                Release|Win32 = Release|Win32
     10        EndGlobalSection
     11        GlobalSection(ProjectConfigurationPlatforms) = postSolution
     12                {CF177559-077D-4A08-AABE-BE0FD35F6C63}.Debug|Win32.ActiveCfg = Debug|Win32
     13                {CF177559-077D-4A08-AABE-BE0FD35F6C63}.Debug|Win32.Build.0 = Debug|Win32
     14                {CF177559-077D-4A08-AABE-BE0FD35F6C63}.Release|Win32.ActiveCfg = Release|Win32
     15                {CF177559-077D-4A08-AABE-BE0FD35F6C63}.Release|Win32.Build.0 = Release|Win32
     16        EndGlobalSection
     17        GlobalSection(SolutionProperties) = preSolution
     18                HideSolutionNode = FALSE
     19        EndGlobalSection
     20EndGlobal
  • new file tools/create_project/msvc10/create_project.vcxproj

    diff -r e24b1c8ca942 tools/create_project/msvc10/create_project.vcxproj
    - +  
     1<?xml version="1.0" encoding="utf-8"?>
     2<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
     3  <ItemGroup Label="ProjectConfigurations">
     4    <ProjectConfiguration Include="Debug|Win32">
     5      <Configuration>Debug</Configuration>
     6      <Platform>Win32</Platform>
     7    </ProjectConfiguration>
     8    <ProjectConfiguration Include="Release|Win32">
     9      <Configuration>Release</Configuration>
     10      <Platform>Win32</Platform>
     11    </ProjectConfiguration>
     12  </ItemGroup>
     13  <PropertyGroup Label="Globals">
     14    <ProjectGuid>{CF177559-077D-4A08-AABE-BE0FD35F6C63}</ProjectGuid>
     15    <RootNamespace>create_project</RootNamespace>
     16  </PropertyGroup>
     17  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
     18  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     19    <ConfigurationType>Application</ConfigurationType>
     20    <CharacterSet>MultiByte</CharacterSet>
     21    <WholeProgramOptimization>true</WholeProgramOptimization>
     22  </PropertyGroup>
     23  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     24    <ConfigurationType>Application</ConfigurationType>
     25    <CharacterSet>MultiByte</CharacterSet>
     26  </PropertyGroup>
     27  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
     28  <ImportGroup Label="ExtensionSettings">
     29  </ImportGroup>
     30  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
     31    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
     32  </ImportGroup>
     33  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
     34    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
     35  </ImportGroup>
     36  <PropertyGroup Label="UserMacros" />
     37  <PropertyGroup>
     38    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
     39    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
     40    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
     41    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
     42    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
     43  </PropertyGroup>
     44  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     45    <ClCompile>
     46      <Optimization>Disabled</Optimization>
     47      <MinimalRebuild>true</MinimalRebuild>
     48      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
     49      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
     50      <WarningLevel>Level4</WarningLevel>
     51      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
     52      <DisableLanguageExtensions>false</DisableLanguageExtensions>
     53      <DisableSpecificWarnings>4003;4512;4127</DisableSpecificWarnings>
     54    </ClCompile>
     55    <Link>
     56      <AdditionalDependencies>Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
     57      <GenerateDebugInformation>true</GenerateDebugInformation>
     58      <TargetMachine>MachineX86</TargetMachine>
     59    </Link>
     60    <PostBuildEvent>
     61      <Command>xcopy /Y $(TargetPath) $(SolutionDir)\..\..\..\dists\msvc10\
     62xcopy /Y $(TargetPath) $(SolutionDir)\..\..\..\dists\msvc9\
     63xcopy /Y $(TargetPath) $(SolutionDir)\..\..\..\dists\msvc8\
     64xcopy /Y $(TargetPath) $(SolutionDir)\..\..\..\dists\codeblocks\</Command>
     65    </PostBuildEvent>
     66  </ItemDefinitionGroup>
     67  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     68    <ClCompile>
     69      <Optimization>MaxSpeed</Optimization>
     70      <IntrinsicFunctions>true</IntrinsicFunctions>
     71      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
     72      <FunctionLevelLinking>true</FunctionLevelLinking>
     73      <WarningLevel>Level3</WarningLevel>
     74      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
     75      <DisableSpecificWarnings>4003;4512;4127</DisableSpecificWarnings>
     76    </ClCompile>
     77    <Link>
     78      <AdditionalDependencies>Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
     79      <GenerateDebugInformation>true</GenerateDebugInformation>
     80      <OptimizeReferences>true</OptimizeReferences>
     81      <EnableCOMDATFolding>true</EnableCOMDATFolding>
     82      <TargetMachine>MachineX86</TargetMachine>
     83    </Link>
     84    <PostBuildEvent>
     85      <Command>xcopy /Y $(TargetPath) $(SolutionDir)\..\..\..\dists\msvc10\
     86xcopy /Y $(TargetPath) $(SolutionDir)\..\..\..\dists\msvc9\
     87xcopy /Y $(TargetPath) $(SolutionDir)\..\..\..\dists\msvc8\
     88xcopy /Y $(TargetPath) $(SolutionDir)\..\..\..\dists\codeblocks\</Command>
     89    </PostBuildEvent>
     90  </ItemDefinitionGroup>
     91  <ItemGroup>
     92    <ClCompile Include="..\codeblocks.cpp" />
     93    <ClCompile Include="..\create_project.cpp" />
     94    <ClCompile Include="..\msvc.cpp" />
     95  </ItemGroup>
     96  <ItemGroup>
     97    <ClInclude Include="..\codeblocks.h" />
     98    <ClInclude Include="..\create_project.h" />
     99    <ClInclude Include="..\msvc.h" />
     100  </ItemGroup>
     101  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
     102  <ImportGroup Label="ExtensionTargets">
     103  </ImportGroup>
     104</Project>
     105 No newline at end of file
  • new file tools/create_project/msvc10/create_project.vcxproj.filters

    diff -r e24b1c8ca942 tools/create_project/msvc10/create_project.vcxproj.filters
    - +  
     1<?xml version="1.0" encoding="utf-8"?>
     2<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
     3  <ItemGroup>
     4    <Filter Include="Header Files">
     5      <UniqueIdentifier>{2e3580c8-ec3a-4c81-8351-b668c668db2a}</UniqueIdentifier>
     6    </Filter>
     7    <Filter Include="Source Files">
     8      <UniqueIdentifier>{31aaf58c-d3cb-4ed6-8eca-163b4a9b31a6}</UniqueIdentifier>
     9    </Filter>
     10  </ItemGroup>
     11  <ItemGroup>
     12    <ClInclude Include="..\codeblocks.h">
     13      <Filter>Header Files</Filter>
     14    </ClInclude>
     15    <ClInclude Include="..\create_project.h">
     16      <Filter>Header Files</Filter>
     17    </ClInclude>
     18    <ClInclude Include="..\msvc.h">
     19      <Filter>Header Files</Filter>
     20    </ClInclude>
     21  </ItemGroup>
     22  <ItemGroup>
     23    <ClCompile Include="..\codeblocks.cpp">
     24      <Filter>Source Files</Filter>
     25    </ClCompile>
     26    <ClCompile Include="..\create_project.cpp">
     27      <Filter>Source Files</Filter>
     28    </ClCompile>
     29    <ClCompile Include="..\msvc.cpp">
     30      <Filter>Source Files</Filter>
     31    </ClCompile>
     32  </ItemGroup>
     33</Project>
     34 No newline at end of file
  • new file tools/create_project/msvc8/create_project.sln

    diff -r e24b1c8ca942 tools/create_project/msvc8/create_project.sln
    - +  
     1
     2Microsoft Visual Studio Solution File, Format Version 9.00
     3# Visual Studio 2005
     4Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "create_project", "create_project.vcproj", "{CF177559-077D-4A08-AABE-BE0FD35F6C63}"
     5EndProject
     6Global
     7        GlobalSection(SolutionConfigurationPlatforms) = preSolution
     8                Debug|Win32 = Debug|Win32
     9                Release|Win32 = Release|Win32
     10        EndGlobalSection
     11        GlobalSection(ProjectConfigurationPlatforms) = postSolution
     12                {CF177559-077D-4A08-AABE-BE0FD35F6C63}.Debug|Win32.ActiveCfg = Debug|Win32
     13                {CF177559-077D-4A08-AABE-BE0FD35F6C63}.Debug|Win32.Build.0 = Debug|Win32
     14                {CF177559-077D-4A08-AABE-BE0FD35F6C63}.Release|Win32.ActiveCfg = Release|Win32
     15                {CF177559-077D-4A08-AABE-BE0FD35F6C63}.Release|Win32.Build.0 = Release|Win32
     16        EndGlobalSection
     17        GlobalSection(SolutionProperties) = preSolution
     18                HideSolutionNode = FALSE
     19        EndGlobalSection
     20EndGlobal
  • new file tools/create_project/msvc8/create_project.vcproj

    diff -r e24b1c8ca942 tools/create_project/msvc8/create_project.vcproj
    - +  
     1<?xml version="1.0" encoding="Windows-1252"?>
     2<VisualStudioProject
     3        ProjectType="Visual C++"
     4        Version="8.00"
     5        Name="create_project"
     6        ProjectGUID="{CF177559-077D-4A08-AABE-BE0FD35F6C63}"
     7        RootNamespace="create_project"
     8        >
     9        <Platforms>
     10                <Platform
     11                        Name="Win32"
     12                />
     13        </Platforms>
     14        <ToolFiles>
     15        </ToolFiles>
     16        <Configurations>
     17                <Configuration
     18                        Name="Debug|Win32"
     19                        OutputDirectory="$(SolutionDir)$(ConfigurationName)"
     20                        IntermediateDirectory="$(ConfigurationName)"
     21                        ConfigurationType="1"
     22                        CharacterSet="2"
     23                        >
     24                        <Tool
     25                                Name="VCPreBuildEventTool"
     26                        />
     27                        <Tool
     28                                Name="VCCustomBuildTool"
     29                        />
     30                        <Tool
     31                                Name="VCXMLDataGeneratorTool"
     32                        />
     33                        <Tool
     34                                Name="VCWebServiceProxyGeneratorTool"
     35                        />
     36                        <Tool
     37                                Name="VCMIDLTool"
     38                        />
     39                        <Tool
     40                                Name="VCCLCompilerTool"
     41                                Optimization="0"
     42                                MinimalRebuild="true"
     43                                BasicRuntimeChecks="3"
     44                                RuntimeLibrary="3"
     45                                WarningLevel="4"
     46                                DebugInformationFormat="4"
     47                                DisableSpecificWarnings="4003;4512;4127"
     48                        />
     49                        <Tool
     50                                Name="VCManagedResourceCompilerTool"
     51                        />
     52                        <Tool
     53                                Name="VCResourceCompilerTool"
     54                        />
     55                        <Tool
     56                                Name="VCPreLinkEventTool"
     57                        />
     58                        <Tool
     59                                Name="VCLinkerTool"
     60                                AdditionalDependencies="Rpcrt4.lib"
     61                                GenerateDebugInformation="true"
     62                                TargetMachine="1"
     63                        />
     64                        <Tool
     65                                Name="VCALinkTool"
     66                        />
     67                        <Tool
     68                                Name="VCManifestTool"
     69                        />
     70                        <Tool
     71                                Name="VCXDCMakeTool"
     72                        />
     73                        <Tool
     74                                Name="VCBscMakeTool"
     75                        />
     76                        <Tool
     77                                Name="VCFxCopTool"
     78                        />
     79                        <Tool
     80                                Name="VCAppVerifierTool"
     81                        />
     82                        <Tool
     83                                Name="VCPostBuildEventTool"
     84                        />
     85                </Configuration>
     86                <Configuration
     87                        Name="Release|Win32"
     88                        OutputDirectory="$(SolutionDir)$(ConfigurationName)"
     89                        IntermediateDirectory="$(ConfigurationName)"
     90                        ConfigurationType="1"
     91                        CharacterSet="2"
     92                        WholeProgramOptimization="1"
     93                        >
     94                        <Tool
     95                                Name="VCPreBuildEventTool"
     96                        />
     97                        <Tool
     98                                Name="VCCustomBuildTool"
     99                        />
     100                        <Tool
     101                                Name="VCXMLDataGeneratorTool"
     102                        />
     103                        <Tool
     104                                Name="VCWebServiceProxyGeneratorTool"
     105                        />
     106                        <Tool
     107                                Name="VCMIDLTool"
     108                        />
     109                        <Tool
     110                                Name="VCCLCompilerTool"
     111                                Optimization="2"
     112                                EnableIntrinsicFunctions="true"
     113                                RuntimeLibrary="2"
     114                                EnableFunctionLevelLinking="true"
     115                                WarningLevel="3"
     116                                DebugInformationFormat="3"
     117                                DisableSpecificWarnings="4003;4512;4127"
     118                        />
     119                        <Tool
     120                                Name="VCManagedResourceCompilerTool"
     121                        />
     122                        <Tool
     123                                Name="VCResourceCompilerTool"
     124                        />
     125                        <Tool
     126                                Name="VCPreLinkEventTool"
     127                        />
     128                        <Tool
     129                                Name="VCLinkerTool"
     130                                AdditionalDependencies="Rpcrt4.lib"
     131                                GenerateDebugInformation="true"
     132                                OptimizeReferences="2"
     133                                EnableCOMDATFolding="2"
     134                                TargetMachine="1"
     135                        />
     136                        <Tool
     137                                Name="VCALinkTool"
     138                        />
     139                        <Tool
     140                                Name="VCManifestTool"
     141                        />
     142                        <Tool
     143                                Name="VCXDCMakeTool"
     144                        />
     145                        <Tool
     146                                Name="VCBscMakeTool"
     147                        />
     148                        <Tool
     149                                Name="VCFxCopTool"
     150                        />
     151                        <Tool
     152                                Name="VCAppVerifierTool"
     153                        />
     154                        <Tool
     155                                Name="VCPostBuildEventTool"
     156                        />
     157                </Configuration>
     158        </Configurations>
     159        <References>
     160        </References>
     161        <Files>
     162                <Filter
     163                        Name="Source Files"
     164                        Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
     165                        UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
     166                        >
     167                        <File
     168                                RelativePath="..\create_project.cpp"
     169                                >
     170                        </File>
     171                        <File
     172                                RelativePath="..\codeblocks.cpp"
     173                                >
     174                        </File>
     175                        <File
     176                                RelativePath="..\msvc.cpp"
     177                                >
     178                        </File>
     179                </Filter>
     180                <Filter
     181                        Name="Header Files"
     182                        Filter="h;hpp;hxx;hm;inl;inc;xsd"
     183                        UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
     184                        >
     185                        <File
     186                                RelativePath="..\create_project.h"
     187                                >
     188                        </File>
     189                        <File
     190                                RelativePath="..\codeblocks.h"
     191                                >
     192                        </File>
     193                        <File
     194                                RelativePath="..\msvc.h"
     195                                >
     196                        </File>
     197                </Filter>
     198        </Files>
     199        <Globals>
     200        </Globals>
     201</VisualStudioProject>
  • new file tools/create_project/msvc9/create_project.sln

    diff -r e24b1c8ca942 tools/create_project/msvc9/create_project.sln
    - +  
     1
     2Microsoft Visual Studio Solution File, Format Version 10.00
     3# Visual Studio 2008
     4Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "create_project", "create_project.vcproj", "{CF177559-077D-4A08-AABE-BE0FD35F6C63}"
     5EndProject
     6Global
     7        GlobalSection(SolutionConfigurationPlatforms) = preSolution
     8                Debug|Win32 = Debug|Win32
     9                Release|Win32 = Release|Win32
     10        EndGlobalSection
     11        GlobalSection(ProjectConfigurationPlatforms) = postSolution
     12                {CF177559-077D-4A08-AABE-BE0FD35F6C63}.Debug|Win32.ActiveCfg = Debug|Win32
     13                {CF177559-077D-4A08-AABE-BE0FD35F6C63}.Debug|Win32.Build.0 = Debug|Win32
     14                {CF177559-077D-4A08-AABE-BE0FD35F6C63}.Release|Win32.ActiveCfg = Release|Win32
     15                {CF177559-077D-4A08-AABE-BE0FD35F6C63}.Release|Win32.Build.0 = Release|Win32
     16        EndGlobalSection
     17        GlobalSection(SolutionProperties) = preSolution
     18                HideSolutionNode = FALSE
     19        EndGlobalSection
     20EndGlobal
  • new file tools/create_project/msvc9/create_project.vcproj

    diff -r e24b1c8ca942 tools/create_project/msvc9/create_project.vcproj
    - +  
     1<?xml version="1.0" encoding="Windows-1252"?>
     2<VisualStudioProject
     3        ProjectType="Visual C++"
     4        Version="9.00"
     5        Name="create_project"
     6        ProjectGUID="{CF177559-077D-4A08-AABE-BE0FD35F6C63}"
     7        RootNamespace="create_project"
     8        TargetFrameworkVersion="196613"
     9        >
     10        <Platforms>
     11                <Platform
     12                        Name="Win32"
     13                />
     14        </Platforms>
     15        <ToolFiles>
     16        </ToolFiles>
     17        <Configurations>
     18                <Configuration7
     19                        Name="Debug|Win32"
     20                        OutputDirectory="$(SolutionDir)$(ConfigurationName)"
     21                        IntermediateDirectory="$(ConfigurationName)"
     22                        ConfigurationType="1"
     23                        CharacterSet="2"
     24                        >
     25                        <Tool
     26                                Name="VCPreBuildEventTool"
     27                        />
     28                        <Tool
     29                                Name="VCCustomBuildTool"
     30                        />
     31                        <Tool
     32                                Name="VCXMLDataGeneratorTool"
     33                        />
     34                        <Tool
     35                                Name="VCWebServiceProxyGeneratorTool"
     36                        />
     37                        <Tool
     38                                Name="VCMIDLTool"
     39                        />
     40                        <Tool
     41                                Name="VCCLCompilerTool"
     42                                Optimization="0"
     43                                MinimalRebuild="true"
     44                                BasicRuntimeChecks="3"
     45                                RuntimeLibrary="3"
     46                                WarningLevel="4"
     47                                DebugInformationFormat="4"
     48                                DisableSpecificWarnings="4003;4512;4127"
     49                        />
     50                        <Tool
     51                                Name="VCManagedResourceCompilerTool"
     52                        />
     53                        <Tool
     54                                Name="VCResourceCompilerTool"
     55                        />
     56                        <Tool
     57                                Name="VCPreLinkEventTool"
     58                        />
     59                        <Tool
     60                                Name="VCLinkerTool"
     61                                AdditionalDependencies="Rpcrt4.lib"
     62                                GenerateDebugInformation="true"
     63                                TargetMachine="1"
     64                        />
     65                        <Tool
     66                                Name="VCALinkTool"
     67                        />
     68                        <Tool
     69                                Name="VCManifestTool"
     70                        />
     71                        <Tool
     72                                Name="VCXDCMakeTool"
     73                        />
     74                        <Tool
     75                                Name="VCBscMakeTool"
     76                        />
     77                        <Tool
     78                                Name="VCFxCopTool"
     79                        />
     80                        <Tool
     81                                Name="VCAppVerifierTool"
     82                        />
     83                        <Tool
     84                                Name="VCPostBuildEventTool"
     85                        />
     86                </Configuration>
     87                <Configuration
     88                        Name="Release|Win32"
     89                        OutputDirectory="$(SolutionDir)$(ConfigurationName)"
     90                        IntermediateDirectory="$(ConfigurationName)"
     91                        ConfigurationType="1"
     92                        CharacterSet="2"
     93                        WholeProgramOptimization="1"
     94                        >
     95                        <Tool
     96                                Name="VCPreBuildEventTool"
     97                        />
     98                        <Tool
     99                                Name="VCCustomBuildTool"
     100                        />
     101                        <Tool
     102                                Name="VCXMLDataGeneratorTool"
     103                        />
     104                        <Tool
     105                                Name="VCWebServiceProxyGeneratorTool"
     106                        />
     107                        <Tool
     108                                Name="VCMIDLTool"
     109                        />
     110                        <Tool
     111                                Name="VCCLCompilerTool"
     112                                Optimization="2"
     113                                EnableIntrinsicFunctions="true"
     114                                RuntimeLibrary="2"
     115                                EnableFunctionLevelLinking="true"
     116                                WarningLevel="3"
     117                                DebugInformationFormat="3"
     118                                DisableSpecificWarnings="4003;4512;4127"
     119                        />
     120                        <Tool
     121                                Name="VCManagedResourceCompilerTool"
     122                        />
     123                        <Tool
     124                                Name="VCResourceCompilerTool"
     125                        />
     126                        <Tool
     127                                Name="VCPreLinkEventTool"
     128                        />
     129                        <Tool
     130                                Name="VCLinkerTool"
     131                                AdditionalDependencies="Rpcrt4.lib"
     132                                GenerateDebugInformation="true"
     133                                OptimizeReferences="2"
     134                                EnableCOMDATFolding="2"
     135                                TargetMachine="1"
     136                        />
     137                        <Tool
     138                                Name="VCALinkTool"
     139                        />
     140                        <Tool
     141                                Name="VCManifestTool"
     142                        />
     143                        <Tool
     144                                Name="VCXDCMakeTool"
     145                        />
     146                        <Tool
     147                                Name="VCBscMakeTool"
     148                        />
     149                        <Tool
     150                                Name="VCFxCopTool"
     151                        />
     152                        <Tool
     153                                Name="VCAppVerifierTool"
     154                        />
     155                        <Tool
     156                                Name="VCPostBuildEventTool"
     157                        />
     158                </Configuration>
     159        </Configurations>
     160        <References>
     161        </References>
     162        <Files>
     163                <Filter
     164                        Name="Source Files"
     165                        Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
     166                        UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
     167                        >
     168                        <File
     169                                RelativePath="..\create_project.cpp"
     170                                >
     171                        </File>
     172                        <File
     173                                RelativePath="..\codeblocks.cpp"
     174                                >
     175                        </File>
     176                        <File
     177                                RelativePath="..\msvc.cpp"
     178                                >
     179                        </File>
     180                </Filter>
     181                <Filter
     182                        Name="Header Files"
     183                        Filter="h;hpp;hxx;hm;inl;inc;xsd"
     184                        UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
     185                        >
     186                        <File
     187                                RelativePath="..\create_project.h"
     188                                >
     189                        </File>
     190                        <File
     191                                RelativePath="..\codeblocks.h"
     192                                >
     193                        </File>
     194                        <File
     195                                RelativePath="..\msvc.h"
     196                                >
     197                        </File>
     198                </Filter>
     199        </Files>
     200        <Globals>
     201        </Globals>
     202</VisualStudioProject>