source: trunk/qmake/generators/os2/gnumake.cpp@ 117

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

mkspecs/os2-g++: 1) Generate a separate rule for the import library (for the split DLL function). 2) Make link_prl work (in particular, automatically add the required libraries from the .prl file of the library to the target that uses it).

File size: 25.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the qmake application of the Qt Toolkit.
7**
8** Copyright (C) 2009 netlabs.org. OS/2 parts.
9**
10** $QT_BEGIN_LICENSE:LGPL$
11** Commercial Usage
12** Licensees holding valid Qt Commercial licenses may use this file in
13** accordance with the Qt Commercial License Agreement provided with the
14** Software or, alternatively, in accordance with the terms contained in
15** a written agreement between you and Nokia.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 2.1 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 2.1 requirements
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24**
25** In addition, as a special exception, Nokia gives you certain
26** additional rights. These rights are described in the Nokia Qt LGPL
27** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
28** package.
29**
30** GNU General Public License Usage
31** Alternatively, this file may be used under the terms of the GNU
32** General Public License version 3.0 as published by the Free Software
33** Foundation and appearing in the file LICENSE.GPL included in the
34** packaging of this file. Please review the following information to
35** ensure the GNU General Public License version 3.0 requirements will be
36** met: http://www.gnu.org/copyleft/gpl.html.
37**
38** If you are unsure which license is appropriate for your use, please
39** contact the sales department at [email protected].
40** $QT_END_LICENSE$
41**
42****************************************************************************/
43
44#include "gnumake.h"
45#include "option.h"
46#include "meta.h"
47#include <qregexp.h>
48#include <qdir.h>
49#include <stdlib.h>
50#include <time.h>
51
52QT_BEGIN_NAMESPACE
53
54GNUMakefileGenerator::GNUMakefileGenerator() : Win32MakefileGenerator(), init_flag(false)
55{
56 if (isDosLikeShell())
57 quote = "\"";
58 else
59 quote = "'";
60}
61
62bool GNUMakefileGenerator::isDosLikeShell() const
63{
64#ifdef Q_OS_OS2
65 return Option::shellPath.isEmpty();
66#else
67 return Win32MakefileGenerator::isDosLikeShell();
68#endif
69}
70
71QString GNUMakefileGenerator::escapeFilePath(const QString &path) const
72{
73 QString ret = path;
74 if (!isDosLikeShell()) {
75 ret.remove('\"');
76 ret.replace('\\', "/");
77 ret.replace(' ', "\\ ");
78 } else {
79 ret.replace(QRegExp("\""), "");
80 ret.replace(QRegExp("[\\\\/]$"), "");
81 if (ret.contains(QRegExp("[ +&;%]")))
82 ret = quote + ret + quote;
83 }
84 return ret;
85}
86
87QString GNUMakefileGenerator::escapeDependencyPath(const QString &path) const
88{
89 /* dependency escaping is always done Unix-way since this is a requirement
90 * of GNU make which allows " and ' to be part of the file name */
91 QString ret = path;
92 ret.remove('\"');
93 ret.replace(' ', "\\ ");
94 return ret;
95}
96
97QString
98GNUMakefileGenerator::findBestVersion(const QString &d, const QString &stem, const QString &ext)
99{
100 QString bd = Option::fixPathToLocalOS(d, true);
101 if(!exists(bd))
102 return QString();
103
104 QString dllStem = stem + QTDLL_POSTFIX;
105
106 QString versionOverride;
107 if(!project->values("QMAKE_" + stem.toUpper() + "_VERSION_OVERRIDE").isEmpty())
108 versionOverride = project->values("QMAKE_" + stem.toUpper() + "_VERSION_OVERRIDE").first();
109
110 if (project->isActiveConfig("link_prl")) {
111 QMakeMetaInfo libinfo;
112 if (libinfo.readLib(bd + Option::dir_sep + dllStem)) {
113 QString target = libinfo.first("QMAKE_PRL_TARGET");
114 if (target.isEmpty())
115 target = stem;
116 if (!versionOverride.isEmpty())
117 target += versionOverride;
118 else if (!libinfo.isEmpty("QMAKE_PRL_VERSION"))
119 target += libinfo.first("QMAKE_PRL_VERSION").replace(".", "");
120
121 const QStringList &in = libinfo.values("QMAKE_PRL_LIBS");
122 QStringList &out = project->values("QMAKE_INTERNAL_PRL_LIBS");
123 for (QStringList::ConstIterator it = in.begin(); it != in.end(); ++it) {
124 if (!out.contains(*it))
125 out.append((*it));
126 }
127 return target;
128 }
129 }
130
131 if (!versionOverride.isEmpty())
132 return stem + versionOverride;
133
134 int biggest = -1;
135 if(!project->isActiveConfig("no_versionlink")) {
136 QDir dir(bd);
137 QStringList entries = dir.entryList();
138 QRegExp regx(QString("((lib)?%1([0-9]*))(%2)$").arg(dllStem).arg(ext), Qt::CaseInsensitive);
139 for(QStringList::Iterator it = entries.begin(); it != entries.end(); ++it) {
140 if(regx.exactMatch((*it))) {
141 if (!regx.cap(3).isEmpty()) {
142 bool ok = true;
143 int num = regx.cap(3).toInt(&ok);
144 biggest = qMax(biggest, (!ok ? -1 : num));
145 }
146 }
147 }
148 }
149 if (biggest != -1)
150 return stem + QString::number(biggest);
151
152 return QString();
153}
154
155bool GNUMakefileGenerator::findLibraries()
156{
157 QStringList &l = project->values("QMAKE_LIBS");
158
159 QList<QMakeLocalFileName> dirs;
160 {
161 QStringList &libpaths = project->values("QMAKE_LIBDIR");
162 for(QStringList::Iterator libpathit = libpaths.begin();
163 libpathit != libpaths.end(); ++libpathit)
164 dirs.append(QMakeLocalFileName((*libpathit)));
165 }
166
167 for (QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
168 if((*it).startsWith("-L")) {
169 dirs.append(QMakeLocalFileName((*it).mid(2)));
170 } else {
171 QString stem = *it, out;
172
173 if (stem.startsWith("-l"))
174 stem = stem.mid(2);
175
176 QString suffix;
177 if (!project->isEmpty("QMAKE_" + stem.toUpper() + "_SUFFIX"))
178 suffix = project->first("QMAKE_" + stem.toUpper() + "_SUFFIX");
179 for (QList<QMakeLocalFileName>::Iterator dir_it = dirs.begin(); dir_it != dirs.end(); ++dir_it) {
180 QString best = findBestVersion((*dir_it).local(), stem,
181 QString("%1.lib").arg(suffix));
182 if (!best.isEmpty()) {
183 out = best.prepend("-l");
184 break;
185 }
186 }
187 if (!out.isEmpty()) // We assume if it never finds it that its correct
188 if (!project->values("QMAKE_LIBS").contains(out))
189 (*it) = out;
190 }
191 }
192
193 QStringList l2 = project->values("QMAKE_INTERNAL_PRL_LIBS");
194 for (QStringList::ConstIterator it = l2.begin(); it != l2.end(); ++it) {
195 if (!l.contains(*it))
196 l.append((*it));
197 }
198
199 return true;
200}
201
202bool GNUMakefileGenerator::writeMakefile(QTextStream &t)
203{
204 writeHeader(t);
205
206 /* function to convert from DOS-like to Unix-like space escaping in file
207 * names */
208 t << "q = $(subst %,\\%,$(subst ;,\\;,$(subst &,\\&,"
209 "$(subst +,\\+,$(subst $(space),\\ ,$(subst \",,$(1)))))))" << endl << endl;
210
211 if(!project->values("QMAKE_FAILED_REQUIREMENTS").isEmpty()) {
212 t << "all clean:" << "\n\t"
213 << "@echo \"Some of the required modules ("
214 << var("QMAKE_FAILED_REQUIREMENTS") << ") are not available.\"" << "\n\t"
215 << "@echo \"Skipped.\"" << endl << endl;
216 writeMakeQmake(t);
217 return true;
218 }
219
220 if(project->first("TEMPLATE") == "app" ||
221 project->first("TEMPLATE") == "lib") {
222 if(Option::mkfile::do_stub_makefile) {
223 t << "QMAKE = " << (project->isEmpty("QMAKE_QMAKE") ? QString("qmake") : var("QMAKE_QMAKE")) << endl;
224 QStringList &qut = project->values("QMAKE_EXTRA_TARGETS");
225 for(QStringList::ConstIterator it = qut.begin(); it != qut.end(); ++it)
226 t << *it << " ";
227 t << "first all clean install distclean uninstall: qmake" << endl
228 << "qmake_all:" << endl;
229 writeMakeQmake(t);
230 if(project->isEmpty("QMAKE_NOFORCE"))
231 t << "FORCE:" << endl << endl;
232 return true;
233 }
234 writeGNUParts(t);
235 return MakefileGenerator::writeMakefile(t);
236 }
237 else if(project->first("TEMPLATE") == "subdirs") {
238 writeSubDirs(t);
239 return true;
240 }
241 return false;
242 }
243
244void GNUMakefileGenerator::writeGNUParts(QTextStream &t)
245{
246 t << "QMAKESPECDIR = " << quote << specdir() << quote << endl << endl;
247
248 writeStandardParts(t);
249
250 if (!preCompHeaderOut.isEmpty()) {
251 QString header = project->first("PRECOMPILED_HEADER");
252 QString cHeader = preCompHeaderOut + Option::dir_sep + "c";
253 t << escapeDependencyPath(cHeader) << ": " << escapeDependencyPath(header) << " "
254 << escapeDependencyPaths(findDependencies(header)).join(" \\\n\t\t")
255 << "\n\t" << mkdir_p_asstring(preCompHeaderOut)
256 << "\n\t" << "$(CC) -x c-header -c $(CFLAGS) $(INCPATH) -o " << cHeader << " " << header
257 << endl << endl;
258 QString cppHeader = preCompHeaderOut + Option::dir_sep + "c++";
259 t << escapeDependencyPath(cppHeader) << ": " << escapeDependencyPath(header) << " "
260 << escapeDependencyPaths(findDependencies(header)).join(" \\\n\t\t")
261 << "\n\t" << mkdir_p_asstring(preCompHeaderOut)
262 << "\n\t" << "$(CXX) -x c++-header -c $(CXXFLAGS) $(INCPATH) -o " << cppHeader << " " << header
263 << endl << endl;
264 }
265}
266
267void GNUMakefileGenerator::init()
268{
269 if(init_flag)
270 return;
271 init_flag = true;
272
273 if(project->first("TEMPLATE") == "app") {
274 mode = App;
275 project->values("QMAKE_APP_FLAG").append("1");
276 } else if(project->first("TEMPLATE") == "lib") {
277 mode = project->isActiveConfig("staticlib") ? StaticLib : DLL;
278 project->values("QMAKE_LIB_FLAG").append("1");
279 } else if(project->first("TEMPLATE") == "subdirs") {
280 MakefileGenerator::init();
281 if(project->isEmpty("QMAKE_COPY_FILE"))
282 project->values("QMAKE_COPY_FILE").append("$(COPY)");
283 if(project->isEmpty("QMAKE_COPY_DIR"))
284 project->values("QMAKE_COPY_DIR").append("$(COPY)");
285 if(project->isEmpty("QMAKE_INSTALL_FILE"))
286 project->values("QMAKE_INSTALL_FILE").append("$(COPY_FILE)");
287 if(project->isEmpty("QMAKE_INSTALL_PROGRAM"))
288 project->values("QMAKE_INSTALL_PROGRAM").append("$(COPY_FILE)");
289 if(project->isEmpty("QMAKE_INSTALL_DIR"))
290 project->values("QMAKE_INSTALL_DIR").append("$(COPY_DIR)");
291 if(project->values("MAKEFILE").isEmpty())
292 project->values("MAKEFILE").append("Makefile");
293 if(project->values("QMAKE_QMAKE").isEmpty())
294 project->values("QMAKE_QMAKE").append("qmake");
295 return;
296 }
297
298 project->values("TARGET_PRL").append(project->first("TARGET"));
299
300 processVars();
301
302 // LIBS defined in Profile comes first for gcc
303 project->values("QMAKE_LIBS") += escapeFilePaths(project->values("LIBS"));
304
305 QString targetfilename = project->values("TARGET").first();
306 QStringList &configs = project->values("CONFIG");
307
308 if(project->isActiveConfig("qt_dll"))
309 if(configs.indexOf("qt") == -1)
310 configs.append("qt");
311
312 if(project->isActiveConfig("dll")) {
313 QString destDir = "";
314 if(!project->first("DESTDIR").isEmpty())
315 destDir = Option::fixPathToTargetOS(project->first("DESTDIR") + Option::dir_sep, false, false);
316 }
317
318 MakefileGenerator::init();
319
320 // precomp
321 if (!project->first("PRECOMPILED_HEADER").isEmpty()
322 && project->isActiveConfig("precompile_header")) {
323 QString preCompHeader = var("PRECOMPILED_DIR")
324 + QFileInfo(project->first("PRECOMPILED_HEADER")).fileName();
325 preCompHeaderOut = preCompHeader + ".gch";
326 project->values("QMAKE_CLEAN").append(preCompHeaderOut + Option::dir_sep + "c");
327 project->values("QMAKE_CLEAN").append(preCompHeaderOut + Option::dir_sep + "c++");
328
329 project->values("QMAKE_RUN_CC").clear();
330 project->values("QMAKE_RUN_CC").append("$(CC) -c -include " + preCompHeader +
331 " $(CFLAGS) $(INCPATH) -o $obj $src");
332 project->values("QMAKE_RUN_CC_IMP").clear();
333 project->values("QMAKE_RUN_CC_IMP").append("$(CC) -c -include " + preCompHeader +
334 " $(CFLAGS) $(INCPATH) -o $@ $<");
335 project->values("QMAKE_RUN_CXX").clear();
336 project->values("QMAKE_RUN_CXX").append("$(CXX) -c -include " + preCompHeader +
337 " $(CXXFLAGS) $(INCPATH) -o $obj $src");
338 project->values("QMAKE_RUN_CXX_IMP").clear();
339 project->values("QMAKE_RUN_CXX_IMP").append("$(CXX) -c -include " + preCompHeader +
340 " $(CXXFLAGS) $(INCPATH) -o $@ $<");
341 }
342}
343
344void GNUMakefileGenerator::fixTargetExt()
345{
346 if (mode == App)
347 project->values("TARGET_EXT").append(".exe");
348 else if (mode == DLL)
349 project->values("TARGET_EXT").append(project->first("TARGET_VERSION_EXT") + ".dll");
350 else
351 project->values("TARGET_EXT").append(".lib");
352}
353
354void GNUMakefileGenerator::writeIncPart(QTextStream &t)
355{
356 t << "INCPATH =";
357
358 QString opt = var("QMAKE_CFLAGS_INCDIR");
359 QStringList &incs = project->values("INCLUDEPATH");
360 QString incsSemicolon;
361 for(QStringList::Iterator incit = incs.begin(); incit != incs.end(); ++incit) {
362 QString inc = escapeFilePath(*incit);
363 t << " " << opt << inc;
364 incsSemicolon += inc + Option::dirlist_sep;
365 }
366 t << " " << opt << "$(QMAKESPECDIR)" << endl;
367 incsSemicolon += "$(QMAKESPECDIR)";
368 t << "INCLUDEPATH = " << incsSemicolon << endl;
369 /* createCompilerResponseFiles() will need QAKESPECDIR expanded) */
370 project->values("INCLUDEPATH").append(specdir());
371}
372
373void GNUMakefileGenerator::writeLibsPart(QTextStream &t)
374{
375 if (mode == StaticLib) {
376 t << "LIB = " << var("QMAKE_LIB") << endl;
377 } else {
378 t << "LINK = " << var("QMAKE_LINK") << endl;
379 t << "LFLAGS = " << var("QMAKE_LFLAGS") << endl;
380 t << "LIBS =";
381 if(!project->values("QMAKE_LIBDIR").isEmpty())
382 writeLibDirPart(t);
383 QString opt = var("QMAKE_LFLAGS_LIB");
384 QString optL = var("QMAKE_LFLAGS_LIBDIR");
385 QStringList libs = project->values("QMAKE_LIBS");
386 for(QStringList::Iterator it = libs.begin(); it != libs.end(); ++it) {
387 QString lib = escapeFilePath(*it);
388 /* lib may be prefixed with -l which is commonly used in e.g. PRF
389 * (feature) files on all platforms; remove it before prepending
390 * the compiler-specific option. There is even more weird case
391 * when LIBS contains library paths prefixed with -L; we detect
392 * this as well and replace it with the proper option. */
393 if (lib.startsWith("-L")) {
394 lib = lib.mid(2);
395 t << " " << optL << lib;
396 } else {
397 if (lib.startsWith("-l"))
398 lib = lib.mid(2);
399 t << " " << opt << lib;
400 }
401 }
402 t << endl;
403 }
404}
405
406void GNUMakefileGenerator::writeLibDirPart(QTextStream &t)
407{
408 QString opt = var("QMAKE_LFLAGS_LIBDIR");
409 QStringList libDirs = project->values("QMAKE_LIBDIR");
410 for(QStringList::Iterator it = libDirs.begin(); it != libDirs.end(); ++it) {
411 QString libDir = escapeFilePath(*it);
412 /* libDir may be prefixed with -L which is commonly used in e.g. PRF
413 * (feature) files on all platforms; remove it before prepending
414 * the compiler-specific option */
415 if (libDir.startsWith("-L"))
416 libDir = libDir.mid(2);
417 t << " " << opt << libDir;
418 }
419}
420
421void GNUMakefileGenerator::writeObjectsPart(QTextStream &t)
422{
423 Win32MakefileGenerator::writeObjectsPart(t);
424 createLinkerResponseFiles(t);
425
426 /* this function is a nice place to also handle compiler options response
427 * files */
428 createCompilerResponseFiles(t);
429}
430
431void GNUMakefileGenerator::writeBuildRulesPart(QTextStream &t)
432{
433 t << "first: all" << endl;
434 t << "all: " << escapeDependencyPath(fileFixify(Option::output.fileName())) << " " << valGlue(escapeDependencyPaths(project->values("ALL_DEPS"))," "," "," ") << escapeFileVars(" $(DESTDIR_TARGET)") << endl << endl;
435 t << escapeFileVars("$(DESTDIR_TARGET): ") << var("PRE_TARGETDEPS") << " $(OBJECTS) " << var("POST_TARGETDEPS");
436 if (!project->isEmpty("QMAKE_PRE_LINK"))
437 t << "\n\t" <<var("QMAKE_PRE_LINK");
438 if (mode == StaticLib) {
439 /* static library */
440 t << "\n\t" << var("QMAKE_RUN_LIB");
441 } else {
442 /* application or DLL */
443 t << "\n\t" << var("QMAKE_RUN_LINK");
444 if (!project->isEmpty("RES_FILE") && !project->isEmpty("QMAKE_RUN_RC2EXE")) {
445 t << "\n\t" << var("QMAKE_RUN_RC2EXE");
446 }
447 }
448 if(!project->isEmpty("QMAKE_POST_LINK"))
449 t << "\n\t" <<var("QMAKE_POST_LINK");
450 t << endl;
451}
452
453void GNUMakefileGenerator::writeRcAndDefVariables(QTextStream &t)
454{
455 if (!project->isEmpty("RC_FILE")) {
456 t << "RC_FILE = " << escapeFilePath(var("RC_FILE")) << endl;
457 }
458 if (!project->isEmpty("RES_FILE")) {
459 t << "RES_FILE = " << valList(escapeFilePaths(project->values("RES_FILE"))) << endl;
460 }
461
462 if (project->isEmpty("DEF_FILE")) {
463 /* no DEF file supplied, we will generate one */
464 if (mode == DLL) {
465 t << "DEF_FILE = $(basename $(DESTDIR_TARGET)).def" << endl;
466 project->values("QMAKE_CLEAN").append("$(DEF_FILE)");
467 project->values("POST_TARGETDEPS") += escapeFileVars("$(DEF_FILE)");
468 if (!project->isEmpty("DEF_FILE_TEMPLATE")) {
469 t << "DEF_FILE_TEMPLATE = " << escapeFilePath(var("DEF_FILE_TEMPLATE")) << endl;
470 project->values("QMAKE_GENDEF_DEPS") += escapeFileVars("$(DEF_FILE_TEMPLATE)");
471 }
472 if (!project->isEmpty("DEF_FILE_MAP")) {
473 t << "DEF_FILE_MAP = " << escapeFilePath(var("DEF_FILE_MAP")) << endl;
474 project->values("QMAKE_GENDEF_DEPS") += escapeFileVars("$(DEF_FILE_MAP)");
475 }
476 }
477 } else {
478 if (!project->isEmpty("DEF_FILE_TEMPLATE")) {
479 fprintf(stderr, "Both DEF_FILE and DEF_FILE_TEMPLATE are specified.\n");
480 fprintf(stderr, "Please specify one of them, not both.");
481 exit(1);
482 }
483 t << "DEF_FILE = " << escapeFilePath(var("DEF_FILE")) << endl;
484 project->values("POST_TARGETDEPS") += escapeFileVars("$(DEF_FILE)");
485 }
486
487 if (mode == DLL && !project->isEmpty("QMAKE_RUN_IMPLIB")) {
488 t << "TARGET_IMPLIB = $(basename $(DESTDIR_TARGET)).lib" << endl;
489 project->values("QMAKE_CLEAN").append("$(TARGET_IMPLIB)");
490 project->values("POST_TARGETDEPS") += escapeFileVars("$(TARGET_IMPLIB)");
491 }
492}
493
494void GNUMakefileGenerator::writeRcAndDefPart(QTextStream &t)
495{
496 if (!project->isEmpty("RC_FILE") && !project->isEmpty("RES_FILE") &&
497 !project->isEmpty("QMAKE_RUN_RC2RES")) {
498 t << escapeFileVars("$(RES_FILE): $(RC_FILE)\n\t");
499 t << var("QMAKE_RUN_RC2RES") << endl;
500 }
501
502 if (mode == DLL) {
503 if (project->isEmpty("DEF_FILE")) {
504 /* generate a DEF file for the DLL when not supplied */
505 t << escapeFileVars("$(DEF_FILE): ") << var("QMAKE_GENDEF_DEPS");
506 t << valGlue(var("QMAKE_RUN_GENDEF").split(";;"), "\n\t", "\n\t", "") << endl;
507 }
508 if (!project->isEmpty("QMAKE_RUN_IMPLIB")) {
509 /* generate the import library */
510 t << escapeFileVars("$(TARGET_IMPLIB): ") << escapeFileVars("$(DEF_FILE)");
511 t << "\n\t" << var("QMAKE_RUN_IMPLIB") << endl;
512 }
513 }
514}
515
516void GNUMakefileGenerator::processRcFileVar()
517{
518 if (Option::qmake_mode == Option::QMAKE_GENERATE_NOTHING)
519 return;
520
521 if (!project->isEmpty("RC_FILE")) {
522 if (!project->isEmpty("RES_FILE")) {
523 fprintf(stderr, "Both rc and res file specified.\n");
524 fprintf(stderr, "Please specify one of them, not both.");
525 exit(1);
526 }
527 project->values("RES_FILE").prepend(escapeFilePath(QString("$(OBJECTS_DIR)") +
528 QDir::separator() +
529 QFileInfo(var("RC_FILE")).baseName() +
530 ".res"));
531 project->values("CLEAN_FILES") += "$(RES_FILE)";
532 }
533
534 if (!project->isEmpty("RES_FILE"))
535 project->values("POST_TARGETDEPS") += escapeFileVars("$(RES_FILE)");
536}
537
538void GNUMakefileGenerator::processPrlVariable(const QString &var, const QStringList &l)
539{
540 // we don't do any processing here; everything we need is done in
541 // GNUMakefileGenerator::findLibraries()
542 return;
543}
544
545void GNUMakefileGenerator::processPrlFiles()
546{
547 // we don't do any processing here; everything we need is done in
548 // GNUMakefileGenerator::findLibraries()
549 return;
550}
551
552QStringList &GNUMakefileGenerator::findDependencies(const QString &file)
553{
554 QStringList &aList = MakefileGenerator::findDependencies(file);
555 // Note: The QMAKE_IMAGE_COLLECTION file have all images
556 // as dependency, so don't add precompiled header then
557 if (file == project->first("QMAKE_IMAGE_COLLECTION")
558 || preCompHeaderOut.isEmpty())
559 return aList;
560 for (QStringList::Iterator it = Option::c_ext.begin(); it != Option::c_ext.end(); ++it) {
561 if (file.endsWith(*it)) {
562 QString cHeader = preCompHeaderOut + Option::dir_sep + "c";
563 if (!aList.contains(cHeader))
564 aList += cHeader;
565 break;
566 }
567 }
568 for (QStringList::Iterator it = Option::cpp_ext.begin(); it != Option::cpp_ext.end(); ++it) {
569 if (file.endsWith(*it)) {
570 QString cppHeader = preCompHeaderOut + Option::dir_sep + "c++";
571 if (!aList.contains(cppHeader))
572 aList += cppHeader;
573 break;
574 }
575 }
576 return aList;
577}
578
579void GNUMakefileGenerator::writeProjectVarToStream(QTextStream &t, const QString &var)
580{
581 QStringList &list = project->values(var);
582 for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
583 t << (*it) << endl;
584 }
585}
586
587QString GNUMakefileGenerator::makeResponseFileName(const QString &base)
588{
589 QString fileName = base + "." + var("TARGET");
590 if (!var("BUILD_NAME").isEmpty()) {
591 fileName += "." + var("BUILD_NAME");
592 }
593 fileName += ".rsp";
594 QString filePath = project->first("OBJECTS_DIR");
595 if (filePath.isEmpty())
596 filePath = Option::output_dir;
597 filePath = Option::fixPathToTargetOS(filePath + QDir::separator() + fileName);
598 return filePath;
599}
600
601void GNUMakefileGenerator::createCompilerResponseFiles(QTextStream &t)
602{
603 static const char *vars[] = { "CFLAGS", "CXXFLAGS", "DEFINES", "INCPATH" };
604
605 /* QMAKE_XXX_RSP_VAR is used as a flag whether it is necessary to
606 * generate response files to overcome the 1024 chars CMD.EXE limitation.
607 * When this variable is defined, a response file with the relevant
608 * information will be generated and its full path will be stored in an
609 * environment variable with the given name which can then be referred to in
610 * other places of qmake.conf (e.g. rules) */
611
612 for (size_t i = 0; i < sizeof(vars)/sizeof(vars[0]); ++i) {
613 QString rspVar =
614 project->first(QString().sprintf("QMAKE_%s_RSP_VAR", vars[i]));
615 if (!rspVar.isEmpty()) {
616 QString fileName = makeResponseFileName(vars[i]);
617 t << rspVar.leftJustified(14) << "= " << fileName << endl;
618 QFile file(fileName);
619 if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
620 QTextStream rt(&file);
621 if (!qstrcmp(vars[i], "CFLAGS")) {
622 rt << varGlue("QMAKE_CFLAGS", QString::null, "\n", "\n");
623 } else if (!qstrcmp(vars[i], "CXXFLAGS")) {
624 rt << varGlue("QMAKE_CXXFLAGS", QString::null, "\n", "\n");
625 } else if (!qstrcmp(vars[i], "DEFINES")) {
626 rt << varGlue("PRL_EXPORT_DEFINES", "-D", "\n-D", "\n")
627 << varGlue("DEFINES", "-D", "\n-D", "\n");
628 } else if (!qstrcmp(vars[i], "INCPATH")) {
629 QString opt = var("QMAKE_CFLAGS_INCDIR");
630 rt << varGlue("INCLUDEPATH", opt, "\n" + opt, "\n");
631 } else {
632 Q_ASSERT(false);
633 }
634 rt.flush();
635 file.close();
636 }
637 project->values("QMAKE_DISTCLEAN").append("$(" + rspVar + ")");
638 }
639 }
640}
641
642void GNUMakefileGenerator::createLinkerResponseFiles(QTextStream &t)
643{
644 /* see createCompilerResponseFiles() */
645 QString var = project->first("QMAKE_OBJECTS_RSP_VAR");
646 if (!var.isEmpty()) {
647 QString fileName = makeResponseFileName("OBJECTS");
648 t << var.leftJustified(14) << "= " << fileName << endl;
649 QFile file(fileName);
650 if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
651 QTextStream rt(&file);
652 rt << varGlue("OBJECTS", QString::null, "\n", "\n");
653 rt.flush();
654 file.close();
655 }
656 project->values("QMAKE_DISTCLEAN").append("$(" + var + ")");
657 }
658}
659
660QString GNUMakefileGenerator::escapeFileVars(const QString &vars)
661{
662 /* In DOS environment, we escape spaces and other illegal characters in
663 * filenames with double quotes. However, this is not appropriate for make
664 * rule definitions (targets/dependencies) where Unix escaping is
665 * expected. For this reason, we must convert escaping to Unix mode using
666 * the q function that we define in writeMakefile() */
667 if (isDosLikeShell()) {
668 QString ret = vars;
669 ret.replace(QRegExp("\\$\\((.+)\\)"), "$(call q,$(\\1))");
670 return ret;
671 }
672 return vars;
673}
674
675QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.