source: trunk/qmake/generators/mac/pbuilder_pbx.cpp@ 751

Last change on this file since 751 was 651, checked in by Dmitry A. Kuminov, 16 years ago

trunk: Merged in qt 4.6.2 sources.

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