summaryrefslogtreecommitdiff
path: root/qmake/generators/mac/pbuilder_pbx.cpp
Unidiff
Diffstat (limited to 'qmake/generators/mac/pbuilder_pbx.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--qmake/generators/mac/pbuilder_pbx.cpp983
1 files changed, 983 insertions, 0 deletions
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}