From 5042e3cf0d3514552769e441f5aad590c8eaf967 Mon Sep 17 00:00:00 2001 From: kergoth Date: Fri, 01 Nov 2002 00:10:42 +0000 Subject: Adding qmake in preperation for new build system --- (limited to 'qmake/generators/mac') diff --git a/qmake/generators/mac/metrowerks_xml.cpp b/qmake/generators/mac/metrowerks_xml.cpp new file mode 100644 index 0000000..125749d --- a/dev/null +++ b/qmake/generators/mac/metrowerks_xml.cpp @@ -0,0 +1,822 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ________ class. +** +** Created : 970521 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "metrowerks_xml.h" +#include "option.h" +#include +#include +#include +#include +#include +#ifdef Q_OS_MAC +#include +#include +#include +#endif + + +MetrowerksMakefileGenerator::MetrowerksMakefileGenerator(QMakeProject *p) : MakefileGenerator(p), init_flag(FALSE) +{ + +} + +bool +MetrowerksMakefileGenerator::writeMakefile(QTextStream &t) +{ + if(!project->variables()["QMAKE_FAILED_REQUIREMENTS"].isEmpty()) { + /* for now just dump, I need to generated an empty xml or something.. */ + fprintf(stderr, "Project file not generated because all requirements not met:\n\t%s\n", + var("QMAKE_FAILED_REQUIREMENTS").latin1()); + return TRUE; + } + + if(project->first("TEMPLATE") == "app" || + project->first("TEMPLATE") == "lib") { + return writeMakeParts(t); + } + else if(project->first("TEMPLATE") == "subdirs") { + writeHeader(t); + qDebug("Not supported!"); + return TRUE; + } + return FALSE; +} + +bool +MetrowerksMakefileGenerator::writeMakeParts(QTextStream &t) +{ + //..grrr.. libs! + QStringList extra_objs; + bool do_libs = TRUE; + if(project->first("TEMPLATE") == "app") + extra_objs += project->variables()["QMAKE_CRT_OBJECTS"]; + else if(project->first("TEMPLATE") == "lib" && project->isActiveConfig("staticlib")) + do_libs = FALSE; + if(do_libs) + extra_objs += project->variables()["QMAKE_LIBS"]; + for(QStringList::Iterator val_it = extra_objs.begin(); + val_it != extra_objs.end(); ++val_it) { + if((*val_it).startsWith("-L")) { + QString dir((*val_it).right((*val_it).length() - 2)); + fixEnvVariables(dir); + if(project->variables()["DEPENDPATH"].findIndex(dir) == -1 && + project->variables()["INCLUDEPATH"].findIndex(dir) == -1) + project->variables()["INCLUDEPATH"].append(dir); + } else if((*val_it).startsWith("-l")) { + QString lib("lib" + (*val_it).right((*val_it).length() - 2) + "." + + project->first("QMAKE_EXTENSION_SHLIB")); + if(project->variables()["LIBRARIES"].findIndex(lib) == -1) + project->variables()["LIBRARIES"].append(lib); + } else + if((*val_it) == "-framework") { + ++val_it; + if(val_it == extra_objs.end()) + break; + QString frmwrk = (*val_it) + ".framework"; + if(project->variables()["FRAMEWORKS"].findIndex(frmwrk) == -1) + project->variables()["FRAMEWORKS"].append(frmwrk); + } else if((*val_it).left(1) != "-") { + QString lib=(*val_it); + int s = lib.findRev('/'); + if(s != -1) { + QString dir = lib.left(s); + lib = lib.right(lib.length() - s - 1); + fixEnvVariables(dir); + if(project->variables()["DEPENDPATH"].findIndex(dir) == -1 && + project->variables()["INCLUDEPATH"].findIndex(dir) == -1) + project->variables()["INCLUDEPATH"].append(dir); + } + project->variables()["LIBRARIES"].append(lib); + } + } + //let metrowerks find the files & set the files to the type I expect + QDict seen(293); + QString paths[] = { QString("SRCMOC"), QString("FORMS"), QString("UICDECLS"), + QString("UICIMPLS"), QString("SOURCES"),QString("HEADERS"), + QString::null }; + for(int y = 0; paths[y] != QString::null; y++) { + QStringList &l = project->variables()[paths[y]]; + for(QStringList::Iterator val_it = l.begin(); val_it != l.end(); ++val_it) { + //establish file types + seen.insert((*val_it), (void *)1); + createFork((*val_it)); //the file itself + QStringList &d = findDependencies((*val_it)); //depends + for(QStringList::Iterator dep_it = d.begin(); dep_it != d.end(); ++dep_it) { + if(!seen.find((*dep_it))) { + seen.insert((*dep_it), (void *)1); + createFork((*dep_it)); + } + } + //now chop it + int s = (*val_it).findRev('/'); + if(s != -1) { + QString dir = (*val_it).left(s); + (*val_it) = (*val_it).right((*val_it).length() - s - 1); + QString tmpd=dir, tmpv; + if(fixifyToMacPath(tmpd, tmpv)) { + bool add_in = TRUE; + QString deps[] = { QString("DEPENDPATH"), + QString("INCLUDEPATH"), QString::null }, + dd, dv; + for(int yy = 0; deps[yy] != QString::null; yy++) { + QStringList &l2 = project->variables()[deps[yy]]; + for(QStringList::Iterator val_it2 = l2.begin(); + val_it2 != l2.end(); ++val_it2) { + QString dd= (*val_it2), dv; + if(!fixifyToMacPath(dd, dv)) + continue; + if(dd == tmpd && tmpv == dv) { + add_in = FALSE; + break; + } + } + } + if(add_in) + project->variables()["INCLUDEPATH"].append(dir); + } + } + } + } + //need a defines file + if(!project->isEmpty("DEFINES")) { + QString pre_pref = project->first("TARGET_STEM"); + if(project->first("TEMPLATE") == "lib") + pre_pref += project->isActiveConfig("staticlib") ? "_static" : "_shared"; + project->variables()["CODEWARRIOR_PREFIX_HEADER"].append(pre_pref + "_prefix.h"); + } + + QString xmlfile = findTemplate(project->first("QMAKE_XML_TEMPLATE")); + QFile file(xmlfile); + if(!file.open(IO_ReadOnly )) { + fprintf(stderr, "Cannot open XML file: %s\n", + project->first("QMAKE_XML_TEMPLATE").latin1()); + return FALSE; + } + QTextStream xml(&file); + createFork(Option::output.name()); + + int rep; + QString line; + while ( !xml.eof() ) { + line = xml.readLine(); + while((rep = line.find(QRegExp("\\$\\$[!a-zA-Z0-9_-]*"))) != -1) { + QString torep = line.mid(rep, line.find(QRegExp("[^\\$!a-zA-Z0-9_-]"), rep) - rep); + QString variable = torep.right(torep.length()-2); + + t << line.left(rep); //output the left side + line = line.right(line.length() - (rep + torep.length())); //now past the variable + if(variable == "CODEWARRIOR_HEADERS" || variable == "CODEWARRIOR_SOURCES" || + variable == "CODEWARRIOR_LIBRARIES" || variable == "CODEWARRIOR_QPREPROCESS" || + variable == "CODEWARRIOR_QPREPROCESSOUT") { + QString outcmd=variable.right(variable.length() - variable.findRev('_') - 1); + QStringList args; + if(outcmd == "QPREPROCESS") + args << "UICS" << "MOCS"; + else if(outcmd == "QPREPROCESSOUT") + args << "SRCMOC" << "UICIMPLS" << "UICDELCS"; + else + args << outcmd; + for(QStringList::Iterator arit = args.begin(); arit != args.end(); ++arit) { + QString arg = (*arit); + QString kind = "Text"; + if(arg == "LIBRARIES") + kind = "Library"; + if(!project->variables()[arg].isEmpty()) { + QStringList &list = project->variables()[arg]; + for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { + QString flag; + if(project->isActiveConfig("debug")) { + bool debug = TRUE; + if(outcmd == "QPREPROCESS") { + debug = FALSE; + } else { + for(QStringList::Iterator hit = Option::h_ext.begin(); hit != Option::h_ext.end(); ++hit) { + if((*it).endsWith((*hit))) { + debug = FALSE; + break; + } + } + } + if(debug) + flag = "Debug"; + } + t << "\t\t\t\t" << endl + << "\t\t\t\t\tName" << endl + << "\t\t\t\t\t" << (*it) << "" << endl + << "\t\t\t\t\tMacOS" << endl + << "\t\t\t\t\t" << kind << "" << endl + << "\t\t\t\t\t" << flag << "" << endl + << "\t\t\t\t" << endl; + } + } + } + } else if(variable == "CODEWARRIOR_SOURCES_LINKORDER" || + variable == "CODEWARRIOR_HEADERS_LINKORDER" || + variable == "CODEWARRIOR_LIBRARIES_LINKORDER" || + variable == "CODEWARRIOR_QPREPROCESS_LINKORDER" || + variable == "CODEWARRIOR_QPREPROCESSOUT_LINKORDER") { + QString outcmd=variable.mid(variable.find('_')+1, + variable.findRev('_')-(variable.find('_')+1)); + QStringList args; + if(outcmd == "QPREPROCESS") + args << "UICS" << "MOCS"; + else if(outcmd == "QPREPROCESSOUT") + args << "SRCMOC" << "UICIMPLS" << "UICDELCS"; + else + args << outcmd; + for(QStringList::Iterator arit = args.begin(); arit != args.end(); ++arit) { + QString arg = (*arit); + if(!project->variables()[arg].isEmpty()) { + QStringList &list = project->variables()[arg]; + for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { + t << "\t\t\t\t" << endl + << "\t\t\t\t\tName" << endl + << "\t\t\t\t\t" << (*it) << "" << endl + << "\t\t\t\t\tMacOS" << endl + << "\t\t\t\t" << endl; + } + } + } + } else if(variable == "CODEWARRIOR_HEADERS_GROUP" || + variable == "CODEWARRIOR_SOURCES_GROUP" || + variable == "CODEWARRIOR_LIBRARIES_GROUP" || + variable == "CODEWARRIOR_QPREPROCESS_GROUP" || + variable == "CODEWARRIOR_QPREPROCESSOUT_GROUP") { + QString outcmd = variable.mid(variable.find('_')+1, + variable.findRev('_')-(variable.find('_')+1)); + QStringList args; + if(outcmd == "QPREPROCESS") + args << "UICS" << "MOCS"; + else if(outcmd == "QPREPROCESSOUT") + args << "SRCMOC" << "UICIMPLS" << "UICDELCS"; + else + args << outcmd; + for(QStringList::Iterator arit = args.begin(); arit != args.end(); ++arit) { + QString arg = (*arit); + if(!project->variables()[arg].isEmpty()) { + QStringList &list = project->variables()[arg]; + for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { + t << "\t\t\t\t" << endl + << "\t\t\t\t\t" << var("TARGET_STEM") << "" + << endl + << "\t\t\t\t\tName" << endl + << "\t\t\t\t\t" << (*it) << "" << endl + << "\t\t\t\t\tMacOS" << endl + << "\t\t\t\t" << endl; + } + } + } + } else if(variable == "CODEWARRIOR_FRAMEWORKS") { + if(!project->isEmpty("FRAMEWORKS")) { + QStringList &list = project->variables()["FRAMEWORKS"]; + for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { + t << "\t\t\t\t" << endl + << "\t\t\t\t\t" << endl + << "\t\t\t\t\t\tName" << endl + << "\t\t\t\t\t\t" << (*it) << "" << endl + << "\t\t\t\t\t\tMacOS" << endl + << "\t\t\t\t\t" << endl + << "\t\t\t\t" << endl; + } + } + } else if(variable == "CODEWARRIOR_DEPENDPATH" || variable == "CODEWARRIOR_INCLUDEPATH" || + variable == "CODEWARRIOR_FRAMEWORKPATH") { + QString arg=variable.right(variable.length()-variable.find('_')-1); + QStringList list; + if(arg == "INCLUDEPATH") { + list = project->variables()[arg]; + list << Option::mkfile::qmakespec; + list << QDir::current().currentDirPath(); + + QStringList &l = project->variables()["QMAKE_LIBS_PATH"]; + for(QStringList::Iterator val_it = l.begin(); val_it != l.end(); ++val_it) { + QString p = (*val_it), v; + if(!fixifyToMacPath(p, v)) + continue; + + t << "\t\t\t\t\t" << endl + << "\t\t\t\t\t\tSearchPath" << endl + << "\t\t\t\t\t\t\tPath" + << "" << p << "" << endl + << "\t\t\t\t\t\t\tPathFormatMacOS" << endl + << "\t\t\t\t\t\t\tPathRootCodeWarrior" << endl + << "\t\t\t\t\t\t" << endl + << "\t\t\t\t\t\tRecursivetrue" << endl + << "\t\t\t\t\t\tHostFlagsAll" << endl + << "\t\t\t\t\t" << endl; + } + } else if(variable == "DEPENDPATH") { + QStringList &l = project->variables()[arg]; + for(QStringList::Iterator val_it = l.begin(); val_it != l.end(); ++val_it) + { + //apparently tmake used colon separation... + QStringList damn = QStringList::split(':', (*val_it)); + if(!damn.isEmpty()) + list += damn; + else + list.append((*val_it)); + } + } else { + list = project->variables()[arg]; + } + for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { + QString p = (*it), v, recursive = "false", framework = "false"; + if(p.startsWith("recursive--")) { + p = p.right(p.length() - 11); + recursive = "true"; + } + if(!fixifyToMacPath(p, v)) + continue; + if(arg == "FRAMEWORKPATH") + framework = "true"; + + t << "\t\t\t\t\t" << endl + << "\t\t\t\t\t\tSearchPath" << endl + << "\t\t\t\t\t\t\tPath" + << "" << p << "" << endl + << "\t\t\t\t\t\t\tPathFormatMacOS" << endl + << "\t\t\t\t\t\t\tPathRoot" << v << "" << endl + << "\t\t\t\t\t\t" << endl + << "\t\t\t\t\t\tRecursive" << recursive << "" << endl + << "\t\t\t\t\t\tFrameworkPath" << framework << "" << endl + << "\t\t\t\t\t\tHostFlagsAll" << endl + << "\t\t\t\t\t" << endl; + } + } else if(variable == "CODEWARRIOR_WARNING" || variable == "!CODEWARRIOR_WARNING") { + bool b = ((!project->isActiveConfig("warn_off")) && + project->isActiveConfig("warn_on")); + if(variable.startsWith("!")) + b = !b; + t << (int)b; + } else if(variable == "CODEWARRIOR_TEMPLATE") { + if(project->first("TEMPLATE") == "app" ) { + t << "Executable"; + } else if(project->first("TEMPLATE") == "lib") { + if(project->isActiveConfig("staticlib")) + t << "Library"; + else + t << "SharedLibrary"; + } + } else if(variable == "CODEWARRIOR_OUTPUT_DIR") { + QString outdir = "{Project}/", volume; + if(!project->isEmpty("DESTDIR")) + outdir = project->first("DESTDIR"); + if(project->first("TEMPLATE") == "app" && !project->isActiveConfig("console")) + outdir += var("TARGET") + ".app/Contents/MacOS/"; + if(fixifyToMacPath(outdir, volume, FALSE)) { + t << "\t\t\tPath" << outdir << "" + << endl + << "\t\t\tPathFormatMacOS" << endl + << "\t\t\tPathRoot" << volume << "" + << endl; + } + } else if(variable == "CODEWARRIOR_PACKAGER_PANEL") { + if(project->first("TEMPLATE") == "app" && !project->isActiveConfig("console")) { + QString outdir = "{Project}/", volume; + if(!project->isEmpty("DESTDIR")) + outdir = project->first("DESTDIR"); + outdir += var("TARGET") + ".app"; + if(fixifyToMacPath(outdir, volume, FALSE)) { + t << "\t\tMWMacOSPackager_UsePackager" + << "1" << "\n" + << "\t\tMWMacOSPackager_FolderToPackage" << "\n" + << "\t\t\tPath" << outdir + << "" << "\n" + << "\t\t\tPathFormatMacOS" + << "\n" + << "\t\t\tPathRoot" << volume + << "" << "\n" + << "\t\t" << "\n" + << "\t\tMWMacOSPackager_CreateClassicAlias" + << "0" << "\n" + << "\t\tMWMacOSPackager_ClassicAliasMethod" + << "UseTargetOutput" << "\n" + << "\t\tMWMacOSPackager_ClassicAliasPath" + << "" << "\n" + << "\t\tMWMacOSPackager_CreatePkgInfo" + << "1" << "\n" + << "\t\tMWMacOSPackager_PkgCreatorType" + << "CUTE" << "\n" + << "\t\tMWMacOSPackager_PkgFileType" + << "APPL" << endl; + } + } + } else if(variable == "CODEWARRIOR_FILETYPE") { + if(project->first("TEMPLATE") == "lib") + t << "MYDL"; + else + t << "MEXE"; + } else if(variable == "CODEWARRIOR_QTDIR") { + t << getenv("QTDIR"); + } else if(variable == "CODEWARRIOR_CACHEMODDATES") { + t << "true"; + } else { + t << var(variable); + } + } + t << line << endl; + } + t << endl; + file.close(); + + if(mocAware()) { + QString mocs = project->first("MOCS"); + QFile mocfile(mocs); + if(!mocfile.open(IO_WriteOnly)) { + fprintf(stderr, "Cannot open MOCS file: %s\n", mocs.latin1()); + } else { + createFork(mocs); + QTextStream mocs(&mocfile); + QStringList &list = project->variables()["SRCMOC"]; + for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { + QString src = findMocSource((*it)); + if(src.findRev('/') != -1) + src = src.right(src.length() - src.findRev('/') - 1); + mocs << src << endl; + } + mocfile.close(); + } + } + + if(!project->isEmpty("FORMS")) { + QString uics = project->first("UICS"); + QFile uicfile(uics); + if(!uicfile.open(IO_WriteOnly)) { + fprintf(stderr, "Cannot open UICS file: %s\n", uics.latin1()); + } else { + createFork(uics); + QTextStream uics(&uicfile); + QStringList &list = project->variables()["FORMS"]; + for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { + QString ui = (*it); + if(ui.findRev('/') != -1) + ui = ui.right(ui.length() - ui.findRev('/') - 1); + uics << ui << endl; + } + uicfile.close(); + } + } + + if(!project->isEmpty("CODEWARRIOR_PREFIX_HEADER")) { + QFile prefixfile(project->first("CODEWARRIOR_PREFIX_HEADER")); + if(!prefixfile.open(IO_WriteOnly)) { + fprintf(stderr, "Cannot open PREFIX file: %s\n", prefixfile.name().latin1()); + } else { + createFork(project->first("CODEWARRIOR_PREFIX_HEADER")); + QTextStream prefix(&prefixfile); + QStringList &list = project->variables()["DEFINES"]; + for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { + if((*it).find('=') != -1) { + int x = (*it).find('='); + prefix << "#define " << (*it).left(x) << " " << (*it).right((*it).length() - x - 1) << endl; + } else { + prefix << "#define " << (*it) << endl; + } + } + prefixfile.close(); + } + } + return TRUE; +} + + + +void +MetrowerksMakefileGenerator::init() +{ + if(init_flag) + return; + init_flag = TRUE; + + if ( project->isEmpty("QMAKE_XML_TEMPLATE") ) + project->variables()["QMAKE_XML_TEMPLATE"].append("mwerkstmpl.xml"); + + QStringList &configs = project->variables()["CONFIG"]; + if(project->isActiveConfig("qt")) { + if(configs.findIndex("moc")) configs.append("moc"); + if ( !( (project->first("TARGET") == "qt") || (project->first("TARGET") == "qte") || + (project->first("TARGET") == "qt-mt") ) ) + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT"]; + if(configs.findIndex("moc")) + configs.append("moc"); + if ( !project->isActiveConfig("debug") ) + project->variables()["DEFINES"].append("QT_NO_DEBUG"); + } + + //version handling + if(project->variables()["VERSION"].isEmpty()) + project->variables()["VERSION"].append("1.0." + + (project->isEmpty("VER_PAT") ? QString("0") : + project->first("VER_PAT")) ); + QStringList ver = QStringList::split('.', project->first("VERSION")); + ver << "0" << "0"; //make sure there are three + project->variables()["VER_MAJ"].append(ver[0]); + project->variables()["VER_MIN"].append(ver[1]); + project->variables()["VER_PAT"].append(ver[2]); + + if( !project->isEmpty("LIBS") ) + project->variables()["QMAKE_LIBS"] += project->variables()["LIBS"]; + if( project->variables()["QMAKE_EXTENSION_SHLIB"].isEmpty() ) + project->variables()["QMAKE_EXTENSION_SHLIB"].append( "dylib" ); + + if ( project->isActiveConfig("moc") ) { + QString mocfile = project->first("TARGET"); + if(project->first("TEMPLATE") == "lib") + mocfile += project->isActiveConfig("staticlib") ? "_static" : "_shared"; + project->variables()["MOCS"].append(mocfile + ".mocs"); + setMocAware(TRUE); + } + if(!project->isEmpty("FORMS")) { + QString uicfile = project->first("TARGET"); + if(project->first("TEMPLATE") == "lib") + uicfile += project->isActiveConfig("staticlib") ? "_static" : "_shared"; + project->variables()["UICS"].append(uicfile + ".uics"); + } + if(project->isEmpty("DESTDIR")) + project->variables()["DESTDIR"].append(QDir::currentDirPath()); + MakefileGenerator::init(); + + if ( project->isActiveConfig("opengl") ) { + project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_OPENGL"]; + if ( (project->first("TARGET") == "qt") || (project->first("TARGET") == "qte") || + (project->first("TARGET") == "qt-mt") ) + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_OPENGL_QT"]; + else + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_OPENGL"]; + } + + if(project->isActiveConfig("qt")) + project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_QT"]; + if(project->isEmpty("FRAMEWORKPATH")) + project->variables()["FRAMEWORKPATH"].append("/System/Library/Frameworks/"); + + //set the target up + project->variables()["TARGET_STEM"] = project->variables()["TARGET"]; + if(project->first("TEMPLATE") == "lib") { + if(project->isActiveConfig("staticlib")) + project->variables()["TARGET"].first() = "lib" + project->first("TARGET") + ".lib"; + else + project->variables()["TARGET"].first() = "lib" + project->first("TARGET") + "." + + project->first("QMAKE_EXTENSION_SHLIB"); + + project->variables()["CODEWARRIOR_VERSION"].append(project->first("VER_MAJ") + + project->first("VER_MIN") + + project->first("VER_PAT")); + } else { + project->variables()["CODEWARRIOR_VERSION"].append("0"); + if(project->isEmpty("QMAKE_ENTRYPOINT")) + project->variables()["QMAKE_ENTRYPOINT"].append("start"); + project->variables()["CODEWARRIOR_ENTRYPOINT"].append( + project->first("QMAKE_ENTRYPOINT")); + } +} + + +QString +MetrowerksMakefileGenerator::findTemplate(QString file) +{ + QString ret; + if(!QFile::exists(ret = file) && + !QFile::exists((ret = Option::mkfile::qmakespec + QDir::separator() + file)) && + !QFile::exists((ret = QString(getenv("QTDIR")) + "/mkspecs/mac-mwerks/" + file)) && + !QFile::exists((ret = (QString(getenv("HOME")) + "/.tmake/" + file)))) + return ""; + return ret; +} + +bool +MetrowerksMakefileGenerator::createFork(const QString &f) +{ +#if defined(Q_OS_MACX) + FSRef fref; + FSSpec fileSpec; + if(QFile::exists(f)) { + mode_t perms = 0; + { + struct stat s; + stat(f.latin1(), &s); + if(!(s.st_mode & S_IWUSR)) { + perms = s.st_mode; + chmod(f.latin1(), perms | S_IWUSR); + } + } + FILE *o = fopen(f.latin1(), "a"); + if(!o) + return FALSE; + if(FSPathMakeRef((const UInt8 *)f.latin1(), &fref, NULL) == noErr) { + if(FSGetCatalogInfo(&fref, kFSCatInfoNone, NULL, NULL, &fileSpec, NULL) == noErr) + FSpCreateResFile(&fileSpec, 'CUTE', 'TEXT', smSystemScript); + else + qDebug("bogus %d", __LINE__); + } else + qDebug("bogus %d", __LINE__); + fclose(o); + if(perms) + chmod(f.latin1(), perms); + } +#else + Q_UNUSED(f) +#endif + return TRUE; +} + +bool +MetrowerksMakefileGenerator::fixifyToMacPath(QString &p, QString &v, bool ) +{ + v = "Absolute"; + if(p.find(':') != -1) //guess its macish already + return TRUE; + + static QString st_volume; + if(st_volume.isEmpty()) { + st_volume = var("QMAKE_VOLUMENAME"); +#ifdef Q_OS_MAC + if(st_volume.isEmpty()) { + uchar foo[512]; + HVolumeParam pb; + memset(&pb, '\0', sizeof(pb)); + pb.ioVRefNum = 0; + pb.ioNamePtr = foo; + if(PBHGetVInfoSync((HParmBlkPtr)&pb) == noErr) { + int len = foo[0]; + memcpy(foo,foo+1, len); + foo[len] = '\0'; + st_volume = (char *)foo; + } + } +#endif + } + QString volume = st_volume; + + fixEnvVariables(p); + if(p.startsWith("\"") && p.endsWith("\"")) + p = p.mid(1, p.length() - 2); + if(p.isEmpty()) + return FALSE; + if(!p.endsWith("/")) + p += "/"; + if(QDir::isRelativePath(p)) { + if(p.startsWith("{")) { + int eoc = p.find('}'); + if(eoc == -1) + return FALSE; + volume = p.mid(1, eoc - 1); + p = p.right(p.length() - eoc - 1); + } else { + QFileInfo fi(p); + if(fi.convertToAbs()) //strange + return FALSE; + p = fi.filePath(); + } + } + p = QDir::cleanDirPath(p); + if(!volume.isEmpty()) + v = volume; + p.replace("/", ":"); + if(p.right(1) != ":") + p += ':'; + return TRUE; +} + +void +MetrowerksMakefileGenerator::processPrlFiles() +{ + QPtrList libdirs; + libdirs.setAutoDelete(TRUE); + const QString lflags[] = { "QMAKE_LIBS", QString::null }; + for(int i = 0; !lflags[i].isNull(); i++) { + for(bool ret = FALSE; TRUE; ret = FALSE) { + QStringList l_out; + QStringList &l = project->variables()[lflags[i]]; + for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { + QString opt = (*it); + if(opt.startsWith("-")) { + if(opt.startsWith("-L")) { + QString r = opt.right(opt.length() - 2), l = r; + fixEnvVariables(l); + libdirs.append(new MakefileDependDir(r.replace( "\"", ""), + l.replace( "\"", ""))); + } else if(opt.left(2) == "-l") { + QString lib = opt.right(opt.length() - 2), prl; + for(MakefileDependDir *mdd = libdirs.first(); mdd; mdd = libdirs.next() ) { + prl = mdd->local_dir + Option::dir_sep + "lib" + lib + Option::prl_ext; + if(processPrlFile(prl)) { + if(prl.startsWith(mdd->local_dir)) + prl.replace(0, mdd->local_dir.length(), mdd->real_dir); + QRegExp reg("^.*lib(" + lib + "[^.]*)\\." + + project->first("QMAKE_EXTENSION_SHLIB") + "$"); + if(reg.exactMatch(prl)) + prl = "-l" + reg.cap(1); + opt = prl; + ret = TRUE; + break; + } + } + } else if(opt == "-framework") { + l_out.append(opt); + ++it; + opt = (*it); + QString prl = "/System/Library/Frameworks/" + opt + + ".framework/" + opt + Option::prl_ext; + if(processPrlFile(prl)) + ret = TRUE; + } + if(!opt.isEmpty()) + l_out.append(opt); + } else { + if(processPrlFile(opt)) + ret = TRUE; + if(!opt.isEmpty()) + l_out.append(opt); + } + } + if(ret) + l = l_out; + else + break; + } + } +} + +void +MetrowerksMakefileGenerator::processPrlVariable(const QString &var, const QStringList &l) +{ + if(var == "QMAKE_PRL_LIBS") { + QStringList &out = project->variables()["QMAKE_LIBS"]; + for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) { + bool append = TRUE; + if((*it).startsWith("-")) { + if((*it).startsWith("-l") || (*it).startsWith("-L")) { + append = out.findIndex((*it)) == -1; + } else if((*it).startsWith("-framework")) { + ++it; + for(QStringList::ConstIterator outit = out.begin(); + outit != out.end(); ++it) { + if((*outit) == "-framework") { + ++outit; + if((*outit) == (*it)) { + append = FALSE; + break; + } + } + } + } + } else if(QFile::exists((*it))) { + append = out.findIndex((*it)); + } + if(append) + out.append((*it)); + } + } else { + MakefileGenerator::processPrlVariable(var, l); + } +} + + +bool +MetrowerksMakefileGenerator::openOutput(QFile &file) const +{ + QString outdir; + if(!file.name().isEmpty()) { + QFileInfo fi(file); + if(fi.isDir()) + outdir = file.name() + QDir::separator(); + } + if(!outdir.isEmpty() || file.name().isEmpty()) + file.setName(outdir + project->first("TARGET") + ".xml"); + return MakefileGenerator::openOutput(file); +} diff --git a/qmake/generators/mac/metrowerks_xml.h b/qmake/generators/mac/metrowerks_xml.h new file mode 100644 index 0000000..ae3cfae --- a/dev/null +++ b/qmake/generators/mac/metrowerks_xml.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ________ class. +** +** Created : 970521 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef __METROWERKSMAKE_H__ +#define __METROWERKSMAKE_H__ + +#include "makefile.h" + +class MetrowerksMakefileGenerator : public MakefileGenerator +{ + bool createFork(const QString &f); + bool fixifyToMacPath(QString &c, QString &v, bool exists=TRUE); + + bool init_flag; + + bool writeMakeParts(QTextStream &); + bool writeSubDirs(QTextStream &); + + bool writeMakefile(QTextStream &); + QString findTemplate(QString file); + void init(); +public: + MetrowerksMakefileGenerator(QMakeProject *p); + ~MetrowerksMakefileGenerator(); + + bool openOutput(QFile &file) const; +protected: + virtual void processPrlFiles(); + virtual void processPrlVariable(const QString &var, const QStringList &l); + virtual bool doDepends() const { return FALSE; } //never necesary +}; + +inline MetrowerksMakefileGenerator::~MetrowerksMakefileGenerator() +{ } + +#endif /* __METROWERKSMAKE_H__ */ diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp new file mode 100644 index 0000000..8525058 --- a/dev/null +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -0,0 +1,983 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ________ class. +** +** Created : 970521 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "pbuilder_pbx.h" +#include "option.h" +#include +#include +#include +#include +#include +#ifdef Q_OS_UNIX +# include +# include +#endif + +// Note: this is fairly hacky, but it does the job... + + +ProjectBuilderMakefileGenerator::ProjectBuilderMakefileGenerator(QMakeProject *p) : UnixMakefileGenerator(p) +{ + +} + +bool +ProjectBuilderMakefileGenerator::writeMakefile(QTextStream &t) +{ + if(!project->variables()["QMAKE_FAILED_REQUIREMENTS"].isEmpty()) { + /* for now just dump, I need to generated an empty xml or something.. */ + fprintf(stderr, "Project file not generated because all requirements not met:\n\t%s\n", + var("QMAKE_FAILED_REQUIREMENTS").latin1()); + return TRUE; + } + + project->variables()["MAKEFILE"].clear(); + project->variables()["MAKEFILE"].append("Makefile"); + if(project->first("TEMPLATE") == "app" || project->first("TEMPLATE") == "lib") { + return writeMakeParts(t); + } else if(project->first("TEMPLATE") == "subdirs") { + writeSubdirs(t, FALSE); + return TRUE; + } + return FALSE; +} + +bool +ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) +{ + int i; + QStringList tmp; + bool did_preprocess = FALSE; + + //HEADER + t << "// !$*UTF8*$!" << "\n" + << "{" << "\n" + << "\t" << "archiveVersion = 1;" << "\n" + << "\t" << "classes = {" << "\n" << "\t" << "};" << "\n" + << "\t" << "objectVersion = " << pbuilderVersion() << ";" << "\n" + << "\t" << "objects = {" << endl; + + //MAKE QMAKE equivlant + if(!project->isActiveConfig("no_autoqmake") && project->projectFile() != "(stdin)") { + QString mkfile = pbx_dir + Option::dir_sep + "qt_makeqmake.mak"; + QFile mkf(mkfile); + if(mkf.open(IO_WriteOnly | IO_Translate)) { + debug_msg(1, "pbuilder: Creating file: %s", mkfile.latin1()); + QTextStream mkt(&mkf); + writeHeader(mkt); + mkt << "QMAKE = " << + (project->isEmpty("QMAKE_QMAKE") ? QString("$(QTDIR)/bin/qmake") : + var("QMAKE_QMAKE")) << endl; + writeMakeQmake(mkt); + mkf.close(); + } + QString phase_key = keyFor("QMAKE_PBX_MAKEQMAKE_BUILDPHASE"); + mkfile = fileFixify(mkfile, QDir::currentDirPath()); + project->variables()["QMAKE_PBX_BUILDPHASES"].append(phase_key); + t << "\t\t" << phase_key << " = {" << "\n" + << "\t\t\t" << "buildActionMask = 2147483647;" << "\n" + << "\t\t\t" << "files = (" << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "generatedFileNames = (" << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "isa = PBXShellScriptBuildPhase;" << "\n" + << "\t\t\t" << "name = \"Qt Qmake\";" << "\n" + << "\t\t\t" << "neededFileNames = (" << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "shellPath = /bin/sh;" << "\n" + << "\t\t\t" << "shellScript = \"make -C " << QDir::currentDirPath() << + " -f " << mkfile << "\";" << "\n" + << "\t\t" << "};" << "\n"; + } + + //DUMP SOURCES + QMap groups; + QString srcs[] = { "SOURCES", "SRCMOC", "UICIMPLS", QString::null }; + for(i = 0; !srcs[i].isNull(); i++) { + tmp = project->variables()[srcs[i]]; + QStringList &src_list = project->variables()["QMAKE_PBX_" + srcs[i]]; + for(QStringList::Iterator it = tmp.begin(); it != tmp.end(); ++it) { + QString file = fileFixify((*it)); + if(file.endsWith(Option::moc_ext)) + continue; + bool in_root = TRUE; + QString src_key = keyFor(file); + if(!project->isActiveConfig("flat")) { + QString flat_file = fileFixify(file, QDir::currentDirPath(), Option::output_dir, TRUE); + if(QDir::isRelativePath(flat_file) && flat_file.find(Option::dir_sep) != -1) { + QString last_grp("QMAKE_PBX_" + srcs[i] + "_HEIR_GROUP"); + QStringList dirs = QStringList::split(Option::dir_sep, flat_file); + dirs.pop_back(); //remove the file portion as it will be added via src_key + for(QStringList::Iterator dir_it = dirs.begin(); dir_it != dirs.end(); ++dir_it) { + QString new_grp(last_grp + Option::dir_sep + (*dir_it)), + new_grp_key(keyFor(new_grp)), last_grp_key(keyFor(last_grp)); + if(dir_it == dirs.begin()) { + if(!groups.contains(new_grp)) + project->variables()["QMAKE_PBX_" + srcs[i]].append(new_grp_key); + } else { + groups[last_grp] += new_grp_key; + } + last_grp = new_grp; + } + groups[last_grp] += src_key; + in_root = FALSE; + } + } + if(in_root) + src_list.append(src_key); + //source reference + t << "\t\t" << src_key << " = {" << "\n" + << "\t\t\t" << "isa = PBXFileReference;" << "\n" + << "\t\t\t" << "path = \"" << file << "\";" << "\n" + << "\t\t\t" << "refType = " << reftypeForFile(file) << ";" << "\n" + << "\t\t" << "};" << "\n"; + //build reference + QString obj_key = file + ".o"; + obj_key = keyFor(obj_key); + t << "\t\t" << obj_key << " = {" << "\n" + << "\t\t\t" << "fileRef = " << src_key << ";" << "\n" + << "\t\t\t" << "isa = PBXBuildFile;" << "\n" + << "\t\t\t" << "settings = {" << "\n" + << "\t\t\t\t" << "ATTRIBUTES = (" << "\n" + << "\t\t\t\t" << ");" << "\n" + << "\t\t\t" << "};" << "\n" + << "\t\t" << "};" << "\n"; + project->variables()["QMAKE_PBX_OBJ"].append(obj_key); + } + if(!src_list.isEmpty()) { + QString grp; + if(srcs[i] == "SOURCES") { + if(project->first("TEMPLATE") == "app" && !project->isEmpty("RC_FILE")) { //Icon + QString icns_file = keyFor("ICNS_FILE"); + src_list.append(icns_file); + t << "\t\t" << icns_file << " = {" << "\n" + << "\t\t\t" << "isa = PBXFileReference;" << "\n" + << "\t\t\t" << "path = \"" << project->first("RC_FILE") << "\";" << "\n" + << "\t\t\t" << "refType = " << reftypeForFile(project->first("RC_FILE")) << ";" << "\n" + << "\t\t" << "};" << "\n"; + t << "\t\t" << keyFor("ICNS_FILE_REFERENCE") << " = {" << "\n" + << "\t\t\t" << "fileRef = " << icns_file << ";" << "\n" + << "\t\t\t" << "isa = PBXBuildFile;" << "\n" + << "\t\t\t" << "settings = {" << "\n" + << "\t\t\t" << "};" << "\n" + << "\t\t" << "};" << "\n"; + } + grp = "Sources"; + } else if(srcs[i] == "SRCMOC") { + grp = "Mocables"; + } else if(srcs[i] == "UICIMPLS") { + grp = "UICables"; + } + QString grp_key = keyFor(grp); + project->variables()["QMAKE_PBX_GROUPS"].append(grp_key); + t << "\t\t" << grp_key << " = {" << "\n" + << "\t\t\t" << "children = (" << "\n" + << varGlue("QMAKE_PBX_" + srcs[i], "\t\t\t\t", ",\n\t\t\t\t", "\n") + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "isa = PBXGroup;" << "\n" + << "\t\t\t" << "name = " << grp << ";" << "\n" + << "\t\t\t" << "refType = 4;" << "\n" + << "\t\t" << "};" << "\n"; + } + } + for(QMap::Iterator grp_it = groups.begin(); + grp_it != groups.end(); ++grp_it) { + t << "\t\t" << keyFor(grp_it.key()) << " = {" << "\n" + << "\t\t\t" << "isa = PBXGroup;" << "\n" + << "\t\t\t" << "children = (" << "\n" + << valGlue(grp_it.data(), "\t\t\t\t", ",\n\t\t\t\t", "\n") + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "name = \"" << grp_it.key().section(Option::dir_sep, -1) << "\";" << "\n" + << "\t\t\t" << "refType = 4;" << "\n" + << "\t\t" << "};" << "\n"; + } + + //PREPROCESS BUILDPHASE (just a makefile) + if(!project->isEmpty("UICIMPLS") || !project->isEmpty("SRCMOC") || + !project->isEmpty("YACCSOURCES") || !project->isEmpty("LEXSOURCES")) { + QString mkfile = pbx_dir + Option::dir_sep + "qt_preprocess.mak"; + QFile mkf(mkfile); + if(mkf.open(IO_WriteOnly | IO_Translate)) { + did_preprocess = TRUE; + debug_msg(1, "pbuilder: Creating file: %s", mkfile.latin1()); + QTextStream mkt(&mkf); + writeHeader(mkt); + mkt << "MOC = " << var("QMAKE_MOC") << endl; + mkt << "UIC = " << var("QMAKE_UIC") << endl; + mkt << "LEX = " << var("QMAKE_LEX") << endl; + mkt << "LEXFLAGS = " << var("QMAKE_LEXFLAGS") << endl; + mkt << "YACC = " << var("QMAKE_YACC") << endl; + mkt << "YACCFLAGS = " << var("QMAKE_YACCFLAGS") << endl; + mkt << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; + mkt << "MOVE = " << var("QMAKE_MOVE") << endl << endl; + mkt << "FORMS = " << varList("UICIMPLS") << endl; + mkt << "MOCS = " << varList("SRCMOC") << endl; + mkt << "PARSERS ="; + if(!project->isEmpty("YACCSOURCES")) { + QStringList &yaccs = project->variables()["YACCSOURCES"]; + for(QStringList::Iterator yit = yaccs.begin(); yit != yaccs.end(); ++yit) { + QFileInfo fi((*yit)); + mkt << " " << fi.dirPath() << Option::dir_sep << fi.baseName(TRUE) + << Option::yacc_mod << Option::cpp_ext.first(); + } + } + if(!project->isEmpty("LEXSOURCES")) { + QStringList &lexs = project->variables()["LEXSOURCES"]; + for(QStringList::Iterator lit = lexs.begin(); lit != lexs.end(); ++lit) { + QFileInfo fi((*lit)); + mkt << " " << fi.dirPath() << Option::dir_sep << fi.baseName(TRUE) + << Option::lex_mod << Option::cpp_ext.first(); + } + } + mkt << "\n"; + mkt << "preprocess: $(FORMS) $(MOCS) $(PARSERS)" << endl; + mkt << "preprocess_clean: mocclean uiclean parser_clean" << endl << endl; + mkt << "mocclean:" << "\n"; + if(!project->isEmpty("SRCMOC")) + mkt << "\t-rm -f $(MOCS)" << "\n"; + mkt << "uiclean:" << "\n"; + if(!project->isEmpty("UICIMPLS")) + mkt << "\t-rm -f $(FORMS)" << "\n"; + mkt << "parser_clean:" << "\n"; + if(!project->isEmpty("YACCSOURCES") || !project->isEmpty("LEXSOURCES")) + mkt << "\t-rm -f $(PARSERS)" << "\n"; + writeUicSrc(mkt, "FORMS"); + writeMocSrc(mkt, "HEADERS"); + writeMocSrc(mkt, "SOURCES"); + writeMocSrc(mkt, "UICDECLS"); + writeYaccSrc(mkt, "YACCSOURCES"); + writeLexSrc(mkt, "LEXSOURCES"); + mkf.close(); + } + QString target_key = keyFor("QMAKE_PBX_PREPROCESS_TARGET"); + mkfile = fileFixify(mkfile, QDir::currentDirPath()); + t << "\t\t" << target_key << " = {" << "\n" + << "\t\t\t" << "buildArgumentsString = \"-f " << mkfile << "\";" << "\n" + << "\t\t\t" << "buildPhases = (" << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "buildSettings = {" << "\n" + << "\t\t\t" << "};" << "\n" + << "\t\t\t" << "buildToolPath = \"/usr/bin/gnumake\";"<< "\n" + << "\t\t\t" << "buildWorkingDirectory = \"" << QDir::currentDirPath() << "\";" << "\n" + << "\t\t\t" << "dependencies = (" << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "isa = PBXLegacyTarget;" << "\n" + << "\t\t\t" << "name = QtPreprocessors;" << "\n" + << "\t\t\t" << "productName = QtPreprocessors;" << "\n" + << "\t\t\t" << "settingsToExpand = 6;" << "\n" + << "\t\t\t" << "settingsToPassInEnvironment = 287;" << "\n" + << "\t\t\t" << "settingsToPassOnCommandLine = 280;" << "\n" + << "\t\t\t" << "shouldsUseHeadermap = 0;" << "\n" + << "\t\t" << "};" << "\n"; + + QString target_depend_key = keyFor("QMAKE_PBX_PREPROCESS_TARGET_DEPEND"); + project->variables()["QMAKE_PBX_TARGETDEPENDS"].append(target_depend_key); + t << "\t\t" << target_depend_key << " = {" << "\n" + << "\t\t\t" << "isa = PBXTargetDependency;" << "\n" + << "\t\t\t" << "target = " << target_key << ";" << "\n" + << "\t\t" << "};" << "\n"; + } + //SOURCE BUILDPHASE + if(!project->isEmpty("QMAKE_PBX_OBJ")) { + QString grp = "Build Sources", key = keyFor(grp); + project->variables()["QMAKE_PBX_BUILDPHASES"].append(key); + t << "\t\t" << key << " = {" << "\n" + << "\t\t\t" << "buildActionMask = 2147483647;" << "\n" + << "\t\t\t" << "files = (" << "\n" + << varGlue("QMAKE_PBX_OBJ", "\t\t\t\t", ",\n\t\t\t\t", "\n") + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "isa = PBXSourcesBuildPhase;" << "\n" + << "\t\t\t" << "name = \"" << grp << "\";" << "\n" + << "\t\t" << "};" << "\n"; + } + + if(!project->isActiveConfig("staticlib")) { //DUMP LIBRARIES + QStringList &libdirs = project->variables()["QMAKE_PBX_LIBPATHS"]; + QString libs[] = { "QMAKE_LIBDIR_FLAGS", "QMAKE_LIBS", QString::null }; + for(i = 0; !libs[i].isNull(); i++) { + tmp = project->variables()[libs[i]]; + for(QStringList::Iterator it = tmp.begin(); it != tmp.end();) { + bool remove = FALSE; + QString library, name, opt = (*it).stripWhiteSpace(); + if(opt.startsWith("-L")) { + QString r = opt.right(opt.length() - 2); + fixEnvVariables(r); + libdirs.append(r); + } else if(opt.startsWith("-l")) { + name = opt.right(opt.length() - 2); + QString lib("lib" + name); + for(QStringList::Iterator lit = libdirs.begin(); lit != libdirs.end(); ++lit) { + if(project->isActiveConfig("link_prl")) { + /* This isn't real nice, but it is real usefull. This looks in a prl + for what the library will ultimately be called so we can stick it + in the ProjectFile. If the prl format ever changes (not likely) then + this will not really work. However, more concerning is that it will + encode the version number in the Project file which might be a bad + things in days to come? --Sam + */ + QString prl_file = (*lit) + Option::dir_sep + lib + Option::prl_ext; + if(QFile::exists(prl_file)) { + QMakeProject proj; + if(proj.read(prl_file, QDir::currentDirPath())) { + if(!proj.isEmpty("QMAKE_PRL_TARGET")) { + library = (*lit) + Option::dir_sep + proj.first("QMAKE_PRL_TARGET"); + debug_msg(1, "pbuilder: Found library (%s) via PRL %s (%s)", + opt.latin1(), prl_file.latin1(), library.latin1()); + remove = TRUE; + } + } + + } + } + if(!remove) { + QString extns[] = { ".dylib", ".so", ".a", QString::null }; + for(int n = 0; !remove && !extns[n].isNull(); n++) { + QString tmp = (*lit) + Option::dir_sep + lib + extns[n]; + if(QFile::exists(tmp)) { + library = tmp; + debug_msg(1, "pbuilder: Found library (%s) via %s", + opt.latin1(), library.latin1()); + remove = TRUE; + } + } + } + } + } else if(opt == "-framework") { + ++it; + if(it == tmp.end()) + break; + QStringList &fdirs = project->variables()["QMAKE_FRAMEWORKDIR"]; + if(fdirs.isEmpty()) + fdirs.append("/System/Library/Frameworks/"); + for(QStringList::Iterator fit = fdirs.begin(); fit != fdirs.end(); ++fit) { + if(QFile::exists((*fit) + QDir::separator() + (*it) + ".framework")) { + --it; + it = tmp.remove(it); + remove = TRUE; + library = (*fit) + Option::dir_sep + (*it) + ".framework"; + break; + } + } + } else if(opt.left(1) != "-") { + remove = TRUE; + library = opt; + } + if(!library.isEmpty()) { + if(name.isEmpty()) { + int slsh = library.findRev(Option::dir_sep); + if(slsh != -1) + name = library.right(library.length() - slsh - 1); + } + library = fileFixify(library); + QString key = keyFor(library); + bool is_frmwrk = (library.endsWith(".framework")); + t << "\t\t" << key << " = {" << "\n" + << "\t\t\t" << "isa = " << (is_frmwrk ? "PBXFrameworkReference" : "PBXFileReference") << ";" << "\n" + << "\t\t\t" << "name = \"" << name << "\";" << "\n" + << "\t\t\t" << "path = \"" << library << "\";" << "\n" + << "\t\t\t" << "refType = " << reftypeForFile(library) << ";" << "\n" + << "\t\t" << "};" << "\n"; + project->variables()["QMAKE_PBX_LIBRARIES"].append(key); + QString obj_key = library + ".o"; + obj_key = keyFor(obj_key); + t << "\t\t" << obj_key << " = {" << "\n" + << "\t\t\t" << "fileRef = " << key << ";" << "\n" + << "\t\t\t" << "isa = PBXBuildFile;" << "\n" + << "\t\t\t" << "settings = {" << "\n" + << "\t\t\t" << "};" << "\n" + << "\t\t" << "};" << "\n"; + project->variables()["QMAKE_PBX_BUILD_LIBRARIES"].append(obj_key); + } + if(remove) + it = tmp.remove(it); + else + ++it; + } + project->variables()[libs[i]] = tmp; + } + } + //SUBLIBS BUILDPHASE (just another makefile) + if(!project->isEmpty("SUBLIBS")) { + QString mkfile = pbx_dir + Option::dir_sep + "qt_sublibs.mak"; + QFile mkf(mkfile); + if(mkf.open(IO_WriteOnly | IO_Translate)) { + debug_msg(1, "pbuilder: Creating file: %s", mkfile.latin1()); + QTextStream mkt(&mkf); + writeHeader(mkt); + mkt << "SUBLIBS= "; + tmp = project->variables()["SUBLIBS"]; + QStringList::Iterator it; + for(it = tmp.begin(); it != tmp.end(); ++it) + t << "tmp/lib" << (*it) << ".a "; + t << endl << endl; + mkt << "sublibs: $(SUBLIBS)" << endl << endl; + tmp = project->variables()["SUBLIBS"]; + for(it = tmp.begin(); it != tmp.end(); ++it) + t << "tmp/lib" << (*it) << ".a" << ":\n\t" + << var(QString("MAKELIB") + (*it)) << endl << endl; + mkf.close(); + } + QString phase_key = keyFor("QMAKE_PBX_SUBLIBS_BUILDPHASE"); + mkfile = fileFixify(mkfile, QDir::currentDirPath()); + project->variables()["QMAKE_PBX_BUILDPHASES"].append(phase_key); + t << "\t\t" << phase_key << " = {" << "\n" + << "\t\t\t" << "buildActionMask = 2147483647;" << "\n" + << "\t\t\t" << "files = (" << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "generatedFileNames = (" << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "isa = PBXShellScriptBuildPhase;" << "\n" + << "\t\t\t" << "name = \"Qt Sublibs\";" << "\n" + << "\t\t\t" << "neededFileNames = (" << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "shellPath = /bin/sh;" << "\n" + << "\t\t\t" << "shellScript = \"make -C " << QDir::currentDirPath() << + " -f " << mkfile << "\";" << "\n" + << "\t\t" << "};" << "\n"; + } + //LIBRARY BUILDPHASE + if(!project->isEmpty("QMAKE_PBX_LIBRARIES")) { + tmp = project->variables()["QMAKE_PBX_LIBRARIES"]; + if(!tmp.isEmpty()) { + QString grp("External Frameworks and Libraries"), key = keyFor(grp); + project->variables()["QMAKE_PBX_GROUPS"].append(key); + t << "\t\t" << key << " = {" << "\n" + << "\t\t\t" << "children = (" << "\n" + << varGlue("QMAKE_PBX_LIBRARIES", "\t\t\t\t", ",\n\t\t\t\t", "\n") + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "isa = PBXGroup;" << "\n" + << "\t\t\t" << "name = \"" << grp << "\"" << ";" << "\n" + << "\t\t\t" << "path = \"\";" << "\n" + << "\t\t\t" << "refType = 4;" << "\n" + << "\t\t" << "};" << "\n"; + } + } + { + QString grp("Frameworks & Libraries"), key = keyFor(grp); + project->variables()["QMAKE_PBX_BUILDPHASES"].append(key); + t << "\t\t" << key << " = {" << "\n" + << "\t\t\t" << "buildActionMask = 2147483647;" << "\n" + << "\t\t\t" << "files = (" << "\n" + << varGlue("QMAKE_PBX_BUILD_LIBRARIES", "\t\t\t\t", ",\n\t\t\t\t", "\n") + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "isa = PBXFrameworksBuildPhase;" << "\n" + << "\t\t\t" << "name = \"" << grp << "\";" << "\n" + << "\t\t" << "};" << "\n"; + } + if(project->isActiveConfig("resource_fork") && !project->isActiveConfig("console") && + project->first("TEMPLATE") == "app") { //BUNDLE RESOURCES + QString grp("Bundle Resources"), key = keyFor(grp); + project->variables()["QMAKE_PBX_BUILDPHASES"].append(key); + t << "\t\t" << key << " = {" << "\n" + << "\t\t\t" << "buildActionMask = 2147483647;" << "\n" + << "\t\t\t" << "files = (" << "\n" + << (!project->isEmpty("RC_FILE") ? keyFor("ICNS_FILE_REFERENCE") : QString("")) + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "isa = PBXResourcesBuildPhase;" << "\n" + << "\t\t\t" << "name = \"" << grp << "\";" << "\n" + << "\t\t" << "};" << "\n"; + } + + //DUMP EVERYTHING THAT TIES THE ABOVE TOGETHER + //PRODUCTS + { + QString grp("Products"), key = keyFor(grp); + project->variables()["QMAKE_PBX_GROUPS"].append(key); + t << "\t\t" << key << " = {" << "\n" + << "\t\t\t" << "children = (" << "\n" + << "\t\t\t\t" << keyFor("QMAKE_PBX_REFERENCE") << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "isa = PBXGroup;" << "\n" + << "\t\t\t" << "name = Products;" << "\n" + << "\t\t\t" << "refType = 4;" << "\n" + << "\t\t" << "};" << "\n"; + } + { //INSTALL BUILDPHASE (sh script) + QString targ = project->first("TARGET"); + if(project->first("TEMPLATE") == "app" || + (project->first("TEMPLATE") == "lib" && !project->isActiveConfig("staticlib") && + project->isActiveConfig("frameworklib"))) + targ = project->first("QMAKE_ORIG_TARGET"); + int slsh = targ.findRev(Option::dir_sep); + if(slsh != -1) + targ = targ.right(targ.length() - slsh - 1); + fixEnvVariables(targ); + QStringList links; + if(project->first("TEMPLATE") == "app") { + if(project->isActiveConfig("resource_fork") && !project->isActiveConfig("console")) + targ += ".app"; + } else if(!project->isActiveConfig("staticlib") && + !project->isActiveConfig("frameworklib")) { + QString li[] = { "TARGET_", "TARGET_x", "TARGET_x.y", QString::null }; + for(int n = 0; !li[n].isNull(); n++) { + QString t = project->first(li[n]); + slsh = t.findRev(Option::dir_sep); + if(slsh != -1) + t = t.right(t.length() - slsh); + fixEnvVariables(t); + links << t; + } + } + QString script = pbx_dir + Option::dir_sep + "qt_install.sh"; + QFile shf(script); + if(shf.open(IO_WriteOnly | IO_Translate)) { + debug_msg(1, "pbuilder: Creating file: %s", script.latin1()); + QString targ = project->first("QMAKE_ORIG_TARGET"), cpflags; + if(project->first("TEMPLATE") == "app") { + targ = project->first("TARGET"); + if(project->isActiveConfig("resource_fork") && !project->isActiveConfig("console")) { + targ += ".app"; + cpflags += "-r "; + } + } else if(!project->isActiveConfig("frameworklib")) { + if(project->isActiveConfig("staticlib")) + targ = project->first("TARGET"); + else + targ = project->first("TARGET_"); + int slsh = targ.findRev(Option::dir_sep); + if(slsh != -1) + targ = targ.right(targ.length() - slsh - 1); + } + QTextStream sht(&shf); + QString dstdir = project->first("DESTDIR"); + fixEnvVariables(dstdir); + + sht << "#!/bin/sh" << endl; + //copy the actual target + sht << "OUT_TARG=\"" << targ << "\"\n" + << "[ -z \"$BUILD_ROOT\" ] || OUT_TARG=\"${BUILD_ROOT}/${OUT_TARG}\"" << endl; + sht << "[ \"$OUT_TARG\" = \"" + << (dstdir.isEmpty() ? QDir::currentDirPath() + QDir::separator(): dstdir) << targ << "\" ] || " + << "[ \"$OUT_TARG\" = \"" << targ << "\" ] || " + << "cp -r \"$OUT_TARG\" " << "\"" << dstdir << targ << "\"" << endl; + //rename as a framework + if(project->first("TEMPLATE") == "lib" && project->isActiveConfig("frameworklib")) + sht << "ln -sf \"" << targ << "\" " << "\"" << dstdir << targ << "\"" << endl; + //create all the version symlinks (just to be like unixmake) + for(QStringList::Iterator it = links.begin(); it != links.end(); ++it) { + if(targ != (*it)) + sht << "ln -sf \"" << targ << "\" " << "\"" << dstdir << (*it) << "\"" << endl; + } + shf.close(); +#ifdef Q_OS_UNIX + chmod(script.latin1(), S_IRWXU | S_IRWXG); +#endif + QString phase_key = keyFor("QMAKE_PBX_INSTALL_BUILDPHASE"); + script = fileFixify(script, QDir::currentDirPath()); + project->variables()["QMAKE_PBX_BUILDPHASES"].append(phase_key); + t << "\t\t" << phase_key << " = {" << "\n" + << "\t\t\t" << "buildActionMask = 8;" << "\n" //only on install! + << "\t\t\t" << "files = (" << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "generatedFileNames = (" << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "isa = PBXShellScriptBuildPhase;" << "\n" + << "\t\t\t" << "name = \"Qt Install\";" << "\n" + << "\t\t\t" << "neededFileNames = (" << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "shellPath = /bin/sh;" << "\n" + << "\t\t\t" << "shellScript = \"" << script << "\";" << "\n" + << "\t\t" << "};" << "\n"; + } + } + //ROOT_GROUP + t << "\t\t" << keyFor("QMAKE_PBX_ROOT_GROUP") << " = {" << "\n" + << "\t\t\t" << "children = (" << "\n" + << varGlue("QMAKE_PBX_GROUPS", "\t\t\t\t", ",\n\t\t\t\t", "\n") + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "isa = PBXGroup;" << "\n" + << "\t\t\t" << "name = " << project->first("QMAKE_ORIG_TARGET") << ";" << "\n" + << "\t\t\t" << "path = \"\";" << "\n" + << "\t\t\t" << "refType = 4;" << "\n" + << "\t\t" << "};" << "\n"; + //REFERENCE + t << "\t\t" << keyFor("QMAKE_PBX_REFERENCE") << " = {" << "\n"; + if(project->first("TEMPLATE") == "app") { + QString targ = project->first("QMAKE_ORIG_TARGET"); + if(project->isActiveConfig("resource_fork") && !project->isActiveConfig("console")) { + targ += ".app"; + t << "\t\t\t" << "isa = PBXApplicationReference;" << "\n"; + } else { + t << "\t\t\t" << "isa = PBXExecutableFileReference;" << "\n"; + } + QString app = (!project->isEmpty("DESTDIR") ? project->first("DESTDIR") + project->first("QMAKE_ORIG_TARGET") : + QDir::currentDirPath()) + Option::dir_sep + targ; + t << "\t\t\t" << "name = " << targ << ";" << "\n" + << "\t\t\t" << "path = \"" << targ << "\";" << "\n" + << "\t\t\t" << "refType = " << reftypeForFile(app) << ";" << "\n"; + } else { + QString lib = project->first("QMAKE_ORIG_TARGET"); + if(project->isActiveConfig("staticlib")) { + lib = project->first("TARGET"); + } else if(!project->isActiveConfig("frameworklib")) { + if(project->isActiveConfig("plugin")) + lib = project->first("TARGET"); + else + lib = project->first("TARGET_"); + } + int slsh = lib.findRev(Option::dir_sep); + if(slsh != -1) + lib = lib.right(lib.length() - slsh - 1); + t << "\t\t\t" << "isa = PBXLibraryReference;" << "\n" + << "\t\t\t" << "path = " << lib << ";\n" + << "\t\t\t" << "refType = " << reftypeForFile(lib) << ";" << "\n"; + } + t << "\t\t" << "};" << "\n"; + //TARGET + t << "\t\t" << keyFor("QMAKE_PBX_TARGET") << " = {" << "\n" + << "\t\t\t" << "buildPhases = (" << "\n" + << varGlue("QMAKE_PBX_BUILDPHASES", "\t\t\t\t", ",\n\t\t\t\t", "\n") + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "buildSettings = {" << "\n" + << "\t\t\t\t" << "FRAMEWORK_SEARCH_PATHS = \"\";" << "\n" + << "\t\t\t\t" << "HEADER_SEARCH_PATHS = \"" << fixEnvsList("INCLUDEPATH") << " " << fixEnvs(specdir()) << "\";" << "\n" + << "\t\t\t\t" << "LIBRARY_SEARCH_PATHS = \"" << var("QMAKE_PBX_LIBPATHS") << "\";" << "\n" + << "\t\t\t\t" << "OPTIMIZATION_CFLAGS = \"\";" << "\n" + << "\t\t\t\t" << "OTHER_CFLAGS = \"" << + fixEnvsList("QMAKE_CFLAGS") << varGlue("PRL_EXPORT_DEFINES"," -D"," -D","") << + varGlue("DEFINES"," -D"," -D","") << "\";" << "\n" + << "\t\t\t\t" << "LEXFLAGS = \"" << var("QMAKE_LEXFLAGS") << "\";" << "\n" + << "\t\t\t\t" << "YACCFLAGS = \"" << var("QMAKE_YACCFLAGS") << "\";" << "\n" + << "\t\t\t\t" << "OTHER_CPLUSPLUSFLAGS = \"" << + fixEnvsList("QMAKE_CXXFLAGS") << varGlue("PRL_EXPORT_DEFINES"," -D"," -D","") << + varGlue("DEFINES"," -D"," -D","") << "\";" << "\n" + << "\t\t\t\t" << "OTHER_REZFLAGS = \"\";" << "\n" + << "\t\t\t\t" << "SECTORDER_FLAGS = \"\";" << "\n" + << "\t\t\t\t" << "WARNING_CFLAGS = \"\";" << "\n"; +#if 1 + t << "\t\t\t\t" << "BUILD_ROOT = \"" << QDir::currentDirPath() << "\";" << "\n"; +#endif + if(!project->isActiveConfig("staticlib")) + t << "\t\t\t\t" << "OTHER_LDFLAGS = \"" << fixEnvsList("SUBLIBS") << " " << + fixEnvsList("QMAKE_LFLAGS") << " " << fixEnvsList("QMAKE_LIBDIR_FLAGS") << + " " << fixEnvsList("QMAKE_LIBS") << "\";" << "\n"; + if(!project->isEmpty("DESTDIR")) + t << "\t\t\t\t" << "INSTALL_PATH = \"" << project->first("DESTDIR") << "\";" << "\n"; + if(!project->isEmpty("VERSION") && project->first("VERSION") != "0.0.0") + t << "\t\t\t\t" << "DYLIB_CURRENT_VERSION = \"" << project->first("VERSION") << "\";" << "\n"; + if(!project->isEmpty("OBJECTS_DIR")) + t << "\t\t\t\t" << "OBJECT_FILE_DIR = \"" << project->first("OBJECTS_DIR") << "\";" << "\n"; + if(project->first("TEMPLATE") == "app") { + if(project->isActiveConfig("resource_fork") && !project->isActiveConfig("console")) + t << "\t\t\t\t" << "WRAPPER_EXTENSION = app;" << "\n"; + t << "\t\t\t\t" << "PRODUCT_NAME = " << project->first("QMAKE_ORIG_TARGET") << ";" << "\n"; + } else { + QString lib = project->first("QMAKE_ORIG_TARGET"); + if(!project->isActiveConfig("plugin") && project->isActiveConfig("staticlib")) { + t << "\t\t\t\t" << "LIBRARY_STYLE = STATIC;" << "\n"; + lib = project->first("TARGET"); + } else { + t << "\t\t\t\t" << "LIBRARY_STYLE = DYNAMIC;" << "\n"; + if(!project->isActiveConfig("frameworklib")) { + if(project->isActiveConfig("plugin")) + lib = project->first("TARGET"); + else + lib = project->first("TARGET_"); + } + } + int slsh = lib.findRev(Option::dir_sep); + if(slsh != -1) + lib = lib.right(lib.length() - slsh - 1); + t << "\t\t\t\t" << "PRODUCT_NAME = " << lib << ";" << "\n"; + } + tmp = project->variables()["QMAKE_PBX_VARS"]; + for(QStringList::Iterator it = tmp.begin(); it != tmp.end(); ++it) + t << "\t\t\t\t" << (*it) << " = \"" << getenv((*it)) << "\";" << "\n"; + t << "\t\t\t" << "};" << "\n" + << "\t\t\t" << "conditionalBuildSettings = {" << "\n" + << "\t\t\t" << "};" << "\n" + << "\t\t\t" << "dependencies = (" << "\n" + << varGlue("QMAKE_PBX_TARGETDEPENDS", "\t\t\t\t", ",\n\t\t\t\t", "\n") + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "productReference = " << keyFor("QMAKE_PBX_REFERENCE") << ";" << "\n" + << "\t\t\t" << "shouldUseHeadermap = 1;" << "\n"; + if(project->first("TEMPLATE") == "app") { + if(project->isActiveConfig("resource_fork") && !project->isActiveConfig("console")) { + t << "\t\t\t" << "isa = PBXApplicationTarget;" << "\n" + << "\t\t\t" << "productSettingsXML = " << "\"" << "" << "\n" + << "\t\t\t\t" << "" << "\n" + << "\t\t\t\t" << "" << "\n" + << "\t\t\t\t" << "" << "\n" + << "\t\t\t\t\t" << "CFBundleDevelopmentRegion" << "\n" + << "\t\t\t\t\t" << "English" << "\n" + << "\t\t\t\t\t" << "CFBundleExecutable" << "\n" + << "\t\t\t\t\t" << "" << project->first("QMAKE_ORIG_TARGET") << "" << "\n" + << "\t\t\t\t\t" << "CFBundleIconFile" << "\n" + << "\t\t\t\t\t" << "" << var("RC_FILE").section(Option::dir_sep, -1) << "" << "\n" + << "\t\t\t\t\t" << "CFBundleInfoDictionaryVersion" << "\n" + << "\t\t\t\t\t" << "6.0" << "\n" + << "\t\t\t\t\t" << "CFBundlePackageType" << "\n" + << "\t\t\t\t\t" << "APPL" << "\n" + << "\t\t\t\t\t" << "CFBundleSignature" << "\n" + << "\t\t\t\t\t" << "????" << "\n" + << "\t\t\t\t\t" << "CFBundleVersion" << "\n" + << "\t\t\t\t\t" << "0.1" << "\n" + << "\t\t\t\t\t" << "CSResourcesFileMapped" << "\n" + << "\t\t\t\t\t" << "" << "\n" + << "\t\t\t\t" << "" << "\n" + << "\t\t\t\t" << "" << "\";" << "\n"; + } else { + t << "\t\t\t" << "isa = PBXToolTarget;" << "\n"; + } + t << "\t\t\t" << "name = \"" << project->first("QMAKE_ORIG_TARGET") << "\";" << "\n" + << "\t\t\t" << "productName = " << project->first("QMAKE_ORIG_TARGET") << ";" << "\n"; + } else { + QString lib = project->first("QMAKE_ORIG_TARGET"); + if(!project->isActiveConfig("frameworklib")) + lib.prepend("lib"); + t << "\t\t\t" << "isa = PBXLibraryTarget;" << "\n" + << "\t\t\t" << "name = \"" << lib << "\";" << "\n" + << "\t\t\t" << "productName = " << lib << ";" << "\n"; + } + if(!project->isEmpty("DESTDIR")) + t << "\t\t\t" << "productInstallPath = \"" << project->first("DESTDIR") << "\";" << "\n"; + t << "\t\t" << "};" << "\n"; + //DEBUG/RELEASE + for(i = 0; i < 2; i++) { + bool as_release = !i; + if(project->isActiveConfig("debug")) + as_release = i; + QString key = "QMAKE_PBX_" + QString(as_release ? "RELEASE" : "DEBUG"); + key = keyFor(key); + project->variables()["QMAKE_PBX_BUILDSTYLES"].append(key); + t << "\t\t" << key << " = {" << "\n" + << "\t\t\t" << "buildRules = (" << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "buildSettings = {" << "\n" + << "\t\t\t\t" << "COPY_PHASE_STRIP = " << (as_release ? "YES" : "NO") << ";" << "\n"; + if(as_release) + t << "\t\t\t\t" << "DEBUGGING_SYMBOLS = NO;" << "\n"; + t << "\t\t\t" << "};" << "\n" + << "\t\t\t" << "isa = PBXBuildStyle;" << "\n" + << "\t\t\t" << "name = " << (as_release ? "Deployment" : "Development") << ";" << "\n" + << "\t\t" << "};" << "\n"; + } + //ROOT + t << "\t\t" << keyFor("QMAKE_PBX_ROOT") << " = {" << "\n" + << "\t\t\t" << "buildStyles = (" << "\n" + << varGlue("QMAKE_PBX_BUILDSTYLES", "\t\t\t\t", ",\n\t\t\t\t", "\n") + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "isa = PBXProject;" << "\n" + << "\t\t\t" << "mainGroup = " << keyFor("QMAKE_PBX_ROOT_GROUP") << ";" << "\n" + << "\t\t\t" << "targets = (" << "\n" + << "\t\t\t\t" << keyFor("QMAKE_PBX_TARGET") << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t" << "};" << "\n"; + + //FOOTER + t << "\t" << "};" << "\n" + << "\t" << "rootObject = " << keyFor("QMAKE_PBX_ROOT") << ";" << "\n" + << "}" << endl; + + QString mkwrap = fileFixify(pbx_dir + Option::dir_sep + ".." + Option::dir_sep + project->first("MAKEFILE"), + QDir::currentDirPath()); + QFile mkwrapf(mkwrap); + if(mkwrapf.open(IO_WriteOnly | IO_Translate)) { + debug_msg(1, "pbuilder: Creating file: %s", mkwrap.latin1()); + QTextStream mkwrapt(&mkwrapf); + writeHeader(mkwrapt); + const char *cleans = "uiclean mocclean preprocess_clean "; + mkwrapt << "#This is a makefile wrapper for PROJECT BUILDER\n" + << "all:" << "\n\t" + << "cd " << (project->first("QMAKE_ORIG_TARGET") + ".pbproj/ && pbxbuild") << "\n" + << "install: all" << "\n\t" + << "cd " << (project->first("QMAKE_ORIG_TARGET") + ".pbproj/ && pbxbuild install") << "\n" + << "distclean clean: preprocess_clean" << "\n\t" + << "cd " << (project->first("QMAKE_ORIG_TARGET") + ".pbproj/ && pbxbuild clean") << "\n" + << (!did_preprocess ? cleans : "") << ":" << "\n"; + if(did_preprocess) + mkwrapt << cleans << ":" << "\n\t" + << "make -f " + << pbx_dir << Option::dir_sep << "qt_preprocess.mak $@" << endl; + } + return TRUE; +} + +QString +ProjectBuilderMakefileGenerator::fixEnvs(QString file) +{ + QRegExp reg_var("\\$\\((.*)\\)"); + for(int rep = 0; (rep = reg_var.search(file, rep)) != -1; ) { + if(project->variables()["QMAKE_PBX_VARS"].findIndex(reg_var.cap(1)) == -1) + project->variables()["QMAKE_PBX_VARS"].append(reg_var.cap(1)); + rep += reg_var.matchedLength(); + } + return file; +} + +QString +ProjectBuilderMakefileGenerator::fixEnvsList(QString where) +{ + QString ret; + const QStringList &l = project->variables()[where]; + for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) { + fixEnvs((*it)); + if(!ret.isEmpty()) + ret += " "; + ret += (*it); + } + return ret; +} + +QString +ProjectBuilderMakefileGenerator::keyFor(QString block) +{ +#if 0 //This make this code much easier to debug.. + return block; +#endif + + QString ret; + if(!keys.contains(block)) { +#if 0 + static unsigned int r = 0; + ret.sprintf("%024x", ++r); +#else //not really necesary, but makes it look more interesting.. + static struct { unsigned int a1, a2, a3; } r = { 0, 0, 0 }; + if(!r.a1 && !r.a2 && !r.a3) { + r.a1 = rand(); + r.a2 = rand(); + r.a3 = rand(); + } + switch(rand() % 3) { + case 0: ++r.a1; break; + case 1: ++r.a2; break; + case 2: ++r.a3; break; + } + ret.sprintf("%08x%08x%08x", r.a1, r.a2, r.a3); +#endif + ret = ret.upper(); + keys.insert(block, ret); + } else { + ret = keys[block]; + } + return ret; +} + +bool +ProjectBuilderMakefileGenerator::openOutput(QFile &file) const +{ + if(project->first("TEMPLATE") != "subdirs") { + QFileInfo fi(file); + if(fi.extension() != "pbxproj" || file.name().isEmpty()) { + QString output = file.name(); + if(fi.isDir()) + output += QDir::separator(); + if(fi.extension() != "pbproj") { + if(file.name().isEmpty() || fi.isDir()) + output += project->first("TARGET"); + output += QString(".pbproj") + QDir::separator(); + } else if(output[(int)output.length() - 1] != QDir::separator()) { + output += QDir::separator(); + } + output += QString("project.pbxproj"); + file.setName(output); + } + bool ret = UnixMakefileGenerator::openOutput(file); + ((ProjectBuilderMakefileGenerator*)this)->pbx_dir = Option::output_dir.section(Option::dir_sep, 0, -1); + Option::output_dir = pbx_dir.section(Option::dir_sep, 0, -2); + return ret; + } + return UnixMakefileGenerator::openOutput(file); +} + +/* This function is such a hack it is almost pointless, but it + eliminates the warning message from ProjectBuilder that the project + file is for an older version. I guess this could be used someday if + the format of the output is dependant upon the version of + ProjectBuilder as well. +*/ +int +ProjectBuilderMakefileGenerator::pbuilderVersion() const +{ + QString ret; + if(project->isEmpty("QMAKE_PBUILDER_VERSION")) { + QString version, version_plist = project->first("QMAKE_PBUILDER_VERSION_PLIST"); + if(version_plist.isEmpty()) + version_plist = "/Developer/Applications/Project Builder.app/Contents/version.plist"; + else + version_plist = version_plist.replace(QRegExp("\""), ""); + QFile version_file(version_plist); + if(version_file.open(IO_ReadOnly)) { + debug_msg(1, "pbuilder: version.plist: Reading file: %s", version_plist.latin1()); + QTextStream plist(&version_file); + + bool in_dict = FALSE; + QString current_key; + QRegExp keyreg("^(.*)$"), stringreg("^(.*)$"); + while(!plist.eof()) { + QString line = plist.readLine().stripWhiteSpace(); + if(line == "") + in_dict = TRUE; + else if(line == "") + in_dict = FALSE; + else if(in_dict) { + if(keyreg.exactMatch(line)) + current_key = keyreg.cap(1); + else if(current_key == "CFBundleShortVersionString" && stringreg.exactMatch(line)) + version = stringreg.cap(1); + } + } + version_file.close(); + } else debug_msg(1, "pbuilder: version.plist: Failure to open %s", version_plist.latin1()); + if(version.startsWith("2.0")) + ret = "38"; + else if(version == "1.1") + ret = "34"; + } else { + ret = project->first("QMAKE_PBUILDER_VERSION"); + } + if(!ret.isEmpty()) { + bool ok; + int int_ret = ret.toInt(&ok); + if(ok) { + debug_msg(1, "pbuilder: version.plist: Got version: %d", int_ret); + return int_ret; + } + } + debug_msg(1, "pbuilder: version.plist: Fallback to default version"); + return 34; //my fallback +} + +QString +ProjectBuilderMakefileGenerator::reftypeForFile(QString where) +{ + if(QDir::isRelativePath(where)) + return "4"; //relative + return "0"; //absolute +} diff --git a/qmake/generators/mac/pbuilder_pbx.h b/qmake/generators/mac/pbuilder_pbx.h new file mode 100644 index 0000000..ec2e1be --- a/dev/null +++ b/qmake/generators/mac/pbuilder_pbx.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ________ class. +** +** Created : 970521 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef __PBUILDERMAKE_H__ +#define __PBUILDERMAKE_H__ + +#include "unixmake.h" + +class ProjectBuilderMakefileGenerator : public UnixMakefileGenerator +{ + QString pbx_dir; + int pbuilderVersion() const; + bool writeMakeParts(QTextStream &); + bool writeMakefile(QTextStream &); + + QMap keys; + QString keyFor(QString file); + QString fixEnvs(QString file); + QString fixEnvsList(QString where); + QString reftypeForFile(QString file); + +public: + ProjectBuilderMakefileGenerator(QMakeProject *p); + ~ProjectBuilderMakefileGenerator(); + + virtual bool openOutput(QFile &) const; +protected: + virtual bool doDepends() const { return FALSE; } //never necesary +}; + +inline ProjectBuilderMakefileGenerator::~ProjectBuilderMakefileGenerator() +{ } + + +#endif /* __PBUILDERMAKE_H__ */ -- cgit v0.9.0.2