scummvm/devtools/create_project/xcode.h
Julien 9854f1b486 CREATE_PROJECT: Implement basic XCode provider
This only outputs a skeleton project with no files and targets yet
2011-06-02 17:29:36 -04:00

308 lines
9.4 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef TOOLS_CREATE_PROJECT_XCODE_H
#define TOOLS_CREATE_PROJECT_XCODE_H
#include "create_project.h"
#include <algorithm>
#include <vector>
namespace CreateProjectTool {
class XCodeProvider : public ProjectProvider {
public:
XCodeProvider(StringList &global_warnings, std::map<std::string, StringList> &project_warnings, const int version = 0);
protected:
void createWorkspace(const BuildSetup &setup);
void createOtherBuildFiles(const BuildSetup &setup);
void createProjectFile(const std::string &name, const std::string &uuid, const BuildSetup &setup, const std::string &moduleDir,
const StringList &includeList, const StringList &excludeList);
void writeFileListToProject(const FileNode &dir, std::ofstream &projectFile, const int indentation,
const StringList &duplicate, const std::string &objPrefix, const std::string &filePrefix);
private:
enum {
SettingsAsList = 0x01,
SettingsSingleItem = 0x02,
SettingsNoQuote = 0x04,
SettingsQuoteVariable = 0x08,
SettingsNoValue = 0x10
};
// File properties
struct FileProperty {
std::string fileEncoding;
std::string lastKnownFileType;
std::string fileName;
std::string filePath;
std::string sourceTree;
FileProperty(std::string fileType = "", std::string name = "", std::string path = "", std::string source = "") :
fileEncoding(""), lastKnownFileType(fileType), fileName(name), filePath(path), sourceTree(source)
{
}
};
//////////////////////////////////////////////////////////////////////////
// XCObject and children
typedef std::vector<std::string> ValueList;
struct Entry {
std::string value;
std::string comment;
Entry(std::string val, std::string cmt) : value(val), comment(cmt) {}
};
typedef std::vector<Entry> EntryList;
struct Setting {
EntryList entries;
int flags;
int indent;
int order;
explicit Setting(std::string value = "", std::string comment = "", int flgs = 0, int idt = 0, int ord = -1) : flags(flgs), indent(idt), order(ord) {
entries.push_back(Entry(value, comment));
}
explicit Setting(ValueList values, int flgs = 0, int idt = 0, int ord = -1) : flags(flgs), indent(idt), order(ord) {
for (unsigned int i = 0; i < values.size(); i++)
entries.push_back(Entry(values[i], ""));
}
explicit Setting(EntryList ents, int flgs = 0, int idt = 0, int ord = -1) : entries(ents), flags(flgs), indent(idt), order(ord) {}
void addEntry(std::string value, std::string comment = "") {
entries.push_back(Entry(value, comment));
}
};
typedef std::map<std::string, Setting> SettingList;
typedef std::pair<std::string, Setting> SettingPair;
typedef std::vector<SettingPair> OrderedSettingList;
static bool OrderSortPredicate(const SettingPair& s1, const SettingPair& s2) {
return s1.second.order < s2.second.order;
}
struct Property {
public:
SettingList settings;
int flags;
bool hasOrder;
Property() : flags(0), hasOrder(false) {}
// Constructs a simple Property
explicit Property(std::string name, std::string value = "", std::string comment = "", int flgs = 0, int indent = 0, bool order = false) : flags(flgs), hasOrder(order) {
Setting setting(value, comment, flags, indent);
settings[name] = setting;
}
Property(std::string name, ValueList values, int flgs = 0, int indent = 0, bool order = false) : flags(flgs), hasOrder(order) {
Setting setting(values, flags, indent);
settings[name] = setting;
}
// Copy constructor
Property(const Property &rhs) {
settings = rhs.settings;
flags = rhs.flags;
}
OrderedSettingList getOrderedSettingList() {
OrderedSettingList list;
// Prepare vector to sort
for (SettingList::const_iterator setting = settings.begin(); setting != settings.end(); ++setting)
list.push_back(SettingPair(setting->first, setting->second));
// Sort vector using setting order
if (hasOrder)
std::sort(list.begin(), list.end(), OrderSortPredicate);
return list;
}
};
typedef std::map<std::string, Property> PropertyList;
// Main object struct
// This is all a big hack unfortunately, but making everything all properly abstracted would
// be overkill since we only have to generate a single project
struct Object {
public:
std::string id; // Unique identifier for this object
std::string name; // Name (may not be unique - for ex. configuration entries)
std::string refType; // Type of object this references (if any)
std::string comment; // Main comment (empty for no comment)
PropertyList properties; // List of object properties, including output configuration
// Constructs an object and add a default type property
Object(XCodeProvider *objectParent, std::string objectId, std::string objectName, std::string objectType, std::string objectRefType = "", std::string objectComment = "")
: id(objectId), name(objectName), refType(objectRefType), comment(objectComment), parent(objectParent) {
assert(objectParent);
assert(!objectId.empty());
assert(!objectName.empty());
assert(!objectType.empty());
addProperty("isa", objectType, "", SettingsNoQuote|SettingsNoValue);
}
// Add a simple Property with just a name and a value
void addProperty(std::string propName, std::string propValue, std::string propComment = "", int propFlags = 0, int propIndent = 0) {
properties[propName] = Property(propValue, "", propComment, propFlags, propIndent);
}
std::string toString(int flags = 0) {
std::string output;
output = "\t\t" + parent->getHash(id) + (comment.empty() ? "" : " /* " + comment + " */") + " = {";
if (flags & SettingsAsList)
output += "\n";
// Special case: always output the isa property first
output += parent->writeProperty("isa", properties["isa"], flags);
// Write each property
for (PropertyList::iterator property = properties.begin(); property != properties.end(); ++property) {
if ((*property).first == "isa")
continue;
output += parent->writeProperty((*property).first, (*property).second, flags);
}
if (flags & SettingsAsList)
output += "\t\t";
output += "};\n";
return output;
}
private:
XCodeProvider *parent;
// Returns the type property (should always be the first in the properties map)
std::string getType() {
assert(!properties.empty());
assert(!properties["isa"].settings.empty());
SettingList::iterator it = properties["isa"].settings.begin();
return (*it).first;
}
};
struct ObjectList {
private:
std::map<std::string, bool> objectMap;
public:
std::vector<Object *> objects;
std::string comment;
int flags;
void add(Object *obj) {
std::map<std::string, bool>::iterator it = objectMap.find(obj->id);
if (it != objectMap.end() && it->second == true)
return;
objects.push_back(obj);
objectMap[obj->id] = true;
}
std::string toString() {
std::string output;
if (!comment.empty())
output = "\n/* Begin " + comment + " section */\n";
for (std::vector<Object *>::iterator object = objects.begin(); object != objects.end(); ++object)
output += (*object)->toString(flags);
if (!comment.empty())
output += "/* End " + comment + " section */\n";
return output;
}
};
// All objects
std::map<std::string, std::string> _hashDictionnary;
ValueList _defines;
// Targets
ValueList _targets;
// Lists of objects
ObjectList _buildFile;
ObjectList _copyFilesBuildPhase;
ObjectList _fileReference;
ObjectList _frameworksBuildPhase;
ObjectList _groups;
ObjectList _nativeTarget;
ObjectList _project;
ObjectList _resourcesBuildPhase;
ObjectList _sourcesBuildPhase;
ObjectList _buildConfiguration;
ObjectList _configurationList;
void ouputMainProjectFile(const BuildSetup &setup);
// Setup objects
void setupCopyFilesBuildPhase();
void setupFrameworksBuildPhase();
void setupNativeTarget();
void setupProject();
void setupResourcesBuildPhase();
void setupSourcesBuildPhase();
void setupBuildConfiguration();
// Misc
void setupDefines(const BuildSetup &setup); // Setup the list of defines to be used on build configurations
// Hash generation
std::string getHash(std::string key);
std::string newHash() const;
// Output
std::string writeProperty(const std::string &variable, Property &property, int flags = 0) const;
std::string writeSetting(const std::string &variable, std::string name, std::string comment = "", int flags = 0, int indent = 0) const;
std::string writeSetting(const std::string &variable, const Setting &setting) const;
};
} // End of CreateProjectTool namespace
#endif // TOOLS_CREATE_PROJECT_XCODE_H