summaryrefslogtreecommitdiff
path: root/qmake/generators/mac
Unidiff
Diffstat (limited to 'qmake/generators/mac') (more/less context) (show whitespace changes)
-rw-r--r--qmake/generators/mac/metrowerks_xml.cpp822
-rw-r--r--qmake/generators/mac/metrowerks_xml.h69
-rw-r--r--qmake/generators/mac/pbuilder_pbx.cpp983
-rw-r--r--qmake/generators/mac/pbuilder_pbx.h68
4 files changed, 1942 insertions, 0 deletions
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 @@
1/****************************************************************************
2** $Id$
3**
4** Definition of ________ class.
5**
6** Created : 970521
7**
8** Copyright (C) 1992-2002 Trolltech AS. All rights reserved.
9**
10** This file is part of the network module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition licenses may use this
22** file in accordance with the Qt Commercial License Agreement provided
23** with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#include "metrowerks_xml.h"
39#include "option.h"
40#include <qdir.h>
41#include <qdict.h>
42#include <qregexp.h>
43#include <stdlib.h>
44#include <time.h>
45#ifdef Q_OS_MAC
46#include <Carbon/Carbon.h>
47#include <sys/types.h>
48#include <sys/stat.h>
49#endif
50
51
52MetrowerksMakefileGenerator::MetrowerksMakefileGenerator(QMakeProject *p) : MakefileGenerator(p), init_flag(FALSE)
53{
54
55}
56
57bool
58MetrowerksMakefileGenerator::writeMakefile(QTextStream &t)
59{
60 if(!project->variables()["QMAKE_FAILED_REQUIREMENTS"].isEmpty()) {
61 /* for now just dump, I need to generated an empty xml or something.. */
62 fprintf(stderr, "Project file not generated because all requirements not met:\n\t%s\n",
63 var("QMAKE_FAILED_REQUIREMENTS").latin1());
64 return TRUE;
65 }
66
67 if(project->first("TEMPLATE") == "app" ||
68 project->first("TEMPLATE") == "lib") {
69 return writeMakeParts(t);
70 }
71 else if(project->first("TEMPLATE") == "subdirs") {
72 writeHeader(t);
73 qDebug("Not supported!");
74 return TRUE;
75 }
76 return FALSE;
77}
78
79bool
80MetrowerksMakefileGenerator::writeMakeParts(QTextStream &t)
81{
82 //..grrr.. libs!
83 QStringList extra_objs;
84 bool do_libs = TRUE;
85 if(project->first("TEMPLATE") == "app")
86 extra_objs += project->variables()["QMAKE_CRT_OBJECTS"];
87 else if(project->first("TEMPLATE") == "lib" && project->isActiveConfig("staticlib"))
88 do_libs = FALSE;
89 if(do_libs)
90 extra_objs += project->variables()["QMAKE_LIBS"];
91 for(QStringList::Iterator val_it = extra_objs.begin();
92 val_it != extra_objs.end(); ++val_it) {
93 if((*val_it).startsWith("-L")) {
94 QString dir((*val_it).right((*val_it).length() - 2));
95 fixEnvVariables(dir);
96 if(project->variables()["DEPENDPATH"].findIndex(dir) == -1 &&
97 project->variables()["INCLUDEPATH"].findIndex(dir) == -1)
98 project->variables()["INCLUDEPATH"].append(dir);
99 } else if((*val_it).startsWith("-l")) {
100 QString lib("lib" + (*val_it).right((*val_it).length() - 2) + "." +
101 project->first("QMAKE_EXTENSION_SHLIB"));
102 if(project->variables()["LIBRARIES"].findIndex(lib) == -1)
103 project->variables()["LIBRARIES"].append(lib);
104 } else
105 if((*val_it) == "-framework") {
106 ++val_it;
107 if(val_it == extra_objs.end())
108 break;
109 QString frmwrk = (*val_it) + ".framework";
110 if(project->variables()["FRAMEWORKS"].findIndex(frmwrk) == -1)
111 project->variables()["FRAMEWORKS"].append(frmwrk);
112 } else if((*val_it).left(1) != "-") {
113 QString lib=(*val_it);
114 int s = lib.findRev('/');
115 if(s != -1) {
116 QString dir = lib.left(s);
117 lib = lib.right(lib.length() - s - 1);
118 fixEnvVariables(dir);
119 if(project->variables()["DEPENDPATH"].findIndex(dir) == -1 &&
120 project->variables()["INCLUDEPATH"].findIndex(dir) == -1)
121 project->variables()["INCLUDEPATH"].append(dir);
122 }
123 project->variables()["LIBRARIES"].append(lib);
124 }
125 }
126 //let metrowerks find the files & set the files to the type I expect
127 QDict<void> seen(293);
128 QString paths[] = { QString("SRCMOC"), QString("FORMS"), QString("UICDECLS"),
129 QString("UICIMPLS"), QString("SOURCES"),QString("HEADERS"),
130 QString::null };
131 for(int y = 0; paths[y] != QString::null; y++) {
132 QStringList &l = project->variables()[paths[y]];
133 for(QStringList::Iterator val_it = l.begin(); val_it != l.end(); ++val_it) {
134 //establish file types
135 seen.insert((*val_it), (void *)1);
136 createFork((*val_it)); //the file itself
137 QStringList &d = findDependencies((*val_it)); //depends
138 for(QStringList::Iterator dep_it = d.begin(); dep_it != d.end(); ++dep_it) {
139 if(!seen.find((*dep_it))) {
140 seen.insert((*dep_it), (void *)1);
141 createFork((*dep_it));
142 }
143 }
144 //now chop it
145 int s = (*val_it).findRev('/');
146 if(s != -1) {
147 QString dir = (*val_it).left(s);
148 (*val_it) = (*val_it).right((*val_it).length() - s - 1);
149 QString tmpd=dir, tmpv;
150 if(fixifyToMacPath(tmpd, tmpv)) {
151 bool add_in = TRUE;
152 QString deps[] = { QString("DEPENDPATH"),
153 QString("INCLUDEPATH"), QString::null },
154 dd, dv;
155 for(int yy = 0; deps[yy] != QString::null; yy++) {
156 QStringList &l2 = project->variables()[deps[yy]];
157 for(QStringList::Iterator val_it2 = l2.begin();
158 val_it2 != l2.end(); ++val_it2) {
159 QString dd= (*val_it2), dv;
160 if(!fixifyToMacPath(dd, dv))
161 continue;
162 if(dd == tmpd && tmpv == dv) {
163 add_in = FALSE;
164 break;
165 }
166 }
167 }
168 if(add_in)
169 project->variables()["INCLUDEPATH"].append(dir);
170 }
171 }
172 }
173 }
174 //need a defines file
175 if(!project->isEmpty("DEFINES")) {
176 QString pre_pref = project->first("TARGET_STEM");
177 if(project->first("TEMPLATE") == "lib")
178 pre_pref += project->isActiveConfig("staticlib") ? "_static" : "_shared";
179 project->variables()["CODEWARRIOR_PREFIX_HEADER"].append(pre_pref + "_prefix.h");
180 }
181
182 QString xmlfile = findTemplate(project->first("QMAKE_XML_TEMPLATE"));
183 QFile file(xmlfile);
184 if(!file.open(IO_ReadOnly )) {
185 fprintf(stderr, "Cannot open XML file: %s\n",
186 project->first("QMAKE_XML_TEMPLATE").latin1());
187 return FALSE;
188 }
189 QTextStream xml(&file);
190 createFork(Option::output.name());
191
192 int rep;
193 QString line;
194 while ( !xml.eof() ) {
195 line = xml.readLine();
196 while((rep = line.find(QRegExp("\\$\\$[!a-zA-Z0-9_-]*"))) != -1) {
197 QString torep = line.mid(rep, line.find(QRegExp("[^\\$!a-zA-Z0-9_-]"), rep) - rep);
198 QString variable = torep.right(torep.length()-2);
199
200 t << line.left(rep); //output the left side
201 line = line.right(line.length() - (rep + torep.length())); //now past the variable
202 if(variable == "CODEWARRIOR_HEADERS" || variable == "CODEWARRIOR_SOURCES" ||
203 variable == "CODEWARRIOR_LIBRARIES" || variable == "CODEWARRIOR_QPREPROCESS" ||
204 variable == "CODEWARRIOR_QPREPROCESSOUT") {
205 QString outcmd=variable.right(variable.length() - variable.findRev('_') - 1);
206 QStringList args;
207 if(outcmd == "QPREPROCESS")
208 args << "UICS" << "MOCS";
209 else if(outcmd == "QPREPROCESSOUT")
210 args << "SRCMOC" << "UICIMPLS" << "UICDELCS";
211 else
212 args << outcmd;
213 for(QStringList::Iterator arit = args.begin(); arit != args.end(); ++arit) {
214 QString arg = (*arit);
215 QString kind = "Text";
216 if(arg == "LIBRARIES")
217 kind = "Library";
218 if(!project->variables()[arg].isEmpty()) {
219 QStringList &list = project->variables()[arg];
220 for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
221 QString flag;
222 if(project->isActiveConfig("debug")) {
223 bool debug = TRUE;
224 if(outcmd == "QPREPROCESS") {
225 debug = FALSE;
226 } else {
227 for(QStringList::Iterator hit = Option::h_ext.begin(); hit != Option::h_ext.end(); ++hit) {
228 if((*it).endsWith((*hit))) {
229 debug = FALSE;
230 break;
231 }
232 }
233 }
234 if(debug)
235 flag = "Debug";
236 }
237 t << "\t\t\t\t<FILE>" << endl
238 << "\t\t\t\t\t<PATHTYPE>Name</PATHTYPE>" << endl
239 << "\t\t\t\t\t<PATH>" << (*it) << "</PATH>" << endl
240 << "\t\t\t\t\t<PATHFORMAT>MacOS</PATHFORMAT>" << endl
241 << "\t\t\t\t\t<FILEKIND>" << kind << "</FILEKIND>" << endl
242 << "\t\t\t\t\t<FILEFLAGS>" << flag << "</FILEFLAGS>" << endl
243 << "\t\t\t\t</FILE>" << endl;
244 }
245 }
246 }
247 } else if(variable == "CODEWARRIOR_SOURCES_LINKORDER" ||
248 variable == "CODEWARRIOR_HEADERS_LINKORDER" ||
249 variable == "CODEWARRIOR_LIBRARIES_LINKORDER" ||
250 variable == "CODEWARRIOR_QPREPROCESS_LINKORDER" ||
251 variable == "CODEWARRIOR_QPREPROCESSOUT_LINKORDER") {
252 QString outcmd=variable.mid(variable.find('_')+1,
253 variable.findRev('_')-(variable.find('_')+1));
254 QStringList args;
255 if(outcmd == "QPREPROCESS")
256 args << "UICS" << "MOCS";
257 else if(outcmd == "QPREPROCESSOUT")
258 args << "SRCMOC" << "UICIMPLS" << "UICDELCS";
259 else
260 args << outcmd;
261 for(QStringList::Iterator arit = args.begin(); arit != args.end(); ++arit) {
262 QString arg = (*arit);
263 if(!project->variables()[arg].isEmpty()) {
264 QStringList &list = project->variables()[arg];
265 for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
266 t << "\t\t\t\t<FILEREF>" << endl
267 << "\t\t\t\t\t<PATHTYPE>Name</PATHTYPE>" << endl
268 << "\t\t\t\t\t<PATH>" << (*it) << "</PATH>" << endl
269 << "\t\t\t\t\t<PATHFORMAT>MacOS</PATHFORMAT>" << endl
270 << "\t\t\t\t</FILEREF>" << endl;
271 }
272 }
273 }
274 } else if(variable == "CODEWARRIOR_HEADERS_GROUP" ||
275 variable == "CODEWARRIOR_SOURCES_GROUP" ||
276 variable == "CODEWARRIOR_LIBRARIES_GROUP" ||
277 variable == "CODEWARRIOR_QPREPROCESS_GROUP" ||
278 variable == "CODEWARRIOR_QPREPROCESSOUT_GROUP") {
279 QString outcmd = variable.mid(variable.find('_')+1,
280 variable.findRev('_')-(variable.find('_')+1));
281 QStringList args;
282 if(outcmd == "QPREPROCESS")
283 args << "UICS" << "MOCS";
284 else if(outcmd == "QPREPROCESSOUT")
285 args << "SRCMOC" << "UICIMPLS" << "UICDELCS";
286 else
287 args << outcmd;
288 for(QStringList::Iterator arit = args.begin(); arit != args.end(); ++arit) {
289 QString arg = (*arit);
290 if(!project->variables()[arg].isEmpty()) {
291 QStringList &list = project->variables()[arg];
292 for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
293 t << "\t\t\t\t<FILEREF>" << endl
294 << "\t\t\t\t\t<TARGETNAME>" << var("TARGET_STEM") << "</TARGETNAME>"
295 << endl
296 << "\t\t\t\t\t<PATHTYPE>Name</PATHTYPE>" << endl
297 << "\t\t\t\t\t<PATH>" << (*it) << "</PATH>" << endl
298 << "\t\t\t\t\t<PATHFORMAT>MacOS</PATHFORMAT>" << endl
299 << "\t\t\t\t</FILEREF>" << endl;
300 }
301 }
302 }
303 } else if(variable == "CODEWARRIOR_FRAMEWORKS") {
304 if(!project->isEmpty("FRAMEWORKS")) {
305 QStringList &list = project->variables()["FRAMEWORKS"];
306 for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
307 t << "\t\t\t\t<FRAMEWORK>" << endl
308 << "\t\t\t\t\t<FILEREF>" << endl
309 << "\t\t\t\t\t\t<PATHTYPE>Name</PATHTYPE>" << endl
310 << "\t\t\t\t\t\t<PATH>" << (*it) << "</PATH>" << endl
311 << "\t\t\t\t\t\t<PATHFORMAT>MacOS</PATHFORMAT>" << endl
312 << "\t\t\t\t\t</FILEREF>" << endl
313 << "\t\t\t\t</FRAMEWORK>" << endl;
314 }
315 }
316 } else if(variable == "CODEWARRIOR_DEPENDPATH" || variable == "CODEWARRIOR_INCLUDEPATH" ||
317 variable == "CODEWARRIOR_FRAMEWORKPATH") {
318 QString arg=variable.right(variable.length()-variable.find('_')-1);
319 QStringList list;
320 if(arg == "INCLUDEPATH") {
321 list = project->variables()[arg];
322 list << Option::mkfile::qmakespec;
323 list << QDir::current().currentDirPath();
324
325 QStringList &l = project->variables()["QMAKE_LIBS_PATH"];
326 for(QStringList::Iterator val_it = l.begin(); val_it != l.end(); ++val_it) {
327 QString p = (*val_it), v;
328 if(!fixifyToMacPath(p, v))
329 continue;
330
331 t << "\t\t\t\t\t<SETTING>" << endl
332 << "\t\t\t\t\t\t<SETTING><NAME>SearchPath</NAME>" << endl
333 << "\t\t\t\t\t\t\t<SETTING><NAME>Path</NAME>"
334 << "<VALUE>" << p << "</VALUE></SETTING>" << endl
335 << "\t\t\t\t\t\t\t<SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>" << endl
336 << "\t\t\t\t\t\t\t<SETTING><NAME>PathRoot</NAME><VALUE>CodeWarrior</VALUE></SETTING>" << endl
337 << "\t\t\t\t\t\t</SETTING>" << endl
338 << "\t\t\t\t\t\t<SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>" << endl
339 << "\t\t\t\t\t\t<SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>" << endl
340 << "\t\t\t\t\t</SETTING>" << endl;
341 }
342 } else if(variable == "DEPENDPATH") {
343 QStringList &l = project->variables()[arg];
344 for(QStringList::Iterator val_it = l.begin(); val_it != l.end(); ++val_it)
345 {
346 //apparently tmake used colon separation...
347 QStringList damn = QStringList::split(':', (*val_it));
348 if(!damn.isEmpty())
349 list += damn;
350 else
351 list.append((*val_it));
352 }
353 } else {
354 list = project->variables()[arg];
355 }
356 for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
357 QString p = (*it), v, recursive = "false", framework = "false";
358 if(p.startsWith("recursive--")) {
359 p = p.right(p.length() - 11);
360 recursive = "true";
361 }
362 if(!fixifyToMacPath(p, v))
363 continue;
364 if(arg == "FRAMEWORKPATH")
365 framework = "true";
366
367 t << "\t\t\t\t\t<SETTING>" << endl
368 << "\t\t\t\t\t\t<SETTING><NAME>SearchPath</NAME>" << endl
369 << "\t\t\t\t\t\t\t<SETTING><NAME>Path</NAME>"
370 << "<VALUE>" << p << "</VALUE></SETTING>" << endl
371 << "\t\t\t\t\t\t\t<SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>" << endl
372 << "\t\t\t\t\t\t\t<SETTING><NAME>PathRoot</NAME><VALUE>" << v << "</VALUE></SETTING>" << endl
373 << "\t\t\t\t\t\t</SETTING>" << endl
374 << "\t\t\t\t\t\t<SETTING><NAME>Recursive</NAME><VALUE>" << recursive << "</VALUE></SETTING>" << endl
375 << "\t\t\t\t\t\t<SETTING><NAME>FrameworkPath</NAME><VALUE>" << framework << "</VALUE></SETTING>" << endl
376 << "\t\t\t\t\t\t<SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>" << endl
377 << "\t\t\t\t\t</SETTING>" << endl;
378 }
379 } else if(variable == "CODEWARRIOR_WARNING" || variable == "!CODEWARRIOR_WARNING") {
380 bool b = ((!project->isActiveConfig("warn_off")) &&
381 project->isActiveConfig("warn_on"));
382 if(variable.startsWith("!"))
383 b = !b;
384 t << (int)b;
385 } else if(variable == "CODEWARRIOR_TEMPLATE") {
386 if(project->first("TEMPLATE") == "app" ) {
387 t << "Executable";
388 } else if(project->first("TEMPLATE") == "lib") {
389 if(project->isActiveConfig("staticlib"))
390 t << "Library";
391 else
392 t << "SharedLibrary";
393 }
394 } else if(variable == "CODEWARRIOR_OUTPUT_DIR") {
395 QString outdir = "{Project}/", volume;
396 if(!project->isEmpty("DESTDIR"))
397 outdir = project->first("DESTDIR");
398 if(project->first("TEMPLATE") == "app" && !project->isActiveConfig("console"))
399 outdir += var("TARGET") + ".app/Contents/MacOS/";
400 if(fixifyToMacPath(outdir, volume, FALSE)) {
401 t << "\t\t\t<SETTING><NAME>Path</NAME><VALUE>" << outdir << "</VALUE></SETTING>"
402 << endl
403 << "\t\t\t<SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>" << endl
404 << "\t\t\t<SETTING><NAME>PathRoot</NAME><VALUE>" << volume << "</VALUE></SETTING>"
405 << endl;
406 }
407 } else if(variable == "CODEWARRIOR_PACKAGER_PANEL") {
408 if(project->first("TEMPLATE") == "app" && !project->isActiveConfig("console")) {
409 QString outdir = "{Project}/", volume;
410 if(!project->isEmpty("DESTDIR"))
411 outdir = project->first("DESTDIR");
412 outdir += var("TARGET") + ".app";
413 if(fixifyToMacPath(outdir, volume, FALSE)) {
414 t << "\t\t<SETTING><NAME>MWMacOSPackager_UsePackager</NAME>"
415 << "<VALUE>1</VALUE></SETTING>" << "\n"
416 << "\t\t<SETTING><NAME>MWMacOSPackager_FolderToPackage</NAME>" << "\n"
417 << "\t\t\t<SETTING><NAME>Path</NAME><VALUE>" << outdir
418 << "</VALUE></SETTING>" << "\n"
419 << "\t\t\t<SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>"
420 << "\n"
421 << "\t\t\t<SETTING><NAME>PathRoot</NAME><VALUE>" << volume
422 << "</VALUE></SETTING>" << "\n"
423 << "\t\t</SETTING>" << "\n"
424 << "\t\t<SETTING><NAME>MWMacOSPackager_CreateClassicAlias</NAME>"
425 << "<VALUE>0</VALUE></SETTING>" << "\n"
426 << "\t\t<SETTING><NAME>MWMacOSPackager_ClassicAliasMethod</NAME>"
427 << "<VALUE>UseTargetOutput</VALUE></SETTING>" << "\n"
428 << "\t\t<SETTING><NAME>MWMacOSPackager_ClassicAliasPath</NAME>"
429 << "<VALUE></VALUE></SETTING>" << "\n"
430 << "\t\t<SETTING><NAME>MWMacOSPackager_CreatePkgInfo</NAME>"
431 << "<VALUE>1</VALUE></SETTING>" << "\n"
432 << "\t\t<SETTING><NAME>MWMacOSPackager_PkgCreatorType</NAME>"
433 << "<VALUE>CUTE</VALUE></SETTING>" << "\n"
434 << "\t\t<SETTING><NAME>MWMacOSPackager_PkgFileType</NAME>"
435 << "<VALUE>APPL</VALUE></SETTING>" << endl;
436 }
437 }
438 } else if(variable == "CODEWARRIOR_FILETYPE") {
439 if(project->first("TEMPLATE") == "lib")
440 t << "MYDL";
441 else
442 t << "MEXE";
443 } else if(variable == "CODEWARRIOR_QTDIR") {
444 t << getenv("QTDIR");
445 } else if(variable == "CODEWARRIOR_CACHEMODDATES") {
446 t << "true";
447 } else {
448 t << var(variable);
449 }
450 }
451 t << line << endl;
452 }
453 t << endl;
454 file.close();
455
456 if(mocAware()) {
457 QString mocs = project->first("MOCS");
458 QFile mocfile(mocs);
459 if(!mocfile.open(IO_WriteOnly)) {
460 fprintf(stderr, "Cannot open MOCS file: %s\n", mocs.latin1());
461 } else {
462 createFork(mocs);
463 QTextStream mocs(&mocfile);
464 QStringList &list = project->variables()["SRCMOC"];
465 for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
466 QString src = findMocSource((*it));
467 if(src.findRev('/') != -1)
468 src = src.right(src.length() - src.findRev('/') - 1);
469 mocs << src << endl;
470 }
471 mocfile.close();
472 }
473 }
474
475 if(!project->isEmpty("FORMS")) {
476 QString uics = project->first("UICS");
477 QFile uicfile(uics);
478 if(!uicfile.open(IO_WriteOnly)) {
479 fprintf(stderr, "Cannot open UICS file: %s\n", uics.latin1());
480 } else {
481 createFork(uics);
482 QTextStream uics(&uicfile);
483 QStringList &list = project->variables()["FORMS"];
484 for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
485 QString ui = (*it);
486 if(ui.findRev('/') != -1)
487 ui = ui.right(ui.length() - ui.findRev('/') - 1);
488 uics << ui << endl;
489 }
490 uicfile.close();
491 }
492 }
493
494 if(!project->isEmpty("CODEWARRIOR_PREFIX_HEADER")) {
495 QFile prefixfile(project->first("CODEWARRIOR_PREFIX_HEADER"));
496 if(!prefixfile.open(IO_WriteOnly)) {
497 fprintf(stderr, "Cannot open PREFIX file: %s\n", prefixfile.name().latin1());
498 } else {
499 createFork(project->first("CODEWARRIOR_PREFIX_HEADER"));
500 QTextStream prefix(&prefixfile);
501 QStringList &list = project->variables()["DEFINES"];
502 for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
503 if((*it).find('=') != -1) {
504 int x = (*it).find('=');
505 prefix << "#define " << (*it).left(x) << " " << (*it).right((*it).length() - x - 1) << endl;
506 } else {
507 prefix << "#define " << (*it) << endl;
508 }
509 }
510 prefixfile.close();
511 }
512 }
513 return TRUE;
514}
515
516
517
518void
519MetrowerksMakefileGenerator::init()
520{
521 if(init_flag)
522 return;
523 init_flag = TRUE;
524
525 if ( project->isEmpty("QMAKE_XML_TEMPLATE") )
526 project->variables()["QMAKE_XML_TEMPLATE"].append("mwerkstmpl.xml");
527
528 QStringList &configs = project->variables()["CONFIG"];
529 if(project->isActiveConfig("qt")) {
530 if(configs.findIndex("moc")) configs.append("moc");
531 if ( !( (project->first("TARGET") == "qt") || (project->first("TARGET") == "qte") ||
532 (project->first("TARGET") == "qt-mt") ) )
533 project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT"];
534 if(configs.findIndex("moc"))
535 configs.append("moc");
536 if ( !project->isActiveConfig("debug") )
537 project->variables()["DEFINES"].append("QT_NO_DEBUG");
538 }
539
540 //version handling
541 if(project->variables()["VERSION"].isEmpty())
542 project->variables()["VERSION"].append("1.0." +
543 (project->isEmpty("VER_PAT") ? QString("0") :
544 project->first("VER_PAT")) );
545 QStringList ver = QStringList::split('.', project->first("VERSION"));
546 ver << "0" << "0"; //make sure there are three
547 project->variables()["VER_MAJ"].append(ver[0]);
548 project->variables()["VER_MIN"].append(ver[1]);
549 project->variables()["VER_PAT"].append(ver[2]);
550
551 if( !project->isEmpty("LIBS") )
552 project->variables()["QMAKE_LIBS"] += project->variables()["LIBS"];
553 if( project->variables()["QMAKE_EXTENSION_SHLIB"].isEmpty() )
554 project->variables()["QMAKE_EXTENSION_SHLIB"].append( "dylib" );
555
556 if ( project->isActiveConfig("moc") ) {
557 QString mocfile = project->first("TARGET");
558 if(project->first("TEMPLATE") == "lib")
559 mocfile += project->isActiveConfig("staticlib") ? "_static" : "_shared";
560 project->variables()["MOCS"].append(mocfile + ".mocs");
561 setMocAware(TRUE);
562 }
563 if(!project->isEmpty("FORMS")) {
564 QString uicfile = project->first("TARGET");
565 if(project->first("TEMPLATE") == "lib")
566 uicfile += project->isActiveConfig("staticlib") ? "_static" : "_shared";
567 project->variables()["UICS"].append(uicfile + ".uics");
568 }
569 if(project->isEmpty("DESTDIR"))
570 project->variables()["DESTDIR"].append(QDir::currentDirPath());
571 MakefileGenerator::init();
572
573 if ( project->isActiveConfig("opengl") ) {
574 project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_OPENGL"];
575 if ( (project->first("TARGET") == "qt") || (project->first("TARGET") == "qte") ||
576 (project->first("TARGET") == "qt-mt") )
577 project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_OPENGL_QT"];
578 else
579 project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_OPENGL"];
580 }
581
582 if(project->isActiveConfig("qt"))
583 project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_QT"];
584 if(project->isEmpty("FRAMEWORKPATH"))
585 project->variables()["FRAMEWORKPATH"].append("/System/Library/Frameworks/");
586
587 //set the target up
588 project->variables()["TARGET_STEM"] = project->variables()["TARGET"];
589 if(project->first("TEMPLATE") == "lib") {
590 if(project->isActiveConfig("staticlib"))
591 project->variables()["TARGET"].first() = "lib" + project->first("TARGET") + ".lib";
592 else
593 project->variables()["TARGET"].first() = "lib" + project->first("TARGET") + "." +
594 project->first("QMAKE_EXTENSION_SHLIB");
595
596 project->variables()["CODEWARRIOR_VERSION"].append(project->first("VER_MAJ") +
597 project->first("VER_MIN") +
598 project->first("VER_PAT"));
599 } else {
600 project->variables()["CODEWARRIOR_VERSION"].append("0");
601 if(project->isEmpty("QMAKE_ENTRYPOINT"))
602 project->variables()["QMAKE_ENTRYPOINT"].append("start");
603 project->variables()["CODEWARRIOR_ENTRYPOINT"].append(
604 project->first("QMAKE_ENTRYPOINT"));
605 }
606}
607
608
609QString
610MetrowerksMakefileGenerator::findTemplate(QString file)
611{
612 QString ret;
613 if(!QFile::exists(ret = file) &&
614 !QFile::exists((ret = Option::mkfile::qmakespec + QDir::separator() + file)) &&
615 !QFile::exists((ret = QString(getenv("QTDIR")) + "/mkspecs/mac-mwerks/" + file)) &&
616 !QFile::exists((ret = (QString(getenv("HOME")) + "/.tmake/" + file))))
617 return "";
618 return ret;
619}
620
621bool
622MetrowerksMakefileGenerator::createFork(const QString &f)
623{
624#if defined(Q_OS_MACX)
625 FSRef fref;
626 FSSpec fileSpec;
627 if(QFile::exists(f)) {
628 mode_t perms = 0;
629 {
630 struct stat s;
631 stat(f.latin1(), &s);
632 if(!(s.st_mode & S_IWUSR)) {
633 perms = s.st_mode;
634 chmod(f.latin1(), perms | S_IWUSR);
635 }
636 }
637 FILE *o = fopen(f.latin1(), "a");
638 if(!o)
639 return FALSE;
640 if(FSPathMakeRef((const UInt8 *)f.latin1(), &fref, NULL) == noErr) {
641 if(FSGetCatalogInfo(&fref, kFSCatInfoNone, NULL, NULL, &fileSpec, NULL) == noErr)
642 FSpCreateResFile(&fileSpec, 'CUTE', 'TEXT', smSystemScript);
643 else
644 qDebug("bogus %d", __LINE__);
645 } else
646 qDebug("bogus %d", __LINE__);
647 fclose(o);
648 if(perms)
649 chmod(f.latin1(), perms);
650 }
651#else
652 Q_UNUSED(f)
653#endif
654 return TRUE;
655}
656
657bool
658MetrowerksMakefileGenerator::fixifyToMacPath(QString &p, QString &v, bool )
659{
660 v = "Absolute";
661 if(p.find(':') != -1) //guess its macish already
662 return TRUE;
663
664 static QString st_volume;
665 if(st_volume.isEmpty()) {
666 st_volume = var("QMAKE_VOLUMENAME");
667#ifdef Q_OS_MAC
668 if(st_volume.isEmpty()) {
669 uchar foo[512];
670 HVolumeParam pb;
671 memset(&pb, '\0', sizeof(pb));
672 pb.ioVRefNum = 0;
673 pb.ioNamePtr = foo;
674 if(PBHGetVInfoSync((HParmBlkPtr)&pb) == noErr) {
675 int len = foo[0];
676 memcpy(foo,foo+1, len);
677 foo[len] = '\0';
678 st_volume = (char *)foo;
679 }
680 }
681#endif
682 }
683 QString volume = st_volume;
684
685 fixEnvVariables(p);
686 if(p.startsWith("\"") && p.endsWith("\""))
687 p = p.mid(1, p.length() - 2);
688 if(p.isEmpty())
689 return FALSE;
690 if(!p.endsWith("/"))
691 p += "/";
692 if(QDir::isRelativePath(p)) {
693 if(p.startsWith("{")) {
694 int eoc = p.find('}');
695 if(eoc == -1)
696 return FALSE;
697 volume = p.mid(1, eoc - 1);
698 p = p.right(p.length() - eoc - 1);
699 } else {
700 QFileInfo fi(p);
701 if(fi.convertToAbs()) //strange
702 return FALSE;
703 p = fi.filePath();
704 }
705 }
706 p = QDir::cleanDirPath(p);
707 if(!volume.isEmpty())
708 v = volume;
709 p.replace("/", ":");
710 if(p.right(1) != ":")
711 p += ':';
712 return TRUE;
713}
714
715void
716MetrowerksMakefileGenerator::processPrlFiles()
717{
718 QPtrList<MakefileDependDir> libdirs;
719 libdirs.setAutoDelete(TRUE);
720 const QString lflags[] = { "QMAKE_LIBS", QString::null };
721 for(int i = 0; !lflags[i].isNull(); i++) {
722 for(bool ret = FALSE; TRUE; ret = FALSE) {
723 QStringList l_out;
724 QStringList &l = project->variables()[lflags[i]];
725 for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
726 QString opt = (*it);
727 if(opt.startsWith("-")) {
728 if(opt.startsWith("-L")) {
729 QString r = opt.right(opt.length() - 2), l = r;
730 fixEnvVariables(l);
731 libdirs.append(new MakefileDependDir(r.replace( "\"", ""),
732 l.replace( "\"", "")));
733 } else if(opt.left(2) == "-l") {
734 QString lib = opt.right(opt.length() - 2), prl;
735 for(MakefileDependDir *mdd = libdirs.first(); mdd; mdd = libdirs.next() ) {
736 prl = mdd->local_dir + Option::dir_sep + "lib" + lib + Option::prl_ext;
737 if(processPrlFile(prl)) {
738 if(prl.startsWith(mdd->local_dir))
739 prl.replace(0, mdd->local_dir.length(), mdd->real_dir);
740 QRegExp reg("^.*lib(" + lib + "[^.]*)\\." +
741 project->first("QMAKE_EXTENSION_SHLIB") + "$");
742 if(reg.exactMatch(prl))
743 prl = "-l" + reg.cap(1);
744 opt = prl;
745 ret = TRUE;
746 break;
747 }
748 }
749 } else if(opt == "-framework") {
750 l_out.append(opt);
751 ++it;
752 opt = (*it);
753 QString prl = "/System/Library/Frameworks/" + opt +
754 ".framework/" + opt + Option::prl_ext;
755 if(processPrlFile(prl))
756 ret = TRUE;
757 }
758 if(!opt.isEmpty())
759 l_out.append(opt);
760 } else {
761 if(processPrlFile(opt))
762 ret = TRUE;
763 if(!opt.isEmpty())
764 l_out.append(opt);
765 }
766 }
767 if(ret)
768 l = l_out;
769 else
770 break;
771 }
772 }
773}
774
775void
776MetrowerksMakefileGenerator::processPrlVariable(const QString &var, const QStringList &l)
777{
778 if(var == "QMAKE_PRL_LIBS") {
779 QStringList &out = project->variables()["QMAKE_LIBS"];
780 for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) {
781 bool append = TRUE;
782 if((*it).startsWith("-")) {
783 if((*it).startsWith("-l") || (*it).startsWith("-L")) {
784 append = out.findIndex((*it)) == -1;
785 } else if((*it).startsWith("-framework")) {
786 ++it;
787 for(QStringList::ConstIterator outit = out.begin();
788 outit != out.end(); ++it) {
789 if((*outit) == "-framework") {
790 ++outit;
791 if((*outit) == (*it)) {
792 append = FALSE;
793 break;
794 }
795 }
796 }
797 }
798 } else if(QFile::exists((*it))) {
799 append = out.findIndex((*it));
800 }
801 if(append)
802 out.append((*it));
803 }
804 } else {
805 MakefileGenerator::processPrlVariable(var, l);
806 }
807}
808
809
810bool
811MetrowerksMakefileGenerator::openOutput(QFile &file) const
812{
813 QString outdir;
814 if(!file.name().isEmpty()) {
815 QFileInfo fi(file);
816 if(fi.isDir())
817 outdir = file.name() + QDir::separator();
818 }
819 if(!outdir.isEmpty() || file.name().isEmpty())
820 file.setName(outdir + project->first("TARGET") + ".xml");
821 return MakefileGenerator::openOutput(file);
822}
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 @@
1/****************************************************************************
2** $Id$
3**
4** Definition of ________ class.
5**
6** Created : 970521
7**
8** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
9**
10** This file is part of the network module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition licenses may use this
22** file in accordance with the Qt Commercial License Agreement provided
23** with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37#ifndef __METROWERKSMAKE_H__
38#define __METROWERKSMAKE_H__
39
40#include "makefile.h"
41
42class MetrowerksMakefileGenerator : public MakefileGenerator
43{
44 bool createFork(const QString &f);
45 bool fixifyToMacPath(QString &c, QString &v, bool exists=TRUE);
46
47 bool init_flag;
48
49 bool writeMakeParts(QTextStream &);
50 bool writeSubDirs(QTextStream &);
51
52 bool writeMakefile(QTextStream &);
53 QString findTemplate(QString file);
54 void init();
55public:
56 MetrowerksMakefileGenerator(QMakeProject *p);
57 ~MetrowerksMakefileGenerator();
58
59 bool openOutput(QFile &file) const;
60protected:
61 virtual void processPrlFiles();
62 virtual void processPrlVariable(const QString &var, const QStringList &l);
63 virtual bool doDepends() const { return FALSE; } //never necesary
64};
65
66inline MetrowerksMakefileGenerator::~MetrowerksMakefileGenerator()
67{ }
68
69#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 @@
1/****************************************************************************
2** $Id$
3**
4** Definition of ________ class.
5**
6** Created : 970521
7**
8** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
9**
10** This file is part of the network module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition licenses may use this
22** file in accordance with the Qt Commercial License Agreement provided
23** with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#include "pbuilder_pbx.h"
39#include "option.h"
40#include <qdir.h>
41#include <qdict.h>
42#include <qregexp.h>
43#include <stdlib.h>
44#include <time.h>
45#ifdef Q_OS_UNIX
46# include <sys/types.h>
47# include <sys/stat.h>
48#endif
49
50// Note: this is fairly hacky, but it does the job...
51
52
53ProjectBuilderMakefileGenerator::ProjectBuilderMakefileGenerator(QMakeProject *p) : UnixMakefileGenerator(p)
54{
55
56}
57
58bool
59ProjectBuilderMakefileGenerator::writeMakefile(QTextStream &t)
60{
61 if(!project->variables()["QMAKE_FAILED_REQUIREMENTS"].isEmpty()) {
62 /* for now just dump, I need to generated an empty xml or something.. */
63 fprintf(stderr, "Project file not generated because all requirements not met:\n\t%s\n",
64 var("QMAKE_FAILED_REQUIREMENTS").latin1());
65 return TRUE;
66 }
67
68 project->variables()["MAKEFILE"].clear();
69 project->variables()["MAKEFILE"].append("Makefile");
70 if(project->first("TEMPLATE") == "app" || project->first("TEMPLATE") == "lib") {
71 return writeMakeParts(t);
72 } else if(project->first("TEMPLATE") == "subdirs") {
73 writeSubdirs(t, FALSE);
74 return TRUE;
75 }
76 return FALSE;
77}
78
79bool
80ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
81{
82 int i;
83 QStringList tmp;
84 bool did_preprocess = FALSE;
85
86 //HEADER
87 t << "// !$*UTF8*$!" << "\n"
88 << "{" << "\n"
89 << "\t" << "archiveVersion = 1;" << "\n"
90 << "\t" << "classes = {" << "\n" << "\t" << "};" << "\n"
91 << "\t" << "objectVersion = " << pbuilderVersion() << ";" << "\n"
92 << "\t" << "objects = {" << endl;
93
94 //MAKE QMAKE equivlant
95 if(!project->isActiveConfig("no_autoqmake") && project->projectFile() != "(stdin)") {
96 QString mkfile = pbx_dir + Option::dir_sep + "qt_makeqmake.mak";
97 QFile mkf(mkfile);
98 if(mkf.open(IO_WriteOnly | IO_Translate)) {
99 debug_msg(1, "pbuilder: Creating file: %s", mkfile.latin1());
100 QTextStream mkt(&mkf);
101 writeHeader(mkt);
102 mkt << "QMAKE = "<<
103 (project->isEmpty("QMAKE_QMAKE") ? QString("$(QTDIR)/bin/qmake") :
104 var("QMAKE_QMAKE")) << endl;
105 writeMakeQmake(mkt);
106 mkf.close();
107 }
108 QString phase_key = keyFor("QMAKE_PBX_MAKEQMAKE_BUILDPHASE");
109 mkfile = fileFixify(mkfile, QDir::currentDirPath());
110 project->variables()["QMAKE_PBX_BUILDPHASES"].append(phase_key);
111 t << "\t\t" << phase_key << " = {" << "\n"
112 << "\t\t\t" << "buildActionMask = 2147483647;" << "\n"
113 << "\t\t\t" << "files = (" << "\n"
114 << "\t\t\t" << ");" << "\n"
115 << "\t\t\t" << "generatedFileNames = (" << "\n"
116 << "\t\t\t" << ");" << "\n"
117 << "\t\t\t" << "isa = PBXShellScriptBuildPhase;" << "\n"
118 << "\t\t\t" << "name = \"Qt Qmake\";" << "\n"
119 << "\t\t\t" << "neededFileNames = (" << "\n"
120 << "\t\t\t" << ");" << "\n"
121 << "\t\t\t" << "shellPath = /bin/sh;" << "\n"
122 << "\t\t\t" << "shellScript = \"make -C " << QDir::currentDirPath() <<
123 " -f " << mkfile << "\";" << "\n"
124 << "\t\t" << "};" << "\n";
125 }
126
127 //DUMP SOURCES
128 QMap<QString, QStringList> groups;
129 QString srcs[] = { "SOURCES", "SRCMOC", "UICIMPLS", QString::null };
130 for(i = 0; !srcs[i].isNull(); i++) {
131 tmp = project->variables()[srcs[i]];
132 QStringList &src_list = project->variables()["QMAKE_PBX_" + srcs[i]];
133 for(QStringList::Iterator it = tmp.begin(); it != tmp.end(); ++it) {
134 QString file = fileFixify((*it));
135 if(file.endsWith(Option::moc_ext))
136 continue;
137 bool in_root = TRUE;
138 QString src_key = keyFor(file);
139 if(!project->isActiveConfig("flat")) {
140 QString flat_file = fileFixify(file, QDir::currentDirPath(), Option::output_dir, TRUE);
141 if(QDir::isRelativePath(flat_file) && flat_file.find(Option::dir_sep) != -1) {
142 QString last_grp("QMAKE_PBX_" + srcs[i] + "_HEIR_GROUP");
143 QStringList dirs = QStringList::split(Option::dir_sep, flat_file);
144 dirs.pop_back(); //remove the file portion as it will be added via src_key
145 for(QStringList::Iterator dir_it = dirs.begin(); dir_it != dirs.end(); ++dir_it) {
146 QString new_grp(last_grp + Option::dir_sep + (*dir_it)),
147 new_grp_key(keyFor(new_grp)), last_grp_key(keyFor(last_grp));
148 if(dir_it == dirs.begin()) {
149 if(!groups.contains(new_grp))
150 project->variables()["QMAKE_PBX_" + srcs[i]].append(new_grp_key);
151 } else {
152 groups[last_grp] += new_grp_key;
153 }
154 last_grp = new_grp;
155 }
156 groups[last_grp] += src_key;
157 in_root = FALSE;
158 }
159 }
160 if(in_root)
161 src_list.append(src_key);
162 //source reference
163 t << "\t\t" << src_key << " = {" << "\n"
164 << "\t\t\t" << "isa = PBXFileReference;" << "\n"
165 << "\t\t\t" << "path = \"" << file << "\";" << "\n"
166 << "\t\t\t" << "refType = " << reftypeForFile(file) << ";" << "\n"
167 << "\t\t" << "};" << "\n";
168 //build reference
169 QString obj_key = file + ".o";
170 obj_key = keyFor(obj_key);
171 t << "\t\t" << obj_key << " = {" << "\n"
172 << "\t\t\t" << "fileRef = " << src_key << ";" << "\n"
173 << "\t\t\t" << "isa = PBXBuildFile;" << "\n"
174 << "\t\t\t" << "settings = {" << "\n"
175 << "\t\t\t\t" << "ATTRIBUTES = (" << "\n"
176 << "\t\t\t\t" << ");" << "\n"
177 << "\t\t\t" << "};" << "\n"
178 << "\t\t" << "};" << "\n";
179 project->variables()["QMAKE_PBX_OBJ"].append(obj_key);
180 }
181 if(!src_list.isEmpty()) {
182 QString grp;
183 if(srcs[i] == "SOURCES") {
184 if(project->first("TEMPLATE") == "app" && !project->isEmpty("RC_FILE")) { //Icon
185 QString icns_file = keyFor("ICNS_FILE");
186 src_list.append(icns_file);
187 t << "\t\t" << icns_file << " = {" << "\n"
188 << "\t\t\t" << "isa = PBXFileReference;" << "\n"
189 << "\t\t\t" << "path = \"" << project->first("RC_FILE") << "\";" << "\n"
190 << "\t\t\t" << "refType = " << reftypeForFile(project->first("RC_FILE")) << ";" << "\n"
191 << "\t\t" << "};" << "\n";
192 t << "\t\t" << keyFor("ICNS_FILE_REFERENCE") << " = {" << "\n"
193 << "\t\t\t" << "fileRef = " << icns_file << ";" << "\n"
194 << "\t\t\t" << "isa = PBXBuildFile;" << "\n"
195 << "\t\t\t" << "settings = {" << "\n"
196 << "\t\t\t" << "};" << "\n"
197 << "\t\t" << "};" << "\n";
198 }
199 grp = "Sources";
200 } else if(srcs[i] == "SRCMOC") {
201 grp = "Mocables";
202 } else if(srcs[i] == "UICIMPLS") {
203 grp = "UICables";
204 }
205 QString grp_key = keyFor(grp);
206 project->variables()["QMAKE_PBX_GROUPS"].append(grp_key);
207 t << "\t\t" << grp_key << " = {" << "\n"
208 << "\t\t\t" << "children = (" << "\n"
209 << varGlue("QMAKE_PBX_" + srcs[i], "\t\t\t\t", ",\n\t\t\t\t", "\n")
210 << "\t\t\t" << ");" << "\n"
211 << "\t\t\t" << "isa = PBXGroup;" << "\n"
212 << "\t\t\t" << "name = " << grp << ";" << "\n"
213 << "\t\t\t" << "refType = 4;" << "\n"
214 << "\t\t" << "};" << "\n";
215 }
216 }
217 for(QMap<QString, QStringList>::Iterator grp_it = groups.begin();
218 grp_it != groups.end(); ++grp_it) {
219 t << "\t\t" << keyFor(grp_it.key()) << " = {" << "\n"
220 << "\t\t\t" << "isa = PBXGroup;" << "\n"
221 << "\t\t\t" << "children = (" << "\n"
222 << valGlue(grp_it.data(), "\t\t\t\t", ",\n\t\t\t\t", "\n")
223 << "\t\t\t" << ");" << "\n"
224 << "\t\t\t" << "name = \"" << grp_it.key().section(Option::dir_sep, -1) << "\";" << "\n"
225 << "\t\t\t" << "refType = 4;" << "\n"
226 << "\t\t" << "};" << "\n";
227 }
228
229 //PREPROCESS BUILDPHASE (just a makefile)
230 if(!project->isEmpty("UICIMPLS") || !project->isEmpty("SRCMOC") ||
231 !project->isEmpty("YACCSOURCES") || !project->isEmpty("LEXSOURCES")) {
232 QString mkfile = pbx_dir + Option::dir_sep + "qt_preprocess.mak";
233 QFile mkf(mkfile);
234 if(mkf.open(IO_WriteOnly | IO_Translate)) {
235 did_preprocess = TRUE;
236 debug_msg(1, "pbuilder: Creating file: %s", mkfile.latin1());
237 QTextStream mkt(&mkf);
238 writeHeader(mkt);
239 mkt << "MOC = " << var("QMAKE_MOC") << endl;
240 mkt << "UIC = " << var("QMAKE_UIC") << endl;
241 mkt << "LEX = " << var("QMAKE_LEX") << endl;
242 mkt << "LEXFLAGS = " << var("QMAKE_LEXFLAGS") << endl;
243 mkt << "YACC = " << var("QMAKE_YACC") << endl;
244 mkt << "YACCFLAGS = " << var("QMAKE_YACCFLAGS") << endl;
245 mkt << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl;
246 mkt << "MOVE = " << var("QMAKE_MOVE") << endl << endl;
247 mkt << "FORMS = " << varList("UICIMPLS") << endl;
248 mkt << "MOCS = " << varList("SRCMOC") << endl;
249 mkt << "PARSERS =";
250 if(!project->isEmpty("YACCSOURCES")) {
251 QStringList &yaccs = project->variables()["YACCSOURCES"];
252 for(QStringList::Iterator yit = yaccs.begin(); yit != yaccs.end(); ++yit) {
253 QFileInfo fi((*yit));
254 mkt << " " << fi.dirPath() << Option::dir_sep << fi.baseName(TRUE)
255 << Option::yacc_mod << Option::cpp_ext.first();
256 }
257 }
258 if(!project->isEmpty("LEXSOURCES")) {
259 QStringList &lexs = project->variables()["LEXSOURCES"];
260 for(QStringList::Iterator lit = lexs.begin(); lit != lexs.end(); ++lit) {
261 QFileInfo fi((*lit));
262 mkt << " " << fi.dirPath() << Option::dir_sep << fi.baseName(TRUE)
263 << Option::lex_mod << Option::cpp_ext.first();
264 }
265 }
266 mkt << "\n";
267 mkt << "preprocess: $(FORMS) $(MOCS) $(PARSERS)" << endl;
268 mkt << "preprocess_clean: mocclean uiclean parser_clean" << endl << endl;
269 mkt << "mocclean:" << "\n";
270 if(!project->isEmpty("SRCMOC"))
271 mkt << "\t-rm -f $(MOCS)" << "\n";
272 mkt << "uiclean:" << "\n";
273 if(!project->isEmpty("UICIMPLS"))
274 mkt << "\t-rm -f $(FORMS)" << "\n";
275 mkt << "parser_clean:" << "\n";
276 if(!project->isEmpty("YACCSOURCES") || !project->isEmpty("LEXSOURCES"))
277 mkt << "\t-rm -f $(PARSERS)" << "\n";
278 writeUicSrc(mkt, "FORMS");
279 writeMocSrc(mkt, "HEADERS");
280 writeMocSrc(mkt, "SOURCES");
281 writeMocSrc(mkt, "UICDECLS");
282 writeYaccSrc(mkt, "YACCSOURCES");
283 writeLexSrc(mkt, "LEXSOURCES");
284 mkf.close();
285 }
286 QString target_key = keyFor("QMAKE_PBX_PREPROCESS_TARGET");
287 mkfile = fileFixify(mkfile, QDir::currentDirPath());
288 t << "\t\t" << target_key << " = {" << "\n"
289 << "\t\t\t" << "buildArgumentsString = \"-f " << mkfile << "\";" << "\n"
290 << "\t\t\t" << "buildPhases = (" << "\n"
291 << "\t\t\t" << ");" << "\n"
292 << "\t\t\t" << "buildSettings = {" << "\n"
293 << "\t\t\t" << "};" << "\n"
294 << "\t\t\t" << "buildToolPath = \"/usr/bin/gnumake\";"<< "\n"
295 << "\t\t\t" << "buildWorkingDirectory = \"" << QDir::currentDirPath() << "\";" << "\n"
296 << "\t\t\t" << "dependencies = (" << "\n"
297 << "\t\t\t" << ");" << "\n"
298 << "\t\t\t" << "isa = PBXLegacyTarget;" << "\n"
299 << "\t\t\t" << "name = QtPreprocessors;" << "\n"
300 << "\t\t\t" << "productName = QtPreprocessors;" << "\n"
301 << "\t\t\t" << "settingsToExpand = 6;" << "\n"
302 << "\t\t\t" << "settingsToPassInEnvironment = 287;" << "\n"
303 << "\t\t\t" << "settingsToPassOnCommandLine = 280;" << "\n"
304 << "\t\t\t" << "shouldsUseHeadermap = 0;" << "\n"
305 << "\t\t" << "};" << "\n";
306
307 QString target_depend_key = keyFor("QMAKE_PBX_PREPROCESS_TARGET_DEPEND");
308 project->variables()["QMAKE_PBX_TARGETDEPENDS"].append(target_depend_key);
309 t << "\t\t" << target_depend_key << " = {" << "\n"
310 << "\t\t\t" << "isa = PBXTargetDependency;" << "\n"
311 << "\t\t\t" << "target = " << target_key << ";" << "\n"
312 << "\t\t" << "};" << "\n";
313 }
314 //SOURCE BUILDPHASE
315 if(!project->isEmpty("QMAKE_PBX_OBJ")) {
316 QString grp = "Build Sources", key = keyFor(grp);
317 project->variables()["QMAKE_PBX_BUILDPHASES"].append(key);
318 t << "\t\t" << key << " = {" << "\n"
319 << "\t\t\t" << "buildActionMask = 2147483647;" << "\n"
320 << "\t\t\t" << "files = (" << "\n"
321 << varGlue("QMAKE_PBX_OBJ", "\t\t\t\t", ",\n\t\t\t\t", "\n")
322 << "\t\t\t" << ");" << "\n"
323 << "\t\t\t" << "isa = PBXSourcesBuildPhase;" << "\n"
324 << "\t\t\t" << "name = \"" << grp << "\";" << "\n"
325 << "\t\t" << "};" << "\n";
326 }
327
328 if(!project->isActiveConfig("staticlib")) { //DUMP LIBRARIES
329 QStringList &libdirs = project->variables()["QMAKE_PBX_LIBPATHS"];
330 QString libs[] = { "QMAKE_LIBDIR_FLAGS", "QMAKE_LIBS", QString::null };
331 for(i = 0; !libs[i].isNull(); i++) {
332 tmp = project->variables()[libs[i]];
333 for(QStringList::Iterator it = tmp.begin(); it != tmp.end();) {
334 bool remove = FALSE;
335 QString library, name, opt = (*it).stripWhiteSpace();
336 if(opt.startsWith("-L")) {
337 QString r = opt.right(opt.length() - 2);
338 fixEnvVariables(r);
339 libdirs.append(r);
340 } else if(opt.startsWith("-l")) {
341 name = opt.right(opt.length() - 2);
342 QString lib("lib" + name);
343 for(QStringList::Iterator lit = libdirs.begin(); lit != libdirs.end(); ++lit) {
344 if(project->isActiveConfig("link_prl")) {
345 /* This isn't real nice, but it is real usefull. This looks in a prl
346 for what the library will ultimately be called so we can stick it
347 in the ProjectFile. If the prl format ever changes (not likely) then
348 this will not really work. However, more concerning is that it will
349 encode the version number in the Project file which might be a bad
350 things in days to come? --Sam
351 */
352 QString prl_file = (*lit) + Option::dir_sep + lib + Option::prl_ext;
353 if(QFile::exists(prl_file)) {
354 QMakeProject proj;
355 if(proj.read(prl_file, QDir::currentDirPath())) {
356 if(!proj.isEmpty("QMAKE_PRL_TARGET")) {
357 library = (*lit) + Option::dir_sep + proj.first("QMAKE_PRL_TARGET");
358 debug_msg(1, "pbuilder: Found library (%s) via PRL %s (%s)",
359 opt.latin1(), prl_file.latin1(), library.latin1());
360 remove = TRUE;
361 }
362 }
363
364 }
365 }
366 if(!remove) {
367 QString extns[] = { ".dylib", ".so", ".a", QString::null };
368 for(int n = 0; !remove && !extns[n].isNull(); n++) {
369 QString tmp = (*lit) + Option::dir_sep + lib + extns[n];
370 if(QFile::exists(tmp)) {
371 library = tmp;
372 debug_msg(1, "pbuilder: Found library (%s) via %s",
373 opt.latin1(), library.latin1());
374 remove = TRUE;
375 }
376 }
377 }
378 }
379 } else if(opt == "-framework") {
380 ++it;
381 if(it == tmp.end())
382 break;
383 QStringList &fdirs = project->variables()["QMAKE_FRAMEWORKDIR"];
384 if(fdirs.isEmpty())
385 fdirs.append("/System/Library/Frameworks/");
386 for(QStringList::Iterator fit = fdirs.begin(); fit != fdirs.end(); ++fit) {
387 if(QFile::exists((*fit) + QDir::separator() + (*it) + ".framework")) {
388 --it;
389 it = tmp.remove(it);
390 remove = TRUE;
391 library = (*fit) + Option::dir_sep + (*it) + ".framework";
392 break;
393 }
394 }
395 } else if(opt.left(1) != "-") {
396 remove = TRUE;
397 library = opt;
398 }
399 if(!library.isEmpty()) {
400 if(name.isEmpty()) {
401 int slsh = library.findRev(Option::dir_sep);
402 if(slsh != -1)
403 name = library.right(library.length() - slsh - 1);
404 }
405 library = fileFixify(library);
406 QString key = keyFor(library);
407 bool is_frmwrk = (library.endsWith(".framework"));
408 t << "\t\t" << key << " = {" << "\n"
409 << "\t\t\t" << "isa = " << (is_frmwrk ? "PBXFrameworkReference" : "PBXFileReference") << ";" << "\n"
410 << "\t\t\t" << "name = \"" << name << "\";" << "\n"
411 << "\t\t\t" << "path = \"" << library << "\";" << "\n"
412 << "\t\t\t" << "refType = " << reftypeForFile(library) << ";" << "\n"
413 << "\t\t" << "};" << "\n";
414 project->variables()["QMAKE_PBX_LIBRARIES"].append(key);
415 QString obj_key = library + ".o";
416 obj_key = keyFor(obj_key);
417 t << "\t\t" << obj_key << " = {" << "\n"
418 << "\t\t\t" << "fileRef = " << key << ";" << "\n"
419 << "\t\t\t" << "isa = PBXBuildFile;" << "\n"
420 << "\t\t\t" << "settings = {" << "\n"
421 << "\t\t\t" << "};" << "\n"
422 << "\t\t" << "};" << "\n";
423 project->variables()["QMAKE_PBX_BUILD_LIBRARIES"].append(obj_key);
424 }
425 if(remove)
426 it = tmp.remove(it);
427 else
428 ++it;
429 }
430 project->variables()[libs[i]] = tmp;
431 }
432 }
433 //SUBLIBS BUILDPHASE (just another makefile)
434 if(!project->isEmpty("SUBLIBS")) {
435 QString mkfile = pbx_dir + Option::dir_sep + "qt_sublibs.mak";
436 QFile mkf(mkfile);
437 if(mkf.open(IO_WriteOnly | IO_Translate)) {
438 debug_msg(1, "pbuilder: Creating file: %s", mkfile.latin1());
439 QTextStream mkt(&mkf);
440 writeHeader(mkt);
441 mkt << "SUBLIBS= ";
442 tmp = project->variables()["SUBLIBS"];
443 QStringList::Iterator it;
444 for(it = tmp.begin(); it != tmp.end(); ++it)
445 t << "tmp/lib" << (*it) << ".a ";
446 t << endl << endl;
447 mkt << "sublibs: $(SUBLIBS)" << endl << endl;
448 tmp = project->variables()["SUBLIBS"];
449 for(it = tmp.begin(); it != tmp.end(); ++it)
450 t << "tmp/lib" << (*it) << ".a" << ":\n\t"
451 << var(QString("MAKELIB") + (*it)) << endl << endl;
452 mkf.close();
453 }
454 QString phase_key = keyFor("QMAKE_PBX_SUBLIBS_BUILDPHASE");
455 mkfile = fileFixify(mkfile, QDir::currentDirPath());
456 project->variables()["QMAKE_PBX_BUILDPHASES"].append(phase_key);
457 t << "\t\t" << phase_key << " = {" << "\n"
458 << "\t\t\t" << "buildActionMask = 2147483647;" << "\n"
459 << "\t\t\t" << "files = (" << "\n"
460 << "\t\t\t" << ");" << "\n"
461 << "\t\t\t" << "generatedFileNames = (" << "\n"
462 << "\t\t\t" << ");" << "\n"
463 << "\t\t\t" << "isa = PBXShellScriptBuildPhase;" << "\n"
464 << "\t\t\t" << "name = \"Qt Sublibs\";" << "\n"
465 << "\t\t\t" << "neededFileNames = (" << "\n"
466 << "\t\t\t" << ");" << "\n"
467 << "\t\t\t" << "shellPath = /bin/sh;" << "\n"
468 << "\t\t\t" << "shellScript = \"make -C " << QDir::currentDirPath() <<
469 " -f " << mkfile << "\";" << "\n"
470 << "\t\t" << "};" << "\n";
471 }
472 //LIBRARY BUILDPHASE
473 if(!project->isEmpty("QMAKE_PBX_LIBRARIES")) {
474 tmp = project->variables()["QMAKE_PBX_LIBRARIES"];
475 if(!tmp.isEmpty()) {
476 QString grp("External Frameworks and Libraries"), key = keyFor(grp);
477 project->variables()["QMAKE_PBX_GROUPS"].append(key);
478 t << "\t\t" << key << " = {" << "\n"
479 << "\t\t\t" << "children = (" << "\n"
480 << varGlue("QMAKE_PBX_LIBRARIES", "\t\t\t\t", ",\n\t\t\t\t", "\n")
481 << "\t\t\t" << ");" << "\n"
482 << "\t\t\t" << "isa = PBXGroup;" << "\n"
483 << "\t\t\t" << "name = \"" << grp << "\"" << ";" << "\n"
484 << "\t\t\t" << "path = \"\";" << "\n"
485 << "\t\t\t" << "refType = 4;" << "\n"
486 << "\t\t" << "};" << "\n";
487 }
488 }
489 {
490 QString grp("Frameworks & Libraries"), key = keyFor(grp);
491 project->variables()["QMAKE_PBX_BUILDPHASES"].append(key);
492 t << "\t\t" << key << " = {" << "\n"
493 << "\t\t\t" << "buildActionMask = 2147483647;" << "\n"
494 << "\t\t\t" << "files = (" << "\n"
495 << varGlue("QMAKE_PBX_BUILD_LIBRARIES", "\t\t\t\t", ",\n\t\t\t\t", "\n")
496 << "\t\t\t" << ");" << "\n"
497 << "\t\t\t" << "isa = PBXFrameworksBuildPhase;" << "\n"
498 << "\t\t\t" << "name = \"" << grp << "\";" << "\n"
499 << "\t\t" << "};" << "\n";
500 }
501 if(project->isActiveConfig("resource_fork") && !project->isActiveConfig("console") &&
502 project->first("TEMPLATE") == "app") { //BUNDLE RESOURCES
503 QString grp("Bundle Resources"), key = keyFor(grp);
504 project->variables()["QMAKE_PBX_BUILDPHASES"].append(key);
505 t << "\t\t" << key << " = {" << "\n"
506 << "\t\t\t" << "buildActionMask = 2147483647;" << "\n"
507 << "\t\t\t" << "files = (" << "\n"
508 << (!project->isEmpty("RC_FILE") ? keyFor("ICNS_FILE_REFERENCE") : QString(""))
509 << "\t\t\t" << ");" << "\n"
510 << "\t\t\t" << "isa = PBXResourcesBuildPhase;" << "\n"
511 << "\t\t\t" << "name = \"" << grp << "\";" << "\n"
512 << "\t\t" << "};" << "\n";
513 }
514
515 //DUMP EVERYTHING THAT TIES THE ABOVE TOGETHER
516 //PRODUCTS
517 {
518 QString grp("Products"), key = keyFor(grp);
519 project->variables()["QMAKE_PBX_GROUPS"].append(key);
520 t << "\t\t" << key << " = {" << "\n"
521 << "\t\t\t" << "children = (" << "\n"
522 << "\t\t\t\t" << keyFor("QMAKE_PBX_REFERENCE") << "\n"
523 << "\t\t\t" << ");" << "\n"
524 << "\t\t\t" << "isa = PBXGroup;" << "\n"
525 << "\t\t\t" << "name = Products;" << "\n"
526 << "\t\t\t" << "refType = 4;" << "\n"
527 << "\t\t" << "};" << "\n";
528 }
529 { //INSTALL BUILDPHASE (sh script)
530 QString targ = project->first("TARGET");
531 if(project->first("TEMPLATE") == "app" ||
532 (project->first("TEMPLATE") == "lib" && !project->isActiveConfig("staticlib") &&
533 project->isActiveConfig("frameworklib")))
534 targ = project->first("QMAKE_ORIG_TARGET");
535 int slsh = targ.findRev(Option::dir_sep);
536 if(slsh != -1)
537 targ = targ.right(targ.length() - slsh - 1);
538 fixEnvVariables(targ);
539 QStringList links;
540 if(project->first("TEMPLATE") == "app") {
541 if(project->isActiveConfig("resource_fork") && !project->isActiveConfig("console"))
542 targ += ".app";
543 } else if(!project->isActiveConfig("staticlib") &&
544 !project->isActiveConfig("frameworklib")) {
545 QString li[] = { "TARGET_", "TARGET_x", "TARGET_x.y", QString::null };
546 for(int n = 0; !li[n].isNull(); n++) {
547 QString t = project->first(li[n]);
548 slsh = t.findRev(Option::dir_sep);
549 if(slsh != -1)
550 t = t.right(t.length() - slsh);
551 fixEnvVariables(t);
552 links << t;
553 }
554 }
555 QString script = pbx_dir + Option::dir_sep + "qt_install.sh";
556 QFile shf(script);
557 if(shf.open(IO_WriteOnly | IO_Translate)) {
558 debug_msg(1, "pbuilder: Creating file: %s", script.latin1());
559 QString targ = project->first("QMAKE_ORIG_TARGET"), cpflags;
560 if(project->first("TEMPLATE") == "app") {
561 targ = project->first("TARGET");
562 if(project->isActiveConfig("resource_fork") && !project->isActiveConfig("console")) {
563 targ += ".app";
564 cpflags += "-r ";
565 }
566 } else if(!project->isActiveConfig("frameworklib")) {
567 if(project->isActiveConfig("staticlib"))
568 targ = project->first("TARGET");
569 else
570 targ = project->first("TARGET_");
571 int slsh = targ.findRev(Option::dir_sep);
572 if(slsh != -1)
573 targ = targ.right(targ.length() - slsh - 1);
574 }
575 QTextStream sht(&shf);
576 QString dstdir = project->first("DESTDIR");
577 fixEnvVariables(dstdir);
578
579 sht << "#!/bin/sh" << endl;
580 //copy the actual target
581 sht << "OUT_TARG=\"" << targ << "\"\n"
582 << "[ -z \"$BUILD_ROOT\" ] || OUT_TARG=\"${BUILD_ROOT}/${OUT_TARG}\"" << endl;
583 sht << "[ \"$OUT_TARG\" = \""
584 << (dstdir.isEmpty() ? QDir::currentDirPath() + QDir::separator(): dstdir) << targ << "\" ] || "
585 << "[ \"$OUT_TARG\" = \"" << targ << "\" ] || "
586 << "cp -r \"$OUT_TARG\" " << "\"" << dstdir << targ << "\"" << endl;
587 //rename as a framework
588 if(project->first("TEMPLATE") == "lib" && project->isActiveConfig("frameworklib"))
589 sht << "ln -sf \"" << targ << "\" " << "\"" << dstdir << targ << "\"" << endl;
590 //create all the version symlinks (just to be like unixmake)
591 for(QStringList::Iterator it = links.begin(); it != links.end(); ++it) {
592 if(targ != (*it))
593 sht << "ln -sf \"" << targ << "\" " << "\"" << dstdir << (*it) << "\"" << endl;
594 }
595 shf.close();
596#ifdef Q_OS_UNIX
597 chmod(script.latin1(), S_IRWXU | S_IRWXG);
598#endif
599 QString phase_key = keyFor("QMAKE_PBX_INSTALL_BUILDPHASE");
600 script = fileFixify(script, QDir::currentDirPath());
601 project->variables()["QMAKE_PBX_BUILDPHASES"].append(phase_key);
602 t << "\t\t" << phase_key << " = {" << "\n"
603 << "\t\t\t" << "buildActionMask = 8;" << "\n" //only on install!
604 << "\t\t\t" << "files = (" << "\n"
605 << "\t\t\t" << ");" << "\n"
606 << "\t\t\t" << "generatedFileNames = (" << "\n"
607 << "\t\t\t" << ");" << "\n"
608 << "\t\t\t" << "isa = PBXShellScriptBuildPhase;" << "\n"
609 << "\t\t\t" << "name = \"Qt Install\";" << "\n"
610 << "\t\t\t" << "neededFileNames = (" << "\n"
611 << "\t\t\t" << ");" << "\n"
612 << "\t\t\t" << "shellPath = /bin/sh;" << "\n"
613 << "\t\t\t" << "shellScript = \"" << script << "\";" << "\n"
614 << "\t\t" << "};" << "\n";
615 }
616 }
617 //ROOT_GROUP
618 t << "\t\t" << keyFor("QMAKE_PBX_ROOT_GROUP") << " = {" << "\n"
619 << "\t\t\t" << "children = (" << "\n"
620 << varGlue("QMAKE_PBX_GROUPS", "\t\t\t\t", ",\n\t\t\t\t", "\n")
621 << "\t\t\t" << ");" << "\n"
622 << "\t\t\t" << "isa = PBXGroup;" << "\n"
623 << "\t\t\t" << "name = " << project->first("QMAKE_ORIG_TARGET") << ";" << "\n"
624 << "\t\t\t" << "path = \"\";" << "\n"
625 << "\t\t\t" << "refType = 4;" << "\n"
626 << "\t\t" << "};" << "\n";
627 //REFERENCE
628 t << "\t\t" << keyFor("QMAKE_PBX_REFERENCE") << " = {" << "\n";
629 if(project->first("TEMPLATE") == "app") {
630 QString targ = project->first("QMAKE_ORIG_TARGET");
631 if(project->isActiveConfig("resource_fork") && !project->isActiveConfig("console")) {
632 targ += ".app";
633 t << "\t\t\t" << "isa = PBXApplicationReference;" << "\n";
634 } else {
635 t << "\t\t\t" << "isa = PBXExecutableFileReference;" << "\n";
636 }
637 QString app = (!project->isEmpty("DESTDIR") ? project->first("DESTDIR") + project->first("QMAKE_ORIG_TARGET") :
638 QDir::currentDirPath()) + Option::dir_sep + targ;
639 t << "\t\t\t" << "name = " << targ << ";" << "\n"
640 << "\t\t\t" << "path = \"" << targ << "\";" << "\n"
641 << "\t\t\t" << "refType = " << reftypeForFile(app) << ";" << "\n";
642 } else {
643 QString lib = project->first("QMAKE_ORIG_TARGET");
644 if(project->isActiveConfig("staticlib")) {
645 lib = project->first("TARGET");
646 } else if(!project->isActiveConfig("frameworklib")) {
647 if(project->isActiveConfig("plugin"))
648 lib = project->first("TARGET");
649 else
650 lib = project->first("TARGET_");
651 }
652 int slsh = lib.findRev(Option::dir_sep);
653 if(slsh != -1)
654 lib = lib.right(lib.length() - slsh - 1);
655 t << "\t\t\t" << "isa = PBXLibraryReference;" << "\n"
656 << "\t\t\t" << "path = " << lib << ";\n"
657 << "\t\t\t" << "refType = " << reftypeForFile(lib) << ";" << "\n";
658 }
659 t << "\t\t" << "};" << "\n";
660 //TARGET
661 t << "\t\t" << keyFor("QMAKE_PBX_TARGET") << " = {" << "\n"
662 << "\t\t\t" << "buildPhases = (" << "\n"
663 << varGlue("QMAKE_PBX_BUILDPHASES", "\t\t\t\t", ",\n\t\t\t\t", "\n")
664 << "\t\t\t" << ");" << "\n"
665 << "\t\t\t" << "buildSettings = {" << "\n"
666 << "\t\t\t\t" << "FRAMEWORK_SEARCH_PATHS = \"\";" << "\n"
667 << "\t\t\t\t" << "HEADER_SEARCH_PATHS = \"" << fixEnvsList("INCLUDEPATH") << " " << fixEnvs(specdir()) << "\";" << "\n"
668 << "\t\t\t\t" << "LIBRARY_SEARCH_PATHS = \"" << var("QMAKE_PBX_LIBPATHS") << "\";" << "\n"
669 << "\t\t\t\t" << "OPTIMIZATION_CFLAGS = \"\";" << "\n"
670 << "\t\t\t\t" << "OTHER_CFLAGS = \"" <<
671 fixEnvsList("QMAKE_CFLAGS") << varGlue("PRL_EXPORT_DEFINES"," -D"," -D","") <<
672 varGlue("DEFINES"," -D"," -D","") << "\";" << "\n"
673 << "\t\t\t\t" << "LEXFLAGS = \"" << var("QMAKE_LEXFLAGS") << "\";" << "\n"
674 << "\t\t\t\t" << "YACCFLAGS = \"" << var("QMAKE_YACCFLAGS") << "\";" << "\n"
675 << "\t\t\t\t" << "OTHER_CPLUSPLUSFLAGS = \"" <<
676 fixEnvsList("QMAKE_CXXFLAGS") << varGlue("PRL_EXPORT_DEFINES"," -D"," -D","") <<
677 varGlue("DEFINES"," -D"," -D","") << "\";" << "\n"
678 << "\t\t\t\t" << "OTHER_REZFLAGS = \"\";" << "\n"
679 << "\t\t\t\t" << "SECTORDER_FLAGS = \"\";" << "\n"
680 << "\t\t\t\t" << "WARNING_CFLAGS = \"\";" << "\n";
681#if 1
682 t << "\t\t\t\t" << "BUILD_ROOT = \"" << QDir::currentDirPath() << "\";" << "\n";
683#endif
684 if(!project->isActiveConfig("staticlib"))
685 t << "\t\t\t\t" << "OTHER_LDFLAGS = \"" << fixEnvsList("SUBLIBS") << " " <<
686 fixEnvsList("QMAKE_LFLAGS") << " " << fixEnvsList("QMAKE_LIBDIR_FLAGS") <<
687 " " << fixEnvsList("QMAKE_LIBS") << "\";" << "\n";
688 if(!project->isEmpty("DESTDIR"))
689 t << "\t\t\t\t" << "INSTALL_PATH = \"" << project->first("DESTDIR") << "\";" << "\n";
690 if(!project->isEmpty("VERSION") && project->first("VERSION") != "0.0.0")
691 t << "\t\t\t\t" << "DYLIB_CURRENT_VERSION = \"" << project->first("VERSION") << "\";" << "\n";
692 if(!project->isEmpty("OBJECTS_DIR"))
693 t << "\t\t\t\t" << "OBJECT_FILE_DIR = \"" << project->first("OBJECTS_DIR") << "\";" << "\n";
694 if(project->first("TEMPLATE") == "app") {
695 if(project->isActiveConfig("resource_fork") && !project->isActiveConfig("console"))
696 t << "\t\t\t\t" << "WRAPPER_EXTENSION = app;" << "\n";
697 t << "\t\t\t\t" << "PRODUCT_NAME = " << project->first("QMAKE_ORIG_TARGET") << ";" << "\n";
698 } else {
699 QString lib = project->first("QMAKE_ORIG_TARGET");
700 if(!project->isActiveConfig("plugin") && project->isActiveConfig("staticlib")) {
701 t << "\t\t\t\t" << "LIBRARY_STYLE = STATIC;" << "\n";
702 lib = project->first("TARGET");
703 } else {
704 t << "\t\t\t\t" << "LIBRARY_STYLE = DYNAMIC;" << "\n";
705 if(!project->isActiveConfig("frameworklib")) {
706 if(project->isActiveConfig("plugin"))
707 lib = project->first("TARGET");
708 else
709 lib = project->first("TARGET_");
710 }
711 }
712 int slsh = lib.findRev(Option::dir_sep);
713 if(slsh != -1)
714 lib = lib.right(lib.length() - slsh - 1);
715 t << "\t\t\t\t" << "PRODUCT_NAME = " << lib << ";" << "\n";
716 }
717 tmp = project->variables()["QMAKE_PBX_VARS"];
718 for(QStringList::Iterator it = tmp.begin(); it != tmp.end(); ++it)
719 t << "\t\t\t\t" << (*it) << " = \"" << getenv((*it)) << "\";" << "\n";
720 t << "\t\t\t" << "};" << "\n"
721 << "\t\t\t" << "conditionalBuildSettings = {" << "\n"
722 << "\t\t\t" << "};" << "\n"
723 << "\t\t\t" << "dependencies = (" << "\n"
724 << varGlue("QMAKE_PBX_TARGETDEPENDS", "\t\t\t\t", ",\n\t\t\t\t", "\n")
725 << "\t\t\t" << ");" << "\n"
726 << "\t\t\t" << "productReference = " << keyFor("QMAKE_PBX_REFERENCE") << ";" << "\n"
727 << "\t\t\t" << "shouldUseHeadermap = 1;" << "\n";
728 if(project->first("TEMPLATE") == "app") {
729 if(project->isActiveConfig("resource_fork") && !project->isActiveConfig("console")) {
730 t << "\t\t\t" << "isa = PBXApplicationTarget;" << "\n"
731 << "\t\t\t" << "productSettingsXML = " << "\"" << "<?xml version="
732 << "\\\"1.0\\\" encoding=" << "\\\"UTF-8\\\"" << "?>" << "\n"
733 << "\t\t\t\t" << "<!DOCTYPE plist SYSTEM \\\"file://localhost/System/"
734 << "Library/DTDs/PropertyList.dtd\\\">" << "\n"
735 << "\t\t\t\t" << "<plist version=\\\"0.9\\\">" << "\n"
736 << "\t\t\t\t" << "<dict>" << "\n"
737 << "\t\t\t\t\t" << "<key>CFBundleDevelopmentRegion</key>" << "\n"
738 << "\t\t\t\t\t" << "<string>English</string>" << "\n"
739 << "\t\t\t\t\t" << "<key>CFBundleExecutable</key>" << "\n"
740 << "\t\t\t\t\t" << "<string>" << project->first("QMAKE_ORIG_TARGET") << "</string>" << "\n"
741 << "\t\t\t\t\t" << "<key>CFBundleIconFile</key>" << "\n"
742 << "\t\t\t\t\t" << "<string>" << var("RC_FILE").section(Option::dir_sep, -1) << "</string>" << "\n"
743 << "\t\t\t\t\t" << "<key>CFBundleInfoDictionaryVersion</key>" << "\n"
744 << "\t\t\t\t\t" << "<string>6.0</string>" << "\n"
745 << "\t\t\t\t\t" << "<key>CFBundlePackageType</key>" << "\n"
746 << "\t\t\t\t\t" << "<string>APPL</string>" << "\n"
747 << "\t\t\t\t\t" << "<key>CFBundleSignature</key>" << "\n"
748 << "\t\t\t\t\t" << "<string>????</string>" << "\n"
749 << "\t\t\t\t\t" << "<key>CFBundleVersion</key>" << "\n"
750 << "\t\t\t\t\t" << "<string>0.1</string>" << "\n"
751 << "\t\t\t\t\t" << "<key>CSResourcesFileMapped</key>" << "\n"
752 << "\t\t\t\t\t" << "<true/>" << "\n"
753 << "\t\t\t\t" << "</dict>" << "\n"
754 << "\t\t\t\t" << "</plist>" << "\";" << "\n";
755 } else {
756 t << "\t\t\t" << "isa = PBXToolTarget;" << "\n";
757 }
758 t << "\t\t\t" << "name = \"" << project->first("QMAKE_ORIG_TARGET") << "\";" << "\n"
759 << "\t\t\t" << "productName = " << project->first("QMAKE_ORIG_TARGET") << ";" << "\n";
760 } else {
761 QString lib = project->first("QMAKE_ORIG_TARGET");
762 if(!project->isActiveConfig("frameworklib"))
763 lib.prepend("lib");
764 t << "\t\t\t" << "isa = PBXLibraryTarget;" << "\n"
765 << "\t\t\t" << "name = \"" << lib << "\";" << "\n"
766 << "\t\t\t" << "productName = " << lib << ";" << "\n";
767 }
768 if(!project->isEmpty("DESTDIR"))
769 t << "\t\t\t" << "productInstallPath = \"" << project->first("DESTDIR") << "\";" << "\n";
770 t << "\t\t" << "};" << "\n";
771 //DEBUG/RELEASE
772 for(i = 0; i < 2; i++) {
773 bool as_release = !i;
774 if(project->isActiveConfig("debug"))
775 as_release = i;
776 QString key = "QMAKE_PBX_" + QString(as_release ? "RELEASE" : "DEBUG");
777 key = keyFor(key);
778 project->variables()["QMAKE_PBX_BUILDSTYLES"].append(key);
779 t << "\t\t" << key << " = {" << "\n"
780 << "\t\t\t" << "buildRules = (" << "\n"
781 << "\t\t\t" << ");" << "\n"
782 << "\t\t\t" << "buildSettings = {" << "\n"
783 << "\t\t\t\t" << "COPY_PHASE_STRIP = " << (as_release ? "YES" : "NO") << ";" << "\n";
784 if(as_release)
785 t << "\t\t\t\t" << "DEBUGGING_SYMBOLS = NO;" << "\n";
786 t << "\t\t\t" << "};" << "\n"
787 << "\t\t\t" << "isa = PBXBuildStyle;" << "\n"
788 << "\t\t\t" << "name = " << (as_release ? "Deployment" : "Development") << ";" << "\n"
789 << "\t\t" << "};" << "\n";
790 }
791 //ROOT
792 t << "\t\t" << keyFor("QMAKE_PBX_ROOT") << " = {" << "\n"
793 << "\t\t\t" << "buildStyles = (" << "\n"
794 << varGlue("QMAKE_PBX_BUILDSTYLES", "\t\t\t\t", ",\n\t\t\t\t", "\n")
795 << "\t\t\t" << ");" << "\n"
796 << "\t\t\t" << "isa = PBXProject;" << "\n"
797 << "\t\t\t" << "mainGroup = " << keyFor("QMAKE_PBX_ROOT_GROUP") << ";" << "\n"
798 << "\t\t\t" << "targets = (" << "\n"
799 << "\t\t\t\t" << keyFor("QMAKE_PBX_TARGET") << "\n"
800 << "\t\t\t" << ");" << "\n"
801 << "\t\t" << "};" << "\n";
802
803 //FOOTER
804 t << "\t" << "};" << "\n"
805 << "\t" << "rootObject = " << keyFor("QMAKE_PBX_ROOT") << ";" << "\n"
806 << "}" << endl;
807
808 QString mkwrap = fileFixify(pbx_dir + Option::dir_sep + ".." + Option::dir_sep + project->first("MAKEFILE"),
809 QDir::currentDirPath());
810 QFile mkwrapf(mkwrap);
811 if(mkwrapf.open(IO_WriteOnly | IO_Translate)) {
812 debug_msg(1, "pbuilder: Creating file: %s", mkwrap.latin1());
813 QTextStream mkwrapt(&mkwrapf);
814 writeHeader(mkwrapt);
815 const char *cleans = "uiclean mocclean preprocess_clean ";
816 mkwrapt << "#This is a makefile wrapper for PROJECT BUILDER\n"
817 << "all:" << "\n\t"
818 << "cd " << (project->first("QMAKE_ORIG_TARGET") + ".pbproj/ && pbxbuild") << "\n"
819 << "install: all" << "\n\t"
820 << "cd " << (project->first("QMAKE_ORIG_TARGET") + ".pbproj/ && pbxbuild install") << "\n"
821 << "distclean clean: preprocess_clean" << "\n\t"
822 << "cd " << (project->first("QMAKE_ORIG_TARGET") + ".pbproj/ && pbxbuild clean") << "\n"
823 << (!did_preprocess ? cleans : "") << ":" << "\n";
824 if(did_preprocess)
825 mkwrapt << cleans << ":" << "\n\t"
826 << "make -f "
827 << pbx_dir << Option::dir_sep << "qt_preprocess.mak $@" << endl;
828 }
829 return TRUE;
830}
831
832QString
833ProjectBuilderMakefileGenerator::fixEnvs(QString file)
834{
835 QRegExp reg_var("\\$\\((.*)\\)");
836 for(int rep = 0; (rep = reg_var.search(file, rep)) != -1; ) {
837 if(project->variables()["QMAKE_PBX_VARS"].findIndex(reg_var.cap(1)) == -1)
838 project->variables()["QMAKE_PBX_VARS"].append(reg_var.cap(1));
839 rep += reg_var.matchedLength();
840 }
841 return file;
842}
843
844QString
845ProjectBuilderMakefileGenerator::fixEnvsList(QString where)
846{
847 QString ret;
848 const QStringList &l = project->variables()[where];
849 for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) {
850 fixEnvs((*it));
851 if(!ret.isEmpty())
852 ret += " ";
853 ret += (*it);
854 }
855 return ret;
856}
857
858QString
859ProjectBuilderMakefileGenerator::keyFor(QString block)
860{
861#if 0 //This make this code much easier to debug..
862 return block;
863#endif
864
865 QString ret;
866 if(!keys.contains(block)) {
867#if 0
868 static unsigned int r = 0;
869 ret.sprintf("%024x", ++r);
870#else //not really necesary, but makes it look more interesting..
871 static struct { unsigned int a1, a2, a3; } r = { 0, 0, 0 };
872 if(!r.a1 && !r.a2 && !r.a3) {
873 r.a1 = rand();
874 r.a2 = rand();
875 r.a3 = rand();
876 }
877 switch(rand() % 3) {
878 case 0: ++r.a1; break;
879 case 1: ++r.a2; break;
880 case 2: ++r.a3; break;
881 }
882 ret.sprintf("%08x%08x%08x", r.a1, r.a2, r.a3);
883#endif
884 ret = ret.upper();
885 keys.insert(block, ret);
886 } else {
887 ret = keys[block];
888 }
889 return ret;
890}
891
892bool
893ProjectBuilderMakefileGenerator::openOutput(QFile &file) const
894{
895 if(project->first("TEMPLATE") != "subdirs") {
896 QFileInfo fi(file);
897 if(fi.extension() != "pbxproj" || file.name().isEmpty()) {
898 QString output = file.name();
899 if(fi.isDir())
900 output += QDir::separator();
901 if(fi.extension() != "pbproj") {
902 if(file.name().isEmpty() || fi.isDir())
903 output += project->first("TARGET");
904 output += QString(".pbproj") + QDir::separator();
905 } else if(output[(int)output.length() - 1] != QDir::separator()) {
906 output += QDir::separator();
907 }
908 output += QString("project.pbxproj");
909 file.setName(output);
910 }
911 bool ret = UnixMakefileGenerator::openOutput(file);
912 ((ProjectBuilderMakefileGenerator*)this)->pbx_dir = Option::output_dir.section(Option::dir_sep, 0, -1);
913 Option::output_dir = pbx_dir.section(Option::dir_sep, 0, -2);
914 return ret;
915 }
916 return UnixMakefileGenerator::openOutput(file);
917}
918
919/* This function is such a hack it is almost pointless, but it
920 eliminates the warning message from ProjectBuilder that the project
921 file is for an older version. I guess this could be used someday if
922 the format of the output is dependant upon the version of
923 ProjectBuilder as well.
924*/
925int
926ProjectBuilderMakefileGenerator::pbuilderVersion() const
927{
928 QString ret;
929 if(project->isEmpty("QMAKE_PBUILDER_VERSION")) {
930 QString version, version_plist = project->first("QMAKE_PBUILDER_VERSION_PLIST");
931 if(version_plist.isEmpty())
932 version_plist = "/Developer/Applications/Project Builder.app/Contents/version.plist";
933 else
934 version_plist = version_plist.replace(QRegExp("\""), "");
935 QFile version_file(version_plist);
936 if(version_file.open(IO_ReadOnly)) {
937 debug_msg(1, "pbuilder: version.plist: Reading file: %s", version_plist.latin1());
938 QTextStream plist(&version_file);
939
940 bool in_dict = FALSE;
941 QString current_key;
942 QRegExp keyreg("^<key>(.*)</key>$"), stringreg("^<string>(.*)</string>$");
943 while(!plist.eof()) {
944 QString line = plist.readLine().stripWhiteSpace();
945 if(line == "<dict>")
946 in_dict = TRUE;
947 else if(line == "</dict>")
948 in_dict = FALSE;
949 else if(in_dict) {
950 if(keyreg.exactMatch(line))
951 current_key = keyreg.cap(1);
952 else if(current_key == "CFBundleShortVersionString" && stringreg.exactMatch(line))
953 version = stringreg.cap(1);
954 }
955 }
956 version_file.close();
957 } else debug_msg(1, "pbuilder: version.plist: Failure to open %s", version_plist.latin1());
958 if(version.startsWith("2.0"))
959 ret = "38";
960 else if(version == "1.1")
961 ret = "34";
962 } else {
963 ret = project->first("QMAKE_PBUILDER_VERSION");
964 }
965 if(!ret.isEmpty()) {
966 bool ok;
967 int int_ret = ret.toInt(&ok);
968 if(ok) {
969 debug_msg(1, "pbuilder: version.plist: Got version: %d", int_ret);
970 return int_ret;
971 }
972 }
973 debug_msg(1, "pbuilder: version.plist: Fallback to default version");
974 return 34; //my fallback
975}
976
977QString
978ProjectBuilderMakefileGenerator::reftypeForFile(QString where)
979{
980 if(QDir::isRelativePath(where))
981 return "4"; //relative
982 return "0"; //absolute
983}
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 @@
1/****************************************************************************
2** $Id$
3**
4** Definition of ________ class.
5**
6** Created : 970521
7**
8** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
9**
10** This file is part of the network module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition licenses may use this
22** file in accordance with the Qt Commercial License Agreement provided
23** with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37#ifndef __PBUILDERMAKE_H__
38#define __PBUILDERMAKE_H__
39
40#include "unixmake.h"
41
42class ProjectBuilderMakefileGenerator : public UnixMakefileGenerator
43{
44 QString pbx_dir;
45 int pbuilderVersion() const;
46 bool writeMakeParts(QTextStream &);
47 bool writeMakefile(QTextStream &);
48
49 QMap<QString, QString> keys;
50 QString keyFor(QString file);
51 QString fixEnvs(QString file);
52 QString fixEnvsList(QString where);
53 QString reftypeForFile(QString file);
54
55public:
56 ProjectBuilderMakefileGenerator(QMakeProject *p);
57 ~ProjectBuilderMakefileGenerator();
58
59 virtual bool openOutput(QFile &) const;
60protected:
61 virtual bool doDepends() const { return FALSE; } //never necesary
62};
63
64inline ProjectBuilderMakefileGenerator::~ProjectBuilderMakefileGenerator()
65{ }
66
67
68#endif /* __PBUILDERMAKE_H__ */