qmake/generators/mac/pbuilder_pbx.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the qmake application of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "pbuilder_pbx.h"
       
    43 #include "option.h"
       
    44 #include "meta.h"
       
    45 #include <qdir.h>
       
    46 #include <qregexp.h>
       
    47 #include <qcryptographichash.h>
       
    48 #include <qdebug.h>
       
    49 #include <stdlib.h>
       
    50 #include <time.h>
       
    51 #ifdef Q_OS_UNIX
       
    52 #  include <sys/types.h>
       
    53 #  include <sys/stat.h>
       
    54 #endif
       
    55 #ifdef Q_OS_DARWIN
       
    56 #include <ApplicationServices/ApplicationServices.h>
       
    57 #include <private/qcore_mac_p.h>
       
    58 #endif
       
    59 
       
    60 QT_BEGIN_NAMESPACE
       
    61 
       
    62 //#define GENERATE_AGGREGRATE_SUBDIR
       
    63 
       
    64 // Note: this is fairly hacky, but it does the job...
       
    65 
       
    66 static QString qtMD5(const QByteArray &src)
       
    67 {
       
    68     QByteArray digest = QCryptographicHash::hash(src, QCryptographicHash::Md5);
       
    69     return QString::fromLatin1(digest.toHex());
       
    70 }
       
    71 
       
    72 ProjectBuilderMakefileGenerator::ProjectBuilderMakefileGenerator() : UnixMakefileGenerator()
       
    73 {
       
    74 
       
    75 }
       
    76 
       
    77 bool
       
    78 ProjectBuilderMakefileGenerator::writeMakefile(QTextStream &t)
       
    79 {
       
    80     writingUnixMakefileGenerator = false;
       
    81     if(!project->values("QMAKE_FAILED_REQUIREMENTS").isEmpty()) {
       
    82         /* for now just dump, I need to generated an empty xml or something.. */
       
    83         fprintf(stderr, "Project file not generated because all requirements not met:\n\t%s\n",
       
    84                 var("QMAKE_FAILED_REQUIREMENTS").toLatin1().constData());
       
    85         return true;
       
    86     }
       
    87 
       
    88     project->values("MAKEFILE").clear();
       
    89     project->values("MAKEFILE").append("Makefile");
       
    90     if(project->first("TEMPLATE") == "app" || project->first("TEMPLATE") == "lib")
       
    91         return writeMakeParts(t);
       
    92     else if(project->first("TEMPLATE") == "subdirs")
       
    93         return writeSubDirs(t);
       
    94     return false;
       
    95 }
       
    96 
       
    97 struct ProjectBuilderSubDirs {
       
    98     QMakeProject *project;
       
    99     QString subdir;
       
   100     bool autoDelete;
       
   101     ProjectBuilderSubDirs(QMakeProject *p, QString s, bool a=true) : project(p), subdir(s), autoDelete(a) { }
       
   102     ~ProjectBuilderSubDirs() {
       
   103         if(autoDelete)
       
   104             delete project;
       
   105     }
       
   106 };
       
   107 
       
   108 bool
       
   109 ProjectBuilderMakefileGenerator::writeSubDirs(QTextStream &t)
       
   110 {
       
   111     if(project->isActiveConfig("generate_pbxbuild_makefile")) {
       
   112         QString mkwrap = fileFixify(pbx_dir + Option::dir_sep + ".." + Option::dir_sep + project->first("MAKEFILE"),
       
   113                                     qmake_getpwd());
       
   114         QFile mkwrapf(mkwrap);
       
   115         if(mkwrapf.open(QIODevice::WriteOnly | QIODevice::Text)) {
       
   116             if (Option::mkfile::listgen) {
       
   117                 generatePrint(fileInfo(mkwrapf.fileName()).absoluteFilePath());
       
   118             }
       
   119             debug_msg(1, "pbuilder: Creating file: %s", mkwrap.toLatin1().constData());
       
   120             QTextStream mkwrapt(&mkwrapf);
       
   121             writingUnixMakefileGenerator = true;
       
   122             UnixMakefileGenerator::writeSubDirs(mkwrapt);
       
   123             writingUnixMakefileGenerator = false;
       
   124         }
       
   125     }
       
   126 
       
   127     //HEADER
       
   128     const int pbVersion = pbuilderVersion();
       
   129     t << "// !$*UTF8*$!" << "\n"
       
   130       << "{" << "\n"
       
   131       << "\t" << writeSettings("archiveVersion", "1", SettingsNoQuote) << ";" << "\n"
       
   132       << "\t" << "classes = {" << "\n" << "\t" << "};" << "\n"
       
   133       << "\t" << writeSettings("objectVersion", QString::number(pbVersion), SettingsNoQuote) << ";" << "\n"
       
   134       << "\t" << "objects = {" << endl;
       
   135 
       
   136     //SUBDIRS
       
   137     QList<ProjectBuilderSubDirs*> pb_subdirs;
       
   138     pb_subdirs.append(new ProjectBuilderSubDirs(project, QString(), false));
       
   139     QString oldpwd = qmake_getpwd();
       
   140     QMap<QString, QStringList> groups;
       
   141     for(int pb_subdir = 0; pb_subdir < pb_subdirs.size(); ++pb_subdir) {
       
   142         ProjectBuilderSubDirs *pb = pb_subdirs[pb_subdir];
       
   143         const QStringList subdirs = pb->project->values("SUBDIRS");
       
   144         for(int subdir = 0; subdir < subdirs.count(); subdir++) {
       
   145             QString tmp = subdirs[subdir];
       
   146             if(!pb->project->isEmpty(tmp + ".file"))
       
   147                 tmp = pb->project->first(tmp + ".file");
       
   148             else if(!pb->project->isEmpty(tmp + ".subdir"))
       
   149                 tmp = pb->project->first(tmp + ".subdir");
       
   150             if(fileInfo(tmp).isRelative() && !pb->subdir.isEmpty()) {
       
   151                 QString subdir = pb->subdir;
       
   152                 if(!subdir.endsWith(Option::dir_sep))
       
   153                     subdir += Option::dir_sep;
       
   154                 tmp = subdir + tmp;
       
   155             }
       
   156             QFileInfo fi(fileInfo(Option::fixPathToLocalOS(tmp, true)));
       
   157             if(fi.exists()) {
       
   158                 if(fi.isDir()) {
       
   159                     QString profile = tmp;
       
   160                     if(!profile.endsWith(Option::dir_sep))
       
   161                         profile += Option::dir_sep;
       
   162                     profile += fi.baseName() + Option::pro_ext;
       
   163                     fi = QFileInfo(profile);
       
   164                 }
       
   165                 QMakeProject tmp_proj;
       
   166                 QString dir = fi.path(), fn = fi.fileName();
       
   167                 if(!dir.isEmpty()) {
       
   168                     if(!qmake_setpwd(dir))
       
   169                         fprintf(stderr, "Cannot find directory: %s\n", dir.toLatin1().constData());
       
   170                 }
       
   171                 if(tmp_proj.read(fn)) {
       
   172                     if(Option::debug_level) {
       
   173                         QMap<QString, QStringList> &vars = tmp_proj.variables();
       
   174                         for(QMap<QString, QStringList>::Iterator it = vars.begin();
       
   175                             it != vars.end(); ++it) {
       
   176                             if(it.key().left(1) != "." && !it.value().isEmpty())
       
   177                                 debug_msg(1, "%s: %s === %s", fn.toLatin1().constData(), it.key().toLatin1().constData(),
       
   178                                           it.value().join(" :: ").toLatin1().constData());
       
   179                         }
       
   180                     }
       
   181                     if(tmp_proj.first("TEMPLATE") == "subdirs") {
       
   182                         QMakeProject *pp = new QMakeProject(&tmp_proj);
       
   183                         pp->read(0);
       
   184                         pb_subdirs += new ProjectBuilderSubDirs(pp, dir);
       
   185                     } else if(tmp_proj.first("TEMPLATE") == "app" || tmp_proj.first("TEMPLATE") == "lib") {
       
   186                         QString pbxproj = qmake_getpwd() + Option::dir_sep + tmp_proj.first("TARGET") + projectSuffix();
       
   187                         if(!exists(pbxproj)) {
       
   188                             warn_msg(WarnLogic, "Ignored (not found) '%s'", pbxproj.toLatin1().constData());
       
   189                             goto nextfile; // # Dirty!
       
   190                         }
       
   191                         const QString project_key = keyFor(pbxproj + "_PROJECTREF");
       
   192                         project->values("QMAKE_PBX_SUBDIRS") += pbxproj;
       
   193                         //PROJECTREF
       
   194                         {
       
   195                             bool in_root = true;
       
   196                             QString name = qmake_getpwd();
       
   197                             if(project->isActiveConfig("flat")) {
       
   198                                 QString flat_file = fileFixify(name, oldpwd, Option::output_dir, FileFixifyRelative);
       
   199                                 if(flat_file.indexOf(Option::dir_sep) != -1) {
       
   200                                     QStringList dirs = flat_file.split(Option::dir_sep);
       
   201                                     name = dirs.back();
       
   202                                 }
       
   203                             } else {
       
   204                                 QString flat_file = fileFixify(name, oldpwd, Option::output_dir, FileFixifyRelative);
       
   205                                 if(QDir::isRelativePath(flat_file) && flat_file.indexOf(Option::dir_sep) != -1) {
       
   206                                     QString last_grp("QMAKE_SUBDIR_PBX_HEIR_GROUP");
       
   207                                     QStringList dirs = flat_file.split(Option::dir_sep);
       
   208                                     name = dirs.back();
       
   209                                     for(QStringList::Iterator dir_it = dirs.begin(); dir_it != dirs.end(); ++dir_it) {
       
   210                                         QString new_grp(last_grp + Option::dir_sep + (*dir_it)), new_grp_key(keyFor(new_grp));
       
   211                                         if(dir_it == dirs.begin()) {
       
   212                                             if(!groups.contains(new_grp))
       
   213                                                 project->values("QMAKE_SUBDIR_PBX_GROUPS").append(new_grp_key);
       
   214                                         } else {
       
   215                                             if(!groups[last_grp].contains(new_grp_key))
       
   216                                                 groups[last_grp] += new_grp_key;
       
   217                                         }
       
   218                                         last_grp = new_grp;
       
   219                                     }
       
   220                                     groups[last_grp] += project_key;
       
   221                                     in_root = false;
       
   222                                 }
       
   223                             }
       
   224                             if(in_root)
       
   225                                 project->values("QMAKE_SUBDIR_PBX_GROUPS") += project_key;
       
   226                             t << "\t\t" << project_key << " = {" << "\n"
       
   227                               << "\t\t\t" << writeSettings("isa", "PBXFileReference", SettingsNoQuote) << ";" << "\n"
       
   228                               << "\t\t\t" << writeSettings("lastKnownFileType", "wrapper.pb-project") << ";" << "\n"
       
   229                               << "\t\t\t" << writeSettings("name", escapeFilePath(tmp_proj.first("TARGET") + projectSuffix())) << ";" << "\n"
       
   230                               << "\t\t\t" << writeSettings("path", pbxproj) << ";" << "\n"
       
   231                               << "\t\t\t" << writeSettings("refType", "0", SettingsNoQuote) << ";" << "\n"
       
   232                               << "\t\t\t" << writeSettings("sourceTree", "<absolute>") << ";" << "\n"
       
   233                               << "\t\t" << "};" << "\n";
       
   234                             //WRAPPER
       
   235                             t << "\t\t" << keyFor(pbxproj + "_WRAPPER") << " = {" << "\n"
       
   236                               << "\t\t\t" << writeSettings("isa", "PBXReferenceProxy", SettingsNoQuote) << ";" << "\n";
       
   237                             if(tmp_proj.first("TEMPLATE") == "app") {
       
   238                                 t << "\t\t\t" << writeSettings("fileType", "wrapper.application") << ";" << "\n"
       
   239                                   << "\t\t\t" << writeSettings("path", tmp_proj.first("TARGET") + ".app") << ";" << "\n";
       
   240                             } else {
       
   241                                 t << "\t\t\t" << writeSettings("fileType", "compiled.mach-o.dylib") << ";" << "\n"
       
   242                                   << "\t\t\t" << writeSettings("path", tmp_proj.first("TARGET") + ".dylib") << ";" << "\n";
       
   243                             }
       
   244                             t << "\t\t\t" << writeSettings("refType", "3", SettingsNoQuote) << ";" << "\n"
       
   245                               << "\t\t\t" << writeSettings("remoteRef", keyFor(pbxproj + "_WRAPPERREF")) << ";" << "\n"
       
   246                               << "\t\t\t" << writeSettings("sourceTree", "BUILT_PRODUCTS_DIR", SettingsNoQuote) << ";" << "\n"
       
   247                               << "\t\t" << "};" << "\n";
       
   248                             t << "\t\t" << keyFor(pbxproj + "_WRAPPERREF") << " = {" << "\n"
       
   249                               << "\t\t\t" << writeSettings("containerPortal", project_key) << ";" << "\n"
       
   250                               << "\t\t\t" << writeSettings("isa", "PBXContainerItemProxy", SettingsNoQuote) << ";" << "\n"
       
   251                               << "\t\t\t" << writeSettings("proxyType", "2") << ";" << "\n"
       
   252 //                              << "\t\t\t" << writeSettings("remoteGlobalIDString", keyFor(pbxproj + "QMAKE_PBX_REFERENCE")) << ";" << "\n"
       
   253                               << "\t\t\t" << writeSettings("remoteGlobalIDString", keyFor(pbxproj + "QMAKE_PBX_REFERENCE!!!")) << ";" << "\n"
       
   254                               << "\t\t\t" << writeSettings("remoteInfo", tmp_proj.first("TARGET")) << ";" << "\n"
       
   255                               << "\t\t" << "};" << "\n";
       
   256                             //PRODUCTGROUP
       
   257                             t << "\t\t" << keyFor(pbxproj + "_PRODUCTGROUP") << " = {" << "\n"
       
   258                               << "\t\t\t" << writeSettings("children", project->values(pbxproj + "_WRAPPER"), SettingsAsList, 4) << ";" << "\n"
       
   259                               << "\t\t\t" << writeSettings("isa", "PBXGroup", SettingsNoQuote) << ";" << "\n"
       
   260                               << "\t\t\t" << writeSettings("name", "Products") << ";" << "\n"
       
   261                               << "\t\t\t" << writeSettings("refType", "4", SettingsNoQuote) << ";" << "\n"
       
   262                               << "\t\t\t" << writeSettings("sourceTree", "<group>") << ";" << "\n"
       
   263                               << "\t\t" << "};" << "\n";
       
   264                         }
       
   265 #ifdef GENERATE_AGGREGRATE_SUBDIR
       
   266                         //TARGET (for aggregate)
       
   267                         {
       
   268                             //container
       
   269                             const QString container_proxy = keyFor(pbxproj + "_CONTAINERPROXY");
       
   270                             t << "\t\t" << container_proxy << " = {" << "\n"
       
   271                               << "\t\t\t" << writeSettings("containerPortal", project_key) << ";" << "\n"
       
   272                               << "\t\t\t" << writeSettings("isa", "PBXContainerItemProxy", SettingsNoQuote) << ";" << "\n"
       
   273                               << "\t\t\t" << writeSettings("proxyType", "1") << ";" << "\n"
       
   274                               << "\t\t\t" << writeSettings("remoteGlobalIDString", keyFor(pbxproj + "QMAKE_PBX_TARGET")) << ";" << "\n"
       
   275                               << "\t\t\t" << writeSettings("remoteInfo", tmp_proj.first("TARGET")) << ";" << "\n"
       
   276                               << "\t\t" << "};" << "\n";
       
   277                             //targetref
       
   278                             t << "\t\t" << keyFor(pbxproj + "_TARGETREF") << " = {" << "\n"
       
   279                               << "\t\t\t" << writeSettings("isa", "PBXTargetDependency", SettingsNoQuote) << ";" << "\n"
       
   280                               << "\t\t\t" << writeSettings("name", fixForOutput(tmp_proj.first("TARGET") +" (from " + tmp_proj.first("TARGET") + projectSuffix() + ")")) << ";" << "\n"
       
   281                               << "\t\t\t" << writeSettings("targetProxy", container_proxy) << ";" << "\n"
       
   282                               << "\t\t" << "};" << "\n";
       
   283                         }
       
   284 #endif
       
   285                     }
       
   286                 }
       
   287             nextfile:
       
   288                 qmake_setpwd(oldpwd);
       
   289             }
       
   290         }
       
   291     }
       
   292     qDeleteAll(pb_subdirs);
       
   293     pb_subdirs.clear();
       
   294 
       
   295     for(QMap<QString, QStringList>::Iterator grp_it = groups.begin(); grp_it != groups.end(); ++grp_it) {
       
   296         t << "\t\t" << keyFor(grp_it.key()) << " = {" << "\n"
       
   297           << "\t\t\t" << writeSettings("isa", "PBXGroup", SettingsNoQuote) << ";" << "\n"
       
   298           << "\t\t\t" << writeSettings("children", grp_it.value(), SettingsAsList, 4) << ";" << "\n"
       
   299           << "\t\t\t" << writeSettings("name", escapeFilePath(grp_it.key().section(Option::dir_sep, -1))) << ";" << "\n"
       
   300           << "\t\t\t" << writeSettings("refType", "4", SettingsNoQuote) << ";" << "\n"
       
   301           << "\t\t" << "};" << "\n";
       
   302     }
       
   303 
       
   304     //DUMP EVERYTHING THAT TIES THE ABOVE TOGETHER
       
   305     //BUILDSTYLE
       
   306     QString active_buildstyle;
       
   307     for(int as_release = 0; as_release < 2; as_release++)
       
   308     {
       
   309         QMap<QString, QString> settings;
       
   310         settings.insert("COPY_PHASE_STRIP", (as_release ? "YES" : "NO"));
       
   311         if(as_release)
       
   312             settings.insert("GCC_GENERATE_DEBUGGING_SYMBOLS", "NO");
       
   313         if(project->isActiveConfig("sdk") && !project->isEmpty("QMAKE_MAC_SDK"))
       
   314             settings.insert("SDKROOT", project->first("QMAKE_MAC_SDK"));
       
   315         {
       
   316             const QStringList &l = project->values("QMAKE_MAC_XCODE_SETTINGS");
       
   317             for(int i = 0; i < l.size(); ++i) {
       
   318                 QString name = l.at(i);
       
   319                 const QString value = project->values(name + QLatin1String(".value")).join(QString(Option::field_sep));
       
   320                 if(!project->isEmpty(name + QLatin1String(".name")))
       
   321                     name = project->values(name + QLatin1String(".name")).first();
       
   322                 settings.insert(name, value);
       
   323             }
       
   324         }
       
   325 
       
   326         QString name;
       
   327         if(pbVersion >= 42)
       
   328             name = (as_release ? "Release" : "Debug");
       
   329         else
       
   330             name = (as_release ? "Deployment" : "Development");
       
   331         if(pbVersion >= 42) {
       
   332             QString key = keyFor("QMAKE_SUBDIR_PBX_BUILDCONFIG_" + name);
       
   333             project->values("QMAKE_SUBDIR_PBX_BUILDCONFIGS").append(key);
       
   334             t << "\t\t" << key << " = {" << "\n"
       
   335               << "\t\t\t" << writeSettings("isa", "XCBuildConfiguration", SettingsNoQuote) << ";" << "\n"
       
   336               << "\t\t\t" << "buildSettings = {" << "\n";
       
   337             for(QMap<QString, QString>::Iterator set_it = settings.begin(); set_it != settings.end(); ++set_it)
       
   338                 t << "\t\t\t\t" << writeSettings(set_it.key(), set_it.value()) << ";" << "\n";
       
   339             t << "\t\t\t" << "};" << "\n"
       
   340               << "\t\t\t" << writeSettings("name", name) << ";" << "\n"
       
   341               << "\t\t" << "};" << "\n";
       
   342         }
       
   343 
       
   344         QString key = keyFor("QMAKE_SUBDIR_PBX_BUILDSTYLE_" + name);
       
   345         if(project->isActiveConfig("debug") != (bool)as_release) {
       
   346             project->values("QMAKE_SUBDIR_PBX_BUILDSTYLES").append(key);
       
   347             active_buildstyle = name;
       
   348         } else if(pbVersion >= 42) {
       
   349             project->values("QMAKE_SUBDIR_PBX_BUILDSTYLES").append(key);
       
   350         }
       
   351         t << "\t\t" << key << " = {" << "\n"
       
   352           << "\t\t\t" << writeSettings("buildRules", QStringList(), SettingsAsList, 4) << ";" << "\n"
       
   353           << "\t\t\t" << "buildSettings = {" << "\n";
       
   354         for(QMap<QString, QString>::Iterator set_it = settings.begin(); set_it != settings.end(); ++set_it)
       
   355             t << "\t\t\t\t" << writeSettings(set_it.key(), set_it.value()) << ";\n";
       
   356         t << "\t\t\t" << "};" << "\n"
       
   357           << "\t\t\t" << writeSettings("isa", "PBXBuildStyle", SettingsNoQuote) << ";" << "\n"
       
   358           << "\t\t\t" << writeSettings("name", name) << ";" << "\n"
       
   359           << "\t\t" << "};" << "\n";
       
   360     }
       
   361     if(pbVersion >= 42) {
       
   362         t << "\t\t" << keyFor("QMAKE_SUBDIR_PBX_BUILDCONFIG_LIST") << " = {" << "\n"
       
   363           << "\t\t\t" << writeSettings("isa", "XCConfigurationList", SettingsNoQuote) << ";" << "\n"
       
   364           << "\t\t\t" << writeSettings("buildConfigurations", project->values("QMAKE_SUBDIR_PBX_BUILDCONFIGS"), SettingsAsList, 4) << ";" << "\n"
       
   365           << "\t\t\t" << writeSettings("defaultConfigurationIsVisible", "0", SettingsNoQuote) << ";" << "\n"
       
   366           << "\t\t\t" << writeSettings("defaultConfigurationIsName", active_buildstyle) << ";" << "\n"
       
   367           << "\t\t" << "};" << "\n";
       
   368     }
       
   369 
       
   370 #ifdef GENERATE_AGGREGRATE_SUBDIR
       
   371     //target
       
   372     t << "\t\t" << keyFor("QMAKE_SUBDIR_PBX_AGGREGATE_TARGET") << " = {" << "\n"
       
   373       << "\t\t\t" << writeSettings("buildPhases", QStringList(), SettingsAsList, 4) << ";" << "\n"
       
   374       << "\t\t\t" << "buildSettings = {" << "\n"
       
   375       << "\t\t\t\t" << writeSettings("PRODUCT_NAME",  project->values("TARGET").first()) << ";" << "\n"
       
   376       << "\t\t\t" << "};" << "\n";
       
   377     {
       
   378         QStringList dependencies;
       
   379         const QStringList &qmake_subdirs = project->values("QMAKE_PBX_SUBDIRS");
       
   380         for(int i = 0; i < qmake_subdirs.count(); i++)
       
   381             dependencies += keyFor(qmake_subdirs[i] + "_TARGETREF");
       
   382         t << "\t\t\t" << writeSettings("dependencies", dependencies, SettingsAsList, 4) << ";" << "\n"
       
   383     }
       
   384     t << "\t\t\t" << writeSettings("isa", "PBXAggregateTarget", SettingsNoQuote) << ";" << "\n"
       
   385       << "\t\t\t" << writeSettings("name", project->values("TARGET").first()) << ";" << "\n"
       
   386       << "\t\t\t" << writeSettings("productName", project->values("TARGET").first()) << ";" << "\n"
       
   387       << "\t\t" << "};" << "\n";
       
   388 #endif
       
   389 
       
   390     //ROOT_GROUP
       
   391     t << "\t\t" << keyFor("QMAKE_SUBDIR_PBX_ROOT_GROUP") << " = {" << "\n"
       
   392       << "\t\t\t" << writeSettings("children", project->values("QMAKE_SUBDIR_PBX_GROUPS"), SettingsAsList, 4) << ";" << "\n"
       
   393       << "\t\t\t" << writeSettings("isa", "PBXGroup", SettingsNoQuote) << ";" << "\n"
       
   394       << "\t\t\t" << writeSettings("refType", "4", SettingsNoQuote) << ";" << "\n"
       
   395       << "\t\t\t" << writeSettings("sourceTree", "<group>") << ";" << "\n"
       
   396       << "\t\t" << "};" << "\n";
       
   397 
       
   398 
       
   399     //ROOT
       
   400     t << "\t\t" << keyFor("QMAKE_SUBDIR_PBX_ROOT") << " = {" << "\n"
       
   401       << "\t\t\t" << "buildSettings = {" << "\n"
       
   402       << "\t\t\t" << "};" << "\n"
       
   403       << "\t\t\t" << writeSettings("buildStyles", project->values("QMAKE_SUBDIR_PBX_BUILDSTYLES"), SettingsAsList, 4) << ";" << "\n"
       
   404       << "\t\t\t" << writeSettings("isa", "PBXProject", SettingsNoQuote) << ";" << "\n"
       
   405       << "\t\t\t" << writeSettings("mainGroup", keyFor("QMAKE_SUBDIR_PBX_ROOT_GROUP")) << ";" << "\n"
       
   406       << "\t\t\t" << writeSettings("projectDirPath", QStringList()) << ";" << "\n";
       
   407     if(pbVersion >= 42)
       
   408         t << "\t\t\t" << writeSettings("buildConfigurationList", keyFor("QMAKE_SUBDIR_PBX_BUILDCONFIG_LIST")) << ";" << "\n";
       
   409     t << "\t\t\t" << "projectReferences = (" << "\n";
       
   410     {
       
   411         QStringList &qmake_subdirs = project->values("QMAKE_PBX_SUBDIRS");
       
   412         for(int i = 0; i < qmake_subdirs.count(); i++) {
       
   413             QString subdir = qmake_subdirs[i];
       
   414             t << "\t\t\t\t" << "{" << "\n"
       
   415               << "\t\t\t\t\t" << writeSettings("ProductGroup", keyFor(subdir + "_PRODUCTGROUP")) << ";" << "\n"
       
   416               << "\t\t\t\t\t" << writeSettings("ProjectRef", keyFor(subdir + "_PROJECTREF")) << ";" << "\n"
       
   417               << "\t\t\t\t" << "}," << "\n";
       
   418         }
       
   419     }
       
   420     t << "\t\t\t" << ");" << "\n"
       
   421       << "\t\t\t" << writeSettings("targets",
       
   422 #ifdef GENERATE_AGGREGRATE_SUBDIR
       
   423                                  project->values("QMAKE_SUBDIR_AGGREGATE_TARGET"),
       
   424 #else
       
   425                                  QStringList(),
       
   426 #endif
       
   427                                    SettingsAsList, 4) << ";" << "\n"
       
   428       << "\t\t" << "};" << "\n";
       
   429 
       
   430     //FOOTER
       
   431     t << "\t" << "};" << "\n"
       
   432       << "\t" << writeSettings("rootObject", keyFor("QMAKE_SUBDIR_PBX_ROOT")) << ";" << "\n"
       
   433       << "}" << endl;
       
   434 
       
   435     return true;
       
   436 }
       
   437 
       
   438 class ProjectBuilderSources
       
   439 {
       
   440     bool buildable, object_output;
       
   441     QString key, group, compiler;
       
   442 public:
       
   443     ProjectBuilderSources(const QString &key, bool buildable=false, const QString &group=QString(), const QString &compiler=QString(), bool producesObject=false);
       
   444     QStringList files(QMakeProject *project) const;
       
   445     inline bool isBuildable() const { return buildable; }
       
   446     inline QString keyName() const { return key; }
       
   447     inline QString groupName() const { return group; }
       
   448     inline QString compilerName() const { return compiler; }
       
   449     inline bool isObjectOutput(const QString &file) const {
       
   450         bool ret = object_output;
       
   451         for(int i = 0; !ret && i < Option::c_ext.size(); ++i) {
       
   452             if(file.endsWith(Option::c_ext.at(i))) {
       
   453                 ret = true;
       
   454                 break;
       
   455             }
       
   456         }
       
   457         for(int i = 0; !ret && i < Option::cpp_ext.size(); ++i) {
       
   458             if(file.endsWith(Option::cpp_ext.at(i))) {
       
   459                 ret = true;
       
   460                 break;
       
   461             }
       
   462         }
       
   463         return ret;
       
   464     }
       
   465 };
       
   466 
       
   467 ProjectBuilderSources::ProjectBuilderSources(const QString &k, bool b,
       
   468                                              const QString &g, const QString &c, bool o) : buildable(b), object_output(o), key(k), group(g), compiler(c)
       
   469 {
       
   470     if(group.isNull()) {
       
   471         if(k == "SOURCES")
       
   472             group = "Sources";
       
   473         else if(k == "HEADERS")
       
   474             group = "Headers";
       
   475         else if(k == "QMAKE_INTERNAL_INCLUDED_FILES")
       
   476             group = "Sources [qmake]";
       
   477         else if(k == "GENERATED_SOURCES" || k == "GENERATED_FILES")
       
   478             group = "Temporary Sources";
       
   479         else
       
   480             fprintf(stderr, "No group available for %s!\n", k.toLatin1().constData());
       
   481     }
       
   482 }
       
   483 
       
   484 QStringList
       
   485 ProjectBuilderSources::files(QMakeProject *project) const
       
   486 {
       
   487     QStringList ret = project->values(key);
       
   488     if(key == "QMAKE_INTERNAL_INCLUDED_FILES") {
       
   489         QString pfile = project->projectFile();
       
   490         if(pfile != "(stdin)")
       
   491             ret.prepend(pfile);
       
   492         for(int i = 0; i < ret.size(); ++i) {
       
   493             QStringList newret;
       
   494             if(!ret.at(i).endsWith(Option::prf_ext))
       
   495                 newret.append(ret.at(i));
       
   496             ret = newret;
       
   497         }
       
   498     }
       
   499     if(key == "SOURCES" && project->first("TEMPLATE") == "app" && !project->isEmpty("ICON"))
       
   500         ret.append(project->first("ICON"));
       
   501     return ret;
       
   502 }
       
   503 
       
   504 
       
   505 bool
       
   506 ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
       
   507 {
       
   508     QStringList tmp;
       
   509     bool did_preprocess = false;
       
   510 
       
   511     //HEADER
       
   512     const int pbVersion = pbuilderVersion();
       
   513     t << "// !$*UTF8*$!" << "\n"
       
   514       << "{" << "\n"
       
   515       << "\t" << writeSettings("archiveVersion", "1", SettingsNoQuote) << ";" << "\n"
       
   516       << "\t" << "classes = {" << "\n" << "\t" << "};" << "\n"
       
   517       << "\t" << writeSettings("objectVersion", QString::number(pbVersion), SettingsNoQuote) << ";" << "\n"
       
   518       << "\t" << "objects = {" << endl;
       
   519 
       
   520     //MAKE QMAKE equivelant
       
   521     if(!project->isActiveConfig("no_autoqmake") && project->projectFile() != "(stdin)") {
       
   522         QString mkfile = pbx_dir + Option::dir_sep + "qt_makeqmake.mak";
       
   523         QFile mkf(mkfile);
       
   524         if(mkf.open(QIODevice::WriteOnly | QIODevice::Text)) {
       
   525             writingUnixMakefileGenerator = true;
       
   526             if (Option::mkfile::listgen) {
       
   527                 generatePrint(fileInfo(mkf.fileName()).absoluteFilePath());
       
   528             }
       
   529             debug_msg(1, "pbuilder: Creating file: %s", mkfile.toLatin1().constData());
       
   530             QTextStream mkt(&mkf);
       
   531             writeHeader(mkt);
       
   532             mkt << "QMAKE    = "        << (project->isEmpty("QMAKE_QMAKE") ?
       
   533                                             QString((QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmake")) :
       
   534                                             var("QMAKE_QMAKE")) << endl;
       
   535             writeMakeQmake(mkt);
       
   536             mkt.flush();
       
   537             mkf.close();
       
   538             writingUnixMakefileGenerator = false;
       
   539         }
       
   540         QString phase_key = keyFor("QMAKE_PBX_MAKEQMAKE_BUILDPHASE");
       
   541         mkfile = fileFixify(mkfile, qmake_getpwd());
       
   542         project->values("QMAKE_PBX_PRESCRIPT_BUILDPHASES").append(phase_key);
       
   543         t << "\t\t" << phase_key << " = {" << "\n"
       
   544           << "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";" << "\n"
       
   545           << "\t\t\t" << writeSettings("files", QStringList(), SettingsAsList, 4) << ";" << "\n"
       
   546           << "\t\t\t" << writeSettings("generatedFileNames", QStringList(), SettingsAsList, 4) << ";" << "\n"
       
   547           << "\t\t\t" << writeSettings("isa", "PBXShellScriptBuildPhase", SettingsNoQuote) << ";" << "\n"
       
   548           << "\t\t\t" << writeSettings("name", "Qt Qmake") << ";" << "\n"
       
   549           << "\t\t\t" << writeSettings("neededFileNames", QStringList(), SettingsAsList, 4) << ";" << "\n"
       
   550           << "\t\t\t" << writeSettings("shellPath", "/bin/sh") << ";" << "\n"
       
   551           << "\t\t\t" << writeSettings("shellScript", fixForOutput("make -C " + escapeFilePath(qmake_getpwd()) + " -f " + escapeFilePath(mkfile))) << ";" << "\n"
       
   552           << "\t\t" << "};" << "\n";
       
   553     }
       
   554 
       
   555     //DUMP SOURCES
       
   556     QMap<QString, QStringList> groups;
       
   557     QList<ProjectBuilderSources> sources;
       
   558     sources.append(ProjectBuilderSources("SOURCES", true));
       
   559     sources.append(ProjectBuilderSources("GENERATED_SOURCES", true));
       
   560     sources.append(ProjectBuilderSources("GENERATED_FILES"));
       
   561     sources.append(ProjectBuilderSources("HEADERS"));
       
   562     sources.append(ProjectBuilderSources("QMAKE_INTERNAL_INCLUDED_FILES"));
       
   563     if(!project->isEmpty("QMAKE_EXTRA_COMPILERS")) {
       
   564         const QStringList &quc = project->values("QMAKE_EXTRA_COMPILERS");
       
   565         for(QStringList::ConstIterator it = quc.begin(); it != quc.end(); ++it) {
       
   566             QString tmp_out = project->first((*it) + ".output");
       
   567             if(project->isEmpty((*it) + ".output"))
       
   568                 continue;
       
   569             QString name = (*it);
       
   570             if(!project->isEmpty((*it) + ".name"))
       
   571                 name = project->first((*it) + ".name");
       
   572             const QStringList &inputs = project->values((*it) + ".input");
       
   573             for(int input = 0; input < inputs.size(); ++input) {
       
   574                 if(project->isEmpty(inputs.at(input)))
       
   575                     continue;
       
   576                 bool duplicate = false;
       
   577                 for(int i = 0; i < sources.size(); ++i) {
       
   578                     if(sources.at(i).keyName() == inputs.at(input)) {
       
   579                         duplicate = true;
       
   580                         break;
       
   581                     }
       
   582                 }
       
   583                 if(!duplicate) {
       
   584                     bool isObj = project->values((*it) + ".CONFIG").indexOf("no_link") == -1;
       
   585                     const QStringList &outputs = project->values((*it) + ".variable_out");
       
   586                     for(int output = 0; output < outputs.size(); ++output) {
       
   587                         if(outputs.at(output) != "OBJECT") {
       
   588                             isObj = false;
       
   589                             break;
       
   590                         }
       
   591                     }
       
   592                     sources.append(ProjectBuilderSources(inputs.at(input), true,
       
   593                                                          QString("Sources [") + name + "]", (*it), isObj));
       
   594                 }
       
   595             }
       
   596         }
       
   597     }
       
   598     for(int source = 0; source < sources.size(); ++source) {
       
   599         QStringList &src_list = project->values("QMAKE_PBX_" + sources.at(source).keyName());
       
   600         QStringList &root_group_list = project->values("QMAKE_PBX_GROUPS");
       
   601 
       
   602         QStringList files = fileFixify(sources.at(source).files(project));
       
   603         for(int f = 0; f < files.count(); ++f) {
       
   604             QString file = files[f];
       
   605             if(file.length() >= 2 && (file[0] == '"' || file[0] == '\'') && file[(int) file.length()-1] == file[0])
       
   606                 file = file.mid(1, file.length()-2);
       
   607             if(!sources.at(source).compilerName().isNull() &&
       
   608                !verifyExtraCompiler(sources.at(source).compilerName(), file))
       
   609                 continue;
       
   610             if(file.endsWith(Option::prl_ext))
       
   611                 continue;
       
   612 
       
   613             bool in_root = true;
       
   614             QString src_key = keyFor(file), name = file;
       
   615             if(project->isActiveConfig("flat")) {
       
   616                 QString flat_file = fileFixify(file, qmake_getpwd(), Option::output_dir, FileFixifyRelative);
       
   617                 if(flat_file.indexOf(Option::dir_sep) != -1) {
       
   618                     QStringList dirs = flat_file.split(Option::dir_sep);
       
   619                     name = dirs.back();
       
   620                 }
       
   621             } else {
       
   622                 QString flat_file = fileFixify(file, qmake_getpwd(), Option::output_dir, FileFixifyRelative);
       
   623                 if(QDir::isRelativePath(flat_file) && flat_file.indexOf(Option::dir_sep) != -1) {
       
   624                     QString last_grp("QMAKE_PBX_" + sources.at(source).groupName() + "_HEIR_GROUP");
       
   625                     QStringList dirs = flat_file.split(Option::dir_sep);
       
   626                     name = dirs.back();
       
   627                     dirs.pop_back(); //remove the file portion as it will be added via src_key
       
   628                     for(QStringList::Iterator dir_it = dirs.begin(); dir_it != dirs.end(); ++dir_it) {
       
   629                         QString new_grp(last_grp + Option::dir_sep + (*dir_it)), new_grp_key(keyFor(new_grp));
       
   630                         if(dir_it == dirs.begin()) {
       
   631                             if(!src_list.contains(new_grp_key))
       
   632                                 src_list.append(new_grp_key);
       
   633                         } else {
       
   634                             if(!groups[last_grp].contains(new_grp_key))
       
   635                                 groups[last_grp] += new_grp_key;
       
   636                         }
       
   637                         last_grp = new_grp;
       
   638                     }
       
   639                     groups[last_grp] += src_key;
       
   640                     in_root = false;
       
   641                 }
       
   642             }
       
   643             if(in_root)
       
   644                 src_list.append(src_key);
       
   645             //source reference
       
   646             t << "\t\t" << src_key << " = {" << "\n"
       
   647               << "\t\t\t" << writeSettings("isa", "PBXFileReference", SettingsNoQuote) << ";" << "\n"
       
   648               << "\t\t\t" << writeSettings("name", escapeFilePath(name)) << ";" << "\n"
       
   649               << "\t\t\t" << writeSettings("path", escapeFilePath(file)) << ";" << "\n"
       
   650               << "\t\t\t" << writeSettings("refType", QString::number(reftypeForFile(file)), SettingsNoQuote) << ";" << "\n";
       
   651             if(pbVersion >= 38) {
       
   652                 QString filetype;
       
   653                 for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) {
       
   654                     if(file.endsWith((*cppit))) {
       
   655                         filetype = "sourcecode.cpp.cpp";
       
   656                         break;
       
   657                     }
       
   658                 }
       
   659                 if(!filetype.isNull())
       
   660                     t << "\t\t\t" << writeSettings("lastKnownFileType", filetype) << ";" << "\n";
       
   661             }
       
   662             t << "\t\t" << "};" << "\n";
       
   663             if(sources.at(source).isBuildable()) { //build reference
       
   664                 QString build_key = keyFor(file + ".BUILDABLE");
       
   665                 t << "\t\t" << build_key << " = {" << "\n"
       
   666                   << "\t\t\t" << writeSettings("fileRef", src_key) << ";" << "\n"
       
   667                   << "\t\t\t" << writeSettings("isa", "PBXBuildFile", SettingsNoQuote) << ";" << "\n"
       
   668                   << "\t\t\t" << "settings = {" << "\n"
       
   669                   << "\t\t\t\t" << writeSettings("ATTRIBUTES", QStringList(), SettingsAsList, 5) << ";" << "\n"
       
   670                   << "\t\t\t" << "};" << "\n"
       
   671                   << "\t\t" << "};" << "\n";
       
   672                 if(sources.at(source).isObjectOutput(file))
       
   673                     project->values("QMAKE_PBX_OBJ").append(build_key);
       
   674             }
       
   675         }
       
   676         if(!src_list.isEmpty()) {
       
   677             QString group_key = keyFor(sources.at(source).groupName());
       
   678             if(root_group_list.indexOf(group_key) == -1)
       
   679                 root_group_list += group_key;
       
   680 
       
   681             QStringList &group = groups[sources.at(source).groupName()];
       
   682             for(int src = 0; src < src_list.size(); ++src) {
       
   683                 if(group.indexOf(src_list.at(src)) == -1)
       
   684                     group += src_list.at(src);
       
   685             }
       
   686         }
       
   687     }
       
   688     for(QMap<QString, QStringList>::Iterator grp_it = groups.begin(); grp_it != groups.end(); ++grp_it) {
       
   689         t << "\t\t" << keyFor(grp_it.key()) << " = {" << "\n"
       
   690           << "\t\t\t" << writeSettings("isa", "PBXGroup", SettingsNoQuote) << ";" << "\n"
       
   691           << "\t\t\t" << writeSettings("children", grp_it.value(), SettingsAsList, 4) << ";" << "\n"
       
   692           << "\t\t\t" << writeSettings("name", escapeFilePath(grp_it.key().section(Option::dir_sep, -1))) << ";" << "\n"
       
   693           << "\t\t\t" << writeSettings("refType", "4", SettingsNoQuote) << ";" << "\n"
       
   694           << "\t\t" << "};" << "\n";
       
   695     }
       
   696 
       
   697     //PREPROCESS BUILDPHASE (just a makefile)
       
   698     {
       
   699         QString mkfile = pbx_dir + Option::dir_sep + "qt_preprocess.mak";
       
   700         QFile mkf(mkfile);
       
   701         if(mkf.open(QIODevice::WriteOnly | QIODevice::Text)) {
       
   702             writingUnixMakefileGenerator = true;
       
   703             did_preprocess = true;
       
   704             if (Option::mkfile::listgen) {
       
   705                 generatePrint(fileInfo(mkf.fileName()).absoluteFilePath());
       
   706             }
       
   707             debug_msg(1, "pbuilder: Creating file: %s", mkfile.toLatin1().constData());
       
   708             QTextStream mkt(&mkf);
       
   709             writeHeader(mkt);
       
   710             mkt << "MOC       = " << Option::fixPathToTargetOS(var("QMAKE_MOC")) << endl;
       
   711             mkt << "UIC       = " << Option::fixPathToTargetOS(var("QMAKE_UIC")) << endl;
       
   712             mkt << "LEX       = " << var("QMAKE_LEX") << endl;
       
   713             mkt << "LEXFLAGS  = " << var("QMAKE_LEXFLAGS") << endl;
       
   714             mkt << "YACC      = " << var("QMAKE_YACC") << endl;
       
   715             mkt << "YACCFLAGS = " << var("QMAKE_YACCFLAGS") << endl;
       
   716             mkt << "DEFINES       = "
       
   717                 << varGlue("PRL_EXPORT_DEFINES","-D"," -D"," ")
       
   718                 << varGlue("DEFINES","-D"," -D","") << endl;
       
   719             mkt << "INCPATH       = " << "-I" << specdir();
       
   720             if(!project->isActiveConfig("no_include_pwd")) {
       
   721                 QString pwd = escapeFilePath(fileFixify(qmake_getpwd()));
       
   722                 if(pwd.isEmpty())
       
   723                     pwd = ".";
       
   724                 mkt << " -I" << pwd;
       
   725             }
       
   726             {
       
   727                 const QStringList &incs = project->values("INCLUDEPATH");
       
   728                 for(QStringList::ConstIterator incit = incs.begin(); incit != incs.end(); ++incit)
       
   729                     mkt << " " << "-I" << escapeFilePath((*incit));
       
   730             }
       
   731             if(!project->isEmpty("QMAKE_FRAMEWORKPATH_FLAGS"))
       
   732                mkt << " " << var("QMAKE_FRAMEWORKPATH_FLAGS");
       
   733             mkt << endl;
       
   734             mkt << "DEL_FILE  = " << var("QMAKE_DEL_FILE") << endl;
       
   735             mkt << "MOVE      = " << var("QMAKE_MOVE") << endl << endl;
       
   736             mkt << "IMAGES = " << varList("QMAKE_IMAGE_COLLECTION") << endl;
       
   737             mkt << "PARSERS =";
       
   738             if(!project->isEmpty("YACCSOURCES")) {
       
   739                 QStringList &yaccs = project->values("YACCSOURCES");
       
   740                 for(QStringList::Iterator yit = yaccs.begin(); yit != yaccs.end(); ++yit) {
       
   741                     QFileInfo fi(fileInfo((*yit)));
       
   742                     mkt << " " << fi.path() << Option::dir_sep << fi.baseName()
       
   743                         << Option::yacc_mod << Option::cpp_ext.first();
       
   744                 }
       
   745             }
       
   746             if(!project->isEmpty("LEXSOURCES")) {
       
   747                 QStringList &lexs = project->values("LEXSOURCES");
       
   748                 for(QStringList::Iterator lit = lexs.begin(); lit != lexs.end(); ++lit) {
       
   749                     QFileInfo fi(fileInfo((*lit)));
       
   750                     mkt << " " << fi.path() << Option::dir_sep << fi.baseName()
       
   751                         << Option::lex_mod << Option::cpp_ext.first();
       
   752                 }
       
   753             }
       
   754             mkt << "\n";
       
   755             mkt << "preprocess: $(PARSERS) compilers" << endl;
       
   756             mkt << "clean preprocess_clean: parser_clean compiler_clean" << endl << endl;
       
   757             mkt << "parser_clean:" << "\n";
       
   758             if(!project->isEmpty("YACCSOURCES") || !project->isEmpty("LEXSOURCES"))
       
   759                 mkt << "\t-rm -f $(PARSERS)" << "\n";
       
   760             writeExtraTargets(mkt);
       
   761             if(!project->isEmpty("QMAKE_EXTRA_COMPILERS")) {
       
   762                 mkt << "compilers:";
       
   763                 const QStringList &compilers = project->values("QMAKE_EXTRA_COMPILERS");
       
   764                 for(int compiler = 0; compiler < compilers.size(); ++compiler) {
       
   765                     QString tmp_out = project->first(compilers.at(compiler) + ".output");
       
   766                     if(project->isEmpty(compilers.at(compiler) + ".output"))
       
   767                         continue;
       
   768                     const QStringList &inputs = project->values(compilers.at(compiler) + ".input");
       
   769                     for(int input = 0; input < inputs.size(); ++input) {
       
   770                         if(project->isEmpty(inputs.at(input)))
       
   771                             continue;
       
   772                         const QStringList &files = project->values(inputs.at(input));
       
   773                         for(int file = 0, added = 0; file < files.size(); ++file) {
       
   774                             if(!verifyExtraCompiler(compilers.at(compiler), files.at(file)))
       
   775                                 continue;
       
   776                             if(added && !(added % 3))
       
   777                                 mkt << "\\\n\t";
       
   778                             ++added;
       
   779                             const QString file_name = fileFixify(files.at(file), Option::output_dir, Option::output_dir);
       
   780                             mkt << " " << replaceExtraCompilerVariables(tmp_out, file_name, QString());
       
   781                         }
       
   782                     }
       
   783                 }
       
   784                 mkt << endl;
       
   785                 writeExtraCompilerTargets(mkt);
       
   786                 writingUnixMakefileGenerator = false;
       
   787             }
       
   788             mkt.flush();
       
   789             mkf.close();
       
   790         }
       
   791         mkfile = fileFixify(mkfile, qmake_getpwd());
       
   792         QString phase_key = keyFor("QMAKE_PBX_PREPROCESS_TARGET");
       
   793 //        project->values("QMAKE_PBX_BUILDPHASES").append(phase_key);
       
   794         project->values("QMAKE_PBX_PRESCRIPT_BUILDPHASES").append(phase_key);
       
   795         t << "\t\t" << phase_key << " = {" << "\n"
       
   796           << "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";" << "\n"
       
   797           << "\t\t\t" << writeSettings("files", QStringList(), SettingsAsList, 4) << ";" << "\n"
       
   798           << "\t\t\t" << writeSettings("generatedFileNames", fixListForOutput("QMAKE_PBX_OBJ"), SettingsAsList, 4) << ";" << "\n"
       
   799           << "\t\t\t" << writeSettings("isa", "PBXShellScriptBuildPhase", SettingsNoQuote) << ";" << "\n"
       
   800           << "\t\t\t" << writeSettings("name", "Qt Preprocessors") << ";" << "\n"
       
   801           << "\t\t\t" << writeSettings("neededFileNames", fixListForOutput("QMAKE_PBX_OBJ"), SettingsAsList, 4) << ";" << "\n"
       
   802           << "\t\t\t" << writeSettings("shellPath", "/bin/sh") << ";" << "\n"
       
   803           << "\t\t\t" << writeSettings("shellScript", fixForOutput("make -C " + escapeFilePath(qmake_getpwd()) + " -f " + escapeFilePath(mkfile))) << ";" << "\n"
       
   804           << "\t\t" << "};" << "\n";
       
   805    }
       
   806 
       
   807     //SOURCE BUILDPHASE
       
   808     if(!project->isEmpty("QMAKE_PBX_OBJ")) {
       
   809         QString grp = "Build Sources", key = keyFor(grp);
       
   810         project->values("QMAKE_PBX_BUILDPHASES").append(key);
       
   811         t << "\t\t" << key << " = {" << "\n"
       
   812           << "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";" << "\n"
       
   813           << "\t\t\t" << writeSettings("files", fixListForOutput("QMAKE_PBX_OBJ"), SettingsAsList, 4) << ";" << "\n"
       
   814           << "\t\t\t" << writeSettings("isa", "PBXSourcesBuildPhase", SettingsNoQuote) << ";" << "\n"
       
   815           << "\t\t\t" << writeSettings("name", grp) << ";" << "\n"
       
   816           << "\t\t" << "};" << "\n";
       
   817     }
       
   818 
       
   819     if(!project->isActiveConfig("staticlib")) { //DUMP LIBRARIES
       
   820         QStringList &libdirs = project->values("QMAKE_PBX_LIBPATHS"),
       
   821               &frameworkdirs = project->values("QMAKE_FRAMEWORKPATH");
       
   822         QString libs[] = { "QMAKE_LFLAGS", "QMAKE_LIBDIR_FLAGS", "QMAKE_FRAMEWORKPATH_FLAGS",
       
   823                            "QMAKE_LIBS", QString() };
       
   824         for(int i = 0; !libs[i].isNull(); i++) {
       
   825             tmp = project->values(libs[i]);
       
   826             for(int x = 0; x < tmp.count();) {
       
   827                 bool remove = false;
       
   828                 QString library, name, opt = tmp[x].trimmed();
       
   829                 if(opt.length() >= 2 && (opt[0] == '"' || opt[0] == '\'') &&
       
   830                    opt[(int) opt.length()-1] == opt[0])
       
   831                     opt = opt.mid(1, opt.length()-2);
       
   832                 if(opt.startsWith("-L")) {
       
   833                     QString r = opt.right(opt.length() - 2);
       
   834                     fixForOutput(r);
       
   835                     libdirs.append(r);
       
   836                 } else if(opt == "-prebind") {
       
   837                     project->values("QMAKE_DO_PREBINDING").append("TRUE");
       
   838                     remove = true;
       
   839                 } else if(opt.startsWith("-l")) {
       
   840                     name = opt.right(opt.length() - 2);
       
   841                     QString lib("lib" + name);
       
   842                     for(QStringList::Iterator lit = libdirs.begin(); lit != libdirs.end(); ++lit) {
       
   843                         if(project->isActiveConfig("link_prl")) {
       
   844                             /* This isn't real nice, but it is real useful. This looks in a prl
       
   845                                for what the library will ultimately be called so we can stick it
       
   846                                in the ProjectFile. If the prl format ever changes (not likely) then
       
   847                                this will not really work. However, more concerning is that it will
       
   848                                encode the version number in the Project file which might be a bad
       
   849                                things in days to come? --Sam
       
   850                             */
       
   851                             QString lib_file = (*lit) + Option::dir_sep + lib;
       
   852                             if(QMakeMetaInfo::libExists(lib_file)) {
       
   853                                 QMakeMetaInfo libinfo;
       
   854                                 if(libinfo.readLib(lib_file)) {
       
   855                                     if(!libinfo.isEmpty("QMAKE_PRL_TARGET")) {
       
   856                                         library = (*lit) + Option::dir_sep + libinfo.first("QMAKE_PRL_TARGET");
       
   857                                         debug_msg(1, "pbuilder: Found library (%s) via PRL %s (%s)",
       
   858                                                   opt.toLatin1().constData(), lib_file.toLatin1().constData(), library.toLatin1().constData());
       
   859                                         remove = true;
       
   860                                     }
       
   861                                 }
       
   862                             }
       
   863                         }
       
   864                         if(!remove) {
       
   865                             QString extns[] = { ".dylib", ".so", ".a", QString() };
       
   866                             for(int n = 0; !remove && !extns[n].isNull(); n++) {
       
   867                                 QString tmp =  (*lit) + Option::dir_sep + lib + extns[n];
       
   868                                 if(exists(tmp)) {
       
   869                                     library = tmp;
       
   870                                     debug_msg(1, "pbuilder: Found library (%s) via %s",
       
   871                                               opt.toLatin1().constData(), library.toLatin1().constData());
       
   872                                     remove = true;
       
   873                                 }
       
   874                             }
       
   875                         }
       
   876                     }
       
   877                 } else if(opt.startsWith("-F")) {
       
   878                     QString r;
       
   879                     if(opt.size() > 2) {
       
   880                         r = opt.right(opt.length() - 2);
       
   881                     } else {
       
   882                         if(x == tmp.count()-1)
       
   883                             break;
       
   884                         r = tmp[++x];
       
   885                     }
       
   886                     if(!r.isEmpty()) {
       
   887                         fixForOutput(r);
       
   888                         frameworkdirs.append(r);
       
   889                     }
       
   890                 } else if(opt == "-framework") {
       
   891                     if(x == tmp.count()-1)
       
   892                         break;
       
   893                     const QString framework = tmp[x+1];
       
   894                     QStringList fdirs = frameworkdirs;
       
   895                     fdirs << "/System/Library/Frameworks/" << "/Library/Frameworks/";
       
   896                     for(int fdir = 0; fdir < fdirs.count(); fdir++) {
       
   897                         if(exists(fdirs[fdir] + QDir::separator() + framework + ".framework")) {
       
   898                             tmp.removeAt(x);
       
   899                             remove = true;
       
   900                             library = fdirs[fdir] + Option::dir_sep + framework + ".framework";
       
   901                             break;
       
   902                         }
       
   903                     }
       
   904                 } else if(opt.left(1) != "-") {
       
   905                     if(exists(opt)) {
       
   906                         remove = true;
       
   907                         library = opt;
       
   908                     }
       
   909                 }
       
   910                 if(!library.isEmpty()) {
       
   911                     const int slsh = library.lastIndexOf(Option::dir_sep);
       
   912                     if(name.isEmpty()) {
       
   913                         if(slsh != -1)
       
   914                             name = library.right(library.length() - slsh - 1);
       
   915                     }
       
   916                     if(slsh != -1) {
       
   917                         const QString path = QFileInfo(library.left(slsh)).absoluteFilePath();
       
   918                         if(!path.isEmpty() && !libdirs.contains(path))
       
   919                             libdirs += path;
       
   920                     }
       
   921                     library = fileFixify(library);
       
   922                     QString key = keyFor(library);
       
   923                     bool is_frmwrk = (library.endsWith(".framework"));
       
   924                     t << "\t\t" << key << " = {" << "\n"
       
   925                       << "\t\t\t" << writeSettings("isa", (is_frmwrk ? "PBXFrameworkReference" : "PBXFileReference"), SettingsNoQuote) << ";" << "\n"
       
   926                       << "\t\t\t" << writeSettings("name", escapeFilePath(name)) << ";" << "\n"
       
   927                       << "\t\t\t" << writeSettings("path", escapeFilePath(library)) << ";" << "\n"
       
   928                       << "\t\t\t" << writeSettings("refType", QString::number(reftypeForFile(library)), SettingsNoQuote) << ";" << "\n"
       
   929                       << "\t\t" << "};" << "\n";
       
   930                     project->values("QMAKE_PBX_LIBRARIES").append(key);
       
   931                     QString build_key = keyFor(library + ".BUILDABLE");
       
   932                     t << "\t\t" << build_key << " = {" << "\n"
       
   933                       << "\t\t\t" << writeSettings("fileRef", key) << ";" << "\n"
       
   934                       << "\t\t\t" << writeSettings("isa", "PBXBuildFile", SettingsNoQuote) << ";" << "\n"
       
   935                       << "\t\t\t" << "settings = {" << "\n"
       
   936                       << "\t\t\t" << "};" << "\n"
       
   937                       << "\t\t" << "};" << "\n";
       
   938                     project->values("QMAKE_PBX_BUILD_LIBRARIES").append(build_key);
       
   939                 }
       
   940                 if(remove)
       
   941                     tmp.removeAt(x);
       
   942                 else
       
   943                     x++;
       
   944             }
       
   945             project->values(libs[i]) = tmp;
       
   946         }
       
   947     }
       
   948     //SUBLIBS BUILDPHASE (just another makefile)
       
   949     if(!project->isEmpty("SUBLIBS")) {
       
   950         QString mkfile = pbx_dir + Option::dir_sep + "qt_sublibs.mak";
       
   951         QFile mkf(mkfile);
       
   952         if(mkf.open(QIODevice::WriteOnly | QIODevice::Text)) {
       
   953             writingUnixMakefileGenerator = true;
       
   954             if (Option::mkfile::listgen) {
       
   955                 generatePrint(fileInfo(mkf.fileName()).absoluteFilePath());
       
   956             }
       
   957             debug_msg(1, "pbuilder: Creating file: %s", mkfile.toLatin1().constData());
       
   958             QTextStream mkt(&mkf);
       
   959             writeHeader(mkt);
       
   960             mkt << "SUBLIBS= ";
       
   961             tmp = project->values("SUBLIBS");
       
   962             for(int i = 0; i < tmp.count(); i++)
       
   963                 t << "tmp/lib" << tmp[i] << ".a ";
       
   964             t << endl << endl;
       
   965             mkt << "sublibs: $(SUBLIBS)" << endl << endl;
       
   966             tmp = project->values("SUBLIBS");
       
   967             for(int i = 0; i < tmp.count(); i++)
       
   968                 t << "tmp/lib" << tmp[i] << ".a" << ":\n\t"
       
   969                   << var(QString("MAKELIB") + tmp[i]) << endl << endl;
       
   970             mkt.flush();
       
   971             mkf.close();
       
   972             writingUnixMakefileGenerator = false;
       
   973         }
       
   974         QString phase_key = keyFor("QMAKE_PBX_SUBLIBS_BUILDPHASE");
       
   975         mkfile = fileFixify(mkfile, qmake_getpwd());
       
   976         project->values("QMAKE_PBX_PRESCRIPT_BUILDPHASES").append(phase_key);
       
   977         t << "\t\t" << phase_key << " = {" << "\n"
       
   978           << "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";" << "\n"
       
   979           << "\t\t\t" << writeSettings("files", QStringList(), SettingsAsList, 4) << ";" << "\n"
       
   980           << "\t\t\t" << writeSettings("generatedFileNames", QStringList(), SettingsAsList, 4) << ";" << "\n"
       
   981           << "\t\t\t" << writeSettings("isa", "PBXShellScriptBuildPhase", SettingsNoQuote) << ";" << "\n"
       
   982           << "\t\t\t" << writeSettings("name", "Qt Sublibs") << ";" << "\n"
       
   983           << "\t\t\t" << writeSettings("neededFileNames", QStringList(), SettingsAsList, 4) << ";" << "\n"
       
   984           << "\t\t\t" << writeSettings("shellPath", "/bin/sh") << "\n"
       
   985           << "\t\t\t" << writeSettings("shellScript", fixForOutput("make -C " + escapeFilePath(qmake_getpwd()) + " -f " + escapeFilePath(mkfile))) << ";" << "\n"
       
   986           << "\t\t" << "};" << "\n";
       
   987     }
       
   988     //LIBRARY BUILDPHASE
       
   989     if(!project->isEmpty("QMAKE_PBX_LIBRARIES")) {
       
   990         tmp = project->values("QMAKE_PBX_LIBRARIES");
       
   991         if(!tmp.isEmpty()) {
       
   992             QString grp("External Frameworks and Libraries"), key = keyFor(grp);
       
   993             project->values("QMAKE_PBX_GROUPS").append(key);
       
   994             t << "\t\t" << key << " = {" << "\n"
       
   995               << "\t\t\t" << writeSettings("children", project->values("QMAKE_PBX_LIBRARIES"), SettingsAsList, 4) << ";" << "\n"
       
   996               << "\t\t\t" << writeSettings("isa", "PBXGroup", SettingsNoQuote) << ";" << "\n"
       
   997               << "\t\t\t" << writeSettings("name", escapeFilePath(grp)) << ";" << "\n"
       
   998               << "\t\t\t" << writeSettings("path", QStringList()) << ";" << "\n"
       
   999               << "\t\t\t" << writeSettings("refType", "4", SettingsNoQuote) << ";" << "\n"
       
  1000               << "\t\t" << "};" << "\n";
       
  1001         }
       
  1002     }
       
  1003     {
       
  1004         QString grp("Frameworks & Libraries"), key = keyFor(grp);
       
  1005         project->values("QMAKE_PBX_BUILDPHASES").append(key);
       
  1006         t << "\t\t" << key << " = {" << "\n"
       
  1007           << "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";" << "\n"
       
  1008           << "\t\t\t" << writeSettings("files", project->values("QMAKE_PBX_BUILD_LIBRARIES"), SettingsAsList, 4) << ";" << "\n"
       
  1009           << "\t\t\t" << writeSettings("isa", "PBXFrameworksBuildPhase", SettingsNoQuote) << ";" << "\n"
       
  1010           << "\t\t\t" << writeSettings("name", escapeFilePath(grp)) << ";" << "\n"
       
  1011           << "\t\t" << "};" << "\n";
       
  1012     }
       
  1013     if(project->isActiveConfig("app_bundle") && project->first("TEMPLATE") == "app") { //BUNDLE RESOURCES
       
  1014         QString grp("Bundle Resources"), key = keyFor(grp);
       
  1015         project->values("QMAKE_PBX_BUILDPHASES").append(key);
       
  1016         t << "\t\t" << key << " = {" << "\n"
       
  1017           << "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";" << "\n"
       
  1018           << "\t\t\t" << "files = (" << "\n";
       
  1019         if(!project->isEmpty("ICON")) {
       
  1020             QString icon = project->first("ICON");
       
  1021             if(icon.length() >= 2 && (icon[0] == '"' || icon[0] == '\'') && icon[(int)icon.length()-1] == icon[0])
       
  1022                 icon = icon.mid(1, icon.length()-2);
       
  1023             t << "\t\t\t\t" << keyFor(icon + ".BUILDABLE") << ",\n";
       
  1024         }
       
  1025         t << "\t\t\t" << ");" << "\n"
       
  1026           << "\t\t\t" << writeSettings("isa", "PBXResourcesBuildPhase", SettingsNoQuote) << ";" << "\n"
       
  1027           << "\t\t\t" << writeSettings("name", escapeFilePath(grp)) << ";" << "\n"
       
  1028           << "\t\t" << "};" << "\n";
       
  1029     }
       
  1030     { //INSTALL BUILDPHASE (copy)
       
  1031         QString phase_key = keyFor("QMAKE_PBX_TARGET_COPY_PHASE");
       
  1032         QString destDir = Option::output_dir;
       
  1033         if (!project->isEmpty("QMAKE_ORIG_DESTDIR"))
       
  1034             destDir = project->first("QMAKE_ORIG_DESTDIR");
       
  1035         destDir = fixForOutput(destDir);
       
  1036         destDir = fileInfo(Option::fixPathToLocalOS(destDir)).absoluteFilePath();
       
  1037         project->values("QMAKE_PBX_PRESCRIPT_BUILDPHASES").append(phase_key);
       
  1038         t << "\t\t" << phase_key << " = {\n"
       
  1039           << "\t\t\t" << writeSettings("name", "Project Copy") << ";" << "\n"
       
  1040           << "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";" << "\n"
       
  1041           << "\t\t\t" << writeSettings("dstPath", escapeFilePath(destDir)) << ";" << "\n"
       
  1042           << "\t\t\t" << writeSettings("dstSubfolderSpec", "0", SettingsNoQuote) << ";" << "\n"
       
  1043           << "\t\t\t" << writeSettings("files", keyFor("QMAKE_PBX_TARGET_COPY_FILE"), SettingsAsList, 4) << ";" << "\n"
       
  1044           << "\t\t\t" << writeSettings("isa", "PBXCopyFilesBuildPhase", SettingsNoQuote) << ";" << "\n"
       
  1045           << "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";" << "\n"
       
  1046           << "\t\t" << "};\n"
       
  1047           << "\t\t" << keyFor("QMAKE_PBX_TARGET_COPY_FILE")  << " = {\n"
       
  1048           << "\t\t\t" << writeSettings("fileRef", keyFor(pbx_dir + "QMAKE_PBX_REFERENCE")) << ";" << "\n"
       
  1049           << "\t\t\t" << writeSettings("isa", "PBXBuildFile", SettingsNoQuote) << ";" << "\n"
       
  1050           << "\t\t\t" << "settings = {\n"
       
  1051           << "\t\t\t" << "};\n"
       
  1052           << "\t\t" << "};\n";
       
  1053     }
       
  1054     //BUNDLE_DATA BUILDPHASE (copy)
       
  1055     if(!project->isEmpty("QMAKE_BUNDLE_DATA")) {
       
  1056         QStringList bundle_file_refs;
       
  1057         //all bundle data
       
  1058         const QStringList &bundle_data = project->values("QMAKE_BUNDLE_DATA");
       
  1059         for(int i = 0; i < bundle_data.count(); i++) {
       
  1060             QStringList pbx_files;
       
  1061             //all files
       
  1062             const QStringList &files = project->values(bundle_data[i] + ".files");
       
  1063             for(int file = 0; file < files.count(); file++) {
       
  1064                 QString file_ref_key = keyFor("QMAKE_PBX_BUNDLE_COPY_FILE_REF." + bundle_data[i] + "-" + files[file]);
       
  1065                 bundle_file_refs += file_ref_key;
       
  1066                 t << "\t\t" << file_ref_key << " = {" << "\n"
       
  1067                   << "\t\t\t" << writeSettings("isa", "PBXFileReference", SettingsNoQuote) << ";" << "\n"
       
  1068                   << "\t\t\t" << writeSettings("path", escapeFilePath(files[file])) << ";" << "\n"
       
  1069                   << "\t\t\t" << writeSettings("refType", QString::number(reftypeForFile(files[file])), SettingsNoQuote) << ";" << "\n"
       
  1070                   << "\t\t" << "};" << "\n";
       
  1071                 QString copy_file_key = keyFor("QMAKE_PBX_BUNDLE_COPY_FILE." + bundle_data[i] + "-" + files[file]);
       
  1072                 pbx_files += copy_file_key;
       
  1073                 t << "\t\t" <<  copy_file_key << " = {\n"
       
  1074                   << "\t\t\t" << writeSettings("fileRef", file_ref_key) << ";" << "\n"
       
  1075                   << "\t\t\t" << writeSettings("isa", "PBXBuildFile", SettingsNoQuote) << ";" << "\n"
       
  1076                   << "\t\t\t" << "settings = {\n"
       
  1077                   << "\t\t\t" << "}" << ";" << "\n"
       
  1078                   << "\t\t" << "}" << ";" << "\n";
       
  1079             }
       
  1080             //the phase
       
  1081             QString phase_key = keyFor("QMAKE_PBX_BUNDLE_COPY." + bundle_data[i]);
       
  1082             QString path;
       
  1083             if(!project->isEmpty(bundle_data[i] + ".version")) {
       
  1084                 //###
       
  1085             }
       
  1086             path += project->first(bundle_data[i] + ".path");
       
  1087             project->values("QMAKE_PBX_PRESCRIPT_BUILDPHASES").append(phase_key);
       
  1088             t << "\t\t" << phase_key << " = {\n"
       
  1089               << "\t\t\t" << writeSettings("name", "Bundle Copy [" + bundle_data[i] + "]") << ";" << "\n"
       
  1090               << "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";" << "\n"
       
  1091               << "\t\t\t" << writeSettings("dstPath", escapeFilePath(path)) << ";" << "\n"
       
  1092               << "\t\t\t" << writeSettings("dstSubfolderSpec", "1", SettingsNoQuote) << ";" << "\n"
       
  1093               << "\t\t\t" << writeSettings("files", pbx_files, SettingsAsList, 4) << ";" << "\n"
       
  1094               << "\t\t\t" << writeSettings("isa", "PBXCopyFilesBuildPhase", SettingsNoQuote) << ";" << "\n"
       
  1095               << "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";" << "\n"
       
  1096               << "\t\t" << "}" << ";" << "\n";
       
  1097         }
       
  1098         QString bundle_copy_key = keyFor("QMAKE_PBX_BUNDLE_COPY");
       
  1099         project->values("QMAKE_PBX_GROUPS").append(bundle_copy_key);
       
  1100         t << "\t\t" << bundle_copy_key << " = {" << "\n"
       
  1101           << "\t\t\t" << writeSettings("children", bundle_file_refs, SettingsAsList, 4) << ";" << "\n"
       
  1102           << "\t\t\t" << writeSettings("isa", "PBXGroup", SettingsNoQuote) << ";" << "\n"
       
  1103           << "\t\t\t" << writeSettings("name", "Source [bundle data]") << ";" << "\n"
       
  1104           << "\t\t\t" << writeSettings("path", QStringList()) << ";" << "\n"
       
  1105           << "\t\t\t" << writeSettings("refType", "4", SettingsNoQuote) << ";" << "\n"
       
  1106           << "\t\t" << "};" << "\n";
       
  1107     }
       
  1108 
       
  1109     if(/*pbVersion >= 38 &&*/ !project->isEmpty("QMAKE_PBX_PRESCRIPT_BUILDPHASES") && 0) {
       
  1110         // build reference
       
  1111         t << "\t\t" << keyFor("QMAKE_PBX_PRESCRIPT_BUILDREFERENCE") << " = {" << "\n"
       
  1112           << "\t\t\t" << writeSettings("includeInIndex", "0") << ";" << "\n"
       
  1113           << "\t\t\t" << writeSettings("isa", "PBXFileReference", SettingsNoQuote) << ";" << "\n"
       
  1114           << "\t\t\t" << writeSettings("path", "preprocessor.out") << ";" << "\n"
       
  1115           << "\t\t\t" << writeSettings("refType", "3", SettingsNoQuote) << ";" << "\n"
       
  1116           << "\t\t\t" << writeSettings("sourceTree", "BUILT_PRODUCTS_DIR", SettingsNoQuote) << ";" << "\n"
       
  1117           << "\t\t" << "};" << "\n";
       
  1118         project->values("QMAKE_PBX_PRODUCTS").append(keyFor("QMAKE_PBX_PRESCRIPTS_BUILDREFERENCE"));
       
  1119         //build phase
       
  1120         t << "\t\t" << keyFor("QMAKE_PBX_PRESCRIPTS_BUILDPHASE") << " = {" << "\n"
       
  1121           << "\t\t\t" << writeSettings("buildPhases", project->values("QMAKE_PBX_PRESCRIPT_BUILDPHASES"), SettingsAsList, 4) << ";" << "\n"
       
  1122           << "\t\t\t" << writeSettings("buildRules", QStringList(), SettingsAsList, 4) << ";" << "\n"
       
  1123           << "\t\t\t" << writeSettings("buildSettings", QStringList(), SettingsAsList, 4) << ";" << "\n"
       
  1124           << "\t\t\t" << writeSettings("dependencies", QStringList(), SettingsAsList, 4) << ";" << "\n"
       
  1125           << "\t\t\t" << writeSettings("isa", "PBXNativeTarget", SettingsNoQuote) << ";" << "\n"
       
  1126           << "\t\t\t" << writeSettings("name", "Qt Preprocessor Steps") << ";" << "\n"
       
  1127           << "\t\t\t" << writeSettings("productName", "Qt Preprocessor Steps") << ";" << "\n"
       
  1128           << "\t\t\t" << writeSettings("productReference", keyFor("QMAKE_PBX_PRESCRIPTS_BUILDREFERENCE")) << ";" << "\n";
       
  1129         if(!project->isEmpty("QMAKE_PBX_PRODUCT_TYPE"))
       
  1130             t << "\t\t\t" << writeSettings("productType", project->first("QMAKE_PBX_PRODUCT_TYPE")) << ";" << "\n";
       
  1131         else
       
  1132             t << "\t\t\t" << writeSettings("productType", "com.apple.product-type.tool") << ";" << "\n";
       
  1133         t << "\t\t" << "};" << "\n";
       
  1134         //dependency
       
  1135         t << "\t\t" << keyFor("QMAKE_PBX_PRESCRIPTS_DEPENDENCY") << " = {" << "\n"
       
  1136           << "\t\t\t" << writeSettings("isa", "PBXTargetDependency", SettingsNoQuote) << ";" << "\n"
       
  1137           << "\t\t\t" << writeSettings("target", keyFor("QMAKE_PBX_PRESCRIPTS_BUILDPHASE")) << ";" << "\n"
       
  1138           << "\t\t" << "};" << "\n";
       
  1139         project->values("QMAKE_PBX_TARGET_DEPENDS").append(keyFor("QMAKE_PBX_PRESCRIPTS_DEPENDENCY"));
       
  1140         project->values("QMAKE_PBX_PRESCRIPT_BUILDPHASES").clear(); //these are already consumed above
       
  1141    }
       
  1142 
       
  1143     //DUMP EVERYTHING THAT TIES THE ABOVE TOGETHER
       
  1144     //ROOT_GROUP
       
  1145     t << "\t\t" << keyFor("QMAKE_PBX_ROOT_GROUP") << " = {" << "\n"
       
  1146       << "\t\t\t" << writeSettings("children", project->values("QMAKE_PBX_GROUPS"), SettingsAsList, 4) << ";" << "\n"
       
  1147       << "\t\t\t" << writeSettings("isa", "PBXGroup", SettingsNoQuote) << ";" << "\n"
       
  1148       << "\t\t\t" << writeSettings("name", escapeFilePath(project->first("QMAKE_ORIG_TARGET"))) << ";" << "\n"
       
  1149       << "\t\t\t" << writeSettings("path", QStringList()) << ";" << "\n"
       
  1150       << "\t\t\t" << writeSettings("refType", "4", SettingsNoQuote) << ";" << "\n"
       
  1151       << "\t\t" << "};" << "\n";
       
  1152     //REFERENCE
       
  1153     project->values("QMAKE_PBX_PRODUCTS").append(keyFor(pbx_dir + "QMAKE_PBX_REFERENCE"));
       
  1154     t << "\t\t" << keyFor(pbx_dir + "QMAKE_PBX_REFERENCE") << " = {" << "\n"
       
  1155       << "\t\t\t" << writeSettings("isa",  "PBXFileReference", SettingsNoQuote) << ";" << "\n";
       
  1156     if(project->first("TEMPLATE") == "app") {
       
  1157         QString targ = project->first("QMAKE_ORIG_TARGET");
       
  1158         if(project->isActiveConfig("bundle") && !project->isEmpty("QMAKE_BUNDLE_EXTENSION")) {
       
  1159             if(!project->isEmpty("QMAKE_BUNDLE_NAME"))
       
  1160                 targ = project->first("QMAKE_BUNDLE_NAME");
       
  1161             targ += project->first("QMAKE_BUNDLE_EXTENSION");
       
  1162             if(!project->isEmpty("QMAKE_PBX_BUNDLE_TYPE"))
       
  1163                 t << "\t\t\t" << writeSettings("explicitFileType", project->first("QMAKE_PBX_BUNDLE_TYPE")) + ";" << "\n";
       
  1164         } else if(project->isActiveConfig("app_bundle")) {
       
  1165             if(!project->isEmpty("QMAKE_APPLICATION_BUNDLE_NAME"))
       
  1166                 targ = project->first("QMAKE_APPLICATION_BUNDLE_NAME");
       
  1167             targ += ".app";
       
  1168             t << "\t\t\t" << writeSettings("explicitFileType", "wrapper.application") << ";" << "\n";
       
  1169         } else {
       
  1170             t << "\t\t\t" << writeSettings("explicitFileType", "wrapper.executable") << ";" << "\n";
       
  1171         }
       
  1172         QString app = (!project->isEmpty("DESTDIR") ? project->first("DESTDIR") + project->first("QMAKE_ORIG_TARGET") :
       
  1173                        qmake_getpwd()) + Option::dir_sep + targ;
       
  1174         t << "\t\t\t" << writeSettings("path", escapeFilePath(targ)) << ";" << "\n";
       
  1175     } else {
       
  1176         QString lib = project->first("QMAKE_ORIG_TARGET");
       
  1177         if(project->isActiveConfig("staticlib")) {
       
  1178             lib = project->first("TARGET");
       
  1179         } else if(!project->isActiveConfig("lib_bundle")) {
       
  1180             if(project->isActiveConfig("plugin"))
       
  1181                 lib = project->first("TARGET");
       
  1182             else
       
  1183                 lib = project->first("TARGET_");
       
  1184         }
       
  1185         int slsh = lib.lastIndexOf(Option::dir_sep);
       
  1186         if(slsh != -1)
       
  1187             lib = lib.right(lib.length() - slsh - 1);
       
  1188         if(project->isActiveConfig("bundle") && !project->isEmpty("QMAKE_BUNDLE_EXTENSION")) {
       
  1189             if(!project->isEmpty("QMAKE_BUNDLE_NAME"))
       
  1190                 lib = project->first("QMAKE_BUNDLE_NAME");
       
  1191             lib += project->first("QMAKE_BUNDLE_EXTENSION");
       
  1192             if(!project->isEmpty("QMAKE_PBX_BUNDLE_TYPE"))
       
  1193                 t << "\t\t\t" << writeSettings("explicitFileType", project->first("QMAKE_PBX_BUNDLE_TYPE")) << ";" << "\n";
       
  1194         } else if(!project->isActiveConfig("staticlib") && project->isActiveConfig("lib_bundle")) {
       
  1195             if(!project->isEmpty("QMAKE_FRAMEWORK_BUNDLE_NAME"))
       
  1196                 lib = project->first("QMAKE_FRAMEWORK_BUNDLE_NAME");
       
  1197             lib += ".framework";
       
  1198             t << "\t\t\t" << writeSettings("explicitFileType", "wrapper.framework") << ";" << "\n";
       
  1199         } else {
       
  1200             t << "\t\t\t" << writeSettings("explicitFileType", "compiled.mach-o.dylib") << ";" << "\n";
       
  1201         }
       
  1202         t << "\t\t\t" << writeSettings("path", escapeFilePath(lib)) << ";" << "\n";
       
  1203     }
       
  1204     t << "\t\t\t" << writeSettings("refType", "3", SettingsNoQuote) << ";" << "\n"
       
  1205       << "\t\t\t" << writeSettings("sourceTree", "BUILT_PRODUCTS_DIR", SettingsNoQuote) << ";" << "\n"
       
  1206       << "\t\t" << "};" << "\n";
       
  1207     { //Products group
       
  1208         QString grp("Products"), key = keyFor(grp);
       
  1209         project->values("QMAKE_PBX_GROUPS").append(key);
       
  1210         t << "\t\t" << key << " = {" << "\n"
       
  1211           << "\t\t\t" << writeSettings("children", project->values("QMAKE_PBX_PRODUCTS"), SettingsAsList, 4) << ";" << "\n"
       
  1212           << "\t\t\t" << writeSettings("isa", "PBXGroup", SettingsNoQuote) << ";" << "\n"
       
  1213           << "\t\t\t" << writeSettings("name", "Products") << ";" << "\n"
       
  1214           << "\t\t\t" << writeSettings("refType", "4", SettingsNoQuote) << ";" << "\n"
       
  1215           << "\t\t" << "};" << "\n";
       
  1216     }
       
  1217     //TARGET
       
  1218     QString target_key = keyFor(pbx_dir + "QMAKE_PBX_TARGET");
       
  1219     project->values("QMAKE_PBX_TARGETS").append(target_key);
       
  1220     t << "\t\t" << target_key << " = {" << "\n"
       
  1221       << "\t\t\t" << writeSettings("buildPhases", project->values("QMAKE_PBX_PRESCRIPT_BUILDPHASES") + project->values("QMAKE_PBX_BUILDPHASES"),
       
  1222                                    SettingsAsList, 4) << ";" << "\n"
       
  1223       << "\t\t\t" << "buildSettings = {" << "\n";
       
  1224     QString cCompiler = project->first("QMAKE_CC");
       
  1225     if (!cCompiler.isEmpty()) {
       
  1226         t << "\t\t\t\t" << writeSettings("CC", fixForOutput(findProgram(cCompiler))) << ";" << "\n";
       
  1227     }
       
  1228     cCompiler = project->first("QMAKE_CXX");
       
  1229     if (!cCompiler.isEmpty()) {
       
  1230         t << "\t\t\t\t" << writeSettings("CPLUSPLUS", fixForOutput(findProgram(cCompiler))) << ";" << "\n";
       
  1231     }
       
  1232 
       
  1233     t << "\t\t\t\t" << writeSettings("HEADER_SEARCH_PATHS", fixListForOutput("INCLUDEPATH") + QStringList(fixForOutput(specdir())), SettingsAsList, 5) << ";" << "\n"
       
  1234       << "\t\t\t\t" << writeSettings("LIBRARY_SEARCH_PATHS", fixListForOutput("QMAKE_PBX_LIBPATHS"), SettingsAsList, 5) << ";" << "\n"
       
  1235       << "\t\t\t\t" << writeSettings("OPTIMIZATION_CFLAGS", QStringList(), SettingsAsList, 5) << ";" << "\n";
       
  1236     {
       
  1237         QStringList cflags = fixListForOutput("QMAKE_CFLAGS");
       
  1238         const QStringList &prl_defines = project->values("PRL_EXPORT_DEFINES");
       
  1239         for(int i = 0; i < prl_defines.size(); ++i)
       
  1240             cflags += "-D" + prl_defines.at(i);
       
  1241         const QStringList &defines = project->values("DEFINES");
       
  1242         for(int i = 0; i < defines.size(); ++i)
       
  1243             cflags += "-D" + defines.at(i);
       
  1244         t << "\t\t\t\t" << writeSettings("OTHER_CFLAGS", cflags, SettingsAsList, 5) << ";" << "\n";
       
  1245     }
       
  1246     {
       
  1247         QStringList cxxflags = fixListForOutput("QMAKE_CXXFLAGS");
       
  1248         const QStringList &prl_defines = project->values("PRL_EXPORT_DEFINES");
       
  1249         for(int i = 0; i < prl_defines.size(); ++i)
       
  1250             cxxflags += "-D" + prl_defines.at(i);
       
  1251         const QStringList &defines = project->values("DEFINES");
       
  1252         for(int i = 0; i < defines.size(); ++i)
       
  1253             cxxflags += "-D" + defines.at(i);
       
  1254         t << "\t\t\t\t" << writeSettings("OTHER_CPLUSPLUSFLAGS", cxxflags, SettingsAsList, 5) << ";" << "\n";
       
  1255     }
       
  1256     t << "\t\t\t\t" << writeSettings("LEXFLAGS", fixListForOutput("QMAKE_LEXFLAGS")) << ";" << "\n"
       
  1257       << "\t\t\t\t" << writeSettings("YACCFLAGS", fixListForOutput("QMAKE_YACCFLAGS")) << ";" << "\n"
       
  1258       << "\t\t\t\t" << writeSettings("OTHER_REZFLAGS", QStringList()) << ";" << "\n"
       
  1259       << "\t\t\t\t" << writeSettings("SECTORDER_FLAGS", QStringList()) << ";" << "\n"
       
  1260       << "\t\t\t\t" << writeSettings("WARNING_CFLAGS", QStringList()) << ";" << "\n"
       
  1261       << "\t\t\t\t" << writeSettings("PREBINDING", QStringList((project->isEmpty("QMAKE_DO_PREBINDING") ? "NO" : "YES")), SettingsNoQuote) << ";" << "\n";
       
  1262     if(!project->isEmpty("PRECOMPILED_HEADER")) {
       
  1263         if(pbVersion >= 38) {
       
  1264             t << "\t\t\t\t" << writeSettings("GCC_PRECOMPILE_PREFIX_HEADER", "YES") << ";" << "\n"
       
  1265               << "\t\t\t\t" << writeSettings("GCC_PREFIX_HEADER", escapeFilePath(project->first("PRECOMPILED_HEADER"))) << ";" << "\n";
       
  1266         } else {
       
  1267             t << "\t\t\t\t" << writeSettings("PRECOMPILE_PREFIX_HEADER", "YES") << ";" << "\n"
       
  1268               << "\t\t\t\t" << writeSettings("PREFIX_HEADER", escapeFilePath(project->first("PRECOMPILED_HEADER"))) << ";" << "\n";
       
  1269         }
       
  1270     }
       
  1271     if((project->first("TEMPLATE") == "app" && project->isActiveConfig("app_bundle")) ||
       
  1272        (project->first("TEMPLATE") == "lib" && !project->isActiveConfig("staticlib") &&
       
  1273         project->isActiveConfig("lib_bundle"))) {
       
  1274         QString plist = fileFixify(project->first("QMAKE_INFO_PLIST"));
       
  1275         if(plist.isEmpty())
       
  1276             plist = specdir() + QDir::separator() + "Info.plist." + project->first("TEMPLATE");
       
  1277         if(exists(plist)) {
       
  1278             QFile plist_in_file(plist);
       
  1279             if(plist_in_file.open(QIODevice::ReadOnly)) {
       
  1280                 QTextStream plist_in(&plist_in_file);
       
  1281                 QString plist_in_text = plist_in.readAll();
       
  1282                 plist_in_text = plist_in_text.replace("@ICON@",
       
  1283                   (project->isEmpty("ICON") ? QString("") : project->first("ICON").section(Option::dir_sep, -1)));
       
  1284                 if(project->first("TEMPLATE") == "app") {
       
  1285                     plist_in_text = plist_in_text.replace("@EXECUTABLE@", project->first("QMAKE_ORIG_TARGET"));
       
  1286                 } else {
       
  1287                     plist_in_text = plist_in_text.replace("@LIBRARY@", project->first("QMAKE_ORIG_TARGET"));
       
  1288                     plist_in_text = plist_in_text.replace("@SHORT_VERSION@", project->first("VER_MAJ") + "." +
       
  1289                                                           project->first("VER_MIN"));
       
  1290                 }
       
  1291                 plist_in_text = plist_in_text.replace("@TYPEINFO@",
       
  1292                   (project->isEmpty("QMAKE_PKGINFO_TYPEINFO") ? QString::fromLatin1("????") :
       
  1293                    project->first("QMAKE_PKGINFO_TYPEINFO").left(4)));
       
  1294                 QFile plist_out_file("Info.plist");
       
  1295                 if(plist_out_file.open(QIODevice::WriteOnly | QIODevice::Text)) {
       
  1296                     if (Option::mkfile::listgen) {
       
  1297                         generatePrint(fileInfo(plist_out_file.fileName()).absoluteFilePath());
       
  1298                     }
       
  1299                     QTextStream plist_out(&plist_out_file);
       
  1300                     plist_out << plist_in_text;
       
  1301                     t << "\t\t\t\t" << writeSettings("INFOPLIST_FILE", "Info.plist") << ";" << "\n";
       
  1302                 }
       
  1303             }
       
  1304         }
       
  1305     }
       
  1306 #if 1
       
  1307     t << "\t\t\t\t" << writeSettings("BUILD_ROOT", escapeFilePath(qmake_getpwd())) << ";" << "\n";
       
  1308 #endif
       
  1309     if(!project->isActiveConfig("staticlib")) {
       
  1310         t << "\t\t\t\t" << writeSettings("OTHER_LDFLAGS",
       
  1311                                          fixListForOutput("SUBLIBS")
       
  1312                                          + fixListForOutput("QMAKE_LFLAGS")
       
  1313                                          + fixListForOutput("QMAKE_LIBDIR_FLAGS")
       
  1314                                          + fixListForOutput("QMAKE_FRAMEWORKPATH_FLAGS")
       
  1315                                          + fixListForOutput("QMAKE_LIBS"),
       
  1316                                          SettingsAsList, 6) << ";" << "\n";
       
  1317     }
       
  1318     if(!project->isEmpty("DESTDIR")) {
       
  1319         QString dir = project->first("DESTDIR");
       
  1320         if (QDir::isRelativePath(dir))
       
  1321             dir.prepend(qmake_getpwd() + Option::dir_sep);
       
  1322         t << "\t\t\t\t" << writeSettings("INSTALL_DIR", dir) << ";" << "\n";
       
  1323     }
       
  1324     if (project->first("TEMPLATE") == "lib") {
       
  1325         t << "\t\t\t\t" << writeSettings("INSTALL_PATH", QStringList()) << ";" << "\n";
       
  1326     }
       
  1327     if(!project->isEmpty("VERSION") && project->first("VERSION") != "0.0.0") {
       
  1328         t << "\t\t\t\t" << writeSettings("DYLIB_CURRENT_VERSION",  project->first("VER_MAJ")+"."+project->first("VER_MIN")+"."+project->first("VER_PAT")) << ";" << "\n";
       
  1329         if(project->isEmpty("COMPAT_VERSION"))
       
  1330             t << "\t\t\t\t" << writeSettings("DYLIB_COMPATIBILITY_VERSION", project->first("VER_MAJ")+"."+project->first("VER_MIN")) << ";" << "\n";
       
  1331         if(project->first("TEMPLATE") == "lib" && !project->isActiveConfig("staticlib") &&
       
  1332            project->isActiveConfig("lib_bundle"))
       
  1333             t << "\t\t\t\t" << writeSettings("FRAMEWORK_VERSION", project->first("QMAKE_FRAMEWORK_VERSION")) << ";" << "\n";
       
  1334     }
       
  1335     if(!project->isEmpty("COMPAT_FRAMEWORKPATH"))
       
  1336         t << "\t\t\t\t" << writeSettings("FRAMEWORK_SEARCH_PATHS", fixListForOutput("QMAKE_FRAMEWORKPATH"), SettingsAsList, 5) << ";" << "\n";
       
  1337     if(!project->isEmpty("COMPAT_VERSION"))
       
  1338         t << "\t\t\t\t" << writeSettings("DYLIB_COMPATIBILITY_VERSION", project->first("COMPAT_VERSION")) << ";" << "\n";
       
  1339     if(!project->isEmpty("QMAKE_MACOSX_DEPLOYMENT_TARGET"))
       
  1340         t << "\t\t\t\t" << writeSettings("MACOSX_DEPLOYMENT_TARGET", project->first("QMAKE_MACOSX_DEPLOYMENT_TARGET")) << ";" << "\n";
       
  1341     if(pbVersion >= 38) {
       
  1342         if(!project->isEmpty("OBJECTS_DIR"))
       
  1343             t << "\t\t\t\t" << writeSettings("OBJROOT", fixForOutput(project->first("OBJECTS_DIR"))) << ";" << "\n";
       
  1344     }
       
  1345 #if 0
       
  1346     if(!project->isEmpty("DESTDIR"))
       
  1347         t << "\t\t\t\t" << writeSettings("SYMROOT", fixForOutput(project->first("DESTDIR"))) << ";" << "\n";
       
  1348     else
       
  1349         t << "\t\t\t\t" << writeSettings("SYMROOT", fixForOutput(qmake_getpwd())) << ";" << "\n";
       
  1350 #endif
       
  1351     {
       
  1352         QStringList archs;
       
  1353         if(project->isActiveConfig("x86"))
       
  1354             archs += "i386";
       
  1355         if(project->isActiveConfig("ppc")) {
       
  1356             if(!archs.isEmpty())
       
  1357                 archs += " ";
       
  1358             archs += "ppc";
       
  1359         }
       
  1360         if(project->isActiveConfig("ppc64")) {
       
  1361             if(!archs.isEmpty())
       
  1362                 archs += " ";
       
  1363             archs += "ppc64";
       
  1364         }
       
  1365         if(project->isActiveConfig("x86_64")) {
       
  1366             if(!archs.isEmpty())
       
  1367                 archs += " ";
       
  1368             archs += "x86_64";
       
  1369         }
       
  1370         if(!archs.isEmpty())
       
  1371             t << "\t\t\t\t" << writeSettings("ARCHS", archs) << ";" << "\n";
       
  1372 
       
  1373     }
       
  1374     if(project->first("TEMPLATE") == "app") {
       
  1375         if(pbVersion < 38 && project->isActiveConfig("app_bundle"))
       
  1376             t << "\t\t\t\t" << writeSettings("WRAPPER_SUFFIX", "app") << ";" << "\n";
       
  1377         t << "\t\t\t\t" << writeSettings("PRODUCT_NAME", fixForOutput(project->first("QMAKE_ORIG_TARGET"))) << ";" << "\n";
       
  1378     } else {
       
  1379         if(!project->isActiveConfig("plugin") && project->isActiveConfig("staticlib")) {
       
  1380             t << "\t\t\t\t" << writeSettings("LIBRARY_STYLE", "STATIC") << ";" << "\n";
       
  1381         } else {
       
  1382             t << "\t\t\t\t" << writeSettings("LIBRARY_STYLE", "DYNAMIC") << ";" << "\n";
       
  1383         }
       
  1384         QString lib = project->first("QMAKE_ORIG_TARGET");
       
  1385         if(!project->isActiveConfig("lib_bundle") && !project->isActiveConfig("staticlib"))
       
  1386             lib.prepend("lib");
       
  1387         t << "\t\t\t\t" << writeSettings("PRODUCT_NAME", escapeFilePath(lib)) << ";" << "\n";
       
  1388     }
       
  1389     tmp = project->values("QMAKE_PBX_VARS");
       
  1390     for(int i = 0; i < tmp.count(); i++) {
       
  1391         QString var = tmp[i], val = qgetenv(var.toLatin1());
       
  1392         if(val.isEmpty() && var == "TB")
       
  1393             val = "/usr/bin/";
       
  1394         t << "\t\t\t\t" << writeSettings(var, escapeFilePath(val)) << ";" << "\n";
       
  1395     }
       
  1396     t << "\t\t\t" << "};" << "\n"
       
  1397       << "\t\t\t" << "conditionalBuildSettings = {" << "\n"
       
  1398       << "\t\t\t" << "};" << "\n"
       
  1399       << "\t\t\t" << writeSettings("dependencies", project->values("QMAKE_PBX_TARGET_DEPENDS"), SettingsAsList, 4) << ";" << "\n"
       
  1400       << "\t\t\t" << writeSettings("productReference", keyFor(pbx_dir + "QMAKE_PBX_REFERENCE")) << ";" << "\n"
       
  1401       << "\t\t\t" << writeSettings("shouldUseHeadermap", "1", SettingsNoQuote) << ";" << "\n";
       
  1402     if(pbVersion >= 38)
       
  1403         t << "\t\t\t" << writeSettings("isa", "PBXNativeTarget", SettingsNoQuote) << ";" << "\n";
       
  1404     if(project->first("TEMPLATE") == "app") {
       
  1405         if(!project->isActiveConfig("app_bundle")) {
       
  1406             if(pbVersion >= 38) {
       
  1407                 if(!project->isEmpty("QMAKE_PBX_PRODUCT_TYPE"))
       
  1408                     t << "\t\t\t" << writeSettings("productType", project->first("QMAKE_PBX_PRODUCT_TYPE")) << ";" << "\n";
       
  1409                 else
       
  1410                     t << "\t\t\t" << writeSettings("productType", "com.apple.product-type.tool") << ";" << "\n";
       
  1411             } else {
       
  1412                 t << "\t\t\t" << writeSettings("isa", "PBXToolTarget", SettingsNoQuote) << ";" << "\n";
       
  1413             }
       
  1414         } else {
       
  1415             if(pbVersion >= 38) {
       
  1416                 if(!project->isEmpty("QMAKE_PBX_PRODUCT_TYPE"))
       
  1417                     t << "\t\t\t" << writeSettings("productType", project->first("QMAKE_PBX_PRODUCT_TYPE")) << ";" << "\n";
       
  1418                 else
       
  1419                     t << "\t\t\t" << writeSettings("productType",  "com.apple.product-type.application") << ";" << "\n";
       
  1420             } else {
       
  1421                 t << "\t\t\t" << writeSettings("isa", "PBXApplicationTarget", SettingsNoQuote) << ";" << "\n";
       
  1422             }
       
  1423             t << "\t\t\t" << "productSettingsXML = \"";
       
  1424             bool read_plist = false;
       
  1425             if(exists("Info.plist")) {
       
  1426                 QFile plist("Info.plist");
       
  1427                 if (plist.open(QIODevice::ReadOnly)) {
       
  1428                     read_plist = true;
       
  1429                     QTextStream stream(&plist);
       
  1430                     while(!stream.atEnd())
       
  1431                         t << stream.readLine().replace('"', "\\\"") << endl;
       
  1432                 }
       
  1433             }
       
  1434             if(!read_plist) {
       
  1435                 t << "<?xml version="
       
  1436                   << "\\\"1.0\\\" encoding=" << "\\\"UTF-8\\\"" << "?>" << "\n"
       
  1437                   << "\t\t\t\t" << "<!DOCTYPE plist SYSTEM \\\"file://localhost/System/"
       
  1438                   << "Library/DTDs/PropertyList.dtd\\\">" << "\n"
       
  1439                   << "\t\t\t\t" << "<plist version=\\\"0.9\\\">" << "\n"
       
  1440                   << "\t\t\t\t" << "<dict>" << "\n"
       
  1441                   << "\t\t\t\t\t" << "<key>CFBundleDevelopmentRegion</key>" << "\n"
       
  1442                   << "\t\t\t\t\t" << "<string>English</string>" << "\n"
       
  1443                   << "\t\t\t\t\t" << "<key>CFBundleExecutable</key>" << "\n"
       
  1444                   << "\t\t\t\t\t" << "<string>" << project->first("QMAKE_ORIG_TARGET") << "</string>" << "\n"
       
  1445                   << "\t\t\t\t\t" << "<key>CFBundleIconFile</key>" << "\n"
       
  1446                   << "\t\t\t\t\t" << "<string>" << var("ICON").section(Option::dir_sep, -1) << "</string>" << "\n"
       
  1447                   << "\t\t\t\t\t" << "<key>CFBundleInfoDictionaryVersion</key>"  << "\n"
       
  1448                   << "\t\t\t\t\t" << "<string>6.0</string>" << "\n"
       
  1449                   << "\t\t\t\t\t" << "<key>CFBundlePackageType</key>" << "\n"
       
  1450                   << "\t\t\t\t\t" << "<string>APPL</string>" << "\n"
       
  1451                   << "\t\t\t\t\t" << "<key>CFBundleSignature</key>" << "\n"
       
  1452                   << "\t\t\t\t\t" << "<string>"
       
  1453                   << (project->isEmpty("QMAKE_PKGINFO_TYPEINFO") ? QString::fromLatin1("????") :
       
  1454                       project->first("QMAKE_PKGINFO_TYPEINFO").left(4)) << "</string>" << "\n"
       
  1455                   << "\t\t\t\t\t" << "<key>CFBundleVersion</key>" << "\n"
       
  1456                   << "\t\t\t\t\t" << "<string>0.1</string>" << "\n"
       
  1457                   << "\t\t\t\t\t" << "<key>CSResourcesFileMapped</key>" << "\n"
       
  1458                   << "\t\t\t\t\t" << "<true/>" << "\n"
       
  1459                   << "\t\t\t\t" << "</dict>" << "\n"
       
  1460                   << "\t\t\t\t" << "</plist>";
       
  1461             }
       
  1462             t << "\";" << "\n";
       
  1463         }
       
  1464         t << "\t\t\t" << writeSettings("name", escapeFilePath(project->first("QMAKE_ORIG_TARGET"))) << ";" << "\n"
       
  1465           << "\t\t\t" << writeSettings("productName", escapeFilePath(project->first("QMAKE_ORIG_TARGET"))) << ";" << "\n";
       
  1466     } else {
       
  1467         QString lib = project->first("QMAKE_ORIG_TARGET");
       
  1468         if(!project->isActiveConfig("lib_bundle") && !project->isActiveConfig("staticlib"))
       
  1469            lib.prepend("lib");
       
  1470         t << "\t\t\t" << writeSettings("name", escapeFilePath(lib)) << ";" << "\n"
       
  1471           << "\t\t\t" << writeSettings("productName", escapeFilePath(lib)) << ";" << "\n";
       
  1472         if(pbVersion >= 38) {
       
  1473             if(!project->isEmpty("QMAKE_PBX_PRODUCT_TYPE"))
       
  1474                 t << "\t\t\t" << writeSettings("productType", project->first("QMAKE_PBX_PRODUCT_TYPE")) << ";" << "\n";
       
  1475             else if(project->isActiveConfig("staticlib"))
       
  1476                 t << "\t\t\t" << writeSettings("productType", "com.apple.product-type.library.static") << ";" << "\n";
       
  1477             else if(project->isActiveConfig("lib_bundle"))
       
  1478                 t << "\t\t\t" << writeSettings("productType", "com.apple.product-type.framework") << ";" << "\n";
       
  1479             else
       
  1480                 t << "\t\t\t" << writeSettings("productType", "com.apple.product-type.library.dynamic") << ";" << "\n";
       
  1481         } else {
       
  1482             t << "\t\t\t" << writeSettings("isa", "PBXLibraryTarget", SettingsNoQuote) << ";" << "\n";
       
  1483         }
       
  1484     }
       
  1485     t << "\t\t\t" << writeSettings("startupPath", "<<ProjectDirectory>>") << ";" << "\n";
       
  1486     if(!project->isEmpty("DESTDIR"))
       
  1487         t << "\t\t\t" << writeSettings("productInstallPath", escapeFilePath(project->first("DESTDIR"))) << ";" << "\n";
       
  1488     t << "\t\t" << "};" << "\n";
       
  1489     //DEBUG/RELEASE
       
  1490     QString active_buildstyle;
       
  1491     for(int as_release = 0; as_release < 2; as_release++)
       
  1492     {
       
  1493         QMap<QString, QString> settings;
       
  1494         settings.insert("COPY_PHASE_STRIP", (as_release ? "YES" : "NO"));
       
  1495         settings.insert("GCC_GENERATE_DEBUGGING_SYMBOLS", as_release ? "NO" : "YES");
       
  1496         if(!as_release)
       
  1497             settings.insert("GCC_OPTIMIZATION_LEVEL", "0");
       
  1498         if(project->isActiveConfig("sdk") && !project->isEmpty("QMAKE_MAC_SDK"))
       
  1499                 settings.insert("SDKROOT", project->first("QMAKE_MAC_SDK"));
       
  1500         {
       
  1501             const QStringList &l = project->values("QMAKE_MAC_XCODE_SETTINGS");
       
  1502             for(int i = 0; i < l.size(); ++i) {
       
  1503                 QString name = l.at(i);
       
  1504                 const QString value = project->values(name + QLatin1String(".value")).join(QString(Option::field_sep));
       
  1505                 if(!project->isEmpty(name + QLatin1String(".name")))
       
  1506                     name = project->values(name + QLatin1String(".name")).first();
       
  1507                 settings.insert(name, value);
       
  1508             }
       
  1509         }
       
  1510 
       
  1511         QString name;
       
  1512         if(pbVersion >= 42)
       
  1513             name = (as_release ? "Release" : "Debug");
       
  1514         else
       
  1515             name = (as_release ? "Deployment" : "Development");
       
  1516         if(pbVersion >= 42) {
       
  1517             QString key = keyFor("QMAKE_PBX_BUILDCONFIG_" + name);
       
  1518             project->values("QMAKE_PBX_BUILDCONFIGS").append(key);
       
  1519             t << "\t\t" << key << " = {" << "\n"
       
  1520               << "\t\t\t" << writeSettings("isa", "XCBuildConfiguration", SettingsNoQuote) << ";" << "\n"
       
  1521               << "\t\t\t" << "buildSettings = {" << "\n";
       
  1522             for(QMap<QString, QString>::Iterator set_it = settings.begin(); set_it != settings.end(); ++set_it)
       
  1523                 t << "\t\t\t\t" << writeSettings(set_it.key(), set_it.value()) << ";\n";
       
  1524             t << "\t\t\t" << "};" << "\n"
       
  1525               << "\t\t\t" << writeSettings("name", name) << ";" << "\n"
       
  1526               << "\t\t" << "};" << "\n";
       
  1527         }
       
  1528 
       
  1529         QString key = keyFor("QMAKE_PBX_BUILDSTYLE_" + name);
       
  1530         if(project->isActiveConfig("debug") != (bool)as_release) {
       
  1531             project->values("QMAKE_PBX_BUILDSTYLES").append(key);
       
  1532             active_buildstyle = name;
       
  1533         } else if(pbVersion >= 42) {
       
  1534             project->values("QMAKE_PBX_BUILDSTYLES").append(key);
       
  1535         }
       
  1536         t << "\t\t" << key << " = {" << "\n"
       
  1537           << "\t\t\t" << writeSettings("buildRules", QStringList(), SettingsAsList, 4) << ";" << "\n"
       
  1538           << "\t\t\t" << "buildSettings = {" << "\n";
       
  1539         for(QMap<QString, QString>::Iterator set_it = settings.begin(); set_it != settings.end(); ++set_it)
       
  1540             t << "\t\t\t\t" << writeSettings(set_it.key(), set_it.value()) << ";" << "\n";
       
  1541         t << "\t\t\t" << "};" << "\n"
       
  1542           << "\t\t\t" << writeSettings("isa", "PBXBuildStyle") << ";" << "\n"
       
  1543           << "\t\t\t" << writeSettings("name", name) << ";" << "\n"
       
  1544           << "\t\t" << "};" << "\n";
       
  1545     }
       
  1546     if(pbVersion >= 42) {
       
  1547         t << "\t\t" << keyFor("QMAKE_PBX_BUILDCONFIG_LIST") << " = {" << "\n"
       
  1548           << "\t\t\t" << writeSettings("isa", "XCConfigurationList", SettingsNoQuote) << ";" << "\n"
       
  1549           << "\t\t\t" << writeSettings("buildConfigurations", project->values("QMAKE_PBX_BUILDCONFIGS"), SettingsAsList, 4) << ";" << "\n"
       
  1550           << "\t\t\t" << writeSettings("defaultConfigurationIsVisible", "0", SettingsNoQuote) << ";" << "\n"
       
  1551           << "\t\t\t" << writeSettings("defaultConfigurationIsName", active_buildstyle) << ";" << "\n"
       
  1552           << "\t\t" << "};" << "\n";
       
  1553     }
       
  1554     //ROOT
       
  1555     t << "\t\t" << keyFor("QMAKE_PBX_ROOT") << " = {" << "\n"
       
  1556       << "\t\t\t" << writeSettings("buildStyles", project->values("QMAKE_PBX_BUILDSTYLES"), SettingsAsList, 4) << ";" << "\n"
       
  1557       << "\t\t\t" << writeSettings("hasScannedForEncodings", "1", SettingsNoQuote) << ";" << "\n"
       
  1558       << "\t\t\t" << writeSettings("isa", "PBXProject", SettingsNoQuote) << ";" << "\n"
       
  1559       << "\t\t\t" << writeSettings("mainGroup", keyFor("QMAKE_PBX_ROOT_GROUP")) << ";" << "\n";
       
  1560     if(pbVersion >= 42)
       
  1561         t << "\t\t\t" << writeSettings("buildConfigurationList", keyFor("QMAKE_PBX_BUILDCONFIG_LIST")) << ";" << "\n";
       
  1562     t << "\t\t\t" << writeSettings("projectDirPath", QStringList()) << ";" << "\n"
       
  1563       << "\t\t\t" << writeSettings("targets", project->values("QMAKE_PBX_TARGETS"), SettingsAsList, 4) << ";" << "\n"
       
  1564       << "\t\t" << "};" << "\n";
       
  1565 
       
  1566     //FOOTER
       
  1567     t << "\t" << "};" << "\n"
       
  1568       << "\t" << writeSettings("rootObject", keyFor("QMAKE_PBX_ROOT")) << ";" << "\n"
       
  1569       << "}" << endl;
       
  1570 
       
  1571     if(project->isActiveConfig("generate_pbxbuild_makefile")) {
       
  1572         QString mkwrap = fileFixify(pbx_dir + Option::dir_sep + ".." + Option::dir_sep + project->first("MAKEFILE"),
       
  1573                                     qmake_getpwd());
       
  1574         QFile mkwrapf(mkwrap);
       
  1575         if(mkwrapf.open(QIODevice::WriteOnly | QIODevice::Text)) {
       
  1576             writingUnixMakefileGenerator = true;
       
  1577             if (Option::mkfile::listgen) {
       
  1578                 generatePrint(fileInfo(mkwrapf.fileName()).absoluteFilePath());
       
  1579             }
       
  1580             debug_msg(1, "pbuilder: Creating file: %s", mkwrap.toLatin1().constData());
       
  1581             QTextStream mkwrapt(&mkwrapf);
       
  1582             writeHeader(mkwrapt);
       
  1583             const char cleans[] = "preprocess_clean ";
       
  1584             mkwrapt << "#This is a makefile wrapper for PROJECT BUILDER\n"
       
  1585                     << "all:" << "\n\t"
       
  1586                     << "cd " << project->first("QMAKE_ORIG_TARGET") << projectSuffix() << "/ && " << pbxbuild() << "\n"
       
  1587                     << "install: all" << "\n\t"
       
  1588                     << "cd " << project->first("QMAKE_ORIG_TARGET") << projectSuffix() << "/ && " << pbxbuild() << " install\n"
       
  1589                     << "distclean clean: preprocess_clean" << "\n\t"
       
  1590                     << "cd " << project->first("QMAKE_ORIG_TARGET") << projectSuffix() << "/ && " << pbxbuild() << " clean" << "\n"
       
  1591                     << (!did_preprocess ? cleans : "") << ":" << "\n";
       
  1592             if(did_preprocess)
       
  1593                 mkwrapt << cleans << ":" << "\n\t"
       
  1594                         << "make -f "
       
  1595                         << pbx_dir << Option::dir_sep << "qt_preprocess.mak $@" << endl;
       
  1596             writingUnixMakefileGenerator = false;
       
  1597         }
       
  1598     }
       
  1599     return true;
       
  1600 }
       
  1601 
       
  1602 QString
       
  1603 ProjectBuilderMakefileGenerator::findProgram(const QString &prog)
       
  1604 {
       
  1605     QString ret = prog;
       
  1606     if(QDir::isRelativePath(ret)) {
       
  1607         QStringList paths = QString(qgetenv("PATH")).split(':');
       
  1608         for(int i = 0; i < paths.size(); ++i) {
       
  1609             QString path = paths.at(i) + "/" + prog;
       
  1610             if(exists(path)) {
       
  1611                 ret = path;
       
  1612                 break;
       
  1613             }
       
  1614         }
       
  1615     }
       
  1616     return ret;
       
  1617 }
       
  1618 
       
  1619 QString
       
  1620 ProjectBuilderMakefileGenerator::fixForOutput(const QString &values)
       
  1621 {
       
  1622     //get the environment variables references
       
  1623     QRegExp reg_var("\\$\\((.*)\\)");
       
  1624     for(int rep = 0; (rep = reg_var.indexIn(values, rep)) != -1;) {
       
  1625         if(project->values("QMAKE_PBX_VARS").indexOf(reg_var.cap(1)) == -1)
       
  1626             project->values("QMAKE_PBX_VARS").append(reg_var.cap(1));
       
  1627         rep += reg_var.matchedLength();
       
  1628     }
       
  1629     QString ret = values;
       
  1630     ret = ret.replace(QRegExp("\\\\ "), " "); //unescape spaces
       
  1631     ret = ret.replace(QRegExp("('|\\\\|\")"), "\\\\1"); //fix quotes
       
  1632     ret = ret.replace("\t", "    "); //fix tabs
       
  1633     ret = ret.replace(QRegExp(" "), "\\ "); //escape spaces
       
  1634     return ret;
       
  1635 }
       
  1636 
       
  1637 QStringList
       
  1638 ProjectBuilderMakefileGenerator::fixListForOutput(const QString &where)
       
  1639 {
       
  1640     QStringList ret;
       
  1641     const QStringList &l = project->values(where);
       
  1642     for(int i = 0; i < l.count(); i++)
       
  1643         ret += fixForOutput(l[i]);
       
  1644     return ret;
       
  1645 }
       
  1646 
       
  1647 QString
       
  1648 ProjectBuilderMakefileGenerator::keyFor(const QString &block)
       
  1649 {
       
  1650 #if 1 //This make this code much easier to debug..
       
  1651     if(project->isActiveConfig("no_pb_munge_key"))
       
  1652        return block;
       
  1653 #endif
       
  1654     QString ret;
       
  1655     if(!keys.contains(block)) {
       
  1656         ret = qtMD5(block.toUtf8()).left(24).toUpper();
       
  1657         keys.insert(block, ret);
       
  1658     } else {
       
  1659         ret = keys[block];
       
  1660     }
       
  1661     return ret;
       
  1662 }
       
  1663 
       
  1664 bool
       
  1665 ProjectBuilderMakefileGenerator::openOutput(QFile &file, const QString &build) const
       
  1666 {
       
  1667     if(QDir::isRelativePath(file.fileName()))
       
  1668         file.setFileName(Option::output_dir + "/" + file.fileName()); //pwd when qmake was run
       
  1669     QFileInfo fi(fileInfo(file.fileName()));
       
  1670     if(fi.suffix() != "pbxproj" || file.fileName().isEmpty()) {
       
  1671         QString output = file.fileName();
       
  1672         if(fi.isDir())
       
  1673             output += QDir::separator();
       
  1674         if(!output.endsWith(projectSuffix())) {
       
  1675             if(file.fileName().isEmpty() || fi.isDir()) {
       
  1676                 if(project->first("TEMPLATE") == "subdirs" || project->isEmpty("QMAKE_ORIG_TARGET"))
       
  1677                     output += fileInfo(project->projectFile()).baseName();
       
  1678                 else
       
  1679                     output += project->first("QMAKE_ORIG_TARGET");
       
  1680             }
       
  1681             output += projectSuffix() + QDir::separator();
       
  1682         } else if(output[(int)output.length() - 1] != QDir::separator()) {
       
  1683             output += QDir::separator();
       
  1684         }
       
  1685         output += QString("project.pbxproj");
       
  1686         output = unescapeFilePath(output);
       
  1687         file.setFileName(output);
       
  1688     }
       
  1689     bool ret = UnixMakefileGenerator::openOutput(file, build);
       
  1690     ((ProjectBuilderMakefileGenerator*)this)->pbx_dir = Option::output_dir.section(Option::dir_sep, 0, -1);
       
  1691     Option::output_dir = pbx_dir.section(Option::dir_sep, 0, -2);
       
  1692     return ret;
       
  1693 }
       
  1694 
       
  1695 /* This function is such a hack it is almost pointless, but it
       
  1696    eliminates the warning message from ProjectBuilder that the project
       
  1697    file is for an older version. I guess this could be used someday if
       
  1698    the format of the output is dependant upon the version of
       
  1699    ProjectBuilder as well.
       
  1700 */
       
  1701 int
       
  1702 ProjectBuilderMakefileGenerator::pbuilderVersion() const
       
  1703 {
       
  1704     QString ret;
       
  1705     if(!project->isEmpty("QMAKE_PBUILDER_VERSION")) {
       
  1706         ret = project->first("QMAKE_PBUILDER_VERSION");
       
  1707     } else {
       
  1708         QString version, version_plist = project->first("QMAKE_PBUILDER_VERSION_PLIST");
       
  1709         if(version_plist.isEmpty()) {
       
  1710 #ifdef Q_OS_DARWIN
       
  1711             ret = QLatin1String("34");
       
  1712             QCFType<CFURLRef> cfurl;
       
  1713             OSStatus err = LSFindApplicationForInfo(0, CFSTR("com.apple.Xcode"), 0, 0, &cfurl);
       
  1714             if (err == noErr) {
       
  1715                 QCFType<CFBundleRef> bundle = CFBundleCreate(0, cfurl);
       
  1716                 if (bundle) {
       
  1717                     CFStringRef str = CFStringRef(CFBundleGetValueForInfoDictionaryKey(bundle,
       
  1718                                                               CFSTR("CFBundleShortVersionString")));
       
  1719                     if (str) {
       
  1720                         QStringList versions = QCFString::toQString(str).split(QLatin1Char('.'));
       
  1721                         int versionMajor = versions.at(0).toInt();
       
  1722                         int versionMinor = versions.at(1).toInt();
       
  1723                         if (versionMajor >= 2) {
       
  1724                             ret = QLatin1String("42");
       
  1725                         } else if (versionMajor == 1 && versionMinor >= 5) {
       
  1726                             ret = QLatin1String("39");
       
  1727                         }
       
  1728                     }
       
  1729                 }
       
  1730             }
       
  1731 #else
       
  1732             if(exists("/Developer/Applications/Xcode.app/Contents/version.plist"))
       
  1733                 version_plist = "/Developer/Applications/Xcode.app/Contents/version.plist";
       
  1734             else
       
  1735                 version_plist = "/Developer/Applications/Project Builder.app/Contents/version.plist";
       
  1736 #endif
       
  1737         } else {
       
  1738             version_plist = version_plist.replace(QRegExp("\""), "");
       
  1739         }
       
  1740         if (ret.isEmpty()) {
       
  1741             QFile version_file(version_plist);
       
  1742             if (version_file.open(QIODevice::ReadOnly)) {
       
  1743                 debug_msg(1, "pbuilder: version.plist: Reading file: %s", version_plist.toLatin1().constData());
       
  1744                 QTextStream plist(&version_file);
       
  1745 
       
  1746                 bool in_dict = false;
       
  1747                 QString current_key;
       
  1748                 QRegExp keyreg("^<key>(.*)</key>$"), stringreg("^<string>(.*)</string>$");
       
  1749                 while(!plist.atEnd()) {
       
  1750                     QString line = plist.readLine().trimmed();
       
  1751                     if(line == "<dict>")
       
  1752                         in_dict = true;
       
  1753                     else if(line == "</dict>")
       
  1754                         in_dict = false;
       
  1755                     else if(in_dict) {
       
  1756                         if(keyreg.exactMatch(line))
       
  1757                             current_key = keyreg.cap(1);
       
  1758                         else if(current_key == "CFBundleShortVersionString" && stringreg.exactMatch(line))
       
  1759                             version = stringreg.cap(1);
       
  1760                     }
       
  1761                 }
       
  1762                 plist.flush();
       
  1763                 version_file.close();
       
  1764             } else {
       
  1765                 debug_msg(1, "pbuilder: version.plist: Failure to open %s", version_plist.toLatin1().constData());
       
  1766             }
       
  1767             if(version.isEmpty() && version_plist.contains("Xcode")) {
       
  1768                 ret = "39";
       
  1769             } else {
       
  1770                 int versionMajor = version.left(1).toInt();
       
  1771                 if(versionMajor >= 2)
       
  1772                     ret = "42";
       
  1773                 else if(version == "1.5")
       
  1774                     ret = "39";
       
  1775                 else if(version == "1.1")
       
  1776                     ret = "34";
       
  1777             }
       
  1778         }
       
  1779     }
       
  1780 
       
  1781     if(!ret.isEmpty()) {
       
  1782         bool ok;
       
  1783         int int_ret = ret.toInt(&ok);
       
  1784         if(ok) {
       
  1785             debug_msg(1, "pbuilder: version.plist: Got version: %d", int_ret);
       
  1786             return int_ret;
       
  1787         }
       
  1788     }
       
  1789     debug_msg(1, "pbuilder: version.plist: Fallback to default version");
       
  1790     return 42; //my fallback
       
  1791 }
       
  1792 
       
  1793 int
       
  1794 ProjectBuilderMakefileGenerator::reftypeForFile(const QString &where)
       
  1795 {
       
  1796     int ret = 0; //absolute is the default..
       
  1797     if(QDir::isRelativePath(unescapeFilePath(where)))
       
  1798         ret = 4; //relative
       
  1799     return ret;
       
  1800 }
       
  1801 
       
  1802 QString
       
  1803 ProjectBuilderMakefileGenerator::projectSuffix() const
       
  1804 {
       
  1805     const int pbVersion = pbuilderVersion();
       
  1806     if(pbVersion >= 42)
       
  1807         return ".xcodeproj";
       
  1808     else if(pbVersion >= 38)
       
  1809         return ".xcode";
       
  1810     return ".pbproj";
       
  1811 }
       
  1812 
       
  1813 QString
       
  1814 ProjectBuilderMakefileGenerator::pbxbuild()
       
  1815 {
       
  1816     if(exists("/usr/bin/pbbuild"))
       
  1817         return "pbbuild";
       
  1818     if(exists("/usr/bin/xcodebuild"))
       
  1819        return "xcodebuild";
       
  1820     return (pbuilderVersion() >= 38 ? "xcodebuild" : "pbxbuild");
       
  1821 }
       
  1822 
       
  1823 QString
       
  1824 ProjectBuilderMakefileGenerator::escapeFilePath(const QString &path) const
       
  1825 {
       
  1826 #if 1
       
  1827     //in the middle of generating a Makefile!
       
  1828     if(writingUnixMakefileGenerator)
       
  1829         return UnixMakefileGenerator::escapeFilePath(path);
       
  1830 
       
  1831     //generating stuff for the xml file!
       
  1832     QString ret = path;
       
  1833     if(!ret.isEmpty()) {
       
  1834         ret = unescapeFilePath(ret);
       
  1835         debug_msg(2, "EscapeFilePath: %s -> %s", path.toLatin1().constData(), ret.toLatin1().constData());
       
  1836     }
       
  1837     return ret;
       
  1838 #else
       
  1839     return UnixMakefileGenerator::escapeFilePath(path);
       
  1840 #endif
       
  1841 }
       
  1842 
       
  1843 QString
       
  1844 ProjectBuilderMakefileGenerator::writeSettings(QString var, QStringList vals, int flags, int indent_level)
       
  1845 {
       
  1846     QString ret;
       
  1847     const QString quote = (flags & SettingsNoQuote) ? "" : "\"";
       
  1848     const QString escape_quote = quote.isEmpty() ? "" : "\\" + quote;
       
  1849     QString newline = "\n";
       
  1850     for(int i = 0; i < indent_level; ++i)
       
  1851         newline += "\t";
       
  1852     if(flags & SettingsAsList) {
       
  1853         ret += var + " = (" + newline;
       
  1854         for(int i = 0, count = 0; i < vals.size(); ++i) {
       
  1855             QString val = vals.at(i);
       
  1856             if(!val.isEmpty()) {
       
  1857                 if(count++ > 0)
       
  1858                     ret += "," + newline;
       
  1859                 ret += quote + val.replace(quote, escape_quote) + quote;
       
  1860             }
       
  1861         }
       
  1862         ret += ")";
       
  1863     } else {
       
  1864         ret += var + " = " + quote;
       
  1865         for(int i = 0; i < vals.size(); ++i) {
       
  1866             QString val = vals.at(i);
       
  1867 //             if(val.isEmpty())
       
  1868 //                 val = quote + quote;
       
  1869             if(i)
       
  1870                 ret += " ";
       
  1871             ret += val;
       
  1872         }
       
  1873         ret += quote;
       
  1874     }
       
  1875     return ret;
       
  1876 }
       
  1877 
       
  1878 QT_END_NAMESPACE