Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

pbuilder_pbx.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 ** 
00003 **
00004 ** Implementation of ProjectBuilderMakefileGenerator class.
00005 **
00006 ** Copyright (C) 1992-2003 Trolltech AS.  All rights reserved.
00007 **
00008 ** This file is part of qmake.
00009 **
00010 ** This file may be distributed under the terms of the Q Public License
00011 ** as defined by Trolltech AS of Norway and appearing in the file
00012 ** LICENSE.QPL included in the packaging of this file.
00013 **
00014 ** This file may be distributed and/or modified under the terms of the
00015 ** GNU General Public License version 2 as published by the Free Software
00016 ** Foundation and appearing in the file LICENSE.GPL included in the
00017 ** packaging of this file.
00018 **
00019 ** Licensees holding valid Qt Enterprise Edition licenses may use this
00020 ** file in accordance with the Qt Commercial License Agreement provided
00021 ** with the Software.
00022 **
00023 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00024 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00025 **
00026 ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
00027 **   information about Qt Commercial License Agreements.
00028 ** See http://www.trolltech.com/qpl/ for QPL licensing information.
00029 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00030 **
00031 ** Contact info@trolltech.com if any conditions of this licensing are
00032 ** not clear to you.
00033 **
00034 **********************************************************************/
00035 
00036 #include "pbuilder_pbx.h"
00037 #include "option.h"
00038 #include "meta.h"
00039 #include <qdir.h>
00040 #include <qdict.h>
00041 #include <qregexp.h>
00042 #include <stdlib.h>
00043 #include <time.h>
00044 #include "qtmd5.h"
00045 #ifdef Q_OS_UNIX
00046 #  include <sys/types.h>
00047 #  include <sys/stat.h>
00048 #endif
00049 
00050 // Note: this is fairly hacky, but it does the job...
00051 
00052 ProjectBuilderMakefileGenerator::ProjectBuilderMakefileGenerator(QMakeProject *p) : UnixMakefileGenerator(p)
00053 {
00054 
00055 }
00056 
00057 bool
00058 ProjectBuilderMakefileGenerator::writeMakefile(QTextStream &t)
00059 {
00060     if(!project->variables()["QMAKE_FAILED_REQUIREMENTS"].isEmpty()) {
00061         /* for now just dump, I need to generated an empty xml or something.. */
00062         fprintf(stderr, "Project file not generated because all requirements not met:\n\t%s\n",
00063                 var("QMAKE_FAILED_REQUIREMENTS").latin1());
00064         return TRUE;
00065     }
00066 
00067     project->variables()["MAKEFILE"].clear();
00068     project->variables()["MAKEFILE"].append("Makefile");
00069     if(project->first("TEMPLATE") == "app" || project->first("TEMPLATE") == "lib") 
00070         return writeMakeParts(t);
00071     else if(project->first("TEMPLATE") == "subdirs") 
00072         return writeSubdirs(t, FALSE);
00073     return FALSE;
00074 }
00075 
00076 bool
00077 ProjectBuilderMakefileGenerator::writeSubdirs(QTextStream &t, bool direct)
00078 {
00079     QString mkwrap = fileFixify(pbx_dir + Option::dir_sep + ".." + Option::dir_sep + project->first("MAKEFILE"), 
00080                                 QDir::currentDirPath());
00081     QFile mkwrapf(mkwrap);
00082     if(mkwrapf.open(IO_WriteOnly | IO_Translate)) {
00083         debug_msg(1, "pbuilder: Creating file: %s", mkwrap.latin1());
00084         QTextStream mkwrapt(&mkwrapf);
00085         UnixMakefileGenerator::writeSubdirs(mkwrapt, direct);
00086     }
00087 
00088     //HEADER
00089     t << "// !$*UTF8*$!" << "\n"
00090       << "{" << "\n"
00091       << "\t" << "archiveVersion = 1;" << "\n"
00092       << "\t" << "classes = {" << "\n" << "\t" << "};" << "\n"
00093       << "\t" << "objectVersion = " << pbuilderVersion() << ";" << "\n"
00094       << "\t" << "objects = {" << endl;
00095 
00096     //SUBDIRS
00097     QStringList subdirs = project->variables()["SUBDIRS"];
00098     QString oldpwd = QDir::currentDirPath();
00099     QMap<QString, QStringList> groups;
00100     for(QStringList::Iterator it = subdirs.begin(); it != subdirs.end(); ++it) {
00101         QFileInfo fi(Option::fixPathToLocalOS((*it), TRUE));
00102         if(fi.exists()) {
00103             if(fi.isDir()) {
00104                 QString profile = (*it);
00105                 if(!profile.endsWith(Option::dir_sep))
00106                     profile += Option::dir_sep;
00107                 profile += fi.baseName() + ".pro";
00108                 subdirs.append(profile);
00109             } else {
00110                 QMakeProject tmp_proj;
00111                 QString dir = fi.dirPath(), fn = fi.fileName();
00112                 if(!dir.isEmpty()) {
00113                     if(!QDir::setCurrent(dir))
00114                         fprintf(stderr, "Cannot find directory: %s\n", dir.latin1());
00115                 }
00116                 if(tmp_proj.read(fn, oldpwd)) {
00117                     if(Option::debug_level) {
00118                         QMap<QString, QStringList> &vars = tmp_proj.variables();
00119                         for(QMap<QString, QStringList>::Iterator it = vars.begin();
00120                             it != vars.end(); ++it) {
00121                             if(it.key().left(1) != "." && !it.data().isEmpty())
00122                                 debug_msg(1, "%s: %s === %s", fn.latin1(), it.key().latin1(),
00123                                           it.data().join(" :: ").latin1());
00124                         }
00125                     }
00126                     if(tmp_proj.first("TEMPLATE") == "subdirs") {
00127                         subdirs += fileFixify(tmp_proj.variables()["SUBDIRS"]);
00128                     } else if(tmp_proj.first("TEMPLATE") == "app" || tmp_proj.first("TEMPLATE") == "lib") {
00129                         QString pbxproj = QDir::currentDirPath() + Option::dir_sep + tmp_proj.first("TARGET") + projectSuffix();
00130                         if(!QFile::exists(pbxproj)) {
00131                             warn_msg(WarnLogic, "Ignored (not found) '%s'", pbxproj.latin1());
00132                             goto nextfile; // # Dirty!
00133                         }
00134                         project->variables()["QMAKE_PBX_SUBDIRS"] += pbxproj;
00135                         //PROJECTREF
00136                         {
00137                             bool in_root = TRUE;
00138                             QString name = QDir::currentDirPath();
00139                             QString project_key = keyFor(pbxproj + "_PROJECTREF");
00140                             if(project->isActiveConfig("flat")) {
00141                                 QString flat_file = fileFixify(name, oldpwd, Option::output_dir, TRUE);
00142                                 if(flat_file.find(Option::dir_sep) != -1) {
00143                                     QStringList dirs = QStringList::split(Option::dir_sep, flat_file);
00144                                     name = dirs.back();
00145                                 }
00146                             } else {
00147                                 QString flat_file = fileFixify(name, oldpwd, Option::output_dir, TRUE);
00148                                 if(QDir::isRelativePath(flat_file) && flat_file.find(Option::dir_sep) != -1) {
00149                                     QString last_grp("QMAKE_PBX_HEIR_GROUP");
00150                                     QStringList dirs = QStringList::split(Option::dir_sep, flat_file);
00151                                     name = dirs.back();
00152                                     for(QStringList::Iterator dir_it = dirs.begin(); dir_it != dirs.end(); ++dir_it) {
00153                                         QString new_grp(last_grp + Option::dir_sep + (*dir_it)), new_grp_key(keyFor(new_grp));
00154                                         if(dir_it == dirs.begin()) {
00155                                             if(!groups.contains(new_grp)) 
00156                                                 project->variables()["QMAKE_PBX_GROUPS"].append(new_grp_key);
00157                                         } else {
00158                                             if(!groups[last_grp].contains(new_grp_key)) 
00159                                                 groups[last_grp] += new_grp_key;
00160                                         }
00161                                         last_grp = new_grp;
00162                                     }
00163                                     groups[last_grp] += project_key;
00164                                     in_root = FALSE;
00165                                 }
00166                             }
00167                             if(in_root)
00168                                 project->variables()["QMAKE_PBX_GROUPS"] += project_key;
00169                             t << "\t\t" << project_key << " = {" << "\n"
00170                               << "\t\t\t" << "isa = PBXFileReference;" << "\n"
00171                               << "\t\t\t" << "name = " << tmp_proj.first("TARGET") << ";" << "\n"
00172                               << "\t\t\t" << "path = " << pbxproj << ";" << "\n"
00173                               << "\t\t\t" << "refType = 0;" << "\n"
00174                               << "\t\t\t" << "sourceTree = \"<absolute>\";" << "\n"
00175                               << "\t\t" << "};" << "\n";
00176                             //PRODUCTGROUP
00177                             t << "\t\t" << keyFor(pbxproj + "_PRODUCTGROUP") << " = {" << "\n"
00178                               << "\t\t\t" << "children = (" << "\n"
00179                               << "\t\t\t" << ");" << "\n"
00180                               << "\t\t\t" << "isa = PBXGroup;" << "\n"
00181                               << "\t\t\t" << "name = Products;" << "\n"
00182                               << "\t\t\t" << "refType = 4;" << "\n"
00183                               << "\t\t\t" << "sourceTree = \"<group>\";" << "\n"
00184                               << "\t\t" << "};" << "\n";
00185                         }
00186                     }
00187                 }
00188 nextfile:
00189                 QDir::setCurrent(oldpwd);
00190             }
00191         }
00192     }
00193     for(QMap<QString, QStringList>::Iterator grp_it = groups.begin(); grp_it != groups.end(); ++grp_it) {
00194         t << "\t\t" << keyFor(grp_it.key()) << " = {" << "\n"
00195           << "\t\t\t" << "isa = PBXGroup;" << "\n"
00196           << "\t\t\t" << "children = (" << "\n"
00197           << valGlue(grp_it.data(), "\t\t\t\t", ",\n\t\t\t\t", "\n")
00198           << "\t\t\t" << ");" << "\n"
00199           << "\t\t\t" << "name = \"" << grp_it.key().section(Option::dir_sep, -1) << "\";" << "\n"
00200           << "\t\t\t" << "refType = 4;" << "\n"
00201           << "\t\t" << "};" << "\n";
00202     }
00203 
00204     //DUMP EVERYTHING THAT TIES THE ABOVE TOGETHER
00205     //BUILDSTYLE
00206     QString active_buildstyle;
00207 #if 0
00208     for(int as_release = 0; as_release < 2; as_release++) 
00209 #else
00210         bool as_release = !project->isActiveConfig("debug");
00211 #endif
00212     {
00213         QString key = keyFor("QMAKE_PBX_" + QString(as_release ? "RELEASE" : "DEBUG"));
00214         if(project->isActiveConfig("debug") != as_release) 
00215             active_buildstyle = key;
00216         project->variables()["QMAKE_PBX_BUILDSTYLES"].append(key);
00217         t << "\t\t" << key << " = {" << "\n"
00218           << "\t\t\t" << "buildRules = (" << "\n"
00219           << "\t\t\t" << ");" << "\n"
00220           << "\t\t\t" << "buildSettings = {" << "\n"
00221           << "\t\t\t\t" << "COPY_PHASE_STRIP = " << (as_release ? "YES" : "NO") << ";" << "\n";
00222         if(as_release) 
00223             t << "\t\t\t\t" << "DEBUGGING_SYMBOLS = NO;" << "\n";
00224         t << "\t\t\t" << "};" << "\n"
00225           << "\t\t\t" << "isa = PBXBuildStyle;" << "\n"
00226           << "\t\t\t" << "name = " << (as_release ? "Deployment" : "Development") << ";" << "\n"
00227           << "\t\t" << "};" << "\n";
00228     }
00229 
00230     //ROOT_GROUP
00231     t << "\t\t" << keyFor("QMAKE_PBX_ROOT_GROUP") << " = {" << "\n"
00232       << "\t\t\t" << "children = (" << "\n"
00233       << varGlue("QMAKE_PBX_GROUPS", "\t\t\t\t", ",\n\t\t\t\t", "\n")
00234       << "\t\t\t" << ");" << "\n"
00235       << "\t\t\t" << "isa = PBXGroup;" << "\n"
00236       << "\t\t\t" << "refType = 4;" << "\n"
00237       << "\t\t\t" << "sourceTree = \"<group>\";" << "\n"
00238       << "\t\t" << "};" << "\n";
00239 
00240     //ROOT
00241     t << "\t\t" << keyFor("QMAKE_PBX_ROOT") << " = {" << "\n"
00242       << "\t\t\t" << "buildSettings = {" << "\n"
00243       << "\t\t\t" << "};" << "\n"
00244       << "\t\t\t" << "buildStyles = (" << "\n"
00245       << varGlue("QMAKE_PBX_BUILDSTYLES", "\t\t\t\t", ",\n\t\t\t\t", "\n")
00246       << "\t\t\t" << ");" << "\n"
00247       << "\t\t\t" << "isa = PBXProject;" << "\n"
00248       << "\t\t\t" << "mainGroup = " << keyFor("QMAKE_PBX_ROOT_GROUP") << ";" << "\n"
00249       << "\t\t\t" << "projectDirPath = \"\";" << "\n"
00250       << "\t\t\t" << "projectReferences = (" << "\n";
00251     {
00252         QStringList &libdirs = project->variables()["QMAKE_PBX_SUBDIRS"];
00253         for(QStringList::Iterator it = libdirs.begin(); it != libdirs.end(); ++it)
00254             t << "\t\t\t\t" << "{" << "\n"
00255               << "\t\t\t\t\t" << "ProductGroup = " << keyFor((*it) + "_PRODUCTGROUP") << ";" << "\n"
00256               << "\t\t\t\t\t" << "ProjectRef = " << keyFor((*it) + "_PROJECTREF") << ";" << "\n"
00257               << "\t\t\t\t" << "}," << "\n";
00258     }
00259     t << "\t\t\t" << ");" << "\n"
00260       << "\t\t\t" << "targets = (" << "\n"
00261       << "\t\t\t" << ");" << "\n"
00262       << "\t\t" << "};" << "\n";
00263 
00264     //FOOTER
00265     t << "\t" << "};" << "\n"
00266       << "\t" << "rootObject = " << keyFor("QMAKE_PBX_ROOT") << ";" << "\n"
00267       << "}" << endl;
00268 
00269     return TRUE;
00270 }
00271 
00272 bool
00273 ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
00274 {
00275     int i;
00276     QStringList tmp;
00277     bool did_preprocess = FALSE;
00278 
00279     //HEADER
00280     t << "// !$*UTF8*$!" << "\n"
00281       << "{" << "\n"
00282       << "\t" << "archiveVersion = 1;" << "\n"
00283       << "\t" << "classes = {" << "\n" << "\t" << "};" << "\n"
00284       << "\t" << "objectVersion = " << pbuilderVersion() << ";" << "\n"
00285       << "\t" << "objects = {" << endl;
00286 
00287     //MAKE QMAKE equivlant
00288     if(!project->isActiveConfig("no_autoqmake") && project->projectFile() != "(stdin)") {
00289         QString mkfile = pbx_dir + Option::dir_sep + "qt_makeqmake.mak";
00290         QFile mkf(mkfile);
00291         if(mkf.open(IO_WriteOnly | IO_Translate)) {
00292             debug_msg(1, "pbuilder: Creating file: %s", mkfile.latin1());
00293             QTextStream mkt(&mkf);
00294             writeHeader(mkt);
00295             mkt << "QMAKE    = "        <<
00296                 (project->isEmpty("QMAKE_QMAKE") ? QString("$(QTDIR)/bin/qmake") :
00297                  var("QMAKE_QMAKE")) << endl;
00298             writeMakeQmake(mkt);
00299             mkf.close();
00300         }
00301         QString phase_key = keyFor("QMAKE_PBX_MAKEQMAKE_BUILDPHASE");
00302         mkfile = fileFixify(mkfile, QDir::currentDirPath());
00303         project->variables()["QMAKE_PBX_PRESCRIPT_BUILDPHASES"].append(phase_key);
00304         t << "\t\t" << phase_key << " = {" << "\n"
00305           << "\t\t\t" << "buildActionMask = 2147483647;" << "\n"
00306           << "\t\t\t" << "files = (" << "\n"
00307           << "\t\t\t" << ");" << "\n"
00308           << "\t\t\t" << "generatedFileNames = (" << "\n"
00309           << "\t\t\t" << ");" << "\n"
00310           << "\t\t\t" << "isa = PBXShellScriptBuildPhase;" << "\n"
00311           << "\t\t\t" << "name = \"Qt Qmake\";" << "\n"
00312           << "\t\t\t" << "neededFileNames = (" << "\n"
00313           << "\t\t\t" << ");" << "\n"
00314           << "\t\t\t" << "shellPath = /bin/sh;" << "\n"
00315           << "\t\t\t" << "shellScript = \"make -C " << QDir::currentDirPath() <<
00316             " -f " << mkfile << "\";" << "\n"
00317           << "\t\t" << "};" << "\n";
00318     }
00319 
00320     //DUMP SOURCES
00321     QMap<QString, QStringList> groups;
00322     QString srcs[] = { "HEADERS", "SOURCES", "SRCMOC", "UICIMPLS", "QMAKE_IMAGE_COLLECTION", 
00323                        "FORMS", "QMAKE_INTERNAL_INCLUDED_FILES", QString::null };
00324     for(i = 0; !srcs[i].isNull(); i++) {
00325         tmp = project->variables()[srcs[i]];
00326         if(srcs[i] == "QMAKE_INTERNAL_INCLUDED_FILES") {
00327             QString pfile = project->projectFile();
00328             if(pfile != "(stdin)")
00329                 tmp.prepend(pfile);
00330         }
00331         QStringList &src_list = project->variables()["QMAKE_PBX_" + srcs[i]];
00332         QStringList &root_group_list = project->variables()["QMAKE_PBX_GROUPS"];
00333 
00334         //hard coded groups..
00335         QString src_group;
00336         if(srcs[i] == "SOURCES") 
00337             src_group = "Sources";
00338         else if(srcs[i] == "HEADERS")
00339             src_group = "Headers";
00340         else if(srcs[i] == "SRCMOC")
00341             src_group = "Sources [moc]";
00342         else if(srcs[i] == "UICIMPLS" || srcs[i] == "FORMS")
00343             src_group = "Sources [uic]";
00344         else if(srcs[i] == "QMAKE_IMAGE_COLLECTION")
00345             src_group = "Sources [images]";
00346         else if(srcs[i] == "QMAKE_INTERNAL_INCLUDED_FILES")
00347             src_group = "Sources [qmake]";
00348 
00349         for(QStringList::Iterator it = tmp.begin(); it != tmp.end(); ++it) {
00350             QStringList files = (*it);
00351             bool buildable = TRUE;
00352             if(srcs[i] == "FORMS") {
00353                 QString form_dot_h = (*it) + Option::h_ext.first();
00354                 if(QFile::exists(form_dot_h))
00355                     files += form_dot_h;
00356                 buildable = FALSE;
00357             } else if(srcs[i] == "HEADERS" || srcs[i] == "QMAKE_INTERNAL_INCLUDED_FILES") {
00358                 buildable = FALSE;
00359             }
00360 
00361             files = fileFixify(files);
00362             for(QStringList::Iterator file_it = files.begin(); file_it != files.end(); ++file_it) {
00363                 QString file = (*file_it);
00364                 if(file.length() >= 2 && (file[0] == '"' || file[0] == '\'') && file[(int) file.length()-1] == file[0])
00365                     file = file.mid(1, file.length()-2);
00366                 if(file.endsWith(Option::cpp_moc_ext) || file.endsWith(Option::prl_ext)) 
00367                     continue;
00368                 bool in_root = TRUE;
00369                 QString src_key = keyFor(file), name = file;
00370                 if(project->isActiveConfig("flat")) {
00371                     QString flat_file = fileFixify(file, QDir::currentDirPath(), Option::output_dir, TRUE);
00372                     if(flat_file.find(Option::dir_sep) != -1) {
00373                         QStringList dirs = QStringList::split(Option::dir_sep, flat_file);
00374                         name = dirs.back();
00375                     }
00376                 } else {
00377                     QString flat_file = fileFixify(file, QDir::currentDirPath(), Option::output_dir, TRUE);
00378                     if(QDir::isRelativePath(flat_file) && flat_file.find(Option::dir_sep) != -1) {
00379                         QString last_grp("QMAKE_PBX_" + src_group + "_HEIR_GROUP");
00380                         QStringList dirs = QStringList::split(Option::dir_sep, flat_file);
00381                         name = dirs.back();
00382                         dirs.pop_back(); //remove the file portion as it will be added via src_key
00383                         for(QStringList::Iterator dir_it = dirs.begin(); dir_it != dirs.end(); ++dir_it) {
00384                             QString new_grp(last_grp + Option::dir_sep + (*dir_it)), new_grp_key(keyFor(new_grp));
00385                             if(dir_it == dirs.begin()) {
00386                                 if(!src_list.contains(new_grp_key)) 
00387                                     src_list.append(new_grp_key);
00388                             } else {
00389                                 if(!groups[last_grp].contains(new_grp_key))
00390                                     groups[last_grp] += new_grp_key;
00391                             }
00392                             last_grp = new_grp;
00393                         }
00394                         groups[last_grp] += src_key;
00395                         in_root = FALSE;
00396                     }
00397                 }
00398                 if(in_root) 
00399                     src_list.append(src_key);
00400                 //source reference
00401                 t << "\t\t" << src_key << " = {" << "\n"
00402                   << "\t\t\t" << "isa = PBXFileReference;" << "\n"
00403                   << "\t\t\t" << "name = \"" << name << "\";" << "\n"
00404                   << "\t\t\t" << "path = \"" << file << "\";" << "\n"
00405                   << "\t\t\t" << "refType = " << reftypeForFile(file) << ";" << "\n";
00406                 if (ideType() == MAC_XCODE) {
00407                     QString filetype;
00408                     for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) {
00409                         if(file.endsWith((*cppit))) {
00410                             filetype = "sourcecode.cpp.cpp";
00411                             break;
00412                         }
00413                     }
00414                     if(!filetype.isNull())
00415                         t << "\t\t\t" << "lastKnownFileType = " << filetype << ";" << "\n";
00416                 }
00417                 t << "\t\t" << "};" << "\n";
00418                 if(buildable) { //build reference
00419                     QString obj_key = file + ".o";
00420                     obj_key = keyFor(obj_key);
00421                     t << "\t\t" << obj_key << " = {" << "\n"
00422                       << "\t\t\t" << "fileRef = " << src_key << ";" << "\n"
00423                       << "\t\t\t" << "isa = PBXBuildFile;" << "\n"
00424                       << "\t\t\t" << "settings = {" << "\n"
00425                       << "\t\t\t\t" << "ATTRIBUTES = (" << "\n"
00426                       << "\t\t\t\t" << ");" << "\n"
00427                       << "\t\t\t" << "};" << "\n"
00428                       << "\t\t" << "};" << "\n";
00429                     project->variables()["QMAKE_PBX_OBJ"].append(obj_key);
00430                 }
00431             }
00432         }
00433         if(!src_list.isEmpty()) {
00434             if(srcs[i] == "SOURCES") {
00435                 if(project->first("TEMPLATE") == "app" && !project->isEmpty("RC_FILE")) { //Icon
00436                     QString icns_file = keyFor("ICNS_FILE");
00437                     src_list.append(icns_file);
00438                     t << "\t\t" << icns_file << " = {" << "\n"
00439                       << "\t\t\t" << "isa = PBXFileReference;" << "\n"
00440                       << "\t\t\t" << "path = \"" << project->first("RC_FILE") << "\";" << "\n"
00441                       << "\t\t\t" << "refType = " << reftypeForFile(project->first("RC_FILE")) << ";" << "\n"
00442                       << "\t\t" << "};" << "\n";
00443                     t << "\t\t" << keyFor("ICNS_FILE_REFERENCE") << " = {" << "\n"
00444                       << "\t\t\t" << "fileRef = " << icns_file << ";" << "\n"
00445                       << "\t\t\t" << "isa = PBXBuildFile;" << "\n"
00446                       << "\t\t\t" << "settings = {" << "\n"
00447                       << "\t\t\t" << "};" << "\n"
00448                       << "\t\t" << "};" << "\n";
00449                 }
00450             }
00451 
00452             QString src_group_key = keyFor(src_group);
00453             if(root_group_list.findIndex(src_group_key) == -1) 
00454                 root_group_list += src_group_key;
00455             groups[src_group] += src_list;
00456         }
00457     }
00458     for(QMap<QString, QStringList>::Iterator grp_it = groups.begin(); grp_it != groups.end(); ++grp_it) {
00459         t << "\t\t" << keyFor(grp_it.key()) << " = {" << "\n"
00460           << "\t\t\t" << "isa = PBXGroup;" << "\n"
00461           << "\t\t\t" << "children = (" << "\n"
00462           << valGlue(grp_it.data(), "\t\t\t\t", ",\n\t\t\t\t", "\n")
00463           << "\t\t\t" << ");" << "\n"
00464           << "\t\t\t" << "name = \"" << grp_it.key().section(Option::dir_sep, -1) << "\";" << "\n"
00465           << "\t\t\t" << "refType = 4;" << "\n"
00466           << "\t\t" << "};" << "\n";
00467     }
00468 
00469     //PREPROCESS BUILDPHASE (just a makefile)
00470     if(!project->isEmpty("UICIMPLS") || !project->isEmpty("SRCMOC") ||
00471         !project->isEmpty("YACCSOURCES") || !project->isEmpty("LEXSOURCES")) {
00472         QString mkfile = pbx_dir + Option::dir_sep + "qt_preprocess.mak";
00473         QFile mkf(mkfile);
00474         if(mkf.open(IO_WriteOnly | IO_Translate)) {
00475             did_preprocess = TRUE;
00476             debug_msg(1, "pbuilder: Creating file: %s", mkfile.latin1());
00477             QTextStream mkt(&mkf);
00478             writeHeader(mkt);
00479             mkt << "MOC       = " << Option::fixPathToTargetOS(var("QMAKE_MOC")) << endl;
00480             mkt << "UIC       = " << Option::fixPathToTargetOS(var("QMAKE_UIC")) << endl;
00481             mkt << "LEX       = " << var("QMAKE_LEX") << endl;
00482             mkt << "LEXFLAGS  = " << var("QMAKE_LEXFLAGS") << endl;
00483             mkt << "YACC      = " << var("QMAKE_YACC") << endl;
00484             mkt << "YACCFLAGS = " << var("QMAKE_YACCFLAGS") << endl;
00485             mkt << "DEL_FILE  = " << var("QMAKE_DEL_FILE") << endl;
00486             mkt << "MOVE      = " << var("QMAKE_MOVE") << endl << endl;
00487             mkt << "FORMS = " << varList("UICIMPLS") << endl;
00488             mkt << "IMAGES = " << varList("QMAKE_IMAGE_COLLECTION") << endl;
00489             mkt << "MOCS = " << varList("SRCMOC") << endl;
00490             mkt << "PARSERS =";
00491             if(!project->isEmpty("YACCSOURCES")) {
00492                 QStringList &yaccs = project->variables()["YACCSOURCES"];
00493                 for(QStringList::Iterator yit = yaccs.begin(); yit != yaccs.end(); ++yit) {
00494                     QFileInfo fi((*yit));
00495                     mkt << " " << fi.dirPath() << Option::dir_sep << fi.baseName(TRUE)
00496                         << Option::yacc_mod << Option::cpp_ext.first();
00497                 }
00498             }
00499             if(!project->isEmpty("LEXSOURCES")) {
00500                 QStringList &lexs = project->variables()["LEXSOURCES"];
00501                 for(QStringList::Iterator lit = lexs.begin(); lit != lexs.end(); ++lit) {
00502                     QFileInfo fi((*lit));
00503                     mkt << " " << fi.dirPath() << Option::dir_sep << fi.baseName(TRUE)
00504                         << Option::lex_mod << Option::cpp_ext.first();
00505                 }
00506             }
00507             mkt << "\n";
00508             mkt << "preprocess: $(FORMS) $(MOCS) $(PARSERS) $(IMAGES)" << endl;
00509             mkt << "clean preprocess_clean: mocclean uiclean parser_clean" << endl << endl;
00510             mkt << "mocclean:" << "\n";
00511             if(!project->isEmpty("SRCMOC"))
00512                 mkt << "\t-rm -f $(MOCS)" << "\n";
00513             mkt << "uiclean:" << "\n";
00514             if(!project->isEmpty("UICIMPLS"))
00515                 mkt << "\t-rm -f $(FORMS)" << "\n";
00516             if(!project->isEmpty("QMAKE_IMAGE_COLLECTION"))
00517                 mkt << "\t-rm -f $(IMAGES)" << "\n";
00518             mkt << "parser_clean:" << "\n";
00519             if(!project->isEmpty("YACCSOURCES") || !project->isEmpty("LEXSOURCES"))
00520                 mkt << "\t-rm -f $(PARSERS)" << "\n";
00521             writeUicSrc(mkt, "FORMS");
00522             writeMocSrc(mkt, "HEADERS");
00523             writeMocSrc(mkt, "SOURCES");
00524             writeMocSrc(mkt, "UICDECLS");
00525             writeYaccSrc(mkt, "YACCSOURCES");
00526             writeLexSrc(mkt, "LEXSOURCES");
00527             writeImageSrc(mkt, "QMAKE_IMAGE_COLLECTION");
00528             mkf.close();
00529         }
00530         mkfile = fileFixify(mkfile, QDir::currentDirPath());
00531         QString phase_key = keyFor("QMAKE_PBX_PREPROCESS_TARGET");
00532 //      project->variables()["QMAKE_PBX_BUILDPHASES"].append(phase_key);
00533         project->variables()["QMAKE_PBX_PRESCRIPT_BUILDPHASES"].append(phase_key);
00534         t << "\t\t" << phase_key << " = {" << "\n"
00535           << "\t\t\t" << "buildActionMask = 2147483647;" << "\n"
00536           << "\t\t\t" << "files = (" << "\n"
00537           << "\t\t\t" << ");" << "\n"
00538           << "\t\t\t" << "generatedFileNames = (" << "\n"
00539           << varGlue("QMAKE_PBX_OBJ", "\t\t\t\t", ",\n\t\t\t\t", "\n")
00540           << "\t\t\t" << ");" << "\n"
00541           << "\t\t\t" << "isa = PBXShellScriptBuildPhase;" << "\n"
00542           << "\t\t\t" << "name = \"Qt Preprocessors\";" << "\n"
00543           << "\t\t\t" << "neededFileNames = (" << "\n"
00544           << varGlue("QMAKE_PBX_OBJ", "\t\t\t\t", ",\n\t\t\t\t", "\n")
00545           << "\t\t\t" << ");" << "\n"
00546           << "\t\t\t" << "shellPath = /bin/sh;" << "\n"
00547           << "\t\t\t" << "shellScript = \"make -C " << QDir::currentDirPath() <<
00548             " -f " << mkfile << "\";" << "\n"
00549           << "\t\t" << "};" << "\n";
00550    }
00551 
00552     //SOURCE BUILDPHASE
00553     if(!project->isEmpty("QMAKE_PBX_OBJ")) {
00554         QString grp = "Build Sources", key = keyFor(grp);
00555         project->variables()["QMAKE_PBX_BUILDPHASES"].append(key);
00556         t << "\t\t" << key << " = {" << "\n"
00557           << "\t\t\t" << "buildActionMask = 2147483647;" << "\n"
00558           << "\t\t\t" << "files = (" << "\n"
00559           << varGlue("QMAKE_PBX_OBJ", "\t\t\t\t", ",\n\t\t\t\t", "\n")
00560           << "\t\t\t" << ");" << "\n"
00561           << "\t\t\t" << "isa = PBXSourcesBuildPhase;" << "\n"
00562           << "\t\t\t" << "name = \"" << grp << "\";" << "\n"
00563           << "\t\t" << "};" << "\n";
00564     }
00565 
00566     if(!project->isActiveConfig("staticlib")) { //DUMP LIBRARIES
00567         QStringList &libdirs = project->variables()["QMAKE_PBX_LIBPATHS"];
00568         QString libs[] = { "QMAKE_LFLAGS", "QMAKE_LIBDIR_FLAGS", "QMAKE_LIBS", QString::null };
00569         for(i = 0; !libs[i].isNull(); i++) {
00570             tmp = project->variables()[libs[i]];
00571             for(QStringList::Iterator it = tmp.begin(); it != tmp.end();) {
00572                 bool remove = FALSE;
00573                 QString library, name, opt = (*it).stripWhiteSpace();
00574                 if(opt.length() >= 2 && (opt[0] == '"' || opt[0] == '\'') && opt[(int) opt.length()-1] == opt[0])
00575                     opt = opt.mid(1, opt.length()-2);
00576                 if(opt.startsWith("-L")) {
00577                     QString r = opt.right(opt.length() - 2);
00578                     fixEnvVariables(r);
00579                     libdirs.append(r);
00580                 } else if(opt == "-prebind") {
00581                     project->variables()["QMAKE_DO_PREBINDING"].append("TRUE");
00582                     remove = TRUE;
00583                 } else if(opt.startsWith("-l")) {
00584                     name = opt.right(opt.length() - 2);
00585                     QString lib("lib" + name);
00586                     for(QStringList::Iterator lit = libdirs.begin(); lit != libdirs.end(); ++lit) {
00587                         if(project->isActiveConfig("link_prl")) {
00588                             /* This isn't real nice, but it is real usefull. This looks in a prl
00589                                for what the library will ultimately be called so we can stick it
00590                                in the ProjectFile. If the prl format ever changes (not likely) then
00591                                this will not really work. However, more concerning is that it will
00592                                encode the version number in the Project file which might be a bad
00593                                things in days to come? --Sam
00594                             */
00595                             QString lib_file = (*lit) + Option::dir_sep + lib;
00596                             if(QMakeMetaInfo::libExists(lib_file)) {
00597                                 QMakeMetaInfo libinfo;
00598                                 if(libinfo.readLib(lib_file)) {
00599                                     if(!libinfo.isEmpty("QMAKE_PRL_TARGET")) {
00600                                         library = (*lit) + Option::dir_sep + libinfo.first("QMAKE_PRL_TARGET");
00601                                         debug_msg(1, "pbuilder: Found library (%s) via PRL %s (%s)", 
00602                                                   opt.latin1(), lib_file.latin1(), library.latin1());
00603                                         remove = TRUE;
00604                                     }
00605                                 }
00606                             }
00607                         }
00608                         if(!remove) {
00609                             QString extns[] = { ".dylib", ".so", ".a", QString::null };
00610                             for(int n = 0; !remove && !extns[n].isNull(); n++) {
00611                                 QString tmp =  (*lit) + Option::dir_sep + lib + extns[n];
00612                                 if(QFile::exists(tmp)) {
00613                                     library = tmp;
00614                                     debug_msg(1, "pbuilder: Found library (%s) via %s", 
00615                                               opt.latin1(), library.latin1());
00616                                     remove = TRUE;
00617                                 }
00618                             }
00619                         }
00620                     }
00621                 } else if(opt == "-framework") {
00622                     ++it;
00623                     if(it == tmp.end())
00624                         break;
00625                     QStringList &fdirs = project->variables()["QMAKE_FRAMEWORKDIR"];
00626                     if(fdirs.isEmpty())
00627                         fdirs.append("/System/Library/Frameworks/");
00628                     for(QStringList::Iterator fit = fdirs.begin(); fit != fdirs.end(); ++fit) {
00629                         if(QFile::exists((*fit) + QDir::separator() + (*it) + ".framework")) {
00630                             --it;
00631                             it = tmp.remove(it);
00632                             remove = TRUE;
00633                             library = (*fit) + Option::dir_sep + (*it) + ".framework";
00634                             break;
00635                         }
00636                     }
00637                 } else if(opt == "-undefined") {
00638                     ++it; //the next option is not a library..
00639                 } else if(opt.left(1) != "-") {
00640                     remove = TRUE;
00641                     library = opt;
00642                 }
00643                 if(!library.isEmpty()) {
00644                     if(name.isEmpty()) {
00645                         int slsh = library.findRev(Option::dir_sep);
00646                         if(slsh != -1)
00647                             name = library.right(library.length() - slsh - 1);
00648                     }
00649                     library = fileFixify(library);
00650                     QString key = keyFor(library);
00651                     bool is_frmwrk = (library.endsWith(".framework"));
00652                     t << "\t\t" << key << " = {" << "\n"
00653                       << "\t\t\t" << "isa = " << (is_frmwrk ? "PBXFrameworkReference" : "PBXFileReference") << ";" << "\n"
00654                       << "\t\t\t" << "name = \"" << name << "\";" << "\n"
00655                       << "\t\t\t" << "path = \"" << library << "\";" << "\n"
00656                       << "\t\t\t" << "refType = " << reftypeForFile(library) << ";" << "\n"
00657                       << "\t\t" << "};" << "\n";
00658                     project->variables()["QMAKE_PBX_LIBRARIES"].append(key);
00659                     QString obj_key = library + ".o";
00660                     obj_key = keyFor(obj_key);
00661                     t << "\t\t" << obj_key << " = {" << "\n"
00662                       << "\t\t\t" << "fileRef = " << key << ";" << "\n"
00663                       << "\t\t\t" << "isa = PBXBuildFile;" << "\n"
00664                       << "\t\t\t" << "settings = {" << "\n"
00665                       << "\t\t\t" << "};" << "\n"
00666                       << "\t\t" << "};" << "\n";
00667                     project->variables()["QMAKE_PBX_BUILD_LIBRARIES"].append(obj_key);
00668                 }
00669                 if(remove)
00670                     it = tmp.remove(it);
00671                 else
00672                     ++it;
00673             }
00674             project->variables()[libs[i]] = tmp;
00675         }
00676     }
00677     //SUBLIBS BUILDPHASE (just another makefile)
00678     if(!project->isEmpty("SUBLIBS")) {
00679         QString mkfile = pbx_dir + Option::dir_sep + "qt_sublibs.mak";
00680         QFile mkf(mkfile);
00681         if(mkf.open(IO_WriteOnly | IO_Translate)) {
00682             debug_msg(1, "pbuilder: Creating file: %s", mkfile.latin1());
00683             QTextStream mkt(&mkf);
00684             writeHeader(mkt);
00685             mkt << "SUBLIBS= ";
00686             tmp = project->variables()["SUBLIBS"];
00687             QStringList::Iterator it;
00688             for(it = tmp.begin(); it != tmp.end(); ++it)
00689                 t << "tmp/lib" << (*it) << ".a ";
00690             t << endl << endl;
00691             mkt << "sublibs: $(SUBLIBS)" << endl << endl;
00692             tmp = project->variables()["SUBLIBS"];
00693             for(it = tmp.begin(); it != tmp.end(); ++it)
00694                 t << "tmp/lib" << (*it) << ".a" << ":\n\t"
00695                   << var(QString("MAKELIB") + (*it)) << endl << endl;
00696             mkf.close();
00697         }
00698         QString phase_key = keyFor("QMAKE_PBX_SUBLIBS_BUILDPHASE");
00699         mkfile = fileFixify(mkfile, QDir::currentDirPath());
00700         project->variables()["QMAKE_PBX_PRESCRIPT_BUILDPHASES"].append(phase_key);
00701         t << "\t\t" << phase_key << " = {" << "\n"
00702           << "\t\t\t" << "buildActionMask = 2147483647;" << "\n"
00703           << "\t\t\t" << "files = (" << "\n"
00704           << "\t\t\t" << ");" << "\n"
00705           << "\t\t\t" << "generatedFileNames = (" << "\n"
00706           << "\t\t\t" << ");" << "\n"
00707           << "\t\t\t" << "isa = PBXShellScriptBuildPhase;" << "\n"
00708           << "\t\t\t" << "name = \"Qt Sublibs\";" << "\n"
00709           << "\t\t\t" << "neededFileNames = (" << "\n"
00710           << "\t\t\t" << ");" << "\n"
00711           << "\t\t\t" << "shellPath = /bin/sh;" << "\n"
00712           << "\t\t\t" << "shellScript = \"make -C " << QDir::currentDirPath() <<
00713             " -f " << mkfile << "\";" << "\n"
00714           << "\t\t" << "};" << "\n";
00715     }
00716     //LIBRARY BUILDPHASE
00717     if(!project->isEmpty("QMAKE_PBX_LIBRARIES")) {
00718         tmp = project->variables()["QMAKE_PBX_LIBRARIES"];
00719         if(!tmp.isEmpty()) {
00720             QString grp("External Frameworks and Libraries"), key = keyFor(grp);
00721             project->variables()["QMAKE_PBX_GROUPS"].append(key);
00722             t << "\t\t" << key << " = {" << "\n"
00723               << "\t\t\t" << "children = (" << "\n"
00724               << varGlue("QMAKE_PBX_LIBRARIES", "\t\t\t\t", ",\n\t\t\t\t", "\n")
00725               << "\t\t\t" << ");" << "\n"
00726               << "\t\t\t" << "isa = PBXGroup;" << "\n"
00727               << "\t\t\t" << "name = \"" << grp << "\"" << ";" << "\n"
00728               << "\t\t\t" << "path = \"\";" << "\n"
00729               << "\t\t\t" << "refType = 4;" << "\n"
00730               << "\t\t" << "};" << "\n";
00731         }
00732     }
00733     {
00734         QString grp("Frameworks & Libraries"), key = keyFor(grp);
00735         project->variables()["QMAKE_PBX_BUILDPHASES"].append(key);
00736         t << "\t\t" << key << " = {" << "\n"
00737           << "\t\t\t" << "buildActionMask = 2147483647;" << "\n"
00738           << "\t\t\t" << "files = (" << "\n"
00739           << varGlue("QMAKE_PBX_BUILD_LIBRARIES", "\t\t\t\t", ",\n\t\t\t\t", "\n")
00740           << "\t\t\t" << ");" << "\n"
00741           << "\t\t\t" << "isa = PBXFrameworksBuildPhase;" << "\n"
00742           << "\t\t\t" << "name = \"" << grp << "\";" << "\n"
00743           << "\t\t" << "};" << "\n";
00744     }
00745     if(!project->isActiveConfig("console") && project->first("TEMPLATE") == "app") { //BUNDLE RESOURCES
00746         QString grp("Bundle Resources"), key = keyFor(grp);
00747         project->variables()["QMAKE_PBX_BUILDPHASES"].append(key);
00748         t << "\t\t" << key << " = {" << "\n"
00749           << "\t\t\t" << "buildActionMask = 2147483647;" << "\n"
00750           << "\t\t\t" << "files = (" << "\n"
00751           << (!project->isEmpty("RC_FILE") ? keyFor("ICNS_FILE_REFERENCE") : QString(""))
00752           << "\t\t\t" << ");" << "\n"
00753           << "\t\t\t" << "isa = PBXResourcesBuildPhase;" << "\n"
00754           << "\t\t\t" << "name = \"" << grp << "\";" << "\n"
00755           << "\t\t" << "};" << "\n";
00756     }
00757     { //INSTALL BUILDPHASE (sh script)
00758         QString targ = project->first("TARGET");
00759         if(project->first("TEMPLATE") == "app" ||
00760            (project->first("TEMPLATE") == "lib" && !project->isActiveConfig("staticlib") &&
00761             project->isActiveConfig("frameworklib")))
00762             targ = project->first("QMAKE_ORIG_TARGET");
00763         int slsh = targ.findRev(Option::dir_sep);
00764         if(slsh != -1)
00765             targ = targ.right(targ.length() - slsh - 1);
00766         fixEnvVariables(targ);
00767         QStringList links;
00768         if(project->first("TEMPLATE") == "app") {
00769             if(project->isActiveConfig("resource_fork") && !project->isActiveConfig("console"))
00770                 targ += ".app";
00771         } else if(!project->isActiveConfig("staticlib") && !project->isActiveConfig("plugin") && 
00772            !project->isActiveConfig("frameworklib")) {
00773             QString li[] = { "TARGET_", "TARGET_x", "TARGET_x.y", QString::null };
00774             for(int n = 0; !li[n].isNull(); n++) {
00775                 QString t = project->first(li[n]);
00776                 slsh = t.findRev(Option::dir_sep);
00777                 if(slsh != -1)
00778                     t = t.right(t.length() - slsh);
00779                 fixEnvVariables(t);
00780                 links << t;
00781             }
00782         }
00783         QString script = pbx_dir + Option::dir_sep + "qt_install.sh";
00784         QFile shf(script);
00785         if(shf.open(IO_WriteOnly | IO_Translate)) {
00786             debug_msg(1, "pbuilder: Creating file: %s", script.latin1());
00787             QString targ = project->first("QMAKE_ORIG_TARGET"), cpflags;
00788             if(project->first("TEMPLATE") == "app") {
00789                 targ = project->first("TARGET");
00790                 if(!project->isActiveConfig("console")) {
00791                     targ += ".app";
00792                     cpflags += "-r ";
00793                 }
00794             } else if(!project->isActiveConfig("frameworklib")) {
00795                 if(project->isActiveConfig("staticlib"))
00796                     targ = project->first("TARGET");
00797                 else
00798                     targ = project->first("TARGET_");
00799             }
00800             int slsh = targ.findRev(Option::dir_sep);
00801             if(slsh != -1)
00802                 targ = targ.right(targ.length() - slsh - 1);
00803 
00804             QString dstdir = project->first("DESTDIR");
00805             fixEnvVariables(dstdir);
00806 
00807             QTextStream sht(&shf);
00808             sht << "#!/bin/sh" << endl;
00809             //copy the actual target
00810             sht << "OUT_TARG=\"${TARGET_BUILD_DIR}/${FULL_PRODUCT_NAME}\"\n" 
00811                 << "if [ -e \"$OUT_TARG\" ]; then" << "\n"
00812                 << "  [ \"$OUT_TARG\" = \"" 
00813                 << (dstdir.isEmpty() ? QDir::currentDirPath() + QDir::separator(): dstdir) << targ << "\" ] || " 
00814                 << "[ \"$OUT_TARG\" = \"" << targ << "\" ] || " 
00815                 << "cp -r \"$OUT_TARG\" " << "\"" << dstdir << targ << "\"" << "\n"
00816                 << "fi" << endl;
00817             //rename as a framework
00818             if(project->first("TEMPLATE") == "lib" && project->isActiveConfig("frameworklib") && !project->isActiveConfig("plugin"))
00819                 sht << "ln -sf \"" << targ <<  "\" " << "\"" << dstdir << targ << "\"" << endl;
00820             //create all the version symlinks (just to be like unixmake)
00821             for(QStringList::Iterator it = links.begin(); it != links.end(); ++it) {
00822                 if(targ != (*it)) 
00823                     sht << "ln -sf \"" << targ <<  "\" " << "\"" << dstdir << (*it) << "\"" << endl;
00824             }
00825             shf.close();
00826 #ifdef Q_OS_UNIX
00827             chmod(script.latin1(), S_IRWXU | S_IRWXG);
00828 #endif
00829             QString phase_key = keyFor("QMAKE_PBX_INSTALL_BUILDPHASE");
00830             script = fileFixify(script, QDir::currentDirPath());
00831             project->variables()["QMAKE_PBX_BUILDPHASES"].append(phase_key);
00832             t << "\t\t" << phase_key << " = {" << "\n"
00833               << "\t\t\t" << "buildActionMask = 2147483647;" << "\n"
00834               << "\t\t\t" << "files = (" << "\n"
00835               << "\t\t\t" << ");" << "\n"
00836               << "\t\t\t" << "generatedFileNames = (" << "\n"
00837               << "\t\t\t" << ");" << "\n"
00838               << "\t\t\t" << "isa = PBXShellScriptBuildPhase;" << "\n"
00839               << "\t\t\t" << "name = \"Qt Install\";" << "\n"
00840               << "\t\t\t" << "neededFileNames = (" << "\n"
00841               << "\t\t\t" << ");" << "\n"
00842               << "\t\t\t" << "shellPath = /bin/sh;" << "\n"
00843               << "\t\t\t" << "shellScript = \"" << script << "\";" << "\n"
00844               << "\t\t" << "};" << "\n";
00845         }
00846     }
00847     if(/*ideType() == MAC_XCODE &&*/ !project->isEmpty("QMAKE_PBX_PRESCRIPT_BUILDPHASES") && 0) {
00848         // build reference
00849         t << "\t\t" << keyFor("QMAKE_PBX_PRESCRIPT_BUILDREFERENCE") << " = {" << "\n"
00850           << "\t\t\t" << "includeInIndex = 0;" << "\n"
00851           << "\t\t\t" << "isa = PBXFileReference;" << "\n"
00852           << "\t\t\t" << "path = preprocessor.out;" << "\n"
00853           << "\t\t\t" << "refType = 3;" << "\n"
00854           << "\t\t\t" << "sourceTree = BUILT_PRODUCTS_DIR;" << "\n"
00855           << "\t\t" << "};" << "\n";
00856         project->variables()["QMAKE_PBX_PRODUCTS"].append(keyFor("QMAKE_PBX_PRESCRIPTS_BUILDREFERENCE"));
00857         //build phase
00858         QString prescript_key = keyFor("QMAKE_PBX_PRESCRIPTS_BUILDPHASE");
00859         project->variables()["QMAKE_PBX_TARGETS"].append(prescript_key);
00860         t << "\t\t" << prescript_key << " = {" << "\n"
00861           << "\t\t\t" << "buildPhases = (" << "\n"
00862           << varGlue("QMAKE_PBX_PRESCRIPT_BUILDPHASES", "\t\t\t\t", ",\n\t\t\t\t", "\n")
00863           << "\t\t\t" << ");" << "\n"
00864           << "\t\t\t" << "buildRules = (" << "\n"
00865           << "\t\t\t" << ");" << "\n"
00866           << "\t\t\t" << "buildSettings = {" << "\n"
00867           << "\t\t\t" << "};" << "\n"
00868           << "\t\t\t" << "dependencies = (" << "\n"
00869           << "\t\t\t" << ");" << "\n"
00870           << "\t\t\t" << "isa = PBXNativeTarget;" << "\n"
00871           << "\t\t\t" << "name = \"Qt Preprocessor Steps\";" << "\n"
00872           << "\t\t\t" << "productName = \"Qt Preprocessor Steps\";" << "\n"
00873           << "\t\t\t" << "productReference = " << keyFor("QMAKE_PBX_PRESCRIPTS_BUILDREFERENCE") << ";" << "\n"
00874           << "\t\t\t" << "productType = \"com.apple.product-type.tool\";" << "\n"
00875           << "\t\t" << "};" << "\n";
00876         //dependency
00877         t << "\t\t" << keyFor("QMAKE_PBX_PRESCRIPTS_DEPENDENCY") << " = {" << "\n"
00878           << "\t\t\t" << "isa = PBXTargetDependency;" << "\n"
00879           << "\t\t\t" << "target = " << keyFor("QMAKE_PBX_PRESCRIPTS_BUILDPHASE") << ";" << "\n"
00880           << "\t\t" << "};" << "\n";
00881         project->variables()["QMAKE_PBX_TARGET_DEPENDS"].append(keyFor("QMAKE_PBX_PRESCRIPTS_DEPENDENCY"));
00882         project->variables()["QMAKE_PBX_PRESCRIPT_BUILDPHASES"].clear(); //these are already consumed above
00883     }
00884 
00885     //DUMP EVERYTHING THAT TIES THE ABOVE TOGETHER
00886     //ROOT_GROUP
00887     t << "\t\t" << keyFor("QMAKE_PBX_ROOT_GROUP") << " = {" << "\n"
00888       << "\t\t\t" << "children = (" << "\n"
00889       << varGlue("QMAKE_PBX_GROUPS", "\t\t\t\t", ",\n\t\t\t\t", "\n")
00890       << "\t\t\t" << ");" << "\n"
00891       << "\t\t\t" << "isa = PBXGroup;" << "\n"
00892       << "\t\t\t" << "name = " << project->first("QMAKE_ORIG_TARGET") << ";" << "\n"
00893       << "\t\t\t" << "path = \"\";" << "\n"
00894       << "\t\t\t" << "refType = 4;" << "\n"
00895       << "\t\t" << "};" << "\n";
00896     //REFERENCE
00897     project->variables()["QMAKE_PBX_PRODUCTS"].append(keyFor(pbx_dir + "QMAKE_PBX_REFERENCE"));
00898     t << "\t\t" << keyFor(pbx_dir + "QMAKE_PBX_REFERENCE") << " = {" << "\n"
00899       << "\t\t\t" << "fallbackIsa = PBXFileReference;" << "\n";
00900     if(project->first("TEMPLATE") == "app") {
00901         QString targ = project->first("QMAKE_ORIG_TARGET");
00902         if(project->isActiveConfig("resource_fork") && !project->isActiveConfig("console")) {
00903             targ += ".app";
00904             t << "\t\t\t" << "isa = PBXApplicationReference;" << "\n";
00905         } else {
00906             t << "\t\t\t" << "isa = PBXExecutableFileReference;" << "\n";
00907         }
00908         QString app = (!project->isEmpty("DESTDIR") ? project->first("DESTDIR") + project->first("QMAKE_ORIG_TARGET") : 
00909                        QDir::currentDirPath()) + Option::dir_sep + targ;
00910         t << "\t\t\t" << "name = " <<  targ << ";" << "\n"
00911           << "\t\t\t" << "path = \"" << targ << "\";" << "\n"
00912           << "\t\t\t" << "refType = " << reftypeForFile(app) << ";" << "\n";
00913     } else {
00914         QString lib = project->first("QMAKE_ORIG_TARGET");
00915         if(project->isActiveConfig("staticlib")) {
00916             lib = project->first("TARGET");
00917         } else if(!project->isActiveConfig("frameworklib")) {
00918             if(project->isActiveConfig("plugin"))
00919                 lib = project->first("TARGET");
00920             else
00921                 lib = project->first("TARGET_");
00922         }
00923         int slsh = lib.findRev(Option::dir_sep);
00924         if(slsh != -1)
00925             lib = lib.right(lib.length() - slsh - 1);
00926         t << "\t\t\t" << "isa = PBXLibraryReference;" << "\n"
00927           << "\t\t\t" << "expectedFileType = \"compiled.mach-o.dylib\";" << "\n"
00928           << "\t\t\t" << "path = " << lib << ";\n"
00929           << "\t\t\t" << "refType = " << 3/*reftypeForFile(lib)*/ << ";" << "\n"
00930           << "\t\t\t" << "sourceTree = BUILT_PRODUCTS_DIR" << ";" << "\n";
00931     }
00932     t << "\t\t" << "};" << "\n";
00933     { //Products group
00934         QString grp("Products"), key = keyFor(grp);
00935         project->variables()["QMAKE_PBX_GROUPS"].append(key);
00936         t << "\t\t" << key << " = {" << "\n"
00937           << "\t\t\t" << "children = (" << "\n"
00938           << varGlue("QMAKE_PBX_PRODUCTS", "\t\t\t\t", ",\n\t\t\t\t", "\n")
00939           << "\t\t\t" << ");" << "\n"
00940           << "\t\t\t" << "isa = PBXGroup;" << "\n"
00941           << "\t\t\t" << "name = Products;" << "\n"
00942           << "\t\t\t" << "refType = 4;" << "\n"
00943           << "\t\t" << "};" << "\n";
00944     }
00945     //TARGET
00946     QString target_key = keyFor("QMAKE_PBX_TARGET");
00947     project->variables()["QMAKE_PBX_TARGETS"].append(target_key);
00948     t << "\t\t" << target_key << " = {" << "\n"
00949       << "\t\t\t" << "buildPhases = (" << "\n"
00950       << varGlue("QMAKE_PBX_PRESCRIPT_BUILDPHASES", "\t\t\t\t", ",\n\t\t\t\t", ",\n")
00951       << varGlue("QMAKE_PBX_BUILDPHASES", "\t\t\t\t", ",\n\t\t\t\t", "\n")
00952       << "\t\t\t" << ");" << "\n"
00953       << "\t\t\t" << "buildSettings = {" << "\n"
00954       << "\t\t\t\t" << "CC = \"" << fixEnvsList("QMAKE_CC") << "\";" << "\n"
00955       << "\t\t\t\t" << "CPLUSPLUS = \"" << fixEnvsList("QMAKE_CXX") << "\";" << "\n"
00956       << "\t\t\t\t" << "FRAMEWORK_SEARCH_PATHS = \"\";" << "\n"
00957       << "\t\t\t\t" << "HEADER_SEARCH_PATHS = \"" << fixEnvsList("INCLUDEPATH") << " " << fixEnvs(specdir()) << "\";" << "\n"
00958       << "\t\t\t\t" << "LIBRARY_SEARCH_PATHS = \"" << var("QMAKE_PBX_LIBPATHS") << "\";" << "\n"
00959       << "\t\t\t\t" << "OPTIMIZATION_CFLAGS = \"\";" << "\n"
00960       << "\t\t\t\t" << "OTHER_CFLAGS = \"" <<
00961         fixEnvsList("QMAKE_CFLAGS") << fixQuotes(varGlue("PRL_EXPORT_DEFINES"," -D"," -D","")) <<
00962         fixQuotes(varGlue("DEFINES"," -D"," -D","")) << "\";" << "\n"
00963       << "\t\t\t\t" << "LEXFLAGS = \"" << var("QMAKE_LEXFLAGS") << "\";" << "\n"
00964       << "\t\t\t\t" << "YACCFLAGS = \"" << var("QMAKE_YACCFLAGS") << "\";" << "\n"
00965       << "\t\t\t\t" << "OTHER_CPLUSPLUSFLAGS = \"" <<
00966         fixEnvsList("QMAKE_CXXFLAGS") << fixQuotes(varGlue("PRL_EXPORT_DEFINES"," -D"," -D","")) <<
00967         fixQuotes(varGlue("DEFINES"," -D"," -D","")) << "\";" << "\n"
00968       << "\t\t\t\t" << "OTHER_REZFLAGS = \"\";" << "\n"
00969       << "\t\t\t\t" << "SECTORDER_FLAGS = \"\";" << "\n"
00970       << "\t\t\t\t" << "WARNING_CFLAGS = \"\";" << "\n"
00971       << "\t\t\t\t" << "PREBINDING = " << (project->isEmpty("QMAKE_DO_PREBINDING") ? "NO" : "YES") << ";" << "\n";
00972     if(!project->isEmpty("PRECOMPILED_HEADER")) {
00973         if (ideType() == MAC_XCODE) {
00974             t << "\t\t\t\t" << "GCC_PRECOMPILE_PREFIX_HEADER = \"YES\";" << "\n"
00975                 << "\t\t\t\t" << "GCC_PREFIX_HEADER = \"" <<  project->first("PRECOMPILED_HEADER") << "\";" << "\n";
00976         } else {
00977             t << "\t\t\t\t" << "PRECOMPILE_PREFIX_HEADER = \"YES\";" << "\n"
00978                 << "\t\t\t\t" << "PREFIX_HEADER = \"" <<  project->first("PRECOMPILED_HEADER") << "\";" << "\n";
00979         }
00980     }
00981     if(project->first("TEMPLATE") == "app") {
00982         QString plist = fileFixify(project->first("QMAKE_INFO_PLIST"));
00983         if(plist.isEmpty())
00984             plist = specdir() + QDir::separator() + "Info.plist." + project->first("TEMPLATE");
00985         if(QFile::exists(plist)) {
00986             QFile plist_in_file(plist);
00987             if(plist_in_file.open(IO_ReadOnly)) {
00988                 QTextStream plist_in(&plist_in_file);
00989                 QString plist_in_text = plist_in.read();
00990                 plist_in_text = plist_in_text.replace("@ICON@", (project->isEmpty("RC_FILE") ? QString("") : project->first("RC_FILE").section(Option::dir_sep, -1)));
00991                 plist_in_text = plist_in_text.replace("@EXECUTABLE@", project->first("QMAKE_ORIG_TARGET"));
00992                 QFile plist_out_file("Info.plist");
00993                 if(plist_out_file.open(IO_WriteOnly | IO_Translate)) {
00994                     QTextStream plist_out(&plist_out_file);
00995                     plist_out << plist_in_text;
00996                     t << "\t\t\t\t" << "INFOPLIST_FILE = \"Info.plist\";" << "\n";
00997                 }
00998             }
00999         }
01000     }
01001 #if 1
01002     t << "\t\t\t\t" << "BUILD_ROOT = \"" << QDir::currentDirPath() << "\";" << "\n";
01003 #endif
01004     if(!project->isActiveConfig("staticlib")) 
01005         t << "\t\t\t\t" << "OTHER_LDFLAGS = \"" << fixEnvsList("SUBLIBS") << " " <<
01006             fixEnvsList("QMAKE_LFLAGS") << " " << fixEnvsList("QMAKE_LIBDIR_FLAGS") <<
01007             " " << fixEnvsList("QMAKE_LIBS") << "\";" << "\n";
01008     if(!project->isEmpty("DESTDIR")) {
01009         QString dir = project->first("DESTDIR");
01010         if (QDir::isRelativePath(dir))
01011             dir.prepend(QDir::currentDirPath() + Option::dir_sep);
01012         t << "\t\t\t\t" << "INSTALL_DIR = \"" << dir << "\";" << "\n";
01013     }
01014     if ( project->first("TEMPLATE") == "lib") {
01015         t << "\t\t\t\t" << "INSTALL_PATH = \"" <<  "\";" << "\n";
01016     }
01017     if(!project->isEmpty("VERSION") && project->first("VERSION") != "0.0.0") {
01018         t << "\t\t\t\t" << "DYLIB_CURRENT_VERSION = \"" << project->first("VER_MAJ") << "." 
01019           << project->first("VER_MIN") << "." << project->first("VER_PAT")  << "\";" << "\n";
01020         if(project->isEmpty("COMPAT_VERSION"))
01021             t << "\t\t\t\t" << "DYLIB_COMPATIBILITY_VERSION = \"" << project->first("VER_MAJ") << "." 
01022               << project->first("VER_MIN")  << "\";" << "\n";
01023     }
01024     if(!project->isEmpty("COMPAT_VERSION"))
01025         t << "\t\t\t\t" << "DYLIB_COMPATIBILITY_VERSION = \"" << project->first("COMPAT_VERSION") << "\";" << "\n";
01026 
01027     if(ideType() == MAC_XCODE) {
01028         if(!project->isEmpty("OBJECTS_DIR"))
01029             t << "\t\t\t\t" << "OBJROOT = \"" << project->first("OBJECTS_DIR") << "\";" << "\n";
01030     }
01031 #if 0
01032     if(!project->isEmpty("DESTDIR"))
01033         t << "\t\t\t\t" << "SYMROOT = \"" << project->first("DESTDIR") << "\";" << "\n";
01034     else
01035         t << "\t\t\t\t" << "SYMROOT = \"" << QDir::currentDirPath() << "\";" << "\n";
01036 #endif
01037     if(project->first("TEMPLATE") == "app") {
01038         if(ideType() == MAC_PBUILDER && !project->isActiveConfig("console"))
01039             t << "\t\t\t\t" << "WRAPPER_EXTENSION = app;" << "\n";
01040         t << "\t\t\t\t" << "PRODUCT_NAME = " << project->first("QMAKE_ORIG_TARGET") << ";" << "\n";
01041     } else {
01042         if(!project->isActiveConfig("plugin") && project->isActiveConfig("staticlib")) {
01043             t << "\t\t\t\t" << "LIBRARY_STYLE = STATIC;" << "\n";
01044         } else {
01045             t << "\t\t\t\t" << "LIBRARY_STYLE = DYNAMIC;" << "\n";
01046         }
01047         QString lib = project->first("QMAKE_ORIG_TARGET");
01048         if (!project->isActiveConfig("frameworklib") && !project->isActiveConfig("staticlib"))
01049             lib.prepend("lib");
01050         t << "\t\t\t\t" << "PRODUCT_NAME = " << lib << ";" << "\n";
01051     }
01052     tmp = project->variables()["QMAKE_PBX_VARS"];
01053     for(QStringList::Iterator it = tmp.begin(); it != tmp.end(); ++it) {
01054         QString var = (*it), val = getenv(var);
01055         if(!val && var == "TB")
01056             val = "/usr/bin/";
01057         t << "\t\t\t\t" << var << " = \"" << val << "\";" << "\n";
01058     }
01059     t << "\t\t\t" << "};" << "\n"
01060       << "\t\t\t" << "conditionalBuildSettings = {" << "\n"
01061       << "\t\t\t" << "};" << "\n"
01062       << "\t\t\t" << "dependencies = (" << "\n"
01063       << varGlue("QMAKE_PBX_TARGET_DEPENDS", "\t\t\t\t", ",\n\t\t\t\t", "\n")
01064       << "\t\t\t" << ");" << "\n"
01065       << "\t\t\t" << "productReference = " << keyFor(pbx_dir + "QMAKE_PBX_REFERENCE") << ";" << "\n"
01066       << "\t\t\t" << "shouldUseHeadermap = 1;" << "\n";
01067     if(ideType() == MAC_XCODE)
01068         t << "\t\t\t" << "isa = PBXNativeTarget;" << "\n";
01069     if(project->first("TEMPLATE") == "app") {
01070         if(project->isActiveConfig("console")) {
01071             if(ideType() == MAC_XCODE) 
01072                 t << "\t\t\t" << "productType = \"com.apple.product-type.tool\";" << "\n";
01073             else
01074                 t << "\t\t\t" << "isa = PBXToolTarget;" << "\n";
01075         } else {
01076             if(ideType() == MAC_XCODE)
01077                 t << "\t\t\t" << "productType = \"com.apple.product-type.application\";" << "\n";
01078             else
01079                 t << "\t\t\t" << "isa = PBXApplicationReference;" << "\n";
01080             t << "\t\t\t" << "productSettingsXML = \"";
01081             bool read_plist = false;
01082             if(QFile::exists("Info.plist")) {
01083                 QFile plist("Info.plist");
01084                 if(plist.open(IO_ReadOnly)) {
01085                     read_plist = true;
01086                     QTextStream stream(&plist);
01087                     while(!stream.eof()) 
01088                         t << stream.readLine().replace('"', "\\\"") << endl;
01089                 }
01090             }
01091             if(!read_plist) {
01092                 t << "<?xml version=" 
01093                   << "\\\"1.0\\\" encoding=" << "\\\"UTF-8\\\"" << "?>" << "\n"
01094                   << "\t\t\t\t" << "<!DOCTYPE plist SYSTEM \\\"file://localhost/System/" 
01095                   << "Library/DTDs/PropertyList.dtd\\\">" << "\n"
01096                   << "\t\t\t\t" << "<plist version=\\\"0.9\\\">" << "\n"
01097                   << "\t\t\t\t" << "<dict>" << "\n"
01098                   << "\t\t\t\t\t" << "<key>CFBundleDevelopmentRegion</key>" << "\n"
01099                   << "\t\t\t\t\t" << "<string>English</string>" << "\n"
01100                   << "\t\t\t\t\t" << "<key>CFBundleExecutable</key>" << "\n"
01101                   << "\t\t\t\t\t" << "<string>" << project->first("QMAKE_ORIG_TARGET") << "</string>" << "\n"
01102                   << "\t\t\t\t\t" << "<key>CFBundleIconFile</key>" << "\n"
01103                   << "\t\t\t\t\t" << "<string>" << var("RC_FILE").section(Option::dir_sep, -1) << "</string>" << "\n"
01104                   << "\t\t\t\t\t" << "<key>CFBundleInfoDictionaryVersion</key>"  << "\n"
01105                   << "\t\t\t\t\t" << "<string>6.0</string>" << "\n"
01106                   << "\t\t\t\t\t" << "<key>CFBundlePackageType</key>" << "\n"
01107                   << "\t\t\t\t\t" << "<string>APPL</string>" << "\n"
01108                   << "\t\t\t\t\t" << "<key>CFBundleSignature</key>" << "\n"
01109                     //Although the output below looks strange it is to avoid the trigraph ??<
01110                   << "\t\t\t\t\t" << "<string>????" << "</string>" << "\n"
01111                   << "\t\t\t\t\t" << "<key>CFBundleVersion</key>" << "\n"
01112                   << "\t\t\t\t\t" << "<string>0.1</string>" << "\n"
01113                   << "\t\t\t\t\t" << "<key>CSResourcesFileMapped</key>" << "\n"
01114                   << "\t\t\t\t\t" << "<true/>" << "\n"
01115                   << "\t\t\t\t" << "</dict>" << "\n"
01116                   << "\t\t\t\t" << "</plist>";
01117             }
01118         }
01119         t << "\";" << "\n";
01120         t << "\t\t\t" << "name = \"" << project->first("QMAKE_ORIG_TARGET") << "\";" << "\n"
01121           << "\t\t\t" << "productName = " << project->first("QMAKE_ORIG_TARGET") << ";" << "\n";
01122     } else {
01123         QString lib = project->first("QMAKE_ORIG_TARGET");
01124         if(!project->isActiveConfig("frameworklib") && !project->isActiveConfig("staticlib"))
01125            lib.prepend("lib");
01126         t << "\t\t\t" << "name = \"" << lib << "\";" << "\n"
01127           << "\t\t\t" << "productName = " << lib << ";" << "\n";
01128         if(ideType() == MAC_XCODE) {
01129             if(project->isActiveConfig("staticlib"))
01130                 t << "\t\t\t" << "productType = \"com.apple.product-type.library.static\";" << "\n";
01131             else
01132                 t << "\t\t\t" << "productType = \"com.apple.product-type.library.dynamic\";" << "\n";
01133         } else {
01134             t << "\t\t\t" << "isa = PBXLibraryTarget;" << "\n";
01135         }
01136     }
01137     t << "\t\t\t" << "startupPath = \"<<ProjectDirectory>>\";" << "\n";
01138     if(!project->isEmpty("DESTDIR"))
01139         t << "\t\t\t" << "productInstallPath = \"" << project->first("DESTDIR") << "\";" << "\n";
01140     t << "\t\t" << "};" << "\n";
01141     //DEBUG/RELEASE
01142     QString active_buildstyle;
01143 #if 0
01144     for(int as_release = 0; as_release < 2; as_release++) 
01145 #else
01146         bool as_release = !project->isActiveConfig("debug");
01147 #endif
01148     {
01149         QString key = keyFor("QMAKE_PBX_" + QString(as_release ? "RELEASE" : "DEBUG"));
01150         if(project->isActiveConfig("debug") != as_release) 
01151             active_buildstyle = key;
01152         project->variables()["QMAKE_PBX_BUILDSTYLES"].append(key);
01153         t << "\t\t" << key << " = {" << "\n"
01154           << "\t\t\t" << "buildRules = (" << "\n"
01155           << "\t\t\t" << ");" << "\n"
01156           << "\t\t\t" << "buildSettings = {" << "\n"
01157           << "\t\t\t\t" << "COPY_PHASE_STRIP = " << (as_release ? "YES" : "NO") << ";" << "\n";
01158         if(as_release) {
01159             t << "\t\t\t\t" << "DEBUGGING_SYMBOLS = NO;" << "\n";
01160         } else {
01161             t << "\t\t\t\t" << "GCC_ENABLE_FIX_AND_CONTINUE = " 
01162               << (project->isActiveConfig("no_fix_and_continue") ? "NO" : "YES") << ";" << "\n"
01163               << "\t\t\t\t" << "GCC_GENERATE_DEBUGGING_SYMBOLS = YES;" << "\n"
01164               << "\t\t\t\t" << "GCC_OPTIMIZATION_LEVEL = 0;" << "\n"
01165               << "\t\t\t\t" << "ZERO_LINK ="
01166               << (project->isActiveConfig("no_zero_link") ? "NO" : "YES") << ";" << "\n";
01167         }
01168         t << "\t\t\t" << "};" << "\n"
01169           << "\t\t\t" << "isa = PBXBuildStyle;" << "\n"
01170           << "\t\t\t" << "name = " << (as_release ? "Deployment" : "Development") << ";" << "\n"
01171           << "\t\t" << "};" << "\n";
01172     }
01173     //ROOT
01174     t << "\t\t" << keyFor("QMAKE_PBX_ROOT") << " = {" << "\n"
01175       << "\t\t\t" << "buildStyles = (" << "\n"
01176       << varGlue("QMAKE_PBX_BUILDSTYLES", "\t\t\t\t", ",\n\t\t\t\t", "\n")
01177       << "\t\t\t" << ");" << "\n"
01178       << "\t\t\t" << "hasScannedForEncodings = 1;" << "\n"
01179       << "\t\t\t" << "isa = PBXProject;" << "\n"
01180       << "\t\t\t" << "mainGroup = " << keyFor("QMAKE_PBX_ROOT_GROUP") << ";" << "\n"
01181       << "\t\t\t" << "projectDirPath = \"\";" << "\n"
01182       << "\t\t\t" << "targets = (" << "\n"
01183       << varGlue("QMAKE_PBX_TARGETS", "\t\t\t\t", ",\n\t\t\t\t", "\n")
01184       << "\t\t\t" << ");" << "\n"
01185       << "\t\t" << "};" << "\n";
01186 
01187     //FOOTER
01188     t << "\t" << "};" << "\n"
01189       << "\t" << "rootObject = " << keyFor("QMAKE_PBX_ROOT") << ";" << "\n"
01190       << "}" << endl;
01191 
01192     if(project->isActiveConfig("generate_pbxbuild_makefile")) {
01193         QString mkwrap = fileFixify(pbx_dir + Option::dir_sep + ".." + Option::dir_sep + project->first("MAKEFILE"), 
01194                                     QDir::currentDirPath());
01195         QFile mkwrapf(mkwrap);
01196         if(mkwrapf.open(IO_WriteOnly | IO_Translate)) {
01197             debug_msg(1, "pbuilder: Creating file: %s", mkwrap.latin1());
01198             QTextStream mkwrapt(&mkwrapf);
01199             writeHeader(mkwrapt);
01200             const char *cleans = "uiclean mocclean preprocess_clean ";
01201             mkwrapt << "#This is a makefile wrapper for PROJECT BUILDER\n"
01202                     << "all:" << "\n\t" 
01203                     << "cd " << project->first("QMAKE_ORIG_TARGET") << projectSuffix() << "/ && " << pbxbuild() << "\n"
01204                     << "install: all" << "\n\t" 
01205                     << "cd " << project->first("QMAKE_ORIG_TARGET") << projectSuffix() << "/ && " << pbxbuild() << " install\n"
01206                     << "distclean clean: preprocess_clean" << "\n\t" 
01207                     << "cd " << project->first("QMAKE_ORIG_TARGET") << projectSuffix() << "/ && " << pbxbuild() << " clean" << "\n"
01208                     << (!did_preprocess ? cleans : "") << ":" << "\n";
01209             if(did_preprocess) 
01210                 mkwrapt << cleans << ":" << "\n\t"
01211                         << "make -f " 
01212                         << pbx_dir << Option::dir_sep << "qt_preprocess.mak $@" << endl;
01213         }
01214     }
01215     return TRUE;
01216 }
01217 
01218 QString
01219 ProjectBuilderMakefileGenerator::fixQuotes(const QString &val)
01220 {
01221     QString ret(val);
01222     ret = ret.replace(QRegExp("('|\")"), "\\\\1");
01223     return ret;
01224 }
01225 
01226 QString
01227 ProjectBuilderMakefileGenerator::fixEnvs(const QString &file)
01228 {
01229     QRegExp reg_var("\\$\\((.*)\\)");
01230     for(int rep = 0; (rep = reg_var.search(file, rep)) != -1; ) {
01231         if(project->variables()["QMAKE_PBX_VARS"].findIndex(reg_var.cap(1)) == -1)
01232             project->variables()["QMAKE_PBX_VARS"].append(reg_var.cap(1));
01233         rep += reg_var.matchedLength();
01234     }
01235     return file;
01236 }
01237 
01238 QString
01239 ProjectBuilderMakefileGenerator::fixEnvsList(const QString &where)
01240 {
01241     QString ret;
01242     const QStringList &l = project->variables()[where];
01243     for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) {
01244         fixEnvs((*it));
01245         if(!ret.isEmpty())
01246             ret += " ";
01247         ret += (*it);
01248     }
01249     return ret;
01250 }
01251 
01252 QString
01253 ProjectBuilderMakefileGenerator::keyFor(const QString &block)
01254 {
01255 #if 1 //This make this code much easier to debug..
01256     if(project->isActiveConfig("no_pb_munge_key"))
01257        return block;
01258 #endif
01259     QString ret;
01260     if(!keys.contains(block)) {
01261         ret = qtMD5(block.utf8()).left(24).upper();
01262         keys.insert(block, ret);
01263     } else {
01264         ret = keys[block];
01265     }
01266     return ret;
01267 }
01268 
01269 bool
01270 ProjectBuilderMakefileGenerator::openOutput(QFile &file) const
01271 {
01272     if(QDir::isRelativePath(file.name()))
01273         file.setName(Option::output_dir + file.name()); //pwd when qmake was run
01274     QFileInfo fi(file);
01275     if(fi.extension() != "pbxproj" || file.name().isEmpty()) {
01276         QString output = file.name();
01277         if(fi.isDir())
01278             output += QDir::separator();
01279         if(!output.endsWith(projectSuffix())) {
01280             if(file.name().isEmpty() || fi.isDir())
01281                 output += project->first("TARGET");
01282             output += projectSuffix() + QDir::separator();
01283         } else if(output[(int)output.length() - 1] != QDir::separator()) {
01284             output += QDir::separator();
01285         }
01286         output += QString("project.pbxproj");
01287         file.setName(output);
01288     }
01289     bool ret = UnixMakefileGenerator::openOutput(file);
01290     ((ProjectBuilderMakefileGenerator*)this)->pbx_dir = Option::output_dir.section(Option::dir_sep, 0, -1);
01291     Option::output_dir = pbx_dir.section(Option::dir_sep, 0, -2); 
01292     return ret;
01293 }
01294 
01295 /* This function is such a hack it is almost pointless, but it
01296    eliminates the warning message from ProjectBuilder that the project
01297    file is for an older version. I guess this could be used someday if
01298    the format of the output is dependant upon the version of
01299    ProjectBuilder as well.
01300 */
01301 int
01302 ProjectBuilderMakefileGenerator::pbuilderVersion() const
01303 {
01304     QString ret;
01305     if(project->isEmpty("QMAKE_PBUILDER_VERSION")) {
01306         QString version, version_plist = project->first("QMAKE_PBUILDER_VERSION_PLIST");
01307         if(version_plist.isEmpty()) {
01308             if(ideType() == MAC_XCODE && QFile::exists("/Developer/Applications/Xcode.app/Contents/version.plist"))
01309                 version_plist = "/Developer/Applications/Xcode.app/Contents/version.plist";
01310             else
01311                 version_plist = "/Developer/Applications/Project Builder.app/Contents/version.plist";
01312         } else {
01313             version_plist = version_plist.replace(QRegExp("\""), "");
01314         }
01315         QFile version_file(version_plist);
01316         if(version_file.open(IO_ReadOnly)) {
01317             debug_msg(1, "pbuilder: version.plist: Reading file: %s", version_plist.latin1());
01318             QTextStream plist(&version_file);
01319 
01320             bool in_dict = FALSE;
01321             QString current_key;
01322             QRegExp keyreg("^<key>(.*)</key>$"), stringreg("^<string>(.*)</string>$");
01323             while(!plist.eof()) {
01324                 QString line = plist.readLine().stripWhiteSpace();
01325                 if(line == "<dict>")
01326                     in_dict = TRUE;
01327                 else if(line == "</dict>")
01328                     in_dict = FALSE;
01329                 else if(in_dict) {
01330                     if(keyreg.exactMatch(line))
01331                         current_key = keyreg.cap(1);
01332                     else if(current_key == "CFBundleShortVersionString" && stringreg.exactMatch(line))
01333                         version = stringreg.cap(1);
01334                 }
01335             }
01336             version_file.close();
01337         } else { debug_msg(1, "pbuilder: version.plist: Failure to open %s", version_plist.latin1()); }
01338         if(version_plist.contains("Xcode")) {
01339             ret = "39";
01340         } else {
01341             if(version.startsWith("2."))
01342                 ret = "38";
01343             else if(version == "1.1")
01344                 ret = "34";
01345         }
01346     } else {
01347         ret = project->first("QMAKE_PBUILDER_VERSION");
01348     }
01349     if(!ret.isEmpty()) {
01350         bool ok;
01351         int int_ret = ret.toInt(&ok);
01352         if(ok) {
01353             debug_msg(1, "pbuilder: version.plist: Got version: %d", int_ret);
01354             return int_ret;
01355         }
01356     }
01357     debug_msg(1, "pbuilder: version.plist: Fallback to default version");
01358     return 34; //my fallback
01359 }
01360 
01361 int
01362 ProjectBuilderMakefileGenerator::reftypeForFile(const QString &where)
01363 {
01364     int ret = 0; //absolute is the default..
01365     if(QDir::isRelativePath(where))
01366         ret = 4; //relative
01367     return ret; 
01368 }
01369 
01370 ProjectBuilderMakefileGenerator::IDE_TYPE
01371 ProjectBuilderMakefileGenerator::ideType() const
01372 {
01373     if(!project->isActiveConfig("no_pbx_xcode") &&
01374        (QFile::exists("/Developer/Applications/Xcode.app") || project->isActiveConfig("pbx_xcode")))
01375         return ProjectBuilderMakefileGenerator::MAC_XCODE;
01376     return ProjectBuilderMakefileGenerator::MAC_PBUILDER;
01377 }
01378 
01379 QString
01380 ProjectBuilderMakefileGenerator::projectSuffix() const
01381 {
01382     if(ideType() == MAC_XCODE)
01383         return ".xcode";
01384     return ".pbproj";
01385 }
01386 
01387 QString
01388 ProjectBuilderMakefileGenerator::pbxbuild()
01389 {
01390     if(QFile::exists("/usr/bin/pbbuild"))
01391         return "pbbuild";
01392     if(QFile::exists("/usr/bin/xcodebuild"))
01393        return "xcodebuild";
01394     return (ideType() == MAC_XCODE ? "xcodebuild" : "pbxbuild");
01395 }
01396 

Generated on Sat Nov 5 16:18:19 2005 for OPIE by  doxygen 1.4.2