Files
MINGW-packages/mingw-w64-qbs-git/0002-WIP-Xcode-generator.1.4.patch
2015-04-29 01:13:39 +01:00

6368 lines
238 KiB
Diff

From 6545923f08c0afa38fbf6fc95960d4b106941021 Mon Sep 17 00:00:00 2001
From: Jake Petroules <jake.petroules@petroules.com>
Date: Wed, 18 Feb 2015 09:05:29 -0800
Subject: [PATCH 02/10] WIP: Xcode generator.
Task-number: QBS-32
Change-Id: I5ce5cc3148aa801d75a1f64b778fe7334de43af9
---
src/lib/corelib/corelib.qbs | 62 ++
src/lib/corelib/generators/generators.pri | 2 +
.../generators/xcode/opensteppropertylist.cpp | 257 ++++++++
.../generators/xcode/opensteppropertylist.h | 76 +++
src/lib/corelib/generators/xcode/pbx.h | 57 ++
src/lib/corelib/generators/xcode/pbxbuildfile.cpp | 134 +++++
src/lib/corelib/generators/xcode/pbxbuildfile.h | 74 +++
src/lib/corelib/generators/xcode/pbxbuildphase.cpp | 94 +++
src/lib/corelib/generators/xcode/pbxbuildphase.h | 65 +++
src/lib/corelib/generators/xcode/pbxcontainer.cpp | 60 ++
src/lib/corelib/generators/xcode/pbxcontainer.h | 59 ++
.../generators/xcode/pbxcontaineritemproxy.cpp | 113 ++++
.../generators/xcode/pbxcontaineritemproxy.h | 65 +++
src/lib/corelib/generators/xcode/pbxfileencoding.h | 57 ++
.../corelib/generators/xcode/pbxfilereference.cpp | 66 +++
.../corelib/generators/xcode/pbxfilereference.h | 52 ++
src/lib/corelib/generators/xcode/pbxfiletype.cpp | 51 ++
src/lib/corelib/generators/xcode/pbxfiletype.h | 47 ++
.../generators/xcode/pbxframeworksbuildphase.cpp | 27 +
.../generators/xcode/pbxframeworksbuildphase.h | 50 ++
src/lib/corelib/generators/xcode/pbxgroup.cpp | 119 ++++
src/lib/corelib/generators/xcode/pbxgroup.h | 71 +++
.../corelib/generators/xcode/pbxlegacytarget.cpp | 111 ++++
src/lib/corelib/generators/xcode/pbxlegacytarget.h | 65 +++
.../corelib/generators/xcode/pbxnativetarget.cpp | 68 +++
src/lib/corelib/generators/xcode/pbxnativetarget.h | 53 ++
src/lib/corelib/generators/xcode/pbxobject.cpp | 96 +++
src/lib/corelib/generators/xcode/pbxobject.h | 124 ++++
.../corelib/generators/xcode/pbxproducttype.cpp | 75 +++
src/lib/corelib/generators/xcode/pbxproducttype.h | 53 ++
src/lib/corelib/generators/xcode/pbxproject.cpp | 333 +++++++++++
src/lib/corelib/generators/xcode/pbxproject.h | 114 ++++
src/lib/corelib/generators/xcode/pbxreference.cpp | 127 ++++
src/lib/corelib/generators/xcode/pbxreference.h | 72 +++
.../generators/xcode/pbxsourcesbuildphase.cpp | 57 ++
.../generators/xcode/pbxsourcesbuildphase.h | 53 ++
src/lib/corelib/generators/xcode/pbxsourcetree.cpp | 50 ++
src/lib/corelib/generators/xcode/pbxsourcetree.h | 52 ++
src/lib/corelib/generators/xcode/pbxtarget.cpp | 192 ++++++
src/lib/corelib/generators/xcode/pbxtarget.h | 100 ++++
.../generators/xcode/pbxtargetdependency.cpp | 99 ++++
.../corelib/generators/xcode/pbxtargetdependency.h | 65 +++
.../generators/xcode/xcbuildconfiguration.cpp | 92 +++
.../generators/xcode/xcbuildconfiguration.h | 69 +++
.../generators/xcode/xcconfigurationlist.cpp | 147 +++++
.../corelib/generators/xcode/xcconfigurationlist.h | 67 +++
src/lib/corelib/generators/xcode/xcode.pri | 59 ++
.../generators/xcode/xcodebuildsettingmapping.cpp | 366 ++++++++++++
.../generators/xcode/xcodebuildsettingmapping.h | 96 +++
.../corelib/generators/xcode/xcodegenerator.cpp | 643 +++++++++++++++++++++
src/lib/corelib/generators/xcode/xcodegenerator.h | 81 +++
.../generators/xcode/xcodenativegenerator.cpp | 58 ++
.../generators/xcode/xcodenativegenerator.h | 52 ++
.../generators/xcode/xcodesimplegenerator.cpp | 58 ++
.../generators/xcode/xcodesimplegenerator.h | 52 ++
src/lib/corelib/generators/xcode/xcscheme.cpp | 179 ++++++
src/lib/corelib/generators/xcode/xcscheme.h | 69 +++
src/lib/corelib/generators/xcode/xcsettings.cpp | 95 +++
src/lib/corelib/generators/xcode/xcsettings.h | 54 ++
src/lib/corelib/tools/projectgeneratormanager.cpp | 5 +
60 files changed, 5859 insertions(+)
create mode 100644 src/lib/corelib/generators/xcode/opensteppropertylist.cpp
create mode 100644 src/lib/corelib/generators/xcode/opensteppropertylist.h
create mode 100644 src/lib/corelib/generators/xcode/pbx.h
create mode 100644 src/lib/corelib/generators/xcode/pbxbuildfile.cpp
create mode 100644 src/lib/corelib/generators/xcode/pbxbuildfile.h
create mode 100644 src/lib/corelib/generators/xcode/pbxbuildphase.cpp
create mode 100644 src/lib/corelib/generators/xcode/pbxbuildphase.h
create mode 100644 src/lib/corelib/generators/xcode/pbxcontainer.cpp
create mode 100644 src/lib/corelib/generators/xcode/pbxcontainer.h
create mode 100644 src/lib/corelib/generators/xcode/pbxcontaineritemproxy.cpp
create mode 100644 src/lib/corelib/generators/xcode/pbxcontaineritemproxy.h
create mode 100644 src/lib/corelib/generators/xcode/pbxfileencoding.h
create mode 100644 src/lib/corelib/generators/xcode/pbxfilereference.cpp
create mode 100644 src/lib/corelib/generators/xcode/pbxfilereference.h
create mode 100644 src/lib/corelib/generators/xcode/pbxfiletype.cpp
create mode 100644 src/lib/corelib/generators/xcode/pbxfiletype.h
create mode 100644 src/lib/corelib/generators/xcode/pbxframeworksbuildphase.cpp
create mode 100644 src/lib/corelib/generators/xcode/pbxframeworksbuildphase.h
create mode 100644 src/lib/corelib/generators/xcode/pbxgroup.cpp
create mode 100644 src/lib/corelib/generators/xcode/pbxgroup.h
create mode 100644 src/lib/corelib/generators/xcode/pbxlegacytarget.cpp
create mode 100644 src/lib/corelib/generators/xcode/pbxlegacytarget.h
create mode 100644 src/lib/corelib/generators/xcode/pbxnativetarget.cpp
create mode 100644 src/lib/corelib/generators/xcode/pbxnativetarget.h
create mode 100644 src/lib/corelib/generators/xcode/pbxobject.cpp
create mode 100644 src/lib/corelib/generators/xcode/pbxobject.h
create mode 100644 src/lib/corelib/generators/xcode/pbxproducttype.cpp
create mode 100644 src/lib/corelib/generators/xcode/pbxproducttype.h
create mode 100644 src/lib/corelib/generators/xcode/pbxproject.cpp
create mode 100644 src/lib/corelib/generators/xcode/pbxproject.h
create mode 100644 src/lib/corelib/generators/xcode/pbxreference.cpp
create mode 100644 src/lib/corelib/generators/xcode/pbxreference.h
create mode 100644 src/lib/corelib/generators/xcode/pbxsourcesbuildphase.cpp
create mode 100644 src/lib/corelib/generators/xcode/pbxsourcesbuildphase.h
create mode 100644 src/lib/corelib/generators/xcode/pbxsourcetree.cpp
create mode 100644 src/lib/corelib/generators/xcode/pbxsourcetree.h
create mode 100644 src/lib/corelib/generators/xcode/pbxtarget.cpp
create mode 100644 src/lib/corelib/generators/xcode/pbxtarget.h
create mode 100644 src/lib/corelib/generators/xcode/pbxtargetdependency.cpp
create mode 100644 src/lib/corelib/generators/xcode/pbxtargetdependency.h
create mode 100644 src/lib/corelib/generators/xcode/xcbuildconfiguration.cpp
create mode 100644 src/lib/corelib/generators/xcode/xcbuildconfiguration.h
create mode 100644 src/lib/corelib/generators/xcode/xcconfigurationlist.cpp
create mode 100644 src/lib/corelib/generators/xcode/xcconfigurationlist.h
create mode 100644 src/lib/corelib/generators/xcode/xcode.pri
create mode 100644 src/lib/corelib/generators/xcode/xcodebuildsettingmapping.cpp
create mode 100644 src/lib/corelib/generators/xcode/xcodebuildsettingmapping.h
create mode 100644 src/lib/corelib/generators/xcode/xcodegenerator.cpp
create mode 100644 src/lib/corelib/generators/xcode/xcodegenerator.h
create mode 100644 src/lib/corelib/generators/xcode/xcodenativegenerator.cpp
create mode 100644 src/lib/corelib/generators/xcode/xcodenativegenerator.h
create mode 100644 src/lib/corelib/generators/xcode/xcodesimplegenerator.cpp
create mode 100644 src/lib/corelib/generators/xcode/xcodesimplegenerator.h
create mode 100644 src/lib/corelib/generators/xcode/xcscheme.cpp
create mode 100644 src/lib/corelib/generators/xcode/xcscheme.h
create mode 100644 src/lib/corelib/generators/xcode/xcsettings.cpp
create mode 100644 src/lib/corelib/generators/xcode/xcsettings.h
diff --git a/src/lib/corelib/corelib.qbs b/src/lib/corelib/corelib.qbs
index a5fb92a..e6cd421 100644
--- a/src/lib/corelib/corelib.qbs
+++ b/src/lib/corelib/corelib.qbs
@@ -156,6 +156,68 @@ QbsLibrary {
files: "buildgraph/forward_decls.h"
}
Group {
+ name: "Xcode generator"
+ prefix: "generators/xcode/"
+ files: [
+ "opensteppropertylist.cpp",
+ "opensteppropertylist.h",
+ "pbx.h",
+ "pbxbuildfile.cpp",
+ "pbxbuildfile.h",
+ "pbxbuildphase.cpp",
+ "pbxbuildphase.h",
+ "pbxcontainer.cpp",
+ "pbxcontainer.h",
+ "pbxcontaineritemproxy.cpp",
+ "pbxcontaineritemproxy.h",
+ "pbxfileencoding.h",
+ "pbxfilereference.cpp",
+ "pbxfilereference.h",
+ "pbxfiletype.cpp",
+ "pbxfiletype.h",
+ "pbxframeworksbuildphase.cpp",
+ "pbxframeworksbuildphase.h",
+ "pbxgroup.cpp",
+ "pbxgroup.h",
+ "pbxlegacytarget.cpp",
+ "pbxlegacytarget.h",
+ "pbxnativetarget.cpp",
+ "pbxnativetarget.h",
+ "pbxobject.cpp",
+ "pbxobject.h",
+ "pbxproducttype.cpp",
+ "pbxproducttype.h",
+ "pbxproject.cpp",
+ "pbxproject.h",
+ "pbxreference.cpp",
+ "pbxreference.h",
+ "pbxsourcesbuildphase.cpp",
+ "pbxsourcesbuildphase.h",
+ "pbxsourcetree.cpp",
+ "pbxsourcetree.h",
+ "pbxtarget.cpp",
+ "pbxtarget.h",
+ "pbxtargetdependency.cpp",
+ "pbxtargetdependency.h",
+ "xcbuildconfiguration.cpp",
+ "xcbuildconfiguration.h",
+ "xcconfigurationlist.cpp",
+ "xcconfigurationlist.h",
+ "xcodegenerator.cpp",
+ "xcodegenerator.h",
+ "xcodenativegenerator.cpp",
+ "xcodenativegenerator.h",
+ "xcodesimplegenerator.cpp",
+ "xcodesimplegenerator.h",
+ "xcscheme.cpp",
+ "xcscheme.h",
+ "xcsettings.cpp",
+ "xcsettings.h",
+ "xcodebuildsettingmapping.cpp",
+ "xcodebuildsettingmapping.h"
+ ]
+ }
+ Group {
name: "jsextensions"
prefix: name + '/'
files: [
diff --git a/src/lib/corelib/generators/generators.pri b/src/lib/corelib/generators/generators.pri
index 6372e81..2fa095e 100644
--- a/src/lib/corelib/generators/generators.pri
+++ b/src/lib/corelib/generators/generators.pri
@@ -1,2 +1,4 @@
HEADERS += \
$$PWD/generator.h
+
+include(xcode/xcode.pri)
diff --git a/src/lib/corelib/generators/xcode/opensteppropertylist.cpp b/src/lib/corelib/generators/xcode/opensteppropertylist.cpp
new file mode 100644
index 0000000..63adee2
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/opensteppropertylist.cpp
@@ -0,0 +1,257 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Petroules Corporation.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "opensteppropertylist.h"
+#include "pbxobject.h"
+#include <QDebug>
+#include <QStack>
+
+const QChar OpenStepPropertyList::NewlineToken = QLatin1Char('\n');
+const QChar OpenStepPropertyList::DictionaryBeginToken = QLatin1Char('{');
+const QChar OpenStepPropertyList::DictionarySeparatorToken = QLatin1Char(';');
+const QChar OpenStepPropertyList::DictionaryEndToken = QLatin1Char('}');
+const QChar OpenStepPropertyList::ArrayBeginToken = QLatin1Char('(');
+const QChar OpenStepPropertyList::ArraySeparatorToken = QLatin1Char(',');
+const QChar OpenStepPropertyList::ArrayEndToken = QLatin1Char(')');
+const QChar OpenStepPropertyList::QuotedStringBeginToken = QLatin1Char('"');
+const QChar OpenStepPropertyList::QuotedStringEndToken = QLatin1Char('"');
+const QChar OpenStepPropertyList::DataBeginToken = QLatin1Char('<');
+const QChar OpenStepPropertyList::DataEndToken = QLatin1Char('>');
+const QChar OpenStepPropertyList::IndentationToken = QLatin1Char('\t');
+
+#define isValidUnquotedStringCharacter(x) (((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z') || ((x) >= '0' && (x) <= '9') || (x) == '_' || (x) == '$' || (x) == '/' || (x) == ':' || (x) == '.' )
+
+static QString formatString(const QString &string)
+{
+ bool isQuoted = string.isEmpty();
+ if (!isQuoted)
+ {
+ for (int i = 0; i < string.size(); ++i)
+ {
+ if (!isValidUnquotedStringCharacter(string[i]))
+ {
+ isQuoted = true;
+ break;
+ }
+ }
+ }
+
+ QString outString = string;
+ outString.replace(QLatin1String("\\"), QLatin1String("\\\\"));
+ outString.replace(QLatin1String("\""), QLatin1String("\\\""));
+
+ if (isQuoted)
+ outString.prepend(OpenStepPropertyList::QuotedStringBeginToken);
+ if (isQuoted)
+ outString.append(OpenStepPropertyList::QuotedStringEndToken);
+
+ return outString;
+}
+
+QString OpenStepPropertyList::toString(const QVariantMap &propertyList)
+{
+ PBXObjectMap newMap;
+ Q_FOREACH (const QString &key, propertyList.keys()) {
+ newMap.insert(key, propertyList[key]);
+ }
+ return toString(newMap);
+}
+
+QString OpenStepPropertyList::toString(const PBXObjectMap &propertyList)
+{
+ return toString(propertyList, 0) + NewlineToken;
+}
+
+QString OpenStepPropertyList::toString(const QVariantMap &propertyList, int indentationLevel)
+{
+ PBXObjectMap newMap;
+ Q_FOREACH (const QString &key, propertyList.keys()) {
+ newMap.insert(key, propertyList[key]);
+ }
+ return toString(newMap, indentationLevel);
+}
+
+QString OpenStepPropertyList::toString(const PBXObjectMap &propertyList, int indentationLevel)
+{
+ QString string(indentationLevel, IndentationToken);
+ string += DictionaryBeginToken;
+
+ const bool isFlat =
+ propertyList[QLatin1String("isa")] == QLatin1String("PBXBuildFile") ||
+ propertyList[QLatin1String("isa")] == QLatin1String("PBXFileReference");
+ if (!isFlat) {
+ string += NewlineToken;
+ }
+
+ QList<PBXObjectIdentifier> keys = propertyList.keys();
+
+ // Push the isa property to the top of the list as it's always written first
+ const int isaIndex = keys.indexOf(QLatin1String("isa"));
+ if (isaIndex >= 0) {
+ keys.removeAt(isaIndex);
+ keys.insert(0, QLatin1String("isa"));
+ }
+
+ QStack<QString> isas;
+
+ foreach (const PBXObjectIdentifier &vkey, keys)
+ {
+ const QVariant &object = propertyList[vkey];
+
+ if (!vkey.isa().isEmpty()) {
+ if (!isas.empty() && vkey.isa() != isas.top()) {
+ string += QString(QLatin1String("/* End %1 section */\n")).arg(isas.top());
+ isas.pop();
+ }
+
+ if (isas.empty()) {
+ isas.push(vkey.isa());
+ string += QString(QLatin1String("\n/* Begin %1 section */\n")).arg(vkey.isa());
+ }
+ }
+
+ string += QString(!isFlat ? (indentationLevel + 1) : 0, IndentationToken);
+ string += toString(QVariant::fromValue(vkey), -1);
+ string += QLatin1String(" = ");
+
+ if (object.canConvert<PBXObjectMap>() || object.type() == QVariant::Map || object.type() == QVariant::List ||
+ object.type() == QVariant::StringList || object.type() == QVariant::ByteArray)
+ string += toString(object, !isFlat ? (indentationLevel + 1) : 0).trimmed();
+ else
+ string += toString(object, 0);
+
+ string += DictionarySeparatorToken;
+ string += !isFlat ? NewlineToken : QLatin1Char(' ');
+ }
+
+ if (!isas.empty()) {
+ string += QString(QLatin1String("/* End %1 section */\n")).arg(isas.top());
+ isas.pop();
+ }
+
+ if (!isFlat) {
+ string += QString(indentationLevel, IndentationToken);
+ }
+
+ string += DictionaryEndToken;
+ return string;
+}
+
+QString OpenStepPropertyList::toString(const QList<QVariant> &propertyList)
+{
+ return toString(propertyList, 0) + NewlineToken;
+}
+
+QString OpenStepPropertyList::toString(const QList<QVariant> &propertyList, int indentationLevel)
+{
+ QString string(indentationLevel, IndentationToken);
+ string += ArrayBeginToken;
+ string += NewlineToken;
+
+ for (int i = 0; i < propertyList.size(); ++i)
+ {
+ const QVariant &object = propertyList[i];
+ string += toString(object, indentationLevel + 1);
+ string += ArraySeparatorToken;
+ string += NewlineToken;
+ }
+
+ string += QString(indentationLevel, IndentationToken) + ArrayEndToken;
+ return string;
+}
+
+QString OpenStepPropertyList::toString(const QVariant &object, int indentationLevel)
+{
+ if (object.canConvert<PBXObjectIdentifier>()) {
+ PBXObjectIdentifier objid = object.value<PBXObjectIdentifier>();
+ QString s = toString(objid.identifier(), indentationLevel);
+ if (!objid.comment().isEmpty()) {
+ s += QLatin1String(" /* ");
+ s += objid.comment().replace(QLatin1String("*/"), QLatin1String("* /"));
+ s += QLatin1String(" */");
+ }
+ return s;
+ }
+
+ if (object.canConvert<PBXObjectMap>()) {
+ return toString(object.value<PBXObjectMap>(), indentationLevel);
+ }
+
+ switch (object.type())
+ {
+ case QVariant::Bool:
+ return object.toBool() ? QLatin1String("YES") : QLatin1String("NO");
+ case QVariant::ByteArray:
+ return toString(object.toByteArray(), indentationLevel);
+ case QVariant::Date:
+ case QVariant::DateTime:
+ case QVariant::Time:
+ return toString(object.toDateTime(), indentationLevel);
+ case QVariant::Double:
+ return QString::number(object.toDouble());
+ case QVariant::Int:
+ return QString::number(object.toInt());
+ case QVariant::List:
+ case QVariant::StringList:
+ return toString(object.toList(), indentationLevel);
+ case QVariant::LongLong:
+ return QString::number(object.toLongLong());
+ case QVariant::Map:
+ return toString(object.toMap(), indentationLevel);
+ case QVariant::String:
+ return toString(object.toString(), indentationLevel);
+ case QVariant::UInt:
+ return QString::number(object.toUInt());
+ case QVariant::ULongLong:
+ return QString::number(object.toULongLong());
+ default:
+ qDebug() << "Unsupported property list object type" << object;
+ abort();
+ }
+}
+
+QString OpenStepPropertyList::toString(const QByteArray &object, int indentationLevel)
+{
+ QString string(indentationLevel, IndentationToken);
+ string += DataBeginToken + QString::fromLatin1(object.toHex()) + DataEndToken;
+ return string;
+}
+
+QString OpenStepPropertyList::toString(const QDateTime &object, int indentationLevel)
+{
+ return toString(object.toUTC().toString(Qt::ISODate), indentationLevel);
+}
+
+QString OpenStepPropertyList::toString(const QString &object, int indentationLevel)
+{
+ QString string(indentationLevel, IndentationToken);
+ string += formatString(object);
+ return string;
+}
diff --git a/src/lib/corelib/generators/xcode/opensteppropertylist.h b/src/lib/corelib/generators/xcode/opensteppropertylist.h
new file mode 100644
index 0000000..36cef73
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/opensteppropertylist.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Petroules Corporation.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef OPENSTEPPROPERTYLIST_H
+#define OPENSTEPPROPERTYLIST_H
+
+#include <QByteArray>
+#include <QDateTime>
+#include <QList>
+#include <QString>
+#include <QVariant>
+
+class PBXObjectIdentifier;
+typedef QMap<PBXObjectIdentifier, QVariant> PBXObjectMap;
+
+class OpenStepPropertyList
+{
+ Q_DISABLE_COPY(OpenStepPropertyList)
+public:
+ static const QChar NewlineToken;
+ static const QChar DictionaryBeginToken;
+ static const QChar DictionarySeparatorToken;
+ static const QChar DictionaryEndToken;
+ static const QChar ArrayBeginToken;
+ static const QChar ArraySeparatorToken;
+ static const QChar ArrayEndToken;
+ static const QChar QuotedStringBeginToken;
+ static const QChar QuotedStringEndToken;
+ static const QChar DataBeginToken;
+ static const QChar DataEndToken;
+ static const QChar IndentationToken;
+
+ static QString toString(const QVariantMap &propertyList);
+ static QString toString(const PBXObjectMap &propertyList);
+ static QString toString(const QList<QVariant> &propertyList);
+
+private:
+ OpenStepPropertyList();
+
+ static QString toString(const QVariantMap &propertyList, int indentationLevel);
+ static QString toString(const PBXObjectMap &propertyList, int indentationLevel);
+ static QString toString(const QList<QVariant> &propertyList, int indentationLevel);
+ static QString toString(const QVariant &object, int indentationLevel);
+ static QString toString(const QByteArray &object, int indentationLevel);
+ static QString toString(const QDateTime &object, int indentationLevel);
+ static QString toString(const QString &object, int indentationLevel);
+};
+
+#endif // OPENSTEPPROPERTYLIST_H
diff --git a/src/lib/corelib/generators/xcode/pbx.h b/src/lib/corelib/generators/xcode/pbx.h
new file mode 100644
index 0000000..d4cc014
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbx.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef PBX_H
+#define PBX_H
+
+#include "opensteppropertylist.h"
+#include "pbxbuildfile.h"
+#include "pbxbuildphase.h"
+#include "pbxcontainer.h"
+#include "pbxcontaineritemproxy.h"
+#include "pbxfileencoding.h"
+#include "pbxfilereference.h"
+#include "pbxfiletype.h"
+#include "pbxgroup.h"
+#include "pbxlegacytarget.h"
+#include "pbxnativetarget.h"
+#include "pbxobject.h"
+#include "pbxproducttype.h"
+#include "pbxproject.h"
+#include "pbxreference.h"
+#include "pbxsourcetree.h"
+#include "pbxtarget.h"
+#include "pbxtargetdependency.h"
+#include "xcbuildconfiguration.h"
+#include "xcconfigurationlist.h"
+#include "xcscheme.h"
+#include "xcsettings.h"
+
+#endif // PBX_H
diff --git a/src/lib/corelib/generators/xcode/pbxbuildfile.cpp b/src/lib/corelib/generators/xcode/pbxbuildfile.cpp
new file mode 100644
index 0000000..cbe34c0
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxbuildfile.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "pbxbuildfile.h"
+#include "pbxbuildphase.h"
+#include "pbxfilereference.h"
+
+static const QString kPBXBuildFileAttributes = QLatin1String("ATTRIBUTES");
+static const QString kPBXBuildFileLibraryWeakLinked = QLatin1String("Weak");
+
+class PBXBuildFilePrivate
+{
+public:
+ PBXBuildFilePrivate();
+ PBXFileReference *reference;
+ QSet<QString> attributes;
+};
+
+PBXBuildFilePrivate::PBXBuildFilePrivate()
+ : reference()
+{
+}
+
+PBXBuildFile::PBXBuildFile(PBXBuildPhase *parent) :
+ PBXObject(parent), d(new PBXBuildFilePrivate)
+{
+}
+
+PBXBuildFile::~PBXBuildFile()
+{
+ delete d;
+}
+
+QString PBXBuildFile::isa() const
+{
+ return QLatin1String("PBXBuildFile");
+}
+
+PBXObjectMap PBXBuildFile::toMap() const
+{
+ PBXObjectMap self = PBXObject::toMap();
+ if (d->reference) {
+ self.insert(QLatin1String("fileRef"), QVariant::fromValue(d->reference->identifier()));
+ }
+
+ QVariantMap settingsMap;
+ if (!d->attributes.isEmpty()) {
+ QStringList attributes = d->attributes.toList();
+ qSort(attributes);
+ settingsMap.insert(kPBXBuildFileAttributes, attributes);
+ }
+
+ if (!settingsMap.isEmpty()) {
+ self.insert(QLatin1String("settings"), settingsMap);
+ }
+
+ return self;
+}
+
+PBXFileReference *PBXBuildFile::fileReference() const
+{
+ return d->reference;
+}
+
+void PBXBuildFile::setFileReference(PBXFileReference *reference)
+{
+ d->reference = reference;
+}
+
+QSet<QString> PBXBuildFile::attributes() const
+{
+ return d->attributes;
+}
+
+bool PBXBuildFile::isWeakLinkedLibrary() const
+{
+ return d->attributes.contains(kPBXBuildFileLibraryWeakLinked);
+}
+
+void PBXBuildFile::setWeakLinkedLibrary(bool weakLinked)
+{
+ if (weakLinked)
+ d->attributes.insert(kPBXBuildFileLibraryWeakLinked);
+ else
+ d->attributes.remove(kPBXBuildFileLibraryWeakLinked);
+}
+
+QString PBXBuildFile::comment() const
+{
+ if (d->reference) {
+ PBXBuildPhase *phase = dynamic_cast<PBXBuildPhase *>(parent());
+ Q_ASSERT(phase);
+ return QString(QLatin1String("%1 in %2")).arg(d->reference->name()).arg(phase->name());
+ }
+
+ return PBXObject::comment();
+}
+
+QByteArray PBXBuildFile::hashData() const
+{
+ QByteArray data = PBXObject::hashData();
+ if (d->reference) {
+ data.append(d->reference->hashData());
+ }
+
+ return data;
+}
diff --git a/src/lib/corelib/generators/xcode/pbxbuildfile.h b/src/lib/corelib/generators/xcode/pbxbuildfile.h
new file mode 100644
index 0000000..bc25ab8
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxbuildfile.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef PBXBUILDFILE_H
+#define PBXBUILDFILE_H
+
+#include "pbxobject.h"
+#include <QObject>
+#include <QSet>
+
+class PBXBuildPhase;
+class PBXFileReference;
+
+class PBXBuildFilePrivate;
+
+/*!
+ * \brief The PBXBuildFile class represents a file reference that is used in a build phase.
+ * Its primary purpose is to allow additional build settings to be applied at the file level.
+ */
+class PBXBuildFile : public PBXObject
+{
+ Q_OBJECT
+public:
+ explicit PBXBuildFile(PBXBuildPhase *parent = 0);
+ virtual ~PBXBuildFile();
+
+ QString isa() const;
+ PBXObjectMap toMap() const;
+
+ QString comment() const;
+
+ QByteArray hashData() const;
+
+ PBXFileReference *fileReference() const;
+ void setFileReference(PBXFileReference *reference);
+
+ QString absolutePath() const;
+ QSet<QString> attributes() const;
+
+ bool isWeakLinkedLibrary() const;
+ void setWeakLinkedLibrary(bool weakLinked);
+
+private:
+ PBXBuildFilePrivate *d;
+};
+
+#endif // PBXBUILDFILE_H
diff --git a/src/lib/corelib/generators/xcode/pbxbuildphase.cpp b/src/lib/corelib/generators/xcode/pbxbuildphase.cpp
new file mode 100644
index 0000000..fc371aa
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxbuildphase.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "pbxbuildfile.h"
+#include "pbxbuildphase.h"
+#include "pbxfilereference.h"
+#include "pbxtarget.h"
+
+class PBXBuildPhasePrivate
+{
+public:
+ QList<PBXBuildFile *> buildFiles;
+};
+
+PBXBuildPhase::PBXBuildPhase(PBXTarget *parent) :
+ PBXObject(parent), d(new PBXBuildPhasePrivate)
+{
+}
+
+PBXBuildPhase::~PBXBuildPhase()
+{
+ delete d;
+}
+
+PBXObjectMap PBXBuildPhase::toMap() const
+{
+ PBXObjectMap self = PBXObject::toMap();
+ self.insert(QLatin1String("buildActionMask"), std::numeric_limits<int>::max());
+
+ QVariantList fileReferenceList;
+ foreach (PBXBuildFile *buildFile, buildFiles())
+ fileReferenceList += QVariant::fromValue(buildFile->identifier());
+ self.insert(QLatin1String("files"), fileReferenceList);
+
+ self.insert(QLatin1String("runOnlyForDeploymentPostprocessing"), 0);
+
+ return self;
+}
+
+QByteArray PBXBuildPhase::hashData() const
+{
+ QByteArray data;
+ PBXTarget *target = dynamic_cast<PBXTarget *>(parent());
+ if (target) {
+ data.append(target->hashData());
+ }
+ return data; // TODO: Build phases for which a target may have multiple of, will not work
+}
+
+QList<PBXBuildFile *> PBXBuildPhase::buildFiles() const
+{
+ return d->buildFiles;
+}
+
+PBXBuildFile *PBXBuildPhase::addReference(PBXFileReference *reference)
+{
+ Q_FOREACH (PBXBuildFile *buildFile, d->buildFiles) {
+ if (buildFile->fileReference() == reference) {
+ return buildFile;
+ }
+ }
+
+ PBXBuildFile *buildFile = new PBXBuildFile(this);
+ buildFile->setFileReference(reference);
+ d->buildFiles.append(buildFile);
+ return buildFile;
+}
diff --git a/src/lib/corelib/generators/xcode/pbxbuildphase.h b/src/lib/corelib/generators/xcode/pbxbuildphase.h
new file mode 100644
index 0000000..b80ec81
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxbuildphase.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef PBXBUILDPHASE_H
+#define PBXBUILDPHASE_H
+
+#include "pbxobject.h"
+#include <QObject>
+
+class PBXBuildFile;
+class PBXFileReference;
+class PBXTarget;
+
+class PBXBuildPhasePrivate;
+
+class PBXBuildPhase : public PBXObject
+{
+ Q_OBJECT
+public:
+ explicit PBXBuildPhase(PBXTarget *parent = 0);
+ virtual ~PBXBuildPhase();
+
+ virtual QString name() const = 0;
+
+ PBXObjectMap toMap() const;
+
+ QByteArray hashData() const;
+
+ QList<PBXBuildFile *> buildFiles() const;
+
+ PBXBuildFile *addReference(PBXFileReference *reference);
+ bool containsFileReferenceIdenticalTo(PBXFileReference *reference);
+
+private:
+ PBXBuildPhasePrivate *d;
+};
+
+#endif // PBXBUILDPHASE_H
diff --git a/src/lib/corelib/generators/xcode/pbxcontainer.cpp b/src/lib/corelib/generators/xcode/pbxcontainer.cpp
new file mode 100644
index 0000000..6ce359a
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxcontainer.cpp
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "pbxcontainer.h"
+#include "pbxgroup.h"
+
+class PBXContainerPrivate
+{
+public:
+ PBXGroup group;
+};
+
+PBXContainer::PBXContainer(QObject *parent) :
+ PBXObject(parent), d(new PBXContainerPrivate)
+{
+}
+
+PBXContainer::~PBXContainer()
+{
+ delete d;
+}
+
+QByteArray PBXContainer::hashData() const
+{
+ QByteArray data = PBXObject::hashData();
+ data.append(d->group.hashData());
+ return data;
+}
+
+PBXGroup *PBXContainer::rootGroup() const
+{
+ return &d->group;
+}
diff --git a/src/lib/corelib/generators/xcode/pbxcontainer.h b/src/lib/corelib/generators/xcode/pbxcontainer.h
new file mode 100644
index 0000000..3263149
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxcontainer.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef PBXCONTAINER_H
+#define PBXCONTAINER_H
+
+#include "pbxobject.h"
+#include <QObject>
+
+class PBXFileReference;
+class PBXGroup;
+
+class PBXContainerPrivate;
+
+class PBXContainer : public PBXObject
+{
+ Q_OBJECT
+public:
+ explicit PBXContainer(QObject *parent = 0);
+ virtual ~PBXContainer();
+
+ QByteArray hashData() const;
+
+ PBXGroup *rootGroup() const;
+
+ PBXFileReference *fileReferenceForPath(const QString &path);
+
+private:
+ PBXContainerPrivate *d;
+};
+
+#endif // PBXCONTAINER_H
diff --git a/src/lib/corelib/generators/xcode/pbxcontaineritemproxy.cpp b/src/lib/corelib/generators/xcode/pbxcontaineritemproxy.cpp
new file mode 100644
index 0000000..46f18dd
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxcontaineritemproxy.cpp
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "pbxcontaineritemproxy.h"
+#include "pbxproject.h"
+#include "pbxtarget.h"
+#include "pbxtargetdependency.h"
+
+class PBXContainerItemProxyPrivate
+{
+public:
+ PBXProject *containerPortal;
+ PBXTarget *target;
+};
+
+PBXContainerItemProxy::PBXContainerItemProxy(PBXTargetDependency *parent) :
+ PBXObject(parent), d(new PBXContainerItemProxyPrivate)
+{
+}
+
+PBXContainerItemProxy::~PBXContainerItemProxy()
+{
+ delete d;
+}
+
+QString PBXContainerItemProxy::isa() const
+{
+ return QLatin1String("PBXContainerItemProxy");
+}
+
+PBXObjectMap PBXContainerItemProxy::toMap() const
+{
+ PBXObjectMap self = PBXObject::toMap();
+ if (d->containerPortal)
+ self.insert(QLatin1String("containerPortal"), QVariant::fromValue(d->containerPortal->identifier()));
+
+ self.insert(QLatin1String("proxyType"), 1); // TODO: Always the same?
+
+ if (d->target) {
+ // We deliberately don't store the actual PBXObjectIdentifier,
+ // because Xcode itself doesn't write the ID with a comment annotation
+ self.insert(QLatin1String("remoteGlobalIDString"), d->target->identifier().identifier());
+ self.insert(QLatin1String("remoteInfo"), d->target->name());
+ }
+
+ return self;
+}
+
+QString PBXContainerItemProxy::comment() const
+{
+ return PBXObject::comment();
+}
+
+QByteArray PBXContainerItemProxy::hashData() const
+{
+ QByteArray data = PBXObject::hashData();
+ if (d->containerPortal) {
+ data.append(d->containerPortal->hashData());
+ }
+
+ if (d->target) {
+ data.append(d->target->hashData());
+ }
+
+ return data;
+}
+
+PBXProject *PBXContainerItemProxy::containerPortal() const
+{
+ return d->containerPortal;
+}
+
+void PBXContainerItemProxy::setContainerPortal(PBXProject *containerPortal)
+{
+ d->containerPortal = containerPortal;
+}
+
+PBXTarget *PBXContainerItemProxy::target() const
+{
+ return d->target;
+}
+
+void PBXContainerItemProxy::setTarget(PBXTarget *target)
+{
+ d->target = target;
+}
diff --git a/src/lib/corelib/generators/xcode/pbxcontaineritemproxy.h b/src/lib/corelib/generators/xcode/pbxcontaineritemproxy.h
new file mode 100644
index 0000000..34205aa
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxcontaineritemproxy.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef PBXCONTAINERITEMPROXY_H
+#define PBXCONTAINERITEMPROXY_H
+
+#include "pbxobject.h"
+
+class PBXContainerItemProxyPrivate;
+class PBXProject;
+class PBXTarget;
+class PBXTargetDependency;
+
+class PBXContainerItemProxy : public PBXObject
+{
+ Q_OBJECT
+public:
+ explicit PBXContainerItemProxy(PBXTargetDependency *parent = 0);
+ virtual ~PBXContainerItemProxy();
+
+ QString isa() const;
+ PBXObjectMap toMap() const;
+
+ QString comment() const;
+
+ QByteArray hashData() const;
+
+ PBXProject *containerPortal() const;
+ void setContainerPortal(PBXProject *containerPortal);
+
+ PBXTarget *target() const;
+ void setTarget(PBXTarget *target);
+
+private:
+ PBXContainerItemProxyPrivate *d;
+};
+
+#endif // PBXCONTAINERITEMPROXY_H
diff --git a/src/lib/corelib/generators/xcode/pbxfileencoding.h b/src/lib/corelib/generators/xcode/pbxfileencoding.h
new file mode 100644
index 0000000..50af8c5
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxfileencoding.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef PBXFILEENCODING_H
+#define PBXFILEENCODING_H
+
+namespace PBX
+{
+ typedef enum {
+ Default = 0,
+ UTF8 = 4,
+ UTF16 = 10,
+ UTF16_BE = 0x90000100,
+ UTF16_LE = 0x94000100,
+ Western = 30,
+ Japanese = 0x80000001,
+ TraditionalChinese = 0x80000002,
+ Korean = 0x80000003,
+ Arabic = 0x80000004,
+ Hebrew = 0x80000005,
+ Greek = 0x80000006,
+ Cyrillic = 0x80000007,
+ SimplifiedChinese = 0x80000019,
+ CentralEuropean = 0x8000001D,
+ Turkish = 0x80000023,
+ Icelandic = 0x80000025
+ } PBXFileEncoding;
+}
+
+#endif // PBXFILEENCODING_H
diff --git a/src/lib/corelib/generators/xcode/pbxfilereference.cpp b/src/lib/corelib/generators/xcode/pbxfilereference.cpp
new file mode 100644
index 0000000..b5dbd94
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxfilereference.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "pbxfileencoding.h"
+#include "pbxfilereference.h"
+#include "pbxfiletype.h"
+#include "pbxgroup.h"
+#include "pbxsourcetree.h"
+#include <QFileInfo>
+
+class PBXFileReferencePrivate
+{
+public:
+};
+
+PBXFileReference::PBXFileReference(QObject *parent) :
+ PBXReference(parent), d(new PBXFileReferencePrivate)
+{
+}
+
+PBXFileReference::~PBXFileReference()
+{
+ delete d;
+}
+
+QString PBXFileReference::isa() const
+{
+ return QLatin1String("PBXFileReference");
+}
+
+PBXObjectMap PBXFileReference::toMap() const
+{
+ PBXObjectMap self = PBXReference::toMap();
+ self.insert(QLatin1String("fileEncoding"), PBX::Default);
+ //self.insert(QLatin1String("explicitFileType"), PBXFileType::typeForFileExtension(QFileInfo(path()).suffix())); // PBXFileType
+ //self.insert(QLatin1String("includeInIndex"), 0);
+ self.insert(QLatin1String("lastKnownFileType"), PBXFileType::typeForFileExtension(QFileInfo(path()).suffix())); // PBXFileType
+ return self;
+}
diff --git a/src/lib/corelib/generators/xcode/pbxfilereference.h b/src/lib/corelib/generators/xcode/pbxfilereference.h
new file mode 100644
index 0000000..7a56120
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxfilereference.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef PBXFILEREFERENCE_H
+#define PBXFILEREFERENCE_H
+
+#include "pbxreference.h"
+
+class PBXFileReferencePrivate;
+
+class PBXFileReference : public PBXReference
+{
+ Q_OBJECT
+public:
+ explicit PBXFileReference(QObject *parent = 0);
+ virtual ~PBXFileReference();
+
+ QString isa() const;
+ PBXObjectMap toMap() const;
+
+private:
+ PBXFileReferencePrivate *d;
+};
+
+#endif // PBXFILEREFERENCE_H
diff --git a/src/lib/corelib/generators/xcode/pbxfiletype.cpp b/src/lib/corelib/generators/xcode/pbxfiletype.cpp
new file mode 100644
index 0000000..4f7b58d
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxfiletype.cpp
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "pbxfiletype.h"
+
+PBXFileType::PBXFileType(QObject *parent) :
+ QObject(parent)
+{
+}
+
+QString PBXFileType::typeForFileExtension(const QString &fileExtension)
+{
+ if (fileExtension == QLatin1String("a"))
+ return QLatin1String("archive.ar");
+ if (fileExtension == QLatin1String("app"))
+ return QLatin1String("wrapper.application");
+ if (fileExtension == QLatin1String("cpp"))
+ return QLatin1String("sourcecode.cpp.cpp");
+ if (fileExtension == QLatin1String("dylib"))
+ return QLatin1String("compiled.mach-o.dylib");
+ if (fileExtension == QLatin1String("h"))
+ return QLatin1String("sourcecode.c.h");
+ return QString("text");
+}
diff --git a/src/lib/corelib/generators/xcode/pbxfiletype.h b/src/lib/corelib/generators/xcode/pbxfiletype.h
new file mode 100644
index 0000000..b289250
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxfiletype.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef PBXFILETYPE_H
+#define PBXFILETYPE_H
+
+#include <QObject>
+
+class PBXFileType : public QObject
+{
+ Q_OBJECT
+public:
+ explicit PBXFileType(QObject *parent = 0);
+
+ static QStringList allTypes();
+ static QStringList fileExtensionsForType(const QString &type);
+ static QString typeForFileExtension(const QString &fileExtension);
+};
+
+#endif // PBXFILETYPE_H
diff --git a/src/lib/corelib/generators/xcode/pbxframeworksbuildphase.cpp b/src/lib/corelib/generators/xcode/pbxframeworksbuildphase.cpp
new file mode 100644
index 0000000..6b417e7
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxframeworksbuildphase.cpp
@@ -0,0 +1,27 @@
+#include "pbxframeworksbuildphase.h"
+
+PBXFrameworksBuildPhase::PBXFrameworksBuildPhase(PBXTarget *parent) :
+ PBXBuildPhase(parent)
+{
+}
+
+QString PBXFrameworksBuildPhase::name() const
+{
+ return QLatin1String("Frameworks");
+}
+
+QString PBXFrameworksBuildPhase::isa() const
+{
+ return QLatin1String("PBXFrameworksBuildPhase");
+}
+
+PBXObjectMap PBXFrameworksBuildPhase::toMap() const
+{
+ PBXObjectMap self = PBXBuildPhase::toMap();
+ return self;
+}
+
+QString PBXFrameworksBuildPhase::comment() const
+{
+ return name();
+}
diff --git a/src/lib/corelib/generators/xcode/pbxframeworksbuildphase.h b/src/lib/corelib/generators/xcode/pbxframeworksbuildphase.h
new file mode 100644
index 0000000..0553089
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxframeworksbuildphase.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef PBXFRAMEWORKSBUILDPHASE_H
+#define PBXFRAMEWORKSBUILDPHASE_H
+
+#include "pbxbuildphase.h"
+
+class PBXFrameworksBuildPhase : public PBXBuildPhase
+{
+ Q_OBJECT
+public:
+ explicit PBXFrameworksBuildPhase(PBXTarget *parent = 0);
+
+ QString name() const;
+
+ QString isa() const;
+ PBXObjectMap toMap() const;
+
+ QString comment() const;
+};
+
+#endif // PBXFRAMEWORKSBUILDPHASE_H
diff --git a/src/lib/corelib/generators/xcode/pbxgroup.cpp b/src/lib/corelib/generators/xcode/pbxgroup.cpp
new file mode 100644
index 0000000..ea48b22
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxgroup.cpp
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "pbxfilereference.h"
+#include "pbxgroup.h"
+
+class PBXGroupPrivate
+{
+public:
+ QList<PBXReference *> children;
+};
+
+PBXGroup::PBXGroup(QObject *parent) :
+ PBXReference(parent), d(new PBXGroupPrivate)
+{
+}
+
+PBXGroup::~PBXGroup()
+{
+ delete d;
+}
+
+PBXGroup *PBXGroup::groupWithName(const QString &name, PBXGroup *parentGroup)
+{
+ PBXGroup *group = new PBXGroup();
+ group->setName(name);
+
+ if (parentGroup) {
+ group->setParent(parentGroup);
+ parentGroup->addItem(group);
+ }
+
+ return group;
+}
+
+QString PBXGroup::isa() const
+{
+ return QLatin1String("PBXGroup");
+}
+
+PBXObjectMap PBXGroup::toMap() const
+{
+ PBXObjectMap self = PBXReference::toMap();
+
+ QVariantList childIdentifiers;
+ foreach (PBXReference *reference, d->children)
+ childIdentifiers += QVariant::fromValue(reference->identifier());
+
+ self.insert(QLatin1String("children"), childIdentifiers);
+
+ return self;
+}
+
+QList<PBXReference *> PBXGroup::children() const
+{
+ return d->children;
+}
+
+void PBXGroup::addItem(PBXReference *item)
+{
+ d->children.append(item);
+}
+
+void PBXGroup::insertItem(PBXReference *item, int index)
+{
+ d->children.insert(index, item);
+}
+
+void PBXGroup::removeItem(PBXReference *item)
+{
+ d->children.removeOne(item);
+}
+
+QList<PBXFileReference *> PBXGroup::addFiles(const QStringList &files, bool copy, bool createGroupsRecursively)
+{
+ QList<PBXFileReference *> fileRefs;
+ foreach (const QString &filePath, files)
+ {
+ PBXFileReference *fileReference = new PBXFileReference(this);
+ fileReference->setPath(filePath);
+ fileReference->setName(filePath.mid(filePath.lastIndexOf('/') + 1));
+ d->children.append(fileReference);
+ fileRefs.append(fileReference);
+ }
+
+ return fileRefs;
+}
+
+QString PBXGroup::comment() const
+{
+ return !path().isEmpty() ? path() : PBXReference::comment();
+}
diff --git a/src/lib/corelib/generators/xcode/pbxgroup.h b/src/lib/corelib/generators/xcode/pbxgroup.h
new file mode 100644
index 0000000..e03b8eb
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxgroup.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef PBXGROUP_H
+#define PBXGROUP_H
+
+#include "pbxreference.h"
+
+class PBXFileReference;
+
+class PBXGroupPrivate;
+
+class PBXGroup : public PBXReference
+{
+ Q_OBJECT
+public:
+ explicit PBXGroup(QObject *parent = 0);
+ virtual ~PBXGroup();
+
+ static PBXGroup *groupWithName(const QString &name, PBXGroup *parentGroup = 0);
+
+ QString isa() const;
+ PBXObjectMap toMap() const;
+
+ QList<PBXReference *> children() const;
+
+ bool containsItem(PBXReference *item) const;
+
+ void addItem(PBXReference *item);
+ void insertItem(PBXReference *item, int index);
+ void removeItem(PBXReference *item);
+
+ /*!
+ * \param files list of absolute paths
+ */
+ QList<PBXFileReference *> addFiles(const QStringList &files, bool copy, bool createGroupsRecursively);
+
+ QString comment() const;
+
+private:
+ PBXGroupPrivate *d;
+};
+
+#endif // PBXGROUP_H
diff --git a/src/lib/corelib/generators/xcode/pbxlegacytarget.cpp b/src/lib/corelib/generators/xcode/pbxlegacytarget.cpp
new file mode 100644
index 0000000..7f887b3
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxlegacytarget.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "pbxfilereference.h"
+#include "pbxlegacytarget.h"
+#include "pbxproject.h"
+
+class PBXLegacyTargetPrivate
+{
+public:
+ QString buildToolPath;
+ QString buildArgumentsString;
+ QString buildWorkingDirectory;
+ bool passBuildSettingsInEnvironment;
+};
+
+PBXLegacyTarget::PBXLegacyTarget(PBXProject *parent) :
+ PBXTarget(parent), d(new PBXLegacyTargetPrivate)
+{
+ d->buildToolPath = QLatin1String("/bin/bash");
+ d->buildArgumentsString = QLatin1String("$(ACTION)");
+ d->buildWorkingDirectory = QLatin1String("$BUILT_PRODUCTS_DIR");
+ d->passBuildSettingsInEnvironment = true;
+}
+
+PBXLegacyTarget::~PBXLegacyTarget()
+{
+ delete d;
+}
+
+QString PBXLegacyTarget::isa() const
+{
+ return QLatin1String("PBXLegacyTarget");
+}
+
+PBXObjectMap PBXLegacyTarget::toMap() const
+{
+ PBXObjectMap self = PBXTarget::toMap();
+ self.insert(QLatin1String("buildToolPath"), d->buildToolPath);
+ self.insert(QLatin1String("buildArgumentsString"), d->buildArgumentsString);
+ self.insert(QLatin1String("buildWorkingDirectory"), d->buildWorkingDirectory);
+ self.insert(QLatin1String("passBuildSettingsInEnvironment"), d->passBuildSettingsInEnvironment ? 1 : 0);
+ return self;
+}
+
+QString PBXLegacyTarget::buildToolPath() const
+{
+ return d->buildToolPath;
+}
+
+void PBXLegacyTarget::setBuildToolPath(const QString &buildToolPath)
+{
+ d->buildToolPath = buildToolPath;
+}
+
+QString PBXLegacyTarget::buildArgumentsString() const
+{
+ return d->buildArgumentsString;
+}
+
+void PBXLegacyTarget::setBuildArgumentsString(const QString &buildArgumentsString)
+{
+ d->buildArgumentsString = buildArgumentsString;
+}
+
+QString PBXLegacyTarget::buildWorkingDirectory() const
+{
+ return d->buildWorkingDirectory;
+}
+
+void PBXLegacyTarget::setBuildWorkingDirectory(const QString &buildWorkingDirectory)
+{
+ d->buildWorkingDirectory = buildWorkingDirectory;
+}
+
+bool PBXLegacyTarget::passBuildSettingsInEnvironment() const
+{
+ return d->passBuildSettingsInEnvironment;
+}
+
+void PBXLegacyTarget::setPassBuildSettingsInEnvironment(bool passBuildSettingsInEnvironment)
+{
+ d->passBuildSettingsInEnvironment = passBuildSettingsInEnvironment;
+}
diff --git a/src/lib/corelib/generators/xcode/pbxlegacytarget.h b/src/lib/corelib/generators/xcode/pbxlegacytarget.h
new file mode 100644
index 0000000..e6b09d4
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxlegacytarget.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef PBXLEGACYTARGET_H
+#define PBXLEGACYTARGET_H
+
+#include "pbxtarget.h"
+
+class PBXLegacyTargetPrivate;
+
+class PBXLegacyTarget : public PBXTarget
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(PBXLegacyTarget)
+public:
+ explicit PBXLegacyTarget(PBXProject *parent = 0);
+ virtual ~PBXLegacyTarget();
+
+ QString isa() const;
+ PBXObjectMap toMap() const;
+
+ QString buildToolPath() const;
+ void setBuildToolPath(const QString &buildToolPath);
+
+ QString buildArgumentsString() const;
+ void setBuildArgumentsString(const QString &buildArgumentsString);
+
+ QString buildWorkingDirectory() const;
+ void setBuildWorkingDirectory(const QString &buildWorkingDirectory);
+
+ bool passBuildSettingsInEnvironment() const;
+ void setPassBuildSettingsInEnvironment(bool passBuildSettingsInEnvironment);
+
+private:
+ PBXLegacyTargetPrivate *d;
+};
+
+#endif // PBXLEGACYTARGET_H
diff --git a/src/lib/corelib/generators/xcode/pbxnativetarget.cpp b/src/lib/corelib/generators/xcode/pbxnativetarget.cpp
new file mode 100644
index 0000000..f9e648c
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxnativetarget.cpp
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "pbxbuildphase.h"
+#include "pbxfilereference.h"
+#include "pbxnativetarget.h"
+#include "pbxproject.h"
+#include "xcconfigurationlist.h"
+
+class PBXNativeTargetPrivate
+{
+public:
+ PBXNativeTargetPrivate();
+};
+
+PBXNativeTargetPrivate::PBXNativeTargetPrivate()
+{
+}
+
+PBXNativeTarget::PBXNativeTarget(PBXProject *parent) :
+ PBXTarget(parent), d(new PBXNativeTargetPrivate)
+{
+}
+
+PBXNativeTarget::~PBXNativeTarget()
+{
+ delete d;
+}
+
+QString PBXNativeTarget::isa() const
+{
+ return QLatin1String("PBXNativeTarget");
+}
+
+PBXObjectMap PBXNativeTarget::toMap() const
+{
+ PBXObjectMap self = PBXTarget::toMap();
+ self.insert(QLatin1String("productInstallPath"), QLatin1String("$(HOME)/Applications"));
+ self.insert(QLatin1String("buildRules"), QList<QVariant>());
+ return self;
+}
diff --git a/src/lib/corelib/generators/xcode/pbxnativetarget.h b/src/lib/corelib/generators/xcode/pbxnativetarget.h
new file mode 100644
index 0000000..a06b979
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxnativetarget.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef PBXNATIVETARGET_H
+#define PBXNATIVETARGET_H
+
+#include "pbxtarget.h"
+
+class PBXNativeTargetPrivate;
+
+class PBXNativeTarget : public PBXTarget
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(PBXNativeTarget)
+public:
+ explicit PBXNativeTarget(PBXProject *parent = 0);
+ ~PBXNativeTarget();
+
+ QString isa() const;
+ PBXObjectMap toMap() const;
+
+private:
+ PBXNativeTargetPrivate *d;
+};
+
+#endif // PBXNATIVETARGET_H
diff --git a/src/lib/corelib/generators/xcode/pbxobject.cpp b/src/lib/corelib/generators/xcode/pbxobject.cpp
new file mode 100644
index 0000000..0ea69d6
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxobject.cpp
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "pbxobject.h"
+#include <QCryptographicHash>
+#include <QSet>
+#include <QString>
+#include <QUuid>
+
+static QMap<QString, QByteArray> generatedIdentifiers;
+
+class PBXObjectPrivate
+{
+public:
+ QString identifier;
+};
+
+PBXObject::PBXObject(QObject *parent)
+ : QObject(parent), d(new PBXObjectPrivate)
+{
+}
+
+PBXObject::~PBXObject()
+{
+ delete d;
+}
+
+QString PBXObject::createIdentifier(const QByteArray &hashData)
+{
+ if (qgetenv("QBS_XCODE_GENERATOR_DETERMINISTIC_IDENTIFIERS") == QByteArray("1")) {
+ QCryptographicHash hash(QCryptographicHash::Sha3_512);
+ hash.addData(hashData);
+ const QString result = hash.result().left(12).toHex().toUpper();
+ if (generatedIdentifiers.contains(result)
+ /*&& generatedIdentifiers.value(result) != hashData*/) {
+ // hash collision!
+ fprintf(stderr, "hash collision %s - %s\n", result.toUtf8().data(), hashData.data());
+ abort();
+ }
+ generatedIdentifiers.insert(result, hashData);
+ return result;
+ }
+
+ return QUuid::createUuid().toByteArray().left(12).toHex().toUpper();
+}
+
+PBXObjectIdentifier PBXObject::identifier() const
+{
+ if (d->identifier.isEmpty())
+ d->identifier = createIdentifier(isa().toUtf8() + QByteArray(":") + hashData());
+ return PBXObjectIdentifier(d->identifier, isa(), comment());
+}
+
+PBXObjectMap PBXObject::toMap() const
+{
+ PBXObjectMap self;
+ self.insert(QLatin1String("isa"), isa());
+ return self;
+}
+
+QString PBXObject::comment() const
+{
+ return isa();
+}
+
+QByteArray PBXObject::hashData() const
+{
+ return QByteArray();
+}
diff --git a/src/lib/corelib/generators/xcode/pbxobject.h b/src/lib/corelib/generators/xcode/pbxobject.h
new file mode 100644
index 0000000..d4ede7e
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxobject.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef PBXOBJECT_H
+#define PBXOBJECT_H
+
+#include <QObject>
+#include <QString>
+#include <QVariant>
+
+class PBXObjectPrivate;
+
+class PBXObjectIdentifier {
+public:
+ PBXObjectIdentifier() {
+ }
+
+ PBXObjectIdentifier(const PBXObjectIdentifier &other) {
+ _key = other._key;
+ _isa = other._isa;
+ _comment = other._comment;
+ }
+
+ PBXObjectIdentifier(const QLatin1String &identifier, const QString &isa = QString(), const QString &comment = QString()) {
+ _key = identifier;
+ _isa = isa;
+ _comment = comment;
+ }
+
+ PBXObjectIdentifier(const QString &identifier, const QString &isa = QString(), const QString &comment = QString()) {
+ _key = identifier;
+ _isa = isa;
+ _comment = comment;
+ }
+
+ QString toString() const {
+ return identifier();
+ }
+
+ QString identifier() const {
+ return _key;
+ }
+
+ QString isa() const {
+ return _isa;
+ }
+
+ QString comment() const {
+ return _comment;
+ }
+
+ bool operator==(const PBXObjectIdentifier &other) const {
+ return _key == other._key && _isa == other._isa && _comment == other._comment;
+ }
+
+ bool operator<(const PBXObjectIdentifier &other) const {
+ return _isa + _key < other._isa + other._key;
+ }
+
+private:
+ QString _key;
+ QString _isa;
+ QString _comment;
+};
+
+Q_DECLARE_METATYPE(PBXObjectIdentifier)
+
+inline bool qHash(const PBXObjectIdentifier &other) {
+ return qHash(other.toString());
+}
+
+typedef QMap<PBXObjectIdentifier, QVariant> PBXObjectMap;
+Q_DECLARE_METATYPE(PBXObjectMap)
+
+class PBXObject : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(PBXObject)
+protected:
+ explicit PBXObject(QObject *parent = 0);
+
+public:
+ virtual ~PBXObject();
+
+ static QString createIdentifier(const QByteArray &hashData);
+
+ PBXObjectIdentifier identifier() const;
+ virtual QString isa() const = 0;
+ virtual PBXObjectMap toMap() const;
+ virtual QString comment() const;
+ virtual QByteArray hashData() const;
+
+private:
+ PBXObjectPrivate *d;
+};
+
+#endif // PBXOBJECT_H
diff --git a/src/lib/corelib/generators/xcode/pbxproducttype.cpp b/src/lib/corelib/generators/xcode/pbxproducttype.cpp
new file mode 100644
index 0000000..657b020
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxproducttype.cpp
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "pbxproducttype.h"
+
+QString PBX::productTypeString(PBX::PBXProductType productType)
+{
+ switch (productType)
+ {
+ case Application:
+ return QLatin1String("com.apple.product-type.application");
+ case Tool:
+ return QLatin1String("com.apple.product-type.tool");
+ case LibraryStatic:
+ return QLatin1String("com.apple.product-type.library.static");
+ case LibraryDynamic:
+ return QLatin1String("com.apple.product-type.library.dynamic");
+ case Framework:
+ return QLatin1String("com.apple.product-type.framework");
+ case StaticFramework:
+ return QLatin1String("com.apple.product-type.framework.static");
+ case Bundle:
+ return QLatin1String("com.apple.product-type.bundle");
+ case KernelExtension:
+ return QLatin1String("com.apple.product-type.kernel-extension");
+ case KernelExtensionIOKit:
+ return QLatin1String("com.apple.product-type.kernel-extension.iokit");
+ }
+
+ QLatin1String("com.apple.product-type.application.java");
+ QLatin1String("com.apple.product-type.application.shallow");
+ QLatin1String("com.apple.product-type.app-extension");
+ QLatin1String("com.apple.product-type.bundle.shallow");
+ QLatin1String("com.apple.product-type.bundle.unit-test");
+ QLatin1String("com.apple.product-type.bundle.ocunit-test");
+ QLatin1String("com.apple.product-type.framework.shallow");
+ QLatin1String("com.apple.product-type.in-app-purchase-content");
+ QLatin1String("com.apple.product-type.kernel-extension.shallow");
+ QLatin1String("com.apple.product-type.kernel-extension.iokit.shallow");
+ QLatin1String("com.apple.product-type.library.java.archive");
+ QLatin1String("com.apple.product-type.objfile");
+ QLatin1String("com.apple.product-type.pluginkit-plugin");
+ QLatin1String("com.apple.product-type.spotlight-importer");
+ QLatin1String("com.apple.product-type.tool.java");
+ QLatin1String("com.apple.product-type.xpc-service");
+
+ return QString();
+}
diff --git a/src/lib/corelib/generators/xcode/pbxproducttype.h b/src/lib/corelib/generators/xcode/pbxproducttype.h
new file mode 100644
index 0000000..cf2e48e
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxproducttype.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef PBXPRODUCTTYPE_H
+#define PBXPRODUCTTYPE_H
+
+#include <QString>
+
+namespace PBX
+{
+ typedef enum {
+ Application = 1,
+ Tool,
+ LibraryStatic,
+ LibraryDynamic,
+ Framework,
+ StaticFramework,
+ Bundle,
+ KernelExtension,
+ KernelExtensionIOKit
+ } PBXProductType;
+
+ QString productTypeString(PBXProductType productType);
+}
+
+#endif // PBXPRODUCTTYPE_H
diff --git a/src/lib/corelib/generators/xcode/pbxproject.cpp b/src/lib/corelib/generators/xcode/pbxproject.cpp
new file mode 100644
index 0000000..3ab709c
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxproject.cpp
@@ -0,0 +1,333 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "opensteppropertylist.h"
+#include "pbxbuildphase.h"
+#include "pbxbuildfile.h"
+#include "pbxcontaineritemproxy.h"
+#include "pbxgroup.h"
+#include "pbxproject.h"
+#include "pbxtarget.h"
+#include "pbxtargetdependency.h"
+#include "xcbuildconfiguration.h"
+#include "xcconfigurationlist.h"
+#include <QFile>
+#include <QFileInfo>
+#include <QVariant>
+
+static const QString kClassPrefixAttribute = QLatin1String("CLASSPREFIX");
+static const QString kLastUpgradeCheckAttribute = QLatin1String("LastUpgradeCheck");
+static const QString kOrganizationNameAttribute = QLatin1String("ORGANIZATIONNAME");
+static const QString kTargetAttributesAttribute = QLatin1String("TargetAttributes");
+
+class PBXProjectPrivate
+{
+public:
+ QString name;
+ QString projectAbsolutePath;
+ QString projectDirPath;
+ PBXGroup *frameworksRefGroup;
+ PBXGroup *productRefGroup;
+ QList<PBXTarget *> targets;
+ XCConfigurationList *configurationList;
+ QVariantMap attributes;
+};
+
+PBXProject::PBXProject(const QString &projectAbsolutePath, QObject *parent) :
+ PBXContainer(parent), d(new PBXProjectPrivate)
+{
+ d->projectAbsolutePath = projectAbsolutePath;
+ d->configurationList = new XCConfigurationList(this);
+
+ d->frameworksRefGroup = new PBXGroup(rootGroup());
+ d->frameworksRefGroup->setName(QLatin1String("Frameworks"));
+
+ d->productRefGroup = new PBXGroup(rootGroup());
+ d->productRefGroup->setName(QLatin1String("Products"));
+ d->productRefGroup->setSourceTree(PBX::Group);
+}
+
+PBXProject::~PBXProject()
+{
+ delete d;
+}
+
+QString PBXProject::isa() const
+{
+ return QLatin1String("PBXProject");
+}
+
+PBXObjectMap PBXProject::toMap() const
+{
+ // HACK: Make sure "Frameworks", "Products" groups are always at the bottom
+ rootGroup()->removeItem(d->frameworksRefGroup);
+ rootGroup()->removeItem(d->productRefGroup);
+ rootGroup()->addItem(d->frameworksRefGroup);
+ rootGroup()->addItem(d->productRefGroup);
+
+ PBXObjectMap self = PBXObject::toMap();
+ self.insert(QLatin1String("attributes"), d->attributes);
+ self.insert(QLatin1String("buildConfigurationList"), QVariant::fromValue(buildConfigurationList()->identifier()));
+ self.insert(QLatin1String("compatibilityVersion"), QLatin1String("Xcode 3.2"));
+ self.insert(QLatin1String("developmentRegion"), QLatin1String("English"));
+ self.insert(QLatin1String("hasScannedForEncodings"), QLatin1String("1"));
+ self.insert(QLatin1String("knownRegions"), QStringList() << QLatin1String("en"));
+ self.insert(QLatin1String("mainGroup"), QVariant::fromValue(rootGroup()->identifier()));
+ self.insert(QLatin1String("productRefGroup"), QVariant::fromValue(productRefGroup()->identifier()));
+ self.insert(QLatin1String("projectDirPath"), d->projectDirPath);
+ //self.insert(QLatin1String("projectReferences"), QVariantList()); // array of map { ProductGroup:, ProjectRef: }?
+ self.insert(QLatin1String("projectRoot"), QLatin1String(""));
+
+ QVariantList targetIdentifiers;
+ foreach (PBXTarget *target, targets())
+ targetIdentifiers += QVariant::fromValue(target->identifier());
+ self.insert(QLatin1String("targets"), targetIdentifiers);
+
+ return self;
+}
+
+QString PBXProject::comment() const
+{
+ return QLatin1String("Project object");
+}
+
+QByteArray PBXProject::hashData() const
+{
+ QByteArray data = PBXObject::hashData();
+ data.append(d->name);
+ return data;
+}
+
+PBXGroup *PBXProject::productRefGroup() const
+{
+ return d->productRefGroup;
+}
+
+PBXGroup *PBXProject::frameworksRefGroup() const
+{
+ return d->frameworksRefGroup;
+}
+
+QList<PBXTarget *> PBXProject::targets() const
+{
+ return d->targets;
+}
+
+PBXTarget *PBXProject::targetNamed(const QString &targetName) const
+{
+ foreach (PBXTarget *target, d->targets)
+ {
+ if (target->name() == targetName)
+ return target;
+ }
+
+ return NULL;
+}
+
+void PBXProject::addTarget(PBXTarget *target)
+{
+ d->targets.append(target);
+}
+
+QString PBXProject::name() const
+{
+ return d->name;
+}
+
+void PBXProject::setName(const QString &name)
+{
+ d->name = name;
+}
+
+QVariantMap PBXProject::attributes() const
+{
+ return d->attributes;
+}
+
+void PBXProject::setAttributes(const QVariantMap &attributes)
+{
+ d->attributes = attributes;
+}
+
+QVariant PBXProject::attribute(const QString &name) const
+{
+ return d->attributes[name];
+}
+
+void PBXProject::setAttribute(const QString &name, const QVariant &value)
+{
+ d->attributes[name] = value;
+}
+
+void PBXProject::removeAttribute(const QString &name)
+{
+ d->attributes.remove(name);
+}
+
+PBXProject::Version PBXProject::lastUpgradeCheck() const
+{
+ const QString s = d->attributes[kLastUpgradeCheckAttribute].toString().mid(0, 3);
+ Version v;
+ v.major = s.left(2).toInt();
+ v.minor = s.right(1).toInt();
+ return v;
+}
+
+void PBXProject::setLastUpgradeCheck(const PBXProject::Version &version)
+{
+ const int major = qBound(0, version.major, 99);
+ const int minor = qBound(0, version.minor, 9);
+ d->attributes[kLastUpgradeCheckAttribute] =
+ QString::number(major).rightJustified(2, QLatin1Char('0')) +
+ QString::number(minor).leftJustified(2, QLatin1Char('0'));
+}
+
+QString PBXProject::classPrefix() const
+{
+ return d->attributes[kClassPrefixAttribute].toString();
+}
+
+void PBXProject::setClassPrefix(const QString &classPrefix)
+{
+ d->attributes[kClassPrefixAttribute] = classPrefix;
+}
+
+QString PBXProject::organizationName() const
+{
+ return d->attributes[kOrganizationNameAttribute].toString();
+}
+
+void PBXProject::setOrganizationName(const QString &organizationName)
+{
+ d->attributes[kOrganizationNameAttribute] = organizationName;
+}
+
+QString PBXProject::projectWrapperPath() const
+{
+ return QFileInfo(d->projectAbsolutePath).absolutePath();
+}
+
+QString PBXProject::projectDirPath() const
+{
+ return d->projectDirPath;
+}
+
+void PBXProject::setProjectDirPath(const QString &projectDirPath)
+{
+ d->projectDirPath = projectDirPath;
+}
+
+void PBXProject::setBuildSetting(const QString &key, const QVariant &value)
+{
+ foreach (XCBuildConfiguration *configuration, d->configurationList->buildConfigurations())
+ configuration->setBuildSetting(key, value);
+}
+
+XCConfigurationList *PBXProject::buildConfigurationList() const
+{
+ return d->configurationList;
+}
+
+static void writeGroup(PBXObjectMap &objects, PBXGroup *group)
+{
+ objects.insert(group->identifier(), QVariant::fromValue(group->toMap()));
+ foreach (PBXReference *child, group->children())
+ {
+ if (PBXGroup *group = dynamic_cast<PBXGroup *>(child))
+ writeGroup(objects, group);
+ else
+ objects.insert(child->identifier(), QVariant::fromValue(child->toMap()));
+ }
+}
+
+bool PBXProject::writeToFileSystemProjectFile(bool projectWrite, bool userWrite, bool checkNeedsRevert)
+{
+ PBXObjectMap objects;
+ objects.insert(identifier(), QVariant::fromValue(toMap()));
+
+ // Add the project's root group (i.e. the root node in the file tree which contains everything)
+ writeGroup(objects, rootGroup());
+
+ // Add the project's build configuration list and build configurations to the object map
+ objects.insert(d->configurationList->identifier(), QVariant::fromValue(d->configurationList->toMap()));
+ foreach (XCBuildConfiguration *configuration, d->configurationList->buildConfigurations())
+ objects.insert(configuration->identifier(), QVariant::fromValue(configuration->toMap()));
+
+ // Add the build targets to the object map
+ foreach (PBXTarget *target, targets())
+ {
+ objects.insert(target->identifier(), QVariant::fromValue(target->toMap()));
+
+ // Add the target's build configuration list and build configurations to the object map
+ objects.insert(target->buildConfigurationList()->identifier(), QVariant::fromValue(target->buildConfigurationList()->toMap()));
+ foreach (XCBuildConfiguration *configuration, target->buildConfigurationList()->buildConfigurations())
+ objects.insert(configuration->identifier(), QVariant::fromValue(configuration->toMap()));
+
+ // Add the target's dependency objects to the object map
+ foreach (PBXTargetDependency *dependency, target->targetDependencies()) {
+ objects.insert(dependency->identifier(), QVariant::fromValue(dependency->toMap()));
+
+ if (dependency->targetProxy()) {
+ objects.insert(dependency->targetProxy()->identifier(), QVariant::fromValue(dependency->targetProxy()->toMap()));
+ }
+ }
+
+ // Add the target's build phases...
+ foreach (PBXBuildPhase *buildPhase, target->buildPhases())
+ {
+ objects.insert(buildPhase->identifier(), QVariant::fromValue(buildPhase->toMap()));
+
+ // And each of the files within
+ foreach (PBXBuildFile *buildFile, buildPhase->buildFiles())
+ {
+ objects.insert(buildFile->identifier(), QVariant::fromValue(buildFile->toMap()));
+ }
+ }
+ }
+
+ // add all subobjects to objects map!
+
+ // Build the root pbxproj object map
+ PBXObjectMap map;
+ map.insert(QLatin1String("archiveVersion"), QLatin1String("1"));
+ map.insert(QLatin1String("classes"), QVariantMap());
+ map.insert(QLatin1String("objectVersion"), QLatin1String("46"));
+ map.insert(QLatin1String("objects"), QVariant::fromValue(objects));
+ map.insert(QLatin1String("rootObject"), QVariant::fromValue(identifier()));
+
+ QFile file(d->projectAbsolutePath);
+ if (file.open(QIODevice::WriteOnly))
+ {
+ file.write(QByteArray("// !$*UTF8*$!\n"));
+ file.write(OpenStepPropertyList::toString(map).toUtf8());
+ }
+
+ return file.error() == QFile::NoError;
+}
diff --git a/src/lib/corelib/generators/xcode/pbxproject.h b/src/lib/corelib/generators/xcode/pbxproject.h
new file mode 100644
index 0000000..7a2ed88
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxproject.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef PBXPROJECT_H
+#define PBXPROJECT_H
+
+#include "pbxcontainer.h"
+
+class PBXTarget;
+class XCConfigurationList;
+
+class PBXProjectPrivate;
+
+class PBXProject : public PBXContainer
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(PBXProject)
+public:
+ typedef struct {
+ int major;
+ int minor;
+ } Version;
+
+ explicit PBXProject(const QString &projectAbsolutePath, QObject *parent = 0);
+ ~PBXProject();
+
+ QString isa() const;
+ PBXObjectMap toMap() const;
+
+ QString comment() const;
+
+ QByteArray hashData() const;
+
+ PBXGroup *frameworksRefGroup() const;
+
+ /*!
+ * Group in the root of the Xcode file tree which contains references to product target files.
+ *
+ * For example, this will contain references to output application and library executables.
+ */
+ PBXGroup *productRefGroup() const;
+
+ static bool isProjectWrapperExtension(const QString &extension);
+ static PBXProject *projectWithFile(const QString &projectAbsolutePath);
+
+ QList<PBXTarget *> targets() const;
+ PBXTarget *targetNamed(const QString &targetName) const;
+
+ void addTarget(PBXTarget *target);
+
+ QString name() const;
+ void setName(const QString &name);
+
+ QVariantMap attributes() const;
+ void setAttributes(const QVariantMap &attributes);
+
+ QVariant attribute(const QString &name) const;
+ void setAttribute(const QString &name, const QVariant &value);
+ void removeAttribute(const QString &name);
+
+ Version lastUpgradeCheck() const;
+ void setLastUpgradeCheck(const Version &version);
+
+ QString classPrefix() const;
+ void setClassPrefix(const QString &classPrefix);
+
+ QString organizationName() const;
+ void setOrganizationName(const QString &organizationName);
+
+ /*!
+ * Returns the path of the .xcodeproj wrapper directory.
+ */
+ QString projectWrapperPath() const;
+
+ QString projectDirPath() const;
+ void setProjectDirPath(const QString &projectDirPath);
+
+ void setBuildSetting(const QString &key, const QVariant &value);
+
+ XCConfigurationList *buildConfigurationList() const;
+ bool writeToFileSystemProjectFile(bool projectWrite, bool userWrite, bool checkNeedsRevert);
+
+private:
+ PBXProjectPrivate *d;
+};
+
+#endif // PBXPROJECT_H
diff --git a/src/lib/corelib/generators/xcode/pbxreference.cpp b/src/lib/corelib/generators/xcode/pbxreference.cpp
new file mode 100644
index 0000000..651f6fe
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxreference.cpp
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "pbxreference.h"
+
+class PBXReferencePrivate
+{
+public:
+ PBXReferencePrivate();
+ QString name;
+ QString path;
+ PBX::PBXSourceTree sourceTree;
+};
+
+PBXReferencePrivate::PBXReferencePrivate()
+ : name(), sourceTree()
+{
+}
+
+PBXReference::PBXReference(QObject *parent) :
+ PBXObject(parent), d(new PBXReferencePrivate)
+{
+}
+
+PBXReference::~PBXReference()
+{
+ delete d;
+}
+
+PBXObjectMap PBXReference::toMap() const
+{
+ PBXObjectMap self = PBXObject::toMap();
+
+ if (!name().isEmpty() && name() != path()) {
+ self.insert(QLatin1String("name"), name());
+ }
+
+ // Xcode crashes if path is empty, even though it should never be
+ if (!d->path.isEmpty())
+ self.insert(QLatin1String("path"), d->path); // relative path including the file name
+
+ self.insert(QLatin1String("sourceTree"), PBX::sourceTreeString(sourceTree()));
+ return self;
+}
+
+/*!
+ * \brief PBXReference::name
+ * \return display name of file or group, usually the same as the name of the file or directory.
+ */
+QString PBXReference::name() const
+{
+ return d->name;
+}
+
+void PBXReference::setName(const QString &name)
+{
+ d->name = name;
+}
+
+QString PBXReference::path() const
+{
+ return d->path;
+}
+
+void PBXReference::setPath(const QString &filePath)
+{
+ d->path = filePath;
+}
+
+PBX::PBXSourceTree PBXReference::sourceTree() const
+{
+ return d->sourceTree;
+}
+
+void PBXReference::setSourceTree(PBX::PBXSourceTree sourceTree)
+{
+ d->sourceTree = sourceTree;
+}
+
+QString PBXReference::comment() const
+{
+ return name();
+}
+
+QByteArray PBXReference::hashData() const
+{
+ QByteArray data = PBXObject::hashData();
+ if (!d->path.isEmpty()) {
+ QStringList pathComponents;
+ const PBXReference *ref = this;
+ do {
+ pathComponents.insert(0, ref->path().toUtf8());
+ } while ((ref = dynamic_cast<PBXReference *>(ref->parent())));
+
+ data.append(pathComponents.join("/").toUtf8());
+ } else if (!d->name.isEmpty()) {
+ data.append(d->name.toUtf8());
+ }
+ return data;
+}
diff --git a/src/lib/corelib/generators/xcode/pbxreference.h b/src/lib/corelib/generators/xcode/pbxreference.h
new file mode 100644
index 0000000..3400a25
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxreference.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef PBXREFERENCE_H
+#define PBXREFERENCE_H
+
+#include "pbxobject.h"
+#include "pbxsourcetree.h"
+#include <QObject>
+
+class PBXReferencePrivate;
+
+// Mono calls this PBXFileElement?
+class PBXReference : public PBXObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(PBXReference)
+protected:
+ explicit PBXReference(QObject *parent = 0);
+ virtual ~PBXReference();
+
+public:
+ PBXObjectMap toMap() const;
+
+ QString name() const;
+ void setName(const QString &name);
+
+ /*!
+ * File path of the referenced file, relative based on the value of \a sourceTree.
+ */
+ QString path() const;
+ void setPath(const QString &path);
+
+ PBX::PBXSourceTree sourceTree() const;
+ void setSourceTree(PBX::PBXSourceTree sourceTree);
+
+ QString comment() const;
+
+ QByteArray hashData() const;
+
+private:
+ PBXReferencePrivate *d;
+};
+
+#endif // PBXREFERENCE_H
diff --git a/src/lib/corelib/generators/xcode/pbxsourcesbuildphase.cpp b/src/lib/corelib/generators/xcode/pbxsourcesbuildphase.cpp
new file mode 100644
index 0000000..902d05d
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxsourcesbuildphase.cpp
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "pbxsourcesbuildphase.h"
+
+PBXSourcesBuildPhase::PBXSourcesBuildPhase(PBXTarget *parent) :
+ PBXBuildPhase(parent)
+{
+}
+
+QString PBXSourcesBuildPhase::name() const
+{
+ return QLatin1String("Sources");
+}
+
+QString PBXSourcesBuildPhase::isa() const
+{
+ return QLatin1String("PBXSourcesBuildPhase");
+}
+
+PBXObjectMap PBXSourcesBuildPhase::toMap() const
+{
+ PBXObjectMap self = PBXBuildPhase::toMap();
+ return self;
+}
+
+QString PBXSourcesBuildPhase::comment() const
+{
+ return name();
+}
diff --git a/src/lib/corelib/generators/xcode/pbxsourcesbuildphase.h b/src/lib/corelib/generators/xcode/pbxsourcesbuildphase.h
new file mode 100644
index 0000000..e841720
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxsourcesbuildphase.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef PBXSOURCESBUILDPHASE_H
+#define PBXSOURCESBUILDPHASE_H
+
+#include "pbxbuildphase.h"
+
+/*!
+ * \brief The PBXSourcesBuildPhase class represents the build phase in which source files are compiled.
+ */
+class PBXSourcesBuildPhase : public PBXBuildPhase
+{
+ Q_OBJECT
+public:
+ explicit PBXSourcesBuildPhase(PBXTarget *parent = 0);
+
+ QString name() const;
+
+ QString isa() const;
+ PBXObjectMap toMap() const;
+
+ QString comment() const;
+};
+
+#endif // PBXSOURCESBUILDPHASE_H
diff --git a/src/lib/corelib/generators/xcode/pbxsourcetree.cpp b/src/lib/corelib/generators/xcode/pbxsourcetree.cpp
new file mode 100644
index 0000000..d2163aa
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxsourcetree.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "pbxsourcetree.h"
+
+QString PBX::sourceTreeString(PBX::PBXSourceTree tree)
+{
+ switch (tree)
+ {
+ case Absolute:
+ return QLatin1String("<absolute>");
+ case Group:
+ return QLatin1String("<group>");
+ case SourceRoot:
+ return QLatin1String("SOURCE_ROOT");
+ case BuildProductDir:
+ return QLatin1String("BUILT_PRODUCTS_DIR");
+ case SdkRoot:
+ return QLatin1String("SDKROOT");
+ }
+
+ return QString();
+}
diff --git a/src/lib/corelib/generators/xcode/pbxsourcetree.h b/src/lib/corelib/generators/xcode/pbxsourcetree.h
new file mode 100644
index 0000000..f5252eb
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxsourcetree.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef PBXSOURCETREE_H
+#define PBXSOURCETREE_H
+
+#include <QString>
+
+namespace PBX
+{
+ /*!
+ * Location that the file reference's path is relative to.
+ */
+ typedef enum {
+ Absolute,
+ Group,
+ SourceRoot,
+ BuildProductDir,
+ SdkRoot
+ } PBXSourceTree;
+
+ QString sourceTreeString(PBXSourceTree tree);
+}
+
+#endif // PBXSOURCETREE_H
diff --git a/src/lib/corelib/generators/xcode/pbxtarget.cpp b/src/lib/corelib/generators/xcode/pbxtarget.cpp
new file mode 100644
index 0000000..03f4407
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxtarget.cpp
@@ -0,0 +1,192 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "pbxfilereference.h"
+#include "pbxframeworksbuildphase.h"
+#include "pbxproject.h"
+#include "pbxsourcesbuildphase.h"
+#include "pbxtarget.h"
+#include "pbxtargetdependency.h"
+#include "xcbuildconfiguration.h"
+#include "xcconfigurationlist.h"
+
+class PBXTargetPrivate
+{
+public:
+ PBXTargetPrivate();
+ QString name;
+ QString productName;
+ PBX::PBXProductType productType;
+ XCConfigurationList *configurationList;
+ PBXFrameworksBuildPhase *frameworksBuildPhase;
+ PBXSourcesBuildPhase *sourcesBuildPhase;
+ PBXFileReference *productReference;
+ QList<PBXTargetDependency *> targetDependencies;
+};
+
+PBXTargetPrivate::PBXTargetPrivate()
+ : name(), productType(), configurationList(), sourcesBuildPhase(), productReference(), targetDependencies()
+{
+}
+
+PBXTarget::PBXTarget(PBXProject *parent) :
+ PBXObject(parent), d(new PBXTargetPrivate)
+{
+ d->configurationList = new XCConfigurationList(this);
+ d->frameworksBuildPhase = new PBXFrameworksBuildPhase(this);
+ d->sourcesBuildPhase = new PBXSourcesBuildPhase(this);
+}
+
+PBXTarget::~PBXTarget()
+{
+ delete d;
+}
+
+PBXObjectMap PBXTarget::toMap() const
+{
+ PBXObjectMap self = PBXObject::toMap();
+ self.insert(QLatin1String("name"), name());
+ self.insert(QLatin1String("productName"), productName());
+ self.insert(QLatin1String("productType"), PBX::productTypeString(d->productType));
+
+ self.insert(QLatin1String("buildConfigurationList"), QVariant::fromValue(buildConfigurationList()->identifier()));
+
+ QVariantList buildPhaseReferences;
+ foreach (PBXBuildPhase *buildPhase, buildPhases())
+ buildPhaseReferences += QVariant::fromValue(buildPhase->identifier());
+ self.insert(QLatin1String("buildPhases"), buildPhaseReferences);
+
+ QVariantList targetDependencyReferences;
+ foreach (PBXTargetDependency *dependency, d->targetDependencies)
+ targetDependencyReferences += QVariant::fromValue(dependency->identifier());
+ self.insert(QLatin1String("dependencies"), targetDependencyReferences);
+
+ if (d->productReference)
+ self.insert(QLatin1String("productReference"), QVariant::fromValue(d->productReference->identifier()));
+
+ return self;
+}
+
+QString PBXTarget::name() const
+{
+ return d->name;
+}
+
+void PBXTarget::setName(const QString &name)
+{
+ d->name = name;
+}
+
+QString PBXTarget::productName() const
+{
+ return d->productName;
+}
+
+void PBXTarget::setProductName(const QString &productName)
+{
+ d->productName = productName;
+}
+
+PBX::PBXProductType PBXTarget::productType() const
+{
+ return d->productType;
+}
+
+void PBXTarget::setProductType(PBX::PBXProductType productType)
+{
+ d->productType = productType;
+}
+
+XCConfigurationList *PBXTarget::buildConfigurationList() const
+{
+ return d->configurationList;
+}
+
+QList<PBXTargetDependency *> &PBXTarget::targetDependencies() const
+{
+ return d->targetDependencies;
+}
+
+QVariant PBXTarget::buildSetting(const QString &key, const QString &buildConfigurationName)
+{
+ foreach (XCBuildConfiguration *configuration, d->configurationList->buildConfigurations()) {
+ if (configuration->name() == buildConfigurationName) {
+ return configuration->buildSetting(key);
+ }
+ }
+
+ return QVariant();
+}
+
+void PBXTarget::setBuildSetting(const QString &key, const QVariant &value)
+{
+ foreach (XCBuildConfiguration *configuration, d->configurationList->buildConfigurations())
+ configuration->setBuildSetting(key, value);
+}
+
+QList<PBXBuildPhase *> PBXTarget::buildPhases() const
+{
+ QList<PBXBuildPhase *> phases;
+ phases.append(d->frameworksBuildPhase);
+ phases.append(d->sourcesBuildPhase);
+ return phases;
+}
+
+PBXBuildPhase *PBXTarget::defaultFrameworksBuildPhase()
+{
+ return d->frameworksBuildPhase;
+}
+
+PBXBuildPhase *PBXTarget::defaultSourceCodeBuildPhase()
+{
+ return d->sourcesBuildPhase;
+}
+
+QString PBXTarget::comment() const
+{
+ return name();
+}
+
+QByteArray PBXTarget::hashData() const
+{
+ QByteArray hashData = PBXObject::hashData();
+ hashData.append(d->name.toUtf8());
+ return hashData;
+}
+
+PBXFileReference *PBXTarget::productReference() const
+{
+ return d->productReference;
+}
+
+void PBXTarget::setProductReference(PBXFileReference *productReference)
+{
+ d->productReference = productReference;
+}
diff --git a/src/lib/corelib/generators/xcode/pbxtarget.h b/src/lib/corelib/generators/xcode/pbxtarget.h
new file mode 100644
index 0000000..e915481
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxtarget.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef PBXTARGET_H
+#define PBXTARGET_H
+
+#include "pbxobject.h"
+#include "pbxproducttype.h"
+#include <QObject>
+
+class PBXBuildPhase;
+class PBXFileReference;
+class PBXProject;
+class PBXTargetDependency;
+class XCConfigurationList;
+
+class PBXTargetPrivate;
+
+class PBXTarget : public PBXObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(PBXTarget)
+public:
+ explicit PBXTarget(PBXProject *parent = 0);
+ ~PBXTarget();
+
+ PBXObjectMap toMap() const;
+
+ QString name() const;
+ void setName(const QString &name);
+
+ QString productName() const;
+ void setProductName(const QString &productName);
+
+ PBX::PBXProductType productType() const;
+ void setProductType(PBX::PBXProductType productType);
+
+ /*!
+ * File reference to the target's output file.
+ */
+ PBXFileReference *productReference() const;
+ void setProductReference(PBXFileReference *productReference);
+
+ /*!
+ * List of the target's build configurations. This is never NULL.
+ */
+ XCConfigurationList *buildConfigurationList() const;
+
+ QList<PBXTargetDependency *> &targetDependencies() const;
+
+ QString expandedValue(const QString &string, void *buildParameters) const;
+
+ QVariant buildSetting(const QString &key, const QString &buildConfigurationName);
+ void setBuildSetting(const QString &key, const QVariant &value);
+
+ QList<PBXBuildPhase *> buildPhases() const;
+ PBXBuildPhase *buildPhaseOfClass(void *clazz) const;
+ void addBuildPhase(PBXBuildPhase *buildPhase);
+ PBXBuildPhase *defaultFrameworksBuildPhase();
+ PBXBuildPhase *defaultLinkBuildPhase();
+ PBXBuildPhase *defaultSourceCodeBuildPhase();
+ PBXBuildPhase *defaultResourceBuildPhase();
+ PBXBuildPhase *defaultHeaderBuildPhase();
+
+ QString comment() const;
+
+ QByteArray hashData() const;
+
+private:
+ PBXTargetPrivate *d;
+};
+
+#endif // PBXTARGET_H
diff --git a/src/lib/corelib/generators/xcode/pbxtargetdependency.cpp b/src/lib/corelib/generators/xcode/pbxtargetdependency.cpp
new file mode 100644
index 0000000..2eedcd6
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxtargetdependency.cpp
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "pbxcontaineritemproxy.h"
+#include "pbxproject.h"
+#include "pbxtarget.h"
+#include "pbxtargetdependency.h"
+
+class PBXTargetDependencyPrivate
+{
+public:
+ PBXTargetDependencyPrivate();
+ PBXContainerItemProxy *targetProxy;
+};
+
+PBXTargetDependencyPrivate::PBXTargetDependencyPrivate()
+ : targetProxy()
+{
+}
+
+PBXTargetDependency::PBXTargetDependency(PBXProject *parent)
+ : PBXObject(parent), d(new PBXTargetDependencyPrivate)
+{
+ d->targetProxy = new PBXContainerItemProxy(this);
+ d->targetProxy->setContainerPortal(parent);
+}
+
+PBXTargetDependency::~PBXTargetDependency()
+{
+ delete d;
+}
+
+QString PBXTargetDependency::isa() const
+{
+ return QLatin1String("PBXTargetDependency");
+}
+
+PBXObjectMap PBXTargetDependency::toMap() const
+{
+ PBXObjectMap self = PBXObject::toMap();
+ if (d->targetProxy) {
+ self.insert(QLatin1String("targetProxy"), QVariant::fromValue(d->targetProxy->identifier()));
+ if (d->targetProxy->target())
+ self.insert(QLatin1String("target"), QVariant::fromValue(d->targetProxy->target()->identifier()));
+ }
+ return self;
+}
+
+QString PBXTargetDependency::comment() const
+{
+ return PBXObject::comment();
+}
+
+PBXTarget *PBXTargetDependency::target() const
+{
+ return d->targetProxy->target();
+}
+
+void PBXTargetDependency::setTarget(PBXTarget *target)
+{
+ d->targetProxy->setTarget(target);
+}
+
+PBXContainerItemProxy *PBXTargetDependency::targetProxy() const
+{
+ return d->targetProxy;
+}
+
+void PBXTargetDependency::setTargetProxy(PBXContainerItemProxy *targetProxy)
+{
+ d->targetProxy = targetProxy;
+}
diff --git a/src/lib/corelib/generators/xcode/pbxtargetdependency.h b/src/lib/corelib/generators/xcode/pbxtargetdependency.h
new file mode 100644
index 0000000..7a146cb
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/pbxtargetdependency.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef PBXTARGETDEPENDENCY_H
+#define PBXTARGETDEPENDENCY_H
+
+#include "pbxobject.h"
+
+class PBXContainerItemProxy;
+class PBXProject;
+class PBXTarget;
+class PBXTargetDependencyPrivate;
+
+class PBXTargetDependency : public PBXObject
+{
+ Q_OBJECT
+public:
+ explicit PBXTargetDependency(PBXProject *parent = 0);
+ virtual ~PBXTargetDependency();
+
+ QString isa() const;
+ PBXObjectMap toMap() const;
+
+ QString comment() const;
+
+ // http://www.monobjc.net/xcode-project-file-format.html claims
+ // this is a PBXNativeTarget but Xcode says "legacy" (shell script) targets work too...
+ PBXTarget *target() const;
+ void setTarget(PBXTarget *target);
+
+ PBXContainerItemProxy *targetProxy() const;
+ void setTargetProxy(PBXContainerItemProxy *targetProxy);
+
+private:
+ PBXTargetDependencyPrivate *d;
+};
+
+#endif // PBXTARGETDEPENDENCY_H
diff --git a/src/lib/corelib/generators/xcode/xcbuildconfiguration.cpp b/src/lib/corelib/generators/xcode/xcbuildconfiguration.cpp
new file mode 100644
index 0000000..541b503
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/xcbuildconfiguration.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "xcbuildconfiguration.h"
+#include "xcconfigurationlist.h"
+
+class XCBuildConfigurationPrivate
+{
+public:
+ QString name;
+ QVariantMap buildSettings;
+ XCBuildConfiguration *baseConfiguration;
+};
+
+XCBuildConfiguration::XCBuildConfiguration(XCConfigurationList *parent) :
+ PBXObject(parent), d(new XCBuildConfigurationPrivate)
+{
+ d->baseConfiguration = 0;
+}
+
+XCBuildConfiguration::~XCBuildConfiguration()
+{
+ delete d;
+}
+
+QString XCBuildConfiguration::isa() const
+{
+ return QLatin1String("XCBuildConfiguration");
+}
+
+PBXObjectMap XCBuildConfiguration::toMap() const
+{
+ PBXObjectMap self = PBXObject::toMap();
+ if (d->baseConfiguration) {
+ self.insert(QLatin1String("baseConfigurationReference"), QVariant::fromValue(d->baseConfiguration->identifier()));
+ }
+ self.insert(QLatin1String("buildSettings"), d->buildSettings);
+ self.insert(QLatin1String("name"), d->name);
+ return self;
+}
+
+QString XCBuildConfiguration::name() const
+{
+ return d->name;
+}
+
+void XCBuildConfiguration::setName(const QString &name)
+{
+ d->name = name;
+}
+
+QVariant XCBuildConfiguration::buildSetting(const QString &key)
+{
+ return d->buildSettings.value(key);
+}
+
+void XCBuildConfiguration::setBuildSetting(const QString &key, const QVariant &value)
+{
+ d->buildSettings.insert(key, value);
+}
+
+QString XCBuildConfiguration::comment() const
+{
+ return name();
+}
diff --git a/src/lib/corelib/generators/xcode/xcbuildconfiguration.h b/src/lib/corelib/generators/xcode/xcbuildconfiguration.h
new file mode 100644
index 0000000..115a88c
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/xcbuildconfiguration.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef XCBUILDCONFIGURATION_H
+#define XCBUILDCONFIGURATION_H
+
+#include "pbxobject.h"
+#include <QObject>
+
+class PBXFileReference;
+class XCConfigurationList;
+
+class XCBuildConfigurationPrivate;
+
+class XCBuildConfiguration : public PBXObject
+{
+ Q_OBJECT
+public:
+ explicit XCBuildConfiguration(XCConfigurationList *parent = 0);
+ ~XCBuildConfiguration();
+
+ QString isa() const;
+ PBXObjectMap toMap() const;
+
+ QString name() const;
+ void setName(const QString &name);
+
+ static bool isValidBaseConfigurationFile(PBXFileReference *reference);
+
+ void setBaseConfigurationReference(PBXFileReference *reference);
+ PBXFileReference *baseConfigurationReference();
+
+ QVariant buildSetting(const QString &key);
+ void setBuildSetting(const QString &key, const QVariant &value);
+
+ QString comment() const;
+
+private:
+ XCBuildConfigurationPrivate *d;
+};
+
+#endif // XCBUILDCONFIGURATION_H
diff --git a/src/lib/corelib/generators/xcode/xcconfigurationlist.cpp b/src/lib/corelib/generators/xcode/xcconfigurationlist.cpp
new file mode 100644
index 0000000..54d2d39
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/xcconfigurationlist.cpp
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "pbxproject.h"
+#include "pbxtarget.h"
+#include "xcbuildconfiguration.h"
+#include "xcconfigurationlist.h"
+
+class XCConfigurationListPrivate
+{
+public:
+ XCConfigurationListPrivate();
+ QList<XCBuildConfiguration *> buildConfigurations;
+ XCBuildConfiguration *defaultBuildConfiguration;
+};
+
+XCConfigurationListPrivate::XCConfigurationListPrivate()
+ : buildConfigurations(), defaultBuildConfiguration()
+{
+}
+
+XCConfigurationList::XCConfigurationList(PBXObject *parent) :
+ PBXObject(parent), d(new XCConfigurationListPrivate)
+{
+}
+
+XCConfigurationList::~XCConfigurationList()
+{
+ delete d;
+}
+
+QString XCConfigurationList::isa() const
+{
+ return QLatin1String("XCConfigurationList");
+}
+
+PBXObjectMap XCConfigurationList::toMap() const
+{
+ PBXObjectMap self = PBXObject::toMap();
+
+ QVariantList buildConfigurationReferences;
+ foreach (XCBuildConfiguration *configuration, buildConfigurations())
+ buildConfigurationReferences += QVariant::fromValue(configuration->identifier());
+ self.insert(QLatin1String("buildConfigurations"), buildConfigurationReferences);
+
+ if (d->defaultBuildConfiguration)
+ {
+ self.insert(QLatin1String("defaultConfigurationIsVisible"), 0);
+ self.insert(QLatin1String("defaultConfigurationName"), d->defaultBuildConfiguration->name());
+ }
+
+ return self;
+}
+
+QList<XCBuildConfiguration *> XCConfigurationList::buildConfigurations() const
+{
+ return d->buildConfigurations;
+}
+
+XCBuildConfiguration *XCConfigurationList::addBuildConfiguration(const QString &name)
+{
+ foreach (XCBuildConfiguration *config, d->buildConfigurations) {
+ if (config->name() == name)
+ return config;
+ }
+
+ XCBuildConfiguration *buildConfiguration = new XCBuildConfiguration();
+ buildConfiguration->setName(name);
+ d->buildConfigurations.append(buildConfiguration);
+ return buildConfiguration;
+}
+
+void XCConfigurationList::removeBuildConfiguration(const QString &name)
+{
+ for (int i = 0; i < d->buildConfigurations.size(); ++i)
+ {
+ if (d->buildConfigurations[i]->name() == name)
+ {
+ XCBuildConfiguration *configuration = d->buildConfigurations.takeAt(i);
+ if (d->defaultBuildConfiguration == configuration)
+ d->defaultBuildConfiguration = NULL;
+ delete configuration;
+ break;
+ }
+ }
+}
+
+void XCConfigurationList::setDefaultBuildConfiguration(const QString &name)
+{
+ foreach (XCBuildConfiguration *configuration, d->buildConfigurations)
+ {
+ if (configuration->name() == name)
+ {
+ d->defaultBuildConfiguration = configuration;
+ break;
+ }
+ }
+}
+
+QString XCConfigurationList::comment() const
+{
+ QString parentIsa;
+ QString parentName;
+
+ PBXTarget *target = dynamic_cast<PBXTarget *>(parent());
+ PBXProject *project = dynamic_cast<PBXProject *>(parent());
+
+ if (target)
+ {
+ parentIsa = target->isa();
+ parentName = target->name();
+ }
+ else if (project)
+ {
+ parentIsa = project->isa();
+ parentName = project->name();
+ }
+
+ return QString(QLatin1String("Build configuration list for %1 \"%2\"")).arg(parentIsa).arg(parentName);
+}
diff --git a/src/lib/corelib/generators/xcode/xcconfigurationlist.h b/src/lib/corelib/generators/xcode/xcconfigurationlist.h
new file mode 100644
index 0000000..b693478
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/xcconfigurationlist.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef XCCONFIGURATIONLIST_H
+#define XCCONFIGURATIONLIST_H
+
+#include "pbxobject.h"
+#include <QObject>
+
+class XCBuildConfiguration;
+
+class XCConfigurationListPrivate;
+
+class XCConfigurationList : public PBXObject
+{
+ Q_OBJECT
+public:
+ explicit XCConfigurationList(PBXObject *parent = 0);
+ ~XCConfigurationList();
+
+ QString isa() const;
+ PBXObjectMap toMap() const;
+
+ QList<XCBuildConfiguration *> buildConfigurations() const;
+
+ /*!
+ * Adds a build configuration named \p name if one with that name does not already exist.
+ * Returns the new or existing build configuration.
+ */
+ XCBuildConfiguration *addBuildConfiguration(const QString &name);
+ void removeBuildConfiguration(const QString &name);
+ void setDefaultBuildConfiguration(const QString &name);
+
+ QString comment() const;
+
+private:
+ XCConfigurationListPrivate *d;
+};
+
+#endif // XCCONFIGURATIONLIST_H
diff --git a/src/lib/corelib/generators/xcode/xcode.pri b/src/lib/corelib/generators/xcode/xcode.pri
new file mode 100644
index 0000000..76ada9e
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/xcode.pri
@@ -0,0 +1,59 @@
+HEADERS += \
+ $$PWD/opensteppropertylist.h \
+ $$PWD/pbx.h \
+ $$PWD/pbxbuildfile.h \
+ $$PWD/pbxbuildphase.h \
+ $$PWD/pbxcontainer.h \
+ $$PWD/pbxcontaineritemproxy.h \
+ $$PWD/pbxfileencoding.h \
+ $$PWD/pbxfilereference.h \
+ $$PWD/pbxfiletype.h \
+ $$PWD/pbxframeworksbuildphase.h \
+ $$PWD/pbxgroup.h \
+ $$PWD/pbxlegacytarget.h \
+ $$PWD/pbxnativetarget.h \
+ $$PWD/pbxobject.h \
+ $$PWD/pbxproducttype.h \
+ $$PWD/pbxproject.h \
+ $$PWD/pbxreference.h \
+ $$PWD/pbxsourcesbuildphase.h \
+ $$PWD/pbxsourcetree.h \
+ $$PWD/pbxtarget.h \
+ $$PWD/pbxtargetdependency.h \
+ $$PWD/xcbuildconfiguration.h \
+ $$PWD/xcconfigurationlist.h \
+ $$PWD/xcodegenerator.h \
+ $$PWD/xcodenativegenerator.h \
+ $$PWD/xcodesimplegenerator.h \
+ $$PWD/xcscheme.h \
+ $$PWD/xcsettings.h \
+ $$PWD/xcodebuildsettingmapping.h
+
+SOURCES += \
+ $$PWD/opensteppropertylist.cpp \
+ $$PWD/pbxbuildfile.cpp \
+ $$PWD/pbxbuildphase.cpp \
+ $$PWD/pbxcontainer.cpp \
+ $$PWD/pbxcontaineritemproxy.cpp \
+ $$PWD/pbxfilereference.cpp \
+ $$PWD/pbxfiletype.cpp \
+ $$PWD/pbxframeworksbuildphase.cpp \
+ $$PWD/pbxgroup.cpp \
+ $$PWD/pbxlegacytarget.cpp \
+ $$PWD/pbxnativetarget.cpp \
+ $$PWD/pbxobject.cpp \
+ $$PWD/pbxproducttype.cpp \
+ $$PWD/pbxproject.cpp \
+ $$PWD/pbxreference.cpp \
+ $$PWD/pbxsourcesbuildphase.cpp \
+ $$PWD/pbxsourcetree.cpp \
+ $$PWD/pbxtarget.cpp \
+ $$PWD/pbxtargetdependency.cpp \
+ $$PWD/xcbuildconfiguration.cpp \
+ $$PWD/xcconfigurationlist.cpp \
+ $$PWD/xcodegenerator.cpp \
+ $$PWD/xcodenativegenerator.cpp \
+ $$PWD/xcodesimplegenerator.cpp \
+ $$PWD/xcscheme.cpp \
+ $$PWD/xcsettings.cpp \
+ $$PWD/xcodebuildsettingmapping.cpp
diff --git a/src/lib/corelib/generators/xcode/xcodebuildsettingmapping.cpp b/src/lib/corelib/generators/xcode/xcodebuildsettingmapping.cpp
new file mode 100644
index 0000000..458bf8f
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/xcodebuildsettingmapping.cpp
@@ -0,0 +1,366 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "xcodebuildsettingmapping.h"
+#include "xcodegenerator.h"
+
+#include <qbs.h>
+#include "pbx.h"
+
+#include <logging/translator.h>
+
+#include <QDebug>
+
+namespace qbs {
+
+using namespace Internal;
+
+static QVariant _xcodeTargetedDeviceFamily(const Project &project, const ProductData &product, const GroupData &group, const QString &moduleName);
+
+static QVariant xcodeExecutablePrefix(const qbs::Project &project, const ProductData &product, const GroupData &group);
+static QVariant xcodeExecutableSuffix(const qbs::Project &project, const ProductData &product, const GroupData &group);
+static QVariant xcodeInfoPlistOutputEncoding(const qbs::Project &project, const ProductData &product, const GroupData &group);
+static QVariant xcodeArchitecture(const qbs::Project &project, const ProductData &product, const GroupData &group);
+static QVariant xcodePreprocessorDefinitions(const qbs::Project &project, const ProductData &product, const GroupData &group);
+static QVariant xcodeResourcesTargetedDeviceFamily(const Project &project, const ProductData &product, const GroupData &group);
+static QVariant xcodeSdkRoot(const qbs::Project &project, const ProductData &product, const GroupData &group);
+static QVariant xcodeSupportedPlatforms(const qbs::Project &project, const ProductData &product, const GroupData &group);
+static QVariant xcodeTargetedDeviceFamily(const Project &project, const ProductData &product, const GroupData &group);
+static QVariant xcodeDylibVersion(const qbs::Project &project, const ProductData &product, const GroupData &group);
+static QVariant xcodeProductName(const qbs::Project &project, const ProductData &product, const GroupData &group);
+static QVariant xcodeUseHeadermap(const qbs::Project &project, const ProductData &product, const GroupData &group);
+
+static QVariant qbsProjectModuleProperty(const QString &qbsModuleName, const QString &qbsPropertyName, const qbs::Project &project)
+{
+ QMapIterator<QString, QVariant> module(project.projectConfiguration());
+ while (module.hasNext()) {
+ module.next();
+ QString qbsModName = qbsModuleName;
+ if (module.key() == qbsModName.replace(QLatin1String("."), QLatin1String("/"))) {
+ QMapIterator<QString, QVariant> property(module.value().toMap());
+ while (property.hasNext()) {
+ property.next();
+ if (qbsPropertyName == property.key()) {
+ return property.value();
+ }
+ }
+ }
+ }
+
+ return QVariant();
+}
+
+static QVariant qbsModuleProperty(const QString &qbsModuleName, const QString &qbsPropertyName, const qbs::Project &project, const qbs::ProductData &product, const qbs::GroupData &group)
+{
+ if (product.isValid()) {
+ return (group.isValid() ? group.properties() : product.moduleProperties()).getModuleProperty(qbsModuleName, qbsPropertyName);
+ } else {
+ return qbsProjectModuleProperty(qbsModuleName, qbsPropertyName, project);
+ }
+ return QVariant();
+}
+
+static QVariantList qbsModuleProperties(const QString &qbsModuleName, const QString &qbsPropertyName, const qbs::Project &project, const qbs::ProductData &product, const qbs::GroupData &group)
+{
+ if (product.isValid()) {
+ return (group.isValid() ? group.properties() : product.moduleProperties()).getModuleProperties(qbsModuleName, qbsPropertyName);
+ } else {
+ return qbsProjectModuleProperty(qbsModuleName, qbsPropertyName, project).toList();
+ }
+ return QVariantList();
+}
+
+void XcodeBuildSettingMapping::applyToProject(PBXProject *xcodeProject,
+ const qbs::Project &project) const {
+ applyToConfiguration(xcodeProject->buildConfigurationList(), project);
+}
+
+void XcodeBuildSettingMapping::applyToTarget(PBXTarget *xcodeTarget,
+ const qbs::Project &project,
+ const qbs::ProductData &productData,
+ const qbs::GroupData &groupData) const {
+ applyToConfiguration(xcodeTarget->buildConfigurationList(), project, productData, groupData);
+}
+
+void XcodeBuildSettingMapping::applyToConfiguration(XCConfigurationList *xcodeConfigurationList,
+ const Project &project,
+ const ProductData &productData,
+ const GroupData &groupData) const {
+ foreach (XCBuildConfiguration *xcodeConfiguration, xcodeConfigurationList->buildConfigurations())
+ applyToConfiguration(xcodeConfiguration, project, productData, groupData);
+}
+
+void XcodeBuildSettingMapping::applyToConfiguration(XCBuildConfiguration *xcodeConfiguration,
+ const qbs::Project &project,
+ const qbs::ProductData &productData,
+ const qbs::GroupData &groupData) const {
+ QVariant xcodeValue;
+ if (function) {
+ xcodeValue = function(project, productData, groupData);
+ } else if (isList) {
+ QVariantList list;
+
+ foreach (const QString &qbsName, qbsNames) {
+ list << qbsModuleProperties(qbsModule, qbsName, project, productData, groupData);
+ }
+
+ if (!list.isEmpty()) {
+ list.append(QLatin1String("$(inherited)"));
+ xcodeValue = list;
+ }
+ } else {
+ xcodeValue = qbsModuleProperty(qbsModule, qbsNames.first(), project, productData, groupData);
+ }
+
+ // TODO: Figure out what Xcode *really* does... I think it's this
+ bool shouldSerializeAsList = serializedAsList;
+ if (xcodeValue.type() == QVariant::List || xcodeValue.type() == QVariant::StringList) {
+ const QStringList l = xcodeValue.toStringList();
+ if (l.size() <= 1) {
+ shouldSerializeAsList = false; // || containsQuotedStrings ??? lineLength?
+ }
+ }
+
+ if (!shouldSerializeAsList && (xcodeValue.type() == QVariant::List
+ || xcodeValue.type() == QVariant::StringList)) {
+ xcodeValue = xcodeValue.toStringList().join(QLatin1Char(' '));
+ }
+
+ if (!xcodeValue.isNull()) {
+ xcodeValue = XcodeGenerator::xcodeInsertPlaceholdersInValue(project, xcodeValue);
+ xcodeConfiguration->setBuildSetting(xcodeName, xcodeValue);
+ }
+}
+
+/*!
+ * \brief Mapping of Xcode build settings to qbs module and property names or functions.
+ */
+QList<XcodeBuildSettingMapping> XcodeBuildSettingMapping::defaultBuildSettingsMap()
+{
+ const QString cpp = QLatin1String("cpp");
+
+ QList<XcodeBuildSettingMapping> settings;
+ settings += XcodeBuildSettingMapping(QLatin1String("APPLICATION_EXTENSION_API_ONLY"), cpp, QLatin1String("requireAppExtensionSafeApi"));
+ settings += XcodeBuildSettingMapping(QLatin1String("ARCHS"), &xcodeArchitecture, true);
+ settings += XcodeBuildSettingMapping(QLatin1String("CLANG_ENABLE_OBJC_ARC"), cpp, QLatin1String("automaticReferenceCounting"));
+ settings += XcodeBuildSettingMapping(QLatin1String("CREATE_INFOPLIST_SECTION_IN_BINARY"), cpp, QLatin1String("embedInfoPlist"));
+ settings += XcodeBuildSettingMapping(QLatin1String("DYLIB_CURRENT_VERSION"), &xcodeDylibVersion, false);
+ settings += XcodeBuildSettingMapping(QLatin1String("DYLIB_INSTALL_NAME_BASE"), cpp, QLatin1String("installNamePrefix"));
+ settings += XcodeBuildSettingMapping(QLatin1String("EXECUTABLE_EXTENSION"), &xcodeExecutableSuffix, false);
+ settings += XcodeBuildSettingMapping(QLatin1String("EXECUTABLE_PREFIX"), &xcodeExecutablePrefix, false);
+ settings += XcodeBuildSettingMapping(QLatin1String("FRAMEWORK_SEARCH_PATHS"), cpp, QStringList() << QLatin1String("frameworkPaths"));
+ settings += XcodeBuildSettingMapping(QLatin1String("GCC_PREFIX_HEADER"), cpp, QLatin1String("precompiledHeader"));
+ settings += XcodeBuildSettingMapping(QLatin1String("GCC_PREPROCESSOR_DEFINITIONS"), &xcodePreprocessorDefinitions, true);
+ settings += XcodeBuildSettingMapping(QLatin1String("HEADER_SEARCH_PATHS"), cpp, QStringList() << QLatin1String("includePaths"));
+ settings += XcodeBuildSettingMapping(QLatin1String("INFOPLIST_EXPAND_BUILD_SETTINGS"), cpp, QLatin1String("processInfoPlist"));
+ settings += XcodeBuildSettingMapping(QLatin1String("INFOPLIST_FILE"), cpp, QLatin1String("infoPlistFile"));
+ settings += XcodeBuildSettingMapping(QLatin1String("INFOPLIST_OUTPUT_FORMAT"), &xcodeInfoPlistOutputEncoding, false);
+ settings += XcodeBuildSettingMapping(QLatin1String("IPHONEOS_DEPLOYMENT_TARGET"), cpp, QLatin1String("minimumIosVersion"));
+ settings += XcodeBuildSettingMapping(QLatin1String("LD_RUNPATH_SEARCH_PATHS"), cpp, QStringList() << QLatin1String("rpaths"), false);
+ settings += XcodeBuildSettingMapping(QLatin1String("LIBRARY_SEARCH_PATHS"), cpp, QStringList() << QLatin1String("libraryPaths"));
+ settings += XcodeBuildSettingMapping(QLatin1String("MACOSX_DEPLOYMENT_TARGET"), cpp, QLatin1String("minimumOsxVersion"));
+ settings += XcodeBuildSettingMapping(QLatin1String("OTHER_CFLAGS"), cpp, QStringList() << QLatin1String("cFlags") << QLatin1String("objcFlags"));
+ settings += XcodeBuildSettingMapping(QLatin1String("OTHER_CPLUSPLUSFLAGS"), cpp, QStringList() << QLatin1String("cxxFlags") << QLatin1String("objcxxFlags"));
+ settings += XcodeBuildSettingMapping(QLatin1String("OTHER_LDFLAGS"), cpp, QStringList() << QLatin1String("linkerFlags"));
+ settings += XcodeBuildSettingMapping(QLatin1String("PRODUCT_NAME"), &xcodeProductName, false);
+ settings += XcodeBuildSettingMapping(QLatin1String("RESOURCES_TARGETED_DEVICE_FAMILY"), &xcodeResourcesTargetedDeviceFamily, false);
+ settings += XcodeBuildSettingMapping(QLatin1String("SDKROOT"), &xcodeSdkRoot, false);
+ settings += XcodeBuildSettingMapping(QLatin1String("SUPPORTED_PLATFORMS"), &xcodeSupportedPlatforms, false);
+ settings += XcodeBuildSettingMapping(QLatin1String("TARGETED_DEVICE_FAMILY"), &xcodeTargetedDeviceFamily, false);
+ settings += XcodeBuildSettingMapping(QLatin1String("USE_HEADERMAP"), &xcodeUseHeadermap, false);
+ return settings;
+}
+
+QVariant xcodeExecutablePrefix(const Project &project, const ProductData &product, const GroupData &group)
+{
+ switch (XcodeGenerator::xcodeProductType(product))
+ {
+ case PBX::Application:
+ case PBX::Tool:
+ case PBX::Bundle:
+ case PBX::Framework:
+ return qbsModuleProperty(QLatin1String("cpp"), QLatin1String("executablePrefix"), project, product, group).toString();
+ case PBX::LibraryDynamic:
+ return qbsModuleProperty(QLatin1String("cpp"), QLatin1String("dynamicLibraryPrefix"), project, product, group).toString();
+ case PBX::LibraryStatic:
+ return qbsModuleProperty(QLatin1String("cpp"), QLatin1String("staticLibraryPrefix"), project, product, group).toString();
+ default:
+ return QString();
+ }
+}
+
+QVariant xcodeExecutableSuffix(const Project &project, const ProductData &product, const GroupData &group)
+{
+ QString suffix;
+ switch (XcodeGenerator::xcodeProductType(product))
+ {
+ case PBX::Application:
+ case PBX::Tool:
+ case PBX::Bundle:
+ case PBX::Framework:
+ suffix = qbsModuleProperty(QLatin1String("cpp"), QLatin1String("executableSuffix"), project, product, group).toString();
+ break;
+ case PBX::LibraryDynamic:
+ suffix = qbsModuleProperty(QLatin1String("cpp"), QLatin1String("dynamicLibrarySuffix"), project, product, group).toString();
+ break;
+ case PBX::LibraryStatic:
+ suffix = qbsModuleProperty(QLatin1String("cpp"), QLatin1String("staticLibrarySuffix"), project, product, group).toString();
+ break;
+ default:
+ break;
+ }
+
+ if (suffix.startsWith(QChar('.')))
+ suffix.remove(0, 1);
+
+ return suffix;
+}
+
+QVariant xcodeInfoPlistOutputEncoding(const Project &project, const ProductData &product, const GroupData &group)
+{
+ const QString format = qbsModuleProperty(QLatin1String("cpp"), QLatin1String("infoPlistFormat"), project, product, group).toString();
+ if (format == QLatin1String("xml1"))
+ return QLatin1String("XML");
+ else if (format == QLatin1String("binary1"))
+ return QLatin1String("binary");
+
+ // If we don't know what the format is, return the original string (which may be invalid)
+ // "same-as-input" is valid
+ return format;
+}
+
+QVariant xcodeArchitecture(const Project &project, const ProductData &product, const GroupData &group)
+{
+ const QString architecture = qbsModuleProperty(QLatin1String("qbs"), QLatin1String("architecture"), project, product, group).toString();
+ if (architecture == QLatin1String("x86"))
+ return QLatin1String("i386");
+ return architecture;
+}
+
+QVariant xcodePreprocessorDefinitions(const qbs::Project &project, const ProductData &product, const GroupData &group)
+{
+ QStringList defs;
+ Q_FOREACH (const QVariant &def, qbsModuleProperties(QLatin1String("cpp"), QLatin1String("defines"), project, product, group)) {
+ // Preprocessor definitions need to be double escaped since Xcode ignores quoted strings
+ defs.append(def.toString().replace(QLatin1String("\""), QLatin1String("\\\"")));
+ }
+ return defs;
+}
+
+QVariant xcodeSdkRoot(const Project &project, const ProductData &product, const GroupData &group)
+{
+ const QString sdkName = qbsModuleProperty(QLatin1String("cpp"), QLatin1String("xcodeSdkName"), project, product, group).toString();
+ if (!sdkName.isEmpty())
+ return sdkName;
+
+ const QString sysroot = qbsModuleProperty(QLatin1String("qbs"), QLatin1String("sysroot"), project, product, group).toString();
+ if (!sysroot.isEmpty())
+ return sysroot;
+
+ const QVariantList targetOS = qbsModuleProperties(QLatin1String("qbs"), QLatin1String("targetOS"), project, product, group);
+ if (targetOS.contains(QLatin1String("osx")))
+ return QLatin1String("macosx");
+ else if (targetOS.contains(QLatin1String("ios")))
+ return QLatin1String("iphoneos");
+ else
+ throw ErrorInfo(Tr::tr("Unsupported platform for Xcode project"));
+}
+
+QVariant xcodeSupportedPlatforms(const Project &project, const ProductData &product, const GroupData &group)
+{
+ QStringList supportedPlatforms;
+ const QVariantList targetOS = qbsModuleProperties(QLatin1String("qbs"), QLatin1String("targetOS"), project, product, group);
+ if (targetOS.contains(QLatin1String("osx"))) {
+ supportedPlatforms.append(QLatin1String("macosx"));
+ } else if (targetOS.contains(QLatin1String("ios"))) {
+ if (targetOS.contains(QLatin1String("ios-simulator"))) {
+ supportedPlatforms.append(QLatin1String("iphonesimulator"));
+ }
+ supportedPlatforms.append(QLatin1String("iphoneos"));
+ }
+ return supportedPlatforms;
+}
+
+static inline int targetDeviceFamilyIdentifierFromName(const QString &name)
+{
+ if (name == "iphone")
+ return 1;
+ if (name == "ipad")
+ return 2;
+ return 0;
+}
+
+QVariant _xcodeTargetedDeviceFamily(const Project &project, const ProductData &product, const GroupData &group, const QString &moduleName)
+{
+ QStringList targetedDeviceFamily;
+ const QVariantList targetDevices = qbsModuleProperties(moduleName, QLatin1String("targetDevices"), project, product, group);
+ Q_FOREACH (const QVariant &targetDevice, targetDevices) {
+ int devId = targetDeviceFamilyIdentifierFromName(targetDevice.toString());
+ if (devId != 0) {
+ targetedDeviceFamily.append(QString::number(devId));
+ }
+ }
+ return targetedDeviceFamily.join(QLatin1Char(','));
+}
+
+QVariant xcodeResourcesTargetedDeviceFamily(const Project &project, const ProductData &product, const GroupData &group)
+{
+ return _xcodeTargetedDeviceFamily(project, product, group, QLatin1String("ib"));
+}
+
+QVariant xcodeTargetedDeviceFamily(const Project &project, const ProductData &product, const GroupData &group)
+{
+ return _xcodeTargetedDeviceFamily(project, product, group, QLatin1String("xcode"));
+}
+
+QVariant xcodeDylibVersion(const Project &project, const ProductData &product, const GroupData &group)
+{
+ Q_UNUSED(project);
+ Q_UNUSED(group);
+ if (product.type().contains(QLatin1String("dynamiclibrary")))
+ return product.version();
+ return QString();
+}
+
+QVariant xcodeProductName(const Project &project, const ProductData &product, const GroupData &group)
+{
+ Q_UNUSED(project);
+ Q_UNUSED(group);
+ if (!product.targetName().isEmpty())
+ return product.targetName();
+ return product.name();
+}
+
+QVariant xcodeUseHeadermap(const Project &, const ProductData &, const GroupData &)
+{
+ return QVariant(false); // We never want to use headermaps in qbs-generated projects
+}
+
+} // namespace qbs
diff --git a/src/lib/corelib/generators/xcode/xcodebuildsettingmapping.h b/src/lib/corelib/generators/xcode/xcodebuildsettingmapping.h
new file mode 100644
index 0000000..39474fb
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/xcodebuildsettingmapping.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef XCODECONFIGURATIONSETTING_H
+#define XCODECONFIGURATIONSETTING_H
+
+#include <QList>
+#include <QString>
+#include <QVariant>
+
+#include <api/project.h>
+#include <api/projectdata.h>
+
+class PBXProject;
+class PBXTarget;
+class XCBuildConfiguration;
+class XCConfigurationList;
+
+namespace qbs {
+
+/*!
+ * \brief Represents the mapping of an Xcode build setting name to a qbs module and property name.
+ */
+struct XcodeBuildSettingMapping {
+ typedef QVariant (*XcodeBuildSettingValueFunction)(const qbs::Project &project,
+ const qbs::ProductData &productData,
+ const qbs::GroupData &groupData);
+
+ QString xcodeName;
+ QString qbsModule;
+ QStringList qbsNames;
+ bool isList;
+ bool serializedAsList;
+ XcodeBuildSettingValueFunction function; // overrides previous 3
+
+ XcodeBuildSettingMapping(const QString &xcodeName, const QString &qbsModule,
+ const QString &qbsName, bool serializedAsList = false)
+ : xcodeName(xcodeName), qbsModule(qbsModule), qbsNames(qbsName), isList(false),
+ serializedAsList(serializedAsList), function(NULL) {}
+
+ XcodeBuildSettingMapping(const QString &xcodeName, const QString &qbsModule,
+ const QStringList &qbsNames, bool serializedAsList = true)
+ : xcodeName(xcodeName), qbsModule(qbsModule), qbsNames(qbsNames), isList(true),
+ serializedAsList(serializedAsList), function(NULL) {}
+
+ XcodeBuildSettingMapping(const QString &xcodeName, XcodeBuildSettingValueFunction function,
+ bool serializedAsList)
+ : xcodeName(xcodeName), isList(serializedAsList),
+ serializedAsList(serializedAsList), function(function) {}
+
+ void applyToProject(PBXProject *xcodeProject, const Project &project) const;
+ void applyToTarget(PBXTarget *xcodeTarget,
+ const Project &project,
+ const ProductData &productData, const GroupData &groupData) const;
+ void applyToConfiguration(XCConfigurationList *xcodeConfigurationList,
+ const Project &project,
+ const ProductData &productData = ProductData(),
+ const GroupData &groupData = GroupData()) const;
+ void applyToConfiguration(XCBuildConfiguration *xcodeConfiguration,
+ const Project &project,
+ const ProductData &productData = ProductData(),
+ const GroupData &groupData = GroupData()) const;
+
+ static QList<XcodeBuildSettingMapping> defaultBuildSettingsMap();
+};
+
+} // namespace qbs
+
+#endif // XCODECONFIGURATIONSETTING_H
diff --git a/src/lib/corelib/generators/xcode/xcodegenerator.cpp b/src/lib/corelib/generators/xcode/xcodegenerator.cpp
new file mode 100644
index 0000000..4bbcb40
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/xcodegenerator.cpp
@@ -0,0 +1,643 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "xcodebuildsettingmapping.h"
+#include "xcodegenerator.h"
+
+#include <qbs.h>
+#include <logging/logger.h>
+#include <logging/translator.h>
+#include <tools/qbsassert.h>
+#include <tools/shellutils.h>
+#include "pbx.h"
+
+#include <QDebug>
+#include <QDir>
+#include <QTextStream>
+#include <QXmlStreamWriter>
+
+static const QString kQbsRunnerFileName = QLatin1String("qbs");
+
+namespace qbs {
+
+using namespace Internal;
+
+XcodeGenerator::XcodeGenerator()
+{
+}
+
+static QString buildVariant(const qbs::Project &project)
+{
+ return project.projectConfiguration()[QLatin1String("qbs")].toMap()[QLatin1String("buildVariant")].toString();
+}
+
+static QString buildVariant(const qbs::ProductData &product)
+{
+ return product.moduleProperties().getModuleProperty(QLatin1String("qbs"), QLatin1String("buildVariant")).toString();
+}
+
+void XcodeGenerator::setupGenerator()
+{
+ QSet<QString> profileNames;
+ QSet<QString> projectNames;
+ QSet<QString> qbsProjectFiles;
+ QSet<QString> buildDirectories;
+
+ foreach (const qbs::Project &proj, projects()) {
+ profileNames << proj.profile();
+ projectNames << proj.projectData().name();
+ qbsProjectFiles << proj.projectData().location().filePath();
+
+ QDir baseBuildDirectory(proj.projectData().buildDirectory());
+ baseBuildDirectory.cdUp();
+ buildDirectories << baseBuildDirectory.absolutePath();
+ }
+
+ QBS_CHECK(!profileNames.isEmpty());
+ QBS_CHECK(projectNames.size() == 1);
+ QBS_CHECK(qbsProjectFiles.size() == 1);
+ QBS_CHECK(buildDirectories.size() == 1);
+
+ m_multipleProfiles = profileNames.size() > 1;
+ m_projectName = projectNames.toList().first();
+ m_qbsProjectFile = qbsProjectFiles.toList().first();
+ m_baseBuildDirectory = buildDirectories.toList().first();
+
+ QBS_CHECK(m_qbsProjectFile.isAbsolute() && m_qbsProjectFile.exists());
+ QBS_CHECK(m_baseBuildDirectory.isAbsolute() && m_baseBuildDirectory.exists());
+
+ m_productGroups.clear();
+}
+
+static inline TargetArtifact runnableOrPrimaryTargetArtifactForProduct(const qbs::ProductData &qbsProductData) {
+ // Easy in this case...
+ if (qbsProductData.targetArtifacts().size() == 1) {
+ return qbsProductData.targetArtifacts().first();
+ }
+
+ const QStringList types = QStringList()
+ << QLatin1String("bundle")
+ << QLatin1String("application")
+ << QLatin1String("dynamiclibrary")
+ << QLatin1String("staticlibrary")
+ << QLatin1String("loadablemodule");
+
+ Q_FOREACH (const TargetArtifact &ta, qbsProductData.targetArtifacts()) {
+ Q_FOREACH (const QString &type, types) {
+ if (qbsProductData.type().contains(type)
+ && ta.fileTags().contains(type)) {
+ return ta;
+ }
+ }
+ }
+
+ return TargetArtifact();
+}
+
+static inline QString installedFilePathForTargetArtifact(const qbs::Project &project,
+ const qbs::ProductData &product,
+ const qbs::InstallOptions &installOptions,
+ const TargetArtifact &ta) {
+ const QList<InstallableFile> &installables
+ = project.installableFilesForProduct(product, installOptions);
+ foreach (const InstallableFile &file, installables) {
+ if (file.sourceFilePath() == ta.filePath())
+ return file.targetFilePath();
+ }
+ return ta.filePath();
+}
+
+void XcodeGenerator::generate(const InstallOptions &installOptions)
+{
+ // TODO: Move to base class and call ProjectGenerator::setupGenerator()
+ setupGenerator();
+
+ const QString xcodeWrapperName = m_projectName + QLatin1String(".xcodeproj");
+ if (!m_baseBuildDirectory.cd(xcodeWrapperName))
+ if (!m_baseBuildDirectory.mkdir(xcodeWrapperName) || !m_baseBuildDirectory.cd(xcodeWrapperName))
+ throw ErrorInfo(Tr::tr("failed to make Xcode project wrapper directory"));
+
+ const QString xcodeWorkspaceWrapperName = QLatin1String("project.xcworkspace");
+ const QString sharedWorkspaceDataDirName = QLatin1String("xcshareddata");
+
+ QDir sharedWorkspaceDataDir = m_baseBuildDirectory;
+ if (!sharedWorkspaceDataDir.cd(xcodeWorkspaceWrapperName))
+ if (!sharedWorkspaceDataDir.mkdir(xcodeWorkspaceWrapperName) || !sharedWorkspaceDataDir.cd(xcodeWorkspaceWrapperName))
+ throw ErrorInfo(Tr::tr("failed to make Xcode workspace wrapper directory"));
+
+ if (!sharedWorkspaceDataDir.cd(sharedWorkspaceDataDirName))
+ if (!sharedWorkspaceDataDir.mkdir(sharedWorkspaceDataDirName) || !sharedWorkspaceDataDir.cd(sharedWorkspaceDataDirName))
+ throw ErrorInfo(Tr::tr("failed to make Xcode workspace shared data directory"));
+
+ const QString sharedWorkspaceSettingsFilePath = sharedWorkspaceDataDir.absoluteFilePath(QLatin1String("WorkspaceSettings.xcsettings"));
+ XCSettings sharedWorkspaceSettings;
+ sharedWorkspaceSettings.setAutocreateSchemes(false);
+ if (!sharedWorkspaceSettings.serialize(sharedWorkspaceSettingsFilePath)) {
+ throw ErrorInfo(Tr::tr("Failed to generate workspace settings %1").arg(sharedWorkspaceSettingsFilePath));
+ }
+
+ // Create a shell script to invoke the qbs binary
+ // This is necessary because qbs hangs when invoked directly from Xcode
+ // TODO: Why?
+ const QString &qbsRunnerFilePath = m_baseBuildDirectory.absoluteFilePath(kQbsRunnerFileName);
+ QFile qbsRunner(qbsRunnerFilePath);
+ if (qbsRunner.open(QIODevice::WriteOnly)) {
+ // The runner script, in addition to invoking qbs itself,
+ // adds symlinks from the Xcode target directory to the qbs build directory
+ // This way, products in the Xcode files listing show up properly
+ QTextStream ts(&qbsRunner);
+ ts << QLatin1String("#!/bin/bash\n")
+ << QLatin1String("set -e\n")
+ << QLatin1String("[ -x \"$QBS\" ] || exit 1\n")
+ << QLatin1String("\"$QBS\" \"$@\"\n")
+ << QLatin1String("if [ ! -e \"$TARGET_BUILD_DIR/$PRODUCT_NAME/$FULL_PRODUCT_NAME\" ] && [ -e \"$QBS_TARGET_PATH\" ] ; then\n")
+ << QLatin1String("mkdir -p \"$TARGET_BUILD_DIR/$PRODUCT_NAME\"\n")
+ << QLatin1String("ln -sf \"$QBS_TARGET_PATH\" \"$TARGET_BUILD_DIR/$PRODUCT_NAME/$FULL_PRODUCT_NAME\"\n")
+ << QLatin1String("fi\n");
+ }
+
+ PBXProject xcodeProject(m_baseBuildDirectory.absoluteFilePath(QLatin1String("project.pbxproj")));
+ xcodeProject.setName(m_projectName);
+
+ // Only potentially add absolute paths if the qbs source directory and build directory differ;
+ // this makes the Xcode project file relocatable (and thus version trackable) if generated in-source
+ const QString qbsSourceDirectory = m_qbsProjectFile.absolutePath();
+ if (m_baseBuildDirectory.absolutePath() != qbsSourceDirectory) {
+ // TODO: Make it relative anyways
+ xcodeProject.setProjectDirPath(qbsSourceDirectory);
+ xcodeProject.rootGroup()->setPath(xcodeProject.projectDirPath());
+ }
+
+ foreach (const qbs::Project &project, projects()) {
+ XCBuildConfiguration *xcconfig = xcodeProject.buildConfigurationList()->addBuildConfiguration(xcodeConfigurationName(project));
+ xcodeProject.buildConfigurationList()->setDefaultBuildConfiguration(xcconfig->name());
+
+ // TODO: Ideally should go into a configuration file instead of in the project file itself
+ // TODO: Is there a better way to find the qbs binary to invoke? For example, someone could use libqbscore to invoke generators...
+ xcconfig->setBuildSetting(QLatin1String("QBS"), QCoreApplication::applicationFilePath());
+ xcconfig->setBuildSetting(QLatin1String("QBS_PROFILE"), project.profile());
+ xcconfig->setBuildSetting(QLatin1String("QBS_PROJECT_DIRECTORY"), xcodeInsertPlaceholdersInValue(project, qbsSourceDirectory));
+ xcconfig->setBuildSetting(QLatin1String("QBS_PROJECT_FILE_NAME"), m_qbsProjectFile.fileName());
+
+ // or baseBuildDirectory + profileName + '-' + buildVariant
+ xcconfig->setBuildSetting(QLatin1String("__QBS_BASE_BUILD_DIRECTORY"), QLatin1String("$(PROJECT_FILE_PATH)/.."));
+ xcconfig->setBuildSetting(QLatin1String("QBS_BUILD_DIRECTORY"), QLatin1String("$(__QBS_BASE_BUILD_DIRECTORY:standardizepath)"));
+
+ xcconfig->setBuildSetting(QLatin1String("QBS_BUILD_VARIANT"), buildVariant(project));
+
+ foreach (const XcodeBuildSettingMapping &setting, XcodeBuildSettingMapping::defaultBuildSettingsMap()) {
+ setting.applyToConfiguration(xcconfig, project);
+ }
+
+ // Add all the Qbs products as Xcode targets
+ addProjectRecursive(project, project.projectData(), installOptions, xcodeProject, xcodeProject.rootGroup());
+
+ // Do some per-target ops
+ foreach (const qbs::ProductData &qbsProductData, project.projectData().allProducts()) {
+ PBXTarget *qbsXcodeTarget = xcodeProject.targetNamed(qbsProductData.name());
+ if (!qbsXcodeTarget)
+ throw new qbs::ErrorInfo(Tr::tr("could not find PBXTarget for qbs product '%1'").arg(qbsProductData.name()));
+
+ // Set up target dependencies
+ foreach (const QString &dependencyName, qbsProductData.dependencies()) {
+ PBXTargetDependency *dependentXcodeTarget = new PBXTargetDependency(&xcodeProject);
+ dependentXcodeTarget->setTarget(xcodeProject.targetNamed(dependencyName));
+ if (!dependentXcodeTarget->target())
+ throw new qbs::ErrorInfo(Tr::tr("could not find PBXTarget for qbs product '%1'").arg(dependencyName));
+
+ qbsXcodeTarget->targetDependencies().append(dependentXcodeTarget);
+ }
+
+ // Set up a scheme for the target
+ static const QString xcshareddata = QLatin1String("xcshareddata");
+ static const QString xcschemes = QLatin1String("xcschemes");
+ QDir schemesDirectory(m_baseBuildDirectory);
+ if (!schemesDirectory.cd(xcshareddata)) {
+ if (!schemesDirectory.mkdir(xcshareddata) || !schemesDirectory.cd(xcshareddata)) {
+ throw ErrorInfo(Tr::tr("failed to make Xcode project shared data directory"));
+ }
+ }
+ if (!schemesDirectory.cd(xcschemes)) {
+ if (!schemesDirectory.mkdir(xcschemes) || !schemesDirectory.cd(xcschemes)) {
+ throw ErrorInfo(Tr::tr("failed to make Xcode project shared schemes directory"));
+ }
+ }
+
+ const QString schemeFilePath(schemesDirectory.absoluteFilePath(QString(QLatin1String("%1.xcscheme")).arg(qbsXcodeTarget->name())));
+ XCScheme xcscheme;
+ xcscheme.setParallelizeBuildables(false); // this must be turned off because it conflicts with qbs build directory locking
+ xcscheme.setProject(&xcodeProject);
+ xcscheme.setTarget(qbsXcodeTarget);
+
+ if (dynamic_cast<PBXLegacyTarget *>(qbsXcodeTarget)) {
+ xcscheme.setCustomExecutableFilePath(installedFilePathForTargetArtifact(project, qbsProductData, installOptions, runnableOrPrimaryTargetArtifactForProduct(qbsProductData)));
+ }
+
+ if (!xcscheme.serialize(schemeFilePath)) {
+ throw ErrorInfo(Tr::tr("Failed to generate scheme %1").arg(schemeFilePath));
+ }
+ }
+ }
+
+ if (xcodeProject.writeToFileSystemProjectFile(true, true, true))
+ qDebug() << "Generated" << qPrintable(xcodeWrapperName);
+ else
+ throw ErrorInfo(Tr::tr("Failed to generate %1").arg(xcodeWrapperName));
+}
+
+QString makePathRelativeTo(const QString &path, const QString &basePath)
+{
+ QString rootPath(basePath);
+ if (!rootPath.endsWith(QLatin1Char('/')))
+ rootPath += QLatin1Char('/');
+
+ QString filePath(path);
+ if (filePath.startsWith(rootPath))
+ filePath.remove(0, rootPath.size());
+
+ return filePath;
+}
+
+void XcodeGenerator::addProjectRecursive(const Project &project, const ProjectData &projectData, const InstallOptions &installOptions, PBXProject &xcodeProject, PBXGroup *xcodeGroup)
+{
+ foreach (const ProjectData &subProjectData, projectData.subProjects())
+ {
+ PBXGroup *baseGroup = PBXGroup::groupWithName(subProjectData.name(), xcodeGroup);
+ baseGroup->setSourceTree(PBX::Group);
+
+ // Add the qbs project file for this project
+ foreach (PBXFileReference *ref, baseGroup->addFiles(QStringList() << makePathRelativeTo(m_qbsProjectFile.absoluteFilePath(), xcodeProject.projectDirPath()), false, false)) {
+ if (!ref->path().startsWith(QLatin1Char('/'))) {
+ ref->setSourceTree(PBX::Group);
+ }
+ }
+
+ addProjectRecursive(project, subProjectData, installOptions, xcodeProject, baseGroup);
+ }
+
+ foreach (const ProductData &product, projectData.products())
+ {
+ addProduct(project, product, installOptions, xcodeProject, xcodeGroup);
+ }
+}
+
+static inline QVariant flattenXcconfigList(const QStringList &list) {
+ if (list.isEmpty())
+ return QString();
+ if (list.size() == 1)
+ return list.first();
+ return list;
+}
+
+void XcodeGenerator::addProduct(const Project &project, const ProductData &product, const InstallOptions &installOptions, PBXProject &xcodeProject, PBXGroup *xcodeGroup)
+{
+ PBXTarget *xcodeTarget = xcodeTargetForProduct(&xcodeProject, product);
+ xcodeTarget->setName(product.name());
+ xcodeTarget->setProductType(xcodeProductType(product));
+
+ PBXLegacyTarget *xcodeLegacyTarget = dynamic_cast<PBXLegacyTarget *>(xcodeTarget);
+ if (xcodeLegacyTarget) {
+ xcodeLegacyTarget->setBuildWorkingDirectory(XcodeGenerator::xcodeInsertPlaceholdersInValue(project, xcodeProject.projectDirPath()).toString());
+ xcodeLegacyTarget->setBuildToolPath(QLatin1String("/bin/bash"));
+
+ QStringList buildArguments;
+ buildArguments << QLatin1String("\"$(PROJECT_FILE_PATH)\"/") + kQbsRunnerFileName;
+ buildArguments << QLatin1String("\"$(ACTION)\"");
+ buildArguments << QLatin1String("-f");
+
+ // Can't use xcodeInsertPlaceholdersInValue because we want to do a little acrobatics to get quoting 100% right...
+ const QDir sourceDirectory(xcodeProject.projectDirPath());
+ QString resultingFilePath = m_qbsProjectFile.absoluteFilePath();
+ if (resultingFilePath.startsWith(sourceDirectory.absolutePath())) {
+ resultingFilePath.replace(0, sourceDirectory.absolutePath().size(), QString());
+ buildArguments << QLatin1String("\"$(SRCROOT)\"") + shellQuote(resultingFilePath);
+ } else {
+ buildArguments << shellQuote(resultingFilePath);
+ }
+
+ buildArguments << QLatin1String("-d");
+ buildArguments << QLatin1String("\"$(CONFIGURATION_BUILD_DIR)\"");
+ buildArguments << QLatin1String("-p");
+ buildArguments << QLatin1String("\"$(TARGET_NAME)\""); // target and product name are opposites in qbs and Xcode
+ buildArguments << QLatin1String("\"$(QBS_BUILD_VARIANT)\"");
+ buildArguments << QLatin1String("\"profile:$(QBS_PROFILE)\"");
+
+ xcodeLegacyTarget->setBuildArgumentsString(buildArguments.join(QLatin1String(" ")));
+ xcodeLegacyTarget->setPassBuildSettingsInEnvironment(true);
+ }
+
+ XCBuildConfiguration *xcconfig = xcodeTarget->buildConfigurationList()->addBuildConfiguration(xcodeConfigurationName(product));
+ xcodeTarget->buildConfigurationList()->setDefaultBuildConfiguration(xcconfig->name());
+
+ // TODO: If a product with the same name was already added, don't add its files AGAIN
+ // Create a root PBX group for the target's files and other groups
+ PBXGroup *xcodeProductGroup = m_productGroups.value(product.name());
+ const bool productFilesAlreadyAdded = !!xcodeProductGroup;
+ if (!productFilesAlreadyAdded) {
+ m_productGroups.insert(product.name(), xcodeProductGroup = PBXGroup::groupWithName(product.name(), xcodeGroup));
+
+ // Add the qbs project file for this product
+ foreach (PBXFileReference *ref, xcodeProductGroup->addFiles(QStringList() << makePathRelativeTo(product.location().filePath(), xcodeProject.projectDirPath()), false, false)) {
+ if (!ref->path().startsWith(QLatin1Char('/'))) {
+ ref->setSourceTree(PBX::Group);
+ }
+ }
+ }
+
+ QSet<QString> excludedSources;
+
+ // Set up all the groups
+ foreach (const GroupData &groupData, product.groups())
+ {
+ PBXGroup *group = xcodeProductGroup;
+ if (groupData.name() == product.name()) {
+ // This group has the same name as the product itself so we'll just add the files
+ // directly to the "product" group we created earlier instead of creating a new one
+ foreach (const XcodeBuildSettingMapping &setting, XcodeBuildSettingMapping::defaultBuildSettingsMap()) {
+ setting.applyToConfiguration(xcconfig, project, product, groupData);
+ }
+
+ xcodeTarget->setProductName(xcodeTarget->buildSetting(QLatin1String("PRODUCT_NAME"), buildVariant(product)).toString());
+ xcconfig->setBuildSetting(QLatin1String("QBS_PROFILE"), product.profile());
+ xcconfig->setBuildSetting(QLatin1String("QBS_BUILD_VARIANT"), buildVariant(product));
+ } else {
+ // Create a group for this group
+ group = PBXGroup::groupWithName(groupData.name(), xcodeProductGroup);
+ }
+
+ // Add the source files to the group
+ group->setSourceTree(PBX::Group);
+ QList<PBXFileReference *> fileRefs;
+ if (!productFilesAlreadyAdded)
+ fileRefs = addGroupFiles(&xcodeProject, group, groupData);
+
+ // If the group is enabled, then we'll actually BUILD them in addition to merely listing them
+ if (groupData.isEnabled()) {
+ foreach (PBXFileReference *ref, fileRefs) {
+ // Skip header files... wish there was a better way
+ if (ref->path().endsWith(QLatin1String(".h")) ||
+ ref->path().endsWith(QLatin1String(".hh"))) {
+ continue;
+ }
+
+ xcodeTarget->defaultSourceCodeBuildPhase()->addReference(ref);
+ }
+ } else {
+ foreach (PBXFileReference *ref, fileRefs)
+ excludedSources.insert(ref->path());
+ }
+ }
+
+ xcconfig->setBuildSetting(QLatin1String("EXCLUDED_SOURCE_FILE_NAMES"), flattenXcconfigList(QStringList(excludedSources.toList())));
+
+ QString sysroot = product.moduleProperties().getModuleProperty(QLatin1String("cpp"), QLatin1String("sysroot")).toString();
+ QStringList frameworkPaths;
+ frameworkPaths += product.moduleProperties().getModulePropertiesAsStringList(QLatin1String("cpp"), QLatin1String("frameworkPaths"));
+ frameworkPaths += product.moduleProperties().getModulePropertiesAsStringList(QLatin1String("cpp"), QLatin1String("systemFrameworkPaths"));
+ frameworkPaths += sysroot + QLatin1String("/Library/Frameworks");
+ frameworkPaths += sysroot + QLatin1String("/System/Library/Frameworks");
+ frameworkPaths += QLatin1String("/Library/Frameworks");
+ frameworkPaths += QLatin1String("/System/Library/Frameworks");
+ const QStringList frameworkNames = product.moduleProperties().getModulePropertiesAsStringList(QLatin1String("cpp"), QLatin1String("frameworks"));
+ const QStringList weakFrameworkNames = product.moduleProperties().getModulePropertiesAsStringList(QLatin1String("cpp"), QLatin1String("weakFrameworks"));
+
+ // TODO TODO TODO dynamicLibraries and weakDynamicLibraries?
+
+ // A framework can't be strongly AND weakly linked... TODO: fail more gracefully
+ QBS_CHECK(frameworkNames.toSet().intersect(weakFrameworkNames.toSet()).isEmpty());
+ const QStringList allFrameworkNames = QStringList() << frameworkNames << weakFrameworkNames;
+
+ Q_FOREACH (const QString &frameworkName, allFrameworkNames) {
+ // Whether a full path equivalent for the framework was found
+ bool foundFramework = false;
+
+ Q_FOREACH (const QString &frameworkPath, frameworkPaths) {
+ QString candidateFrameworkPath = QFileInfo(frameworkPath + QLatin1String("/") + frameworkName + QLatin1String(".framework")).canonicalFilePath();
+ if (QFileInfo(candidateFrameworkPath).exists()) {
+ QBS_CHECK(!candidateFrameworkPath.isEmpty());
+
+ const QString sysrootedCandidateFrameworkPath = candidateFrameworkPath.mid(sysroot.size() + 1 /* for the path separator */);
+
+ // Check for an existing reference (could happen if a framework is specified multiple times)
+ PBXFileReference *existingReference = Q_NULLPTR;
+ Q_FOREACH (PBXReference *ref, xcodeProject.frameworksRefGroup()->children()) {
+ if (PBXFileReference *fileRef = dynamic_cast<PBXFileReference *>(ref)) {
+ if ((fileRef->sourceTree() == PBX::SdkRoot && fileRef->path() == sysrootedCandidateFrameworkPath) ||
+ (fileRef->sourceTree() == PBX::Absolute && fileRef->path() == candidateFrameworkPath)) {
+ existingReference = fileRef;
+ break;
+ }
+ }
+ }
+
+ QList<PBXFileReference *> refs;
+
+ // Create a new file reference since one wasn't already found in the Frameworks group
+ if (!existingReference) {
+ refs = xcodeProject.frameworksRefGroup()->addFiles(QStringList() << candidateFrameworkPath, false, false);
+ Q_FOREACH (PBXFileReference *frameworkRef, refs) {
+ if (!sysroot.isEmpty() && frameworkRef->path().startsWith(sysroot)) {
+ frameworkRef->setPath(sysrootedCandidateFrameworkPath);
+ frameworkRef->setSourceTree(PBX::SdkRoot);
+ }
+ }
+ } else {
+ refs.append(existingReference);
+ }
+
+ // Add the framework to the Frameworks build phase
+ Q_FOREACH (PBXFileReference *frameworkRef, refs) {
+ xcodeTarget->defaultFrameworksBuildPhase()->addReference(frameworkRef);
+ }
+
+ foundFramework = true;
+ break;
+ }
+ }
+
+ // Not a normal case, and will cause a build failure, but is better than silently ignoring it...
+ if (!foundFramework) {
+ Q_FOREACH (PBXFileReference *frameworkRef, xcodeProject.frameworksRefGroup()->addFiles(QStringList() << frameworkName + QLatin1String(".framework"), false, false)) {
+ QBS_CHECK(!frameworkRef->path().isEmpty());
+ if (PBXBuildFile *frameworkBuildRef = xcodeTarget->defaultFrameworksBuildPhase()->addReference(frameworkRef)) {
+ const bool isWeaklyLinked = weakFrameworkNames.contains(frameworkName);
+ frameworkBuildRef->setWeakLinkedLibrary(isWeaklyLinked);
+ }
+ }
+ }
+ }
+
+ // Add a reference for the main target artifact in root "Products" group
+ TargetArtifact artifact = runnableOrPrimaryTargetArtifactForProduct(product);
+ QString realArtifactPath = installedFilePathForTargetArtifact(project, product, installOptions, artifact);
+ if (!realArtifactPath.isEmpty()) {
+ // "simple" generator
+ if (!xcodeLegacyTarget) {
+ // Chop off the Qbs build dir from the artifact path, because they will actually end
+ // up in Xcode's build directory, not the build directory Qbs would use
+ const QString buildDirectory = project.projectData().buildDirectory();
+ if (realArtifactPath.startsWith(buildDirectory))
+ realArtifactPath.remove(0, buildDirectory.size());
+
+ if (realArtifactPath.startsWith(QLatin1Char('/')))
+ realArtifactPath.remove(0, 1);
+ } else {
+ realArtifactPath = xcodeInsertPlaceholdersInValue(project, realArtifactPath).toString();
+ }
+
+ QBS_CHECK(!realArtifactPath.isEmpty());
+
+ QList<PBXFileReference *> refs = xcodeProject.productRefGroup()->addFiles(QStringList() << realArtifactPath, false, false);
+ foreach (PBXFileReference *ref, refs)
+ {
+ if (!xcodeLegacyTarget) {
+ ref->setSourceTree(PBX::BuildProductDir);
+
+ // This causes Xcode to force the file reference to a relative path relative to the build products dir
+ // Therefore, we must symlink artifacts in the Xcode build directory to the ones in the qbs build directory
+ // NOTE: This will crash Xcode if set for a PBXLegacyTarget (claiming an empty string global hex ID)
+ xcodeTarget->setProductReference(ref);
+ }
+
+ // TODO: Technically this should be composed of other variables based on the product type
+ // $(WRAPPER_NAME) for bundles, $(EXECUTABLE_NAME) otherwise?
+ xcconfig->setBuildSetting(QLatin1String("FULL_PRODUCT_NAME"), QFileInfo(realArtifactPath).fileName());
+ xcconfig->setBuildSetting(QLatin1String("QBS_TARGET_PATH"), xcodeInsertPlaceholdersInValue(project, realArtifactPath));
+ }
+ }
+
+ xcodeProject.addTarget(xcodeTarget);
+}
+
+QList<PBXFileReference *> XcodeGenerator::addGroupFiles(PBXProject *xcodeProject, PBXGroup *xcodeGroup, const qbs::GroupData &groupData)
+{
+ QStringList relativeFilePaths;
+ foreach (QString filePath, groupData.allFilePaths()) {
+ relativeFilePaths += makePathRelativeTo(filePath, xcodeProject->projectDirPath());
+ }
+
+ // Add all the files in the group as file references so they show up in the project tree
+ QList<PBXFileReference *> fileRefs = xcodeGroup->addFiles(relativeFilePaths, false, false);
+ foreach (PBXFileReference *ref, fileRefs) {
+ if (!ref->path().startsWith(QLatin1Char('/'))) {
+ ref->setSourceTree(PBX::Group);
+ }
+ }
+
+ return fileRefs;
+}
+
+PBXTarget *XcodeGenerator::xcodeTargetForProduct(PBXProject *xcodeProject, const ProductData &product)
+{
+ Q_UNUSED(xcodeProject);
+ PBXTarget *target = xcodeProject->targetNamed(product.name());
+
+ // Native targets without a type won't build, so use a legacy target in this case
+ if (!target && xcodeProductType(product) == 0) {
+ return new PBXLegacyTarget(xcodeProject);
+ }
+
+ return target;
+}
+
+/*!
+ * Returns the Xcode product type identifier corresponding to the Qbs product type name.
+ */
+PBX::PBXProductType XcodeGenerator::xcodeProductType(const ProductData &product)
+{
+ const QStringList productType = product.type();
+ const bool isBundle = product.moduleProperties().getModuleProperty(QLatin1String("bundle"), QLatin1String("isBundle")).toBool();
+
+ if (productType.contains(QLatin1String("application")))
+ return isBundle ? PBX::Application : PBX::Tool;
+ if (productType.contains(QLatin1String("dynamiclibrary")))
+ return isBundle ? PBX::Framework : PBX::LibraryDynamic;
+ if (productType.contains(QLatin1String("staticlibrary")))
+ return isBundle ? PBX::StaticFramework : PBX::LibraryStatic;
+ if (productType.contains(QLatin1String("bundle")))
+ return PBX::Bundle;
+
+ return (PBX::PBXProductType)0;
+}
+
+static QString _xcodeConfigurationName(QString variantName, const QString &profileName, bool includeProfileName)
+{
+ QBS_CHECK(!variantName.isEmpty());
+ variantName.replace(0, 1, variantName[0].toUpper());
+ if (includeProfileName) {
+ variantName += QLatin1String("_") + profileName;
+ }
+ return variantName;
+}
+
+QString XcodeGenerator::xcodeConfigurationName(const Project &project)
+{
+ return _xcodeConfigurationName(buildVariant(project), project.profile(), m_multipleProfiles);
+}
+
+QString XcodeGenerator::xcodeConfigurationName(const ProductData &product)
+{
+ return _xcodeConfigurationName(buildVariant(product), product.profile(), m_multipleProfiles);
+}
+
+/*!
+ * \brief If the value is a path or list of paths,
+ * returns it with the prefixes of paths replaced by $(SRCROOT), $(PROJECT_FILE_PATH)/.., etc.,
+ * as appropriate.
+ * If the value is not a path, returns the original value unmodified.
+ */
+QVariant XcodeGenerator::xcodeInsertPlaceholdersInValue(const qbs::Project &project, const QVariant &variant)
+{
+ if (variant.type() == QVariant::List) {
+ QVariantList list;
+ foreach (const QVariant &v, variant.toList())
+ list.append(xcodeInsertPlaceholdersInValue(project, v));
+ return list;
+ }
+
+ // If the value is a path and it begins with the value of SRCROOT or PROJECT_FILE_PATH/.., replace it
+ if (variant.type() == QVariant::String) {
+ // This should end up being the same as PBXProject::projectDirPath(), but if projectDirPath
+ // is the empty string (for example, when the xcodeproj resides in the qbs source directory,
+ // things would break, so prefer the Qbs value (plus, it saves a parameter to this function)
+ const QDir sourceDirectory = QFileInfo(project.projectData().location().filePath()).absolutePath();
+ if (variant.toString().startsWith(sourceDirectory.absolutePath()))
+ return variant.toString().replace(0, sourceDirectory.absolutePath().size(), QLatin1String("$(SRCROOT)"));
+
+ const QDir buildDirectory(project.projectData().buildDirectory());
+ Q_ASSERT(buildDirectory.isAbsolute() && buildDirectory.exists());
+ if (variant.toString().startsWith(buildDirectory.absolutePath()))
+ return variant.toString().replace(0, buildDirectory.absolutePath().size(), QLatin1String("$(QBS_BUILD_DIRECTORY)/$(QBS_PROFILE)-$(QBS_BUILD_VARIANT)"));
+ }
+
+ return variant;
+}
+
+}
diff --git a/src/lib/corelib/generators/xcode/xcodegenerator.h b/src/lib/corelib/generators/xcode/xcodegenerator.h
new file mode 100644
index 0000000..765174a
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/xcodegenerator.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_XCODEGENERATOR_H
+#define QBS_XCODEGENERATOR_H
+
+#include <api/projectdata.h>
+#include <generators/generator.h>
+#include "pbxproducttype.h"
+
+#include <QDir>
+
+class PBXFileReference;
+class PBXGroup;
+class PBXProject;
+class PBXTarget;
+
+namespace qbs {
+
+class ProductData;
+struct XcodeBuildSettingMapping;
+
+class XcodeGenerator : public qbs::ProjectGenerator
+{
+public:
+ virtual void generate(const InstallOptions &installOptions);
+ virtual void addProjectRecursive(const Project &project, const ProjectData &projectData, const InstallOptions &installOptions, PBXProject &xcodeProject, PBXGroup *xcodeGroup);
+ virtual void addProduct(const Project &project, const ProductData &product, const InstallOptions &installOptions, PBXProject &xcodeProject, PBXGroup *xcodeGroup);
+ virtual QList<PBXFileReference *> addGroupFiles(PBXProject *xcodeProject, PBXGroup *xcodeGroup, const qbs::GroupData &groupData);
+
+ virtual PBXTarget *xcodeTargetForProduct(PBXProject *xcodeProject, const ProductData &product);
+
+ QString xcodeConfigurationName(const Project &project);
+ QString xcodeConfigurationName(const ProductData &product);
+
+ static QVariant xcodeInsertPlaceholdersInValue(const qbs::Project &project, const QVariant &variant);
+
+ static PBX::PBXProductType xcodeProductType(const ProductData &product);
+
+protected:
+ XcodeGenerator();
+
+ // TODO: Move to base class
+ virtual void setupGenerator();
+ bool m_multipleProfiles;
+ QString m_projectName;
+ QFileInfo m_qbsProjectFile;
+ QDir m_baseBuildDirectory;
+ QMap<QString, PBXGroup*> m_productGroups;
+};
+
+}
+
+#endif // QBS_XCODEGENERATOR_H
diff --git a/src/lib/corelib/generators/xcode/xcodenativegenerator.cpp b/src/lib/corelib/generators/xcode/xcodenativegenerator.cpp
new file mode 100644
index 0000000..7654b8f
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/xcodenativegenerator.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "xcodenativegenerator.h"
+
+#include "pbx.h"
+
+namespace qbs {
+
+using namespace Internal;
+
+XcodeNativeGenerator::XcodeNativeGenerator()
+{
+}
+
+QString XcodeNativeGenerator::generatorName() const
+{
+ return QLatin1String("xcode");
+}
+
+void XcodeNativeGenerator::generate(const InstallOptions &installOptions)
+{
+ XcodeGenerator::generate(installOptions);
+}
+
+PBXTarget *XcodeNativeGenerator::xcodeTargetForProduct(PBXProject *xcodeProject, const ProductData &product)
+{
+ return XcodeGenerator::xcodeTargetForProduct(xcodeProject, product) ?: new PBXLegacyTarget(xcodeProject);
+}
+
+}
diff --git a/src/lib/corelib/generators/xcode/xcodenativegenerator.h b/src/lib/corelib/generators/xcode/xcodenativegenerator.h
new file mode 100644
index 0000000..a04f8df
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/xcodenativegenerator.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_XCODENATIVEGENERATOR_H
+#define QBS_XCODENATIVEGENERATOR_H
+
+#include "xcodegenerator.h"
+#include <QString>
+
+namespace qbs {
+
+class XcodeNativeGenerator : public XcodeGenerator
+{
+public:
+ XcodeNativeGenerator();
+
+ QString generatorName() const;
+
+ void generate(const InstallOptions &installOptions);
+ PBXTarget *xcodeTargetForProduct(PBXProject *xcodeProject, const ProductData &product);
+};
+
+}
+
+#endif // QBS_XCODENATIVEGENERATOR_H
diff --git a/src/lib/corelib/generators/xcode/xcodesimplegenerator.cpp b/src/lib/corelib/generators/xcode/xcodesimplegenerator.cpp
new file mode 100644
index 0000000..e1bceca
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/xcodesimplegenerator.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "xcodesimplegenerator.h"
+
+#include "pbx.h"
+
+namespace qbs {
+
+using namespace Internal;
+
+XcodeSimpleGenerator::XcodeSimpleGenerator()
+{
+}
+
+QString XcodeSimpleGenerator::generatorName() const
+{
+ return QLatin1String("xcode-simple");
+}
+
+void XcodeSimpleGenerator::generate(const InstallOptions &installOptions)
+{
+ XcodeGenerator::generate(installOptions);
+}
+
+PBXTarget *XcodeSimpleGenerator::xcodeTargetForProduct(PBXProject *xcodeProject, const ProductData &product)
+{
+ return XcodeGenerator::xcodeTargetForProduct(xcodeProject, product) ?: new PBXNativeTarget(xcodeProject);
+}
+
+}
diff --git a/src/lib/corelib/generators/xcode/xcodesimplegenerator.h b/src/lib/corelib/generators/xcode/xcodesimplegenerator.h
new file mode 100644
index 0000000..66f6419
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/xcodesimplegenerator.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_XCODESIMPLEGENERATOR_H
+#define QBS_XCODESIMPLEGENERATOR_H
+
+#include "xcodegenerator.h"
+#include <QString>
+
+namespace qbs {
+
+class XcodeSimpleGenerator : public XcodeGenerator
+{
+public:
+ XcodeSimpleGenerator();
+
+ QString generatorName() const;
+
+ void generate(const InstallOptions &installOptions);
+ PBXTarget *xcodeTargetForProduct(PBXProject *xcodeProject, const ProductData &product);
+};
+
+}
+
+#endif // QBS_XCODESIMPLEGENERATOR_H
diff --git a/src/lib/corelib/generators/xcode/xcscheme.cpp b/src/lib/corelib/generators/xcode/xcscheme.cpp
new file mode 100644
index 0000000..dbcb994
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/xcscheme.cpp
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "pbxobject.h"
+#include "pbxproject.h"
+#include "pbxtarget.h"
+#include "xcscheme.h"
+#include <QFile>
+#include <QDir>
+#include <QXmlStreamWriter>
+
+static const QString yes = QLatin1String("YES");
+static const QString no = QLatin1String("NO");
+
+class XCSchemePrivate
+{
+public:
+ XCSchemePrivate();
+ PBXProject *project;
+ PBXTarget *target;
+ bool parallelizeBuildables;
+ bool buildImplicitDependencies;
+ QString customExecutableFilePath;
+};
+
+XCSchemePrivate::XCSchemePrivate()
+ : project()
+ , target()
+ , parallelizeBuildables(true)
+ , buildImplicitDependencies(true)
+{
+}
+
+XCScheme::XCScheme(QObject *parent) :
+ QObject(parent), d(new XCSchemePrivate)
+{
+}
+
+XCScheme::~XCScheme()
+{
+ delete d;
+}
+
+PBXProject *XCScheme::project() const
+{
+ return d->project;
+}
+
+void XCScheme::setProject(PBXProject *project)
+{
+ d->project = project;
+}
+
+PBXTarget *XCScheme::target() const
+{
+ return d->target;
+}
+
+void XCScheme::setTarget(PBXTarget *target)
+{
+ d->target = target;
+}
+
+bool XCScheme::parallelizeBuildables() const
+{
+ return d->parallelizeBuildables;
+}
+
+void XCScheme::setParallelizeBuildables(bool parallelize)
+{
+ d->parallelizeBuildables = parallelize;
+}
+
+bool XCScheme::buildImplicitDependencies() const
+{
+ return d->buildImplicitDependencies;
+}
+
+void XCScheme::setBuildImplicitDependencies(bool build)
+{
+ d->buildImplicitDependencies = build;
+}
+
+QString XCScheme::customExecutableFilePath() const
+{
+ return d->customExecutableFilePath;
+}
+
+void XCScheme::setCustomExecutableFilePath(const QString &customExecutableFilePath)
+{
+ d->customExecutableFilePath = customExecutableFilePath;
+}
+
+bool XCScheme::serialize(const QString &filePath)
+{
+ QFile file(filePath);
+ if (file.open(QIODevice::WriteOnly)) {
+ QXmlStreamWriter writer(&file);
+ writer.setAutoFormatting(true);
+ writer.setAutoFormattingIndent(2);
+
+ writer.writeStartDocument();
+ writer.writeStartElement(QLatin1String("Scheme"));
+
+ // now the "actions"
+ writer.writeStartElement(QLatin1String("BuildAction"));
+ writer.writeAttribute(QLatin1String("parallelizeBuildables"), d->parallelizeBuildables ? yes : no);
+ writer.writeAttribute(QLatin1String("buildImplicitDependencies"), d->buildImplicitDependencies ? yes : no);
+ writer.writeStartElement(QLatin1String("BuildActionEntries"));
+ writer.writeStartElement(QLatin1String("BuildActionEntry"));
+ writer.writeAttribute(QLatin1String("buildForTesting"), yes);
+ writer.writeAttribute(QLatin1String("buildForRunning"), yes);
+ writer.writeAttribute(QLatin1String("buildForProfiling"), yes);
+ writer.writeAttribute(QLatin1String("buildForArchiving"), yes);
+ writer.writeAttribute(QLatin1String("buildForAnalyzing"), yes);
+ writer.writeStartElement(QLatin1String("BuildableReference"));
+ writer.writeAttribute(QLatin1String("BuildableIdentifier"), QLatin1String("primary"));
+
+ QByteArray bytes;
+ bytes.append(QLatin1String("BlueprintIdentifier:"));
+ bytes.append(filePath);
+
+ writer.writeAttribute(QLatin1String("BlueprintIdentifier"), PBXObject::createIdentifier(bytes));
+ if (d->target) {
+ writer.writeAttribute(QLatin1String("BuildableName"), d->target->name());
+ writer.writeAttribute(QLatin1String("BlueprintName"), d->target->name());
+ }
+ if (d->project) {
+ const QString relativePath = QDir(d->project->projectDirPath()).relativeFilePath(d->project->projectWrapperPath());
+ writer.writeAttribute(QLatin1String("ReferencedContainer"), QString(QLatin1String("container:%1")).arg(relativePath));
+ }
+ writer.writeEndElement();
+ writer.writeEndElement();
+ writer.writeEndElement();
+ writer.writeEndElement();
+
+ if (!d->customExecutableFilePath.isEmpty()) {
+ writer.writeStartElement(QLatin1String("LaunchAction"));
+ writer.writeStartElement(QLatin1String("PathRunnable"));
+ writer.writeAttribute(QLatin1String("FilePath"), d->customExecutableFilePath);
+ writer.writeEndElement();
+ writer.writeEndElement();
+ }
+
+ writer.writeEndElement();
+ writer.writeEndDocument();
+
+ return file.error() == QFile::NoError;
+ }
+
+ return false;
+}
diff --git a/src/lib/corelib/generators/xcode/xcscheme.h b/src/lib/corelib/generators/xcode/xcscheme.h
new file mode 100644
index 0000000..270cca3
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/xcscheme.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef XCSCHEME_H
+#define XCSCHEME_H
+
+#include <QObject>
+
+class PBXProject;
+class PBXTarget;
+
+class XCSchemePrivate;
+
+class XCScheme : public QObject
+{
+ Q_OBJECT
+public:
+ explicit XCScheme(QObject *parent = 0);
+ virtual ~XCScheme();
+
+ PBXProject *project() const;
+ void setProject(PBXProject *project);
+
+ PBXTarget *target() const;
+ void setTarget(PBXTarget *target);
+
+ bool parallelizeBuildables() const;
+ void setParallelizeBuildables(bool parallelize);
+
+ bool buildImplicitDependencies() const;
+ void setBuildImplicitDependencies(bool build);
+
+ QString customExecutableFilePath() const;
+ void setCustomExecutableFilePath(const QString &customExecutableFilePath);
+
+ bool serialize(const QString &filePath);
+
+private:
+ XCSchemePrivate *d;
+};
+
+#endif // XCSCHEME_H
diff --git a/src/lib/corelib/generators/xcode/xcsettings.cpp b/src/lib/corelib/generators/xcode/xcsettings.cpp
new file mode 100644
index 0000000..d34c86e
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/xcsettings.cpp
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "xcsettings.h"
+
+#include <QFile>
+#include <QTextStream>
+#include <QXmlStreamWriter>
+
+class XCSettingsPrivate {
+public:
+ XCSettingsPrivate()
+ : autocreateSchemes()
+ {
+ }
+
+ bool autocreateSchemes;
+};
+
+XCSettings::XCSettings(QObject *parent)
+ : QObject(parent)
+ , d(new XCSettingsPrivate)
+{
+}
+
+XCSettings::~XCSettings()
+{
+ delete d;
+}
+
+bool XCSettings::autocreateSchemes() const
+{
+ return d->autocreateSchemes;
+}
+
+void XCSettings::setAutocreateSchemes(bool autocreateSchemes)
+{
+ d->autocreateSchemes = autocreateSchemes;
+}
+
+bool XCSettings::serialize(const QString &filePath)
+{
+ QFile file(filePath);
+ if (file.open(QIODevice::WriteOnly)) {
+ QXmlStreamWriter writer(&file);
+ writer.setAutoFormatting(true);
+ writer.setAutoFormattingIndent(-1);
+
+ writer.writeStartDocument();
+ writer.writeDTD(QLatin1String("<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"));
+
+ writer.writeStartElement(QLatin1String("plist"));
+ writer.writeAttribute(QLatin1String("version"), QLatin1String("1.0"));
+ writer.writeStartElement(QLatin1String("dict"));
+
+ writer.writeTextElement(QLatin1String("key"), QLatin1String("IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded"));
+ writer.writeEmptyElement(d->autocreateSchemes ? QLatin1String("true") : QLatin1String("false"));
+
+ writer.writeEndElement(); // </dict>
+ writer.writeEndElement(); // </plist>
+ writer.writeEndDocument();
+
+ return file.error() == QFile::NoError;
+ }
+
+ return false;
+}
+
diff --git a/src/lib/corelib/generators/xcode/xcsettings.h b/src/lib/corelib/generators/xcode/xcsettings.h
new file mode 100644
index 0000000..e6f2c5d
--- /dev/null
+++ b/src/lib/corelib/generators/xcode/xcsettings.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jake Petroules.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef XCSETTINGS_H
+#define XCSETTINGS_H
+
+#include <QObject>
+
+class XCSettingsPrivate;
+
+class XCSettings : public QObject
+{
+ Q_OBJECT
+public:
+ explicit XCSettings(QObject *parent = 0);
+ virtual ~XCSettings();
+
+ bool autocreateSchemes() const;
+ void setAutocreateSchemes(bool autocreateSchemes);
+
+ bool serialize(const QString &filePath);
+
+private:
+ XCSettingsPrivate *d;
+};
+
+#endif // XCSETTINGS_H
diff --git a/src/lib/corelib/tools/projectgeneratormanager.cpp b/src/lib/corelib/tools/projectgeneratormanager.cpp
index 4c62fc0..f5d0f81 100644
--- a/src/lib/corelib/tools/projectgeneratormanager.cpp
+++ b/src/lib/corelib/tools/projectgeneratormanager.cpp
@@ -39,6 +39,9 @@
#include <QDirIterator>
#include <QLibrary>
+#include <generators/xcode/xcodenativegenerator.h>
+#include <generators/xcode/xcodesimplegenerator.h>
+
namespace qbs {
using namespace Internal;
@@ -60,6 +63,8 @@ ProjectGeneratorManager *ProjectGeneratorManager::instance()
ProjectGeneratorManager::ProjectGeneratorManager()
{
QList<QSharedPointer<ProjectGenerator> > generators;
+ generators << QSharedPointer<XcodeNativeGenerator>::create();
+ generators << QSharedPointer<XcodeSimpleGenerator>::create();
foreach (QSharedPointer<ProjectGenerator> generator, generators) {
m_generators[generator->generatorName()] = generator;
}
--
2.3.5