From 92347c167dfa778fffc25cf2c03cc4cfd80a5ce0 Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Wed, 18 Feb 2015 09:05:29 -0800 Subject: [PATCH 2/5] 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 a5c1ab6..771f7e6 100644 --- a/src/lib/corelib/corelib.qbs +++ b/src/lib/corelib/corelib.qbs @@ -154,6 +154,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 +#include + +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 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 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() || 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 &propertyList) +{ + return toString(propertyList, 0) + NewlineToken; +} + +QString OpenStepPropertyList::toString(const QList &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 objid = object.value(); + 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()) { + return toString(object.value(), 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 +#include +#include +#include +#include + +class PBXObjectIdentifier; +typedef QMap 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 &propertyList); + +private: + OpenStepPropertyList(); + + static QString toString(const QVariantMap &propertyList, int indentationLevel); + static QString toString(const PBXObjectMap &propertyList, int indentationLevel); + static QString toString(const QList &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 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 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(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 +#include + +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 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 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::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(parent()); + if (target) { + data.append(target->hashData()); + } + return data; // TODO: Build phases for which a target may have multiple of, will not work +} + +QList 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 + +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 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 + +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 + +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 + +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 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 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 PBXGroup::addFiles(const QStringList &files, bool copy, bool createGroupsRecursively) +{ + QList 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 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 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()); + 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 +#include +#include +#include + +static QMap 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 +#include +#include + +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 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 + +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 +#include +#include + +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 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 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(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 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(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 + +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(""); + case Group: + return QLatin1String(""); + 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 + +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 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 &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 PBXTarget::buildPhases() const +{ + QList 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 + +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 &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 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 + +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 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 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(parent()); + PBXProject *project = dynamic_cast(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 + +class XCBuildConfiguration; + +class XCConfigurationListPrivate; + +class XCConfigurationList : public PBXObject +{ + Q_OBJECT +public: + explicit XCConfigurationList(PBXObject *parent = 0); + ~XCConfigurationList(); + + QString isa() const; + PBXObjectMap toMap() const; + + QList 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 +#include "pbx.h" + +#include + +#include + +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 module(project.projectConfiguration()); + while (module.hasNext()) { + module.next(); + QString qbsModName = qbsModuleName; + if (module.key() == qbsModName.replace(QLatin1String("."), QLatin1String("/"))) { + QMapIterator 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::defaultBuildSettingsMap() +{ + const QString cpp = QLatin1String("cpp"); + + QList 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 +#include +#include + +#include +#include + +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 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 +#include +#include +#include +#include +#include "pbx.h" + +#include +#include +#include +#include + +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 profileNames; + QSet projectNames; + QSet qbsProjectFiles; + QSet 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 &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(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(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 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 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(ref)) { + if ((fileRef->sourceTree() == PBX::SdkRoot && fileRef->path() == sysrootedCandidateFrameworkPath) || + (fileRef->sourceTree() == PBX::Absolute && fileRef->path() == candidateFrameworkPath)) { + existingReference = fileRef; + break; + } + } + } + + QList 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 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 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 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 +#include +#include "pbxproducttype.h" + +#include + +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 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 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 + +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 + +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 +#include +#include + +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 + +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 +#include +#include + +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("")); + + 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(); // + writer.writeEndElement(); // + 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 + +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 #include +#include +#include + namespace qbs { using namespace Internal; @@ -60,6 +63,8 @@ ProjectGeneratorManager *ProjectGeneratorManager::instance() ProjectGeneratorManager::ProjectGeneratorManager() { QList > generators; + generators << QSharedPointer::create(); + generators << QSharedPointer::create(); foreach (QSharedPointer generator, generators) { m_generators[generator->generatorName()] = generator; } -- 2.3.5