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

Last change on this file since 57 was 57, checked in by Dmitry A. Kuminov, 11 years ago

qmake: os2/GNUMAKE: There may be things like -L<some_path> in LIBS variables which would appear as -l-L<some_path> in generated Makefiles; fixed now.

File size: 23.7 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information (qt-info@nokia.com)
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 qt-sales@nokia.com.
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
97bool GNUMakefileGenerator::findLibraries()
98{
99    QStringList &l = project->values("QMAKE_LIBS");
100
101    QList<QMakeLocalFileName> dirs;
102    {
103        QStringList &libpaths = project->values("QMAKE_LIBDIR");
104        for(QStringList::Iterator libpathit = libpaths.begin();
105            libpathit != libpaths.end(); ++libpathit)
106            dirs.append(QMakeLocalFileName((*libpathit)));
107    }
108
109    QStringList::Iterator it = l.begin();
110    while (it != l.end()) {
111        if ((*it).startsWith("-l")) {
112            QString steam = (*it).mid(2), out;
113            QString suffix;
114            if (!project->isEmpty("QMAKE_" + steam.toUpper() + "_SUFFIX"))
115                suffix = project->first("QMAKE_" + steam.toUpper() + "_SUFFIX");
116            for (QList<QMakeLocalFileName>::Iterator dir_it = dirs.begin(); dir_it != dirs.end(); ++dir_it) {
117                QString extension;
118                int ver = findHighestVersion((*dir_it).local(), steam, "dll.lib|lib");
119                if (ver != -1)
120                    extension += QString::number(ver);
121                extension += suffix;
122                if(QMakeMetaInfo::libExists((*dir_it).local() + Option::dir_sep + steam) ||
123                    exists((*dir_it).local() + Option::dir_sep + steam + extension + ".lib") ||
124                    exists((*dir_it).local() + Option::dir_sep + steam + extension + ".dll.lib")) {
125                        out = (*it) + extension;
126                        break;
127                }
128            }
129            if (!out.isEmpty()) // We assume if it never finds it that its correct
130                (*it) = out;
131            } else if((*it).startsWith("-L")) {
132            dirs.append(QMakeLocalFileName((*it).mid(2)));
133        }
134
135        ++it;
136    }
137    return true;
138}
139
140bool GNUMakefileGenerator::writeMakefile(QTextStream &t)
141{
142    writeHeader(t);
143
144    /* function to convert from DOS-like to Unix-like space escaping in file
145     * names */
146    t << "q = $(subst %,\\%,$(subst ;,\\;,$(subst &,\\&,"
147         "$(subst +,\\+,$(subst $(space),\\ ,$(subst \",,$(1)))))))" << endl << endl;
148
149    if(!project->values("QMAKE_FAILED_REQUIREMENTS").isEmpty()) {
150        t << "all clean:" << "\n\t"
151          << "@echo \"Some of the required modules ("
152          << var("QMAKE_FAILED_REQUIREMENTS") << ") are not available.\"" << "\n\t"
153          << "@echo \"Skipped.\"" << endl << endl;
154        writeMakeQmake(t);
155        return true;
156    }
157
158    if(project->first("TEMPLATE") == "app" ||
159       project->first("TEMPLATE") == "lib") {
160        if(Option::mkfile::do_stub_makefile) {
161            t << "QMAKE    = "        << (project->isEmpty("QMAKE_QMAKE") ? QString("qmake") : var("QMAKE_QMAKE")) << endl;
162            QStringList &qut = project->values("QMAKE_EXTRA_TARGETS");
163            for(QStringList::ConstIterator it = qut.begin(); it != qut.end(); ++it)
164                t << *it << " ";
165            t << "first all clean install distclean uninstall: qmake" << endl
166              << "qmake_all:" << endl;
167            writeMakeQmake(t);
168            if(project->isEmpty("QMAKE_NOFORCE"))
169                t << "FORCE:" << endl << endl;
170            return true;
171        }
172        writeGNUParts(t);
173        return MakefileGenerator::writeMakefile(t);
174    }
175    else if(project->first("TEMPLATE") == "subdirs") {
176        writeSubDirs(t);
177        return true;
178    }
179    return false;
180 }
181
182void GNUMakefileGenerator::writeGNUParts(QTextStream &t)
183{
184    t << "QMAKESPECDIR  = " << quote << specdir() << quote << endl << endl;
185
186    writeStandardParts(t);
187
188    if (!preCompHeaderOut.isEmpty()) {
189        QString header = project->first("PRECOMPILED_HEADER");
190        QString cHeader = preCompHeaderOut + Option::dir_sep + "c";
191        t << escapeDependencyPath(cHeader) << ": " << escapeDependencyPath(header) << " "
192            << escapeDependencyPaths(findDependencies(header)).join(" \\\n\t\t")
193            << "\n\t" << mkdir_p_asstring(preCompHeaderOut)
194            << "\n\t" << "$(CC) -x c-header -c $(CFLAGS) $(INCPATH) -o " << cHeader << " " << header
195            << endl << endl;
196        QString cppHeader = preCompHeaderOut + Option::dir_sep + "c++";
197        t << escapeDependencyPath(cppHeader) << ": " << escapeDependencyPath(header) << " "
198            << escapeDependencyPaths(findDependencies(header)).join(" \\\n\t\t")
199            << "\n\t" << mkdir_p_asstring(preCompHeaderOut)
200            << "\n\t" << "$(CXX) -x c++-header -c $(CXXFLAGS) $(INCPATH) -o " << cppHeader << " " << header
201            << endl << endl;
202    }
203}
204
205void GNUMakefileGenerator::init()
206{
207    if(init_flag)
208        return;
209    init_flag = true;
210
211    if(project->first("TEMPLATE") == "app") {
212        mode = App;
213        project->values("QMAKE_APP_FLAG").append("1");
214    } else if(project->first("TEMPLATE") == "lib") {
215        mode = project->isActiveConfig("staticlib") ? StaticLib : DLL;
216        project->values("QMAKE_LIB_FLAG").append("1");
217    } else if(project->first("TEMPLATE") == "subdirs") {
218        MakefileGenerator::init();
219        if(project->isEmpty("QMAKE_COPY_FILE"))
220            project->values("QMAKE_COPY_FILE").append("$(COPY)");
221        if(project->isEmpty("QMAKE_COPY_DIR"))
222            project->values("QMAKE_COPY_DIR").append("$(COPY)");
223        if(project->isEmpty("QMAKE_INSTALL_FILE"))
224            project->values("QMAKE_INSTALL_FILE").append("$(COPY_FILE)");
225        if(project->isEmpty("QMAKE_INSTALL_PROGRAM"))
226            project->values("QMAKE_INSTALL_PROGRAM").append("$(COPY_FILE)");
227        if(project->isEmpty("QMAKE_INSTALL_DIR"))
228            project->values("QMAKE_INSTALL_DIR").append("$(COPY_DIR)");
229        if(project->values("MAKEFILE").isEmpty())
230            project->values("MAKEFILE").append("Makefile");
231        if(project->values("QMAKE_QMAKE").isEmpty())
232            project->values("QMAKE_QMAKE").append("qmake");
233        return;
234    }
235
236    project->values("TARGET_PRL").append(project->first("TARGET"));
237
238    processVars();
239
240    // LIBS defined in Profile comes first for gcc
241    project->values("QMAKE_LIBS") += escapeFilePaths(project->values("LIBS"));
242
243    QString targetfilename = project->values("TARGET").first();
244    QStringList &configs = project->values("CONFIG");
245
246    if(project->isActiveConfig("qt_dll"))
247        if(configs.indexOf("qt") == -1)
248            configs.append("qt");
249
250    if(project->isActiveConfig("dll")) {
251        QString destDir = "";
252        if(!project->first("DESTDIR").isEmpty())
253            destDir = Option::fixPathToTargetOS(project->first("DESTDIR") + Option::dir_sep, false, false);
254    }
255
256    MakefileGenerator::init();
257
258    // precomp
259    if (!project->first("PRECOMPILED_HEADER").isEmpty()
260        && project->isActiveConfig("precompile_header")) {
261        QString preCompHeader = var("PRECOMPILED_DIR")
262                         + QFileInfo(project->first("PRECOMPILED_HEADER")).fileName();
263        preCompHeaderOut = preCompHeader + ".gch";
264        project->values("QMAKE_CLEAN").append(preCompHeaderOut + Option::dir_sep + "c");
265        project->values("QMAKE_CLEAN").append(preCompHeaderOut + Option::dir_sep + "c++");
266
267        project->values("QMAKE_RUN_CC").clear();
268            project->values("QMAKE_RUN_CC").append("$(CC) -c -include " + preCompHeader +
269                                               " $(CFLAGS) $(INCPATH) -o $obj $src");
270        project->values("QMAKE_RUN_CC_IMP").clear();
271        project->values("QMAKE_RUN_CC_IMP").append("$(CC)  -c -include " + preCompHeader +
272                                                   " $(CFLAGS) $(INCPATH) -o $@ $<");
273        project->values("QMAKE_RUN_CXX").clear();
274        project->values("QMAKE_RUN_CXX").append("$(CXX) -c -include " + preCompHeader +
275                                                " $(CXXFLAGS) $(INCPATH) -o $obj $src");
276        project->values("QMAKE_RUN_CXX_IMP").clear();
277        project->values("QMAKE_RUN_CXX_IMP").append("$(CXX) -c -include " + preCompHeader +
278                                                    " $(CXXFLAGS) $(INCPATH) -o $@ $<");
279    }
280}
281
282void GNUMakefileGenerator::fixTargetExt()
283{
284    if (mode == App)
285        project->values("TARGET_EXT").append(".exe");
286    else if (mode == DLL)
287        project->values("TARGET_EXT").append(project->first("TARGET_VERSION_EXT") + ".dll");
288    else
289        project->values("TARGET_EXT").append(".lib");
290}
291
292void GNUMakefileGenerator::writeIncPart(QTextStream &t)
293{
294    t << "INCPATH       =";
295
296    QString opt = var("QMAKE_CFLAGS_INCDIR");
297    QStringList &incs = project->values("INCLUDEPATH");
298    QString incsSemicolon;
299    for(QStringList::Iterator incit = incs.begin(); incit != incs.end(); ++incit) {
300        QString inc = escapeFilePath(*incit);
301        t << " " << opt << inc;
302        incsSemicolon += inc + Option::dirlist_sep;
303    }
304    t << " " << opt << "$(QMAKESPECDIR)" << endl;
305    incsSemicolon += "$(QMAKESPECDIR)";
306    t << "INCLUDEPATH   = " << incsSemicolon << endl;
307    /* createCompilerResponseFiles() will need QAKESPECDIR expanded) */
308    project->values("INCLUDEPATH").append(specdir());
309}
310
311void GNUMakefileGenerator::writeLibsPart(QTextStream &t)
312{
313    if (mode == StaticLib) {
314        t << "LIB           = " << var("QMAKE_LIB") << endl;
315    } else {
316        t << "LINK          = " << var("QMAKE_LINK") << endl;
317        t << "LFLAGS        = " << var("QMAKE_LFLAGS") << endl;
318        t << "LIBS          =";
319        if(!project->values("QMAKE_LIBDIR").isEmpty())
320            writeLibDirPart(t);
321        QString opt = var("QMAKE_LFLAGS_LIB");
322        QString optL = var("QMAKE_LFLAGS_LIBDIR");
323        QStringList libs = project->values("QMAKE_LIBS");
324        for(QStringList::Iterator it = libs.begin(); it != libs.end(); ++it) {
325            QString lib = escapeFilePath(*it);
326            /* lib may be prefixed with -l which is commonly used in e.g. PRF
327             * (feature) files on all platforms; remove it before prepending
328             * the compiler-specific option. There is even more weird case
329             * when LIBS contains library paths prefixed with -L; we detect
330             * this as well and replace it with the proper option. */
331            if (lib.startsWith("-L")) {
332                lib = lib.mid(2);
333                t << " " << optL << lib;
334            } else {
335                if (lib.startsWith("-l"))
336                    lib = lib.mid(2);
337                t << " " << opt << lib;
338            }
339        }
340        t << endl;
341    }
342}
343
344void GNUMakefileGenerator::writeLibDirPart(QTextStream &t)
345{
346    QString opt = var("QMAKE_LFLAGS_LIBDIR");
347    QStringList libDirs = project->values("QMAKE_LIBDIR");
348    for(QStringList::Iterator it = libDirs.begin(); it != libDirs.end(); ++it) {
349        QString libDir = escapeFilePath(*it);
350        /* libDir may be prefixed with -L which is commonly used in e.g. PRF
351         * (feature) files on all platforms; remove it before prepending
352         * the compiler-specific option */
353        if (libDir.startsWith("-L"))
354            libDir = libDir.mid(2);
355        t << " " << opt << libDir;
356    }
357}
358
359void GNUMakefileGenerator::writeObjectsPart(QTextStream &t)
360{
361    Win32MakefileGenerator::writeObjectsPart(t);
362    createLinkerResponseFiles(t);
363
364    /* this function is a nice place to also handle compiler options response
365     * files */
366    createCompilerResponseFiles(t);
367}
368
369void GNUMakefileGenerator::writeBuildRulesPart(QTextStream &t)
370{
371    t << "first: all" << endl;
372    t << "all: " << escapeDependencyPath(fileFixify(Option::output.fileName())) << " " << valGlue(escapeDependencyPaths(project->values("ALL_DEPS"))," "," "," ") << escapeFileVars(" $(DESTDIR_TARGET)") << endl << endl;
373    t << escapeFileVars("$(DESTDIR_TARGET): ") << var("PRE_TARGETDEPS") << " $(OBJECTS) " << var("POST_TARGETDEPS");
374    if (!project->isEmpty("QMAKE_PRE_LINK"))
375        t << "\n\t" <<var("QMAKE_PRE_LINK");
376    if (mode == StaticLib) {
377        /* static library */
378        t << "\n\t" << var("QMAKE_RUN_LIB");
379    } else {
380        /* application or DLL */
381        t << "\n\t" << var("QMAKE_RUN_LINK");
382        if (!project->isEmpty("RES_FILE") && !project->isEmpty("QMAKE_RUN_RC2EXE")) {
383            t << "\n\t" << var("QMAKE_RUN_RC2EXE");
384        }
385        if (mode == DLL && !project->isEmpty("QMAKE_RUN_IMPLIB")) {
386            t << "\n\t" << var("QMAKE_RUN_IMPLIB");
387        }
388    }
389    if(!project->isEmpty("QMAKE_POST_LINK"))
390        t << "\n\t" <<var("QMAKE_POST_LINK");
391    t << endl;
392}
393
394void GNUMakefileGenerator::writeRcAndDefVariables(QTextStream &t)
395{
396    if (!project->isEmpty("RC_FILE")) {
397        t << "RC_FILE       = " << escapeFilePath(var("RC_FILE")) << endl;
398    }
399    if (!project->isEmpty("RES_FILE")) {
400        t << "RES_FILE      = " << valList(escapeFilePaths(project->values("RES_FILE"))) << endl;
401    }
402    if (mode == DLL && !project->isEmpty("QMAKE_RUN_IMPLIB")) {
403        t << "TARGET_IMPLIB = $(basename $(DESTDIR_TARGET)).lib" << endl;
404        project->values("QMAKE_CLEAN").append("$(TARGET_IMPLIB)");
405    }
406
407    if (project->isEmpty("DEF_FILE")) {
408        /* no DEF file supplied, we will generate one */
409        if (mode == DLL) {
410            t << "DEF_FILE      = $(basename $(DESTDIR_TARGET)).def" << endl;
411            project->values("QMAKE_CLEAN").append("$(DEF_FILE)");
412            project->values("POST_TARGETDEPS") += escapeFileVars("$(DEF_FILE)");
413            if (!project->isEmpty("DEF_FILE_TEMPLATE")) {
414                t << "DEF_FILE_TEMPLATE = " << escapeFilePath(var("DEF_FILE_TEMPLATE")) << endl;
415                project->values("QMAKE_GENDEF_DEPS") += escapeFileVars("$(DEF_FILE_TEMPLATE)");
416            }
417            if (!project->isEmpty("DEF_FILE_MAP")) {
418                t << "DEF_FILE_MAP  = " << escapeFilePath(var("DEF_FILE_MAP")) << endl;
419                project->values("QMAKE_GENDEF_DEPS") += escapeFileVars("$(DEF_FILE_MAP)");
420            }
421        }
422    } else {
423        if (!project->isEmpty("DEF_FILE_TEMPLATE")) {
424            fprintf(stderr, "Both DEF_FILE and DEF_FILE_TEMPLATE are specified.\n");
425            fprintf(stderr, "Please specify one of them, not both.");
426            exit(1);
427        }
428        t << "DEF_FILE      = " << escapeFilePath(var("DEF_FILE")) << endl;
429        project->values("POST_TARGETDEPS") += escapeFileVars("$(DEF_FILE)");
430    }
431}
432
433void GNUMakefileGenerator::writeRcAndDefPart(QTextStream &t)
434{
435    if (!project->isEmpty("RC_FILE") && !project->isEmpty("RES_FILE") &&
436        !project->isEmpty("QMAKE_RUN_RC2RES")) {
437        t << escapeFileVars("$(RES_FILE): $(RC_FILE)\n\t");
438        t << var("QMAKE_RUN_RC2RES") << endl;
439    }
440
441    if (project->isEmpty("DEF_FILE") && mode == DLL) {
442        /* generate a DEF file for the DLL when not supplied */
443        t << escapeFileVars("$(DEF_FILE): ") << var("QMAKE_GENDEF_DEPS");
444        t << valGlue(var("QMAKE_RUN_GENDEF").split(";;"), "\n\t", "\n\t", "") << endl;
445    }
446}
447
448void GNUMakefileGenerator::processRcFileVar()
449{
450    if (Option::qmake_mode == Option::QMAKE_GENERATE_NOTHING)
451        return;
452
453    if (!project->isEmpty("RC_FILE")) {
454        if (!project->isEmpty("RES_FILE")) {
455            fprintf(stderr, "Both rc and res file specified.\n");
456            fprintf(stderr, "Please specify one of them, not both.");
457            exit(1);
458        }
459        project->values("RES_FILE").prepend(escapeFilePath(QString("$(OBJECTS_DIR)") +
460                                                           QDir::separator() +
461                                                           QFileInfo(var("RC_FILE")).baseName() +
462                                                           ".res"));
463        project->values("CLEAN_FILES") += "$(RES_FILE)";
464    }
465
466    if (!project->isEmpty("RES_FILE"))
467        project->values("POST_TARGETDEPS") += escapeFileVars("$(RES_FILE)");
468}
469
470void GNUMakefileGenerator::processPrlVariable(const QString &var, const QStringList &l)
471{
472    if (var == "QMAKE_PRL_LIBS") {
473        QString where = "QMAKE_LIBS";
474        if (!project->isEmpty("QMAKE_INTERNAL_PRL_LIBS"))
475            where = project->first("QMAKE_INTERNAL_PRL_LIBS");
476        QStringList &out = project->values(where);
477        for (QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) {
478            out.removeAll((*it));
479            out.append((*it));
480        }
481    } else {
482        Win32MakefileGenerator::processPrlVariable(var, l);
483    }
484}
485
486QStringList &GNUMakefileGenerator::findDependencies(const QString &file)
487{
488    QStringList &aList = MakefileGenerator::findDependencies(file);
489    // Note: The QMAKE_IMAGE_COLLECTION file have all images
490    // as dependency, so don't add precompiled header then
491    if (file == project->first("QMAKE_IMAGE_COLLECTION")
492        || preCompHeaderOut.isEmpty())
493        return aList;
494    for (QStringList::Iterator it = Option::c_ext.begin(); it != Option::c_ext.end(); ++it) {
495        if (file.endsWith(*it)) {
496            QString cHeader = preCompHeaderOut + Option::dir_sep + "c";
497            if (!aList.contains(cHeader))
498                aList += cHeader;
499            break;
500        }
501    }
502    for (QStringList::Iterator it = Option::cpp_ext.begin(); it != Option::cpp_ext.end(); ++it) {
503        if (file.endsWith(*it)) {
504            QString cppHeader = preCompHeaderOut + Option::dir_sep + "c++";
505            if (!aList.contains(cppHeader))
506                aList += cppHeader;
507            break;
508        }
509    }
510    return aList;
511}
512
513void GNUMakefileGenerator::writeProjectVarToStream(QTextStream &t, const QString &var)
514{
515    QStringList &list = project->values(var);
516    for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
517        t << (*it) << endl;
518    }
519}
520
521QString GNUMakefileGenerator::makeResponseFileName(const QString &base)
522{
523    QString fileName = base + "." + var("TARGET");
524    if (!var("BUILD_NAME").isEmpty()) {
525        fileName += "." + var("BUILD_NAME");
526    }
527    fileName += ".rsp";
528    QString filePath = project->first("OBJECTS_DIR");
529    if (filePath.isEmpty())
530        filePath = Option::output_dir;
531    filePath = Option::fixPathToTargetOS(filePath + QDir::separator() + fileName);
532    return filePath;
533}
534
535void GNUMakefileGenerator::createCompilerResponseFiles(QTextStream &t)
536{
537    static const char *vars[] = { "CFLAGS",   /*<=*/ "QMAKE_CFLAGS",
538                                  "CXXFLAGS", /*<=*/ "QMAKE_CXXFLAGS",
539                                  "INCPATH",  /*<=*/ "INCLUDEPATH" };
540
541    /* QMAKE_XXX_RSP_VAR is used as a flag whether it is necessary to
542     * generate response files to overcome the 1024 chars CMD.EXE limitation.
543     * When this variable is defined, a response file with the relevant
544     * information will be generated and its full path will be stored in an
545     * environment variable with the given name which can then be referred to in
546     * other places of qmake.conf (e.g. rules) */
547
548    for (size_t i = 0; i < sizeof(vars)/sizeof(vars[0]); i+=2) {
549        QString rspVar =
550            project->first(QString().sprintf("QMAKE_%s_RSP_VAR", vars[i]));
551        if (!rspVar.isEmpty()) {
552            QString fileName = makeResponseFileName(vars[i]);
553            t << rspVar.leftJustified(14) << "= " << fileName << endl;
554            QFile file(fileName);
555            if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
556                QTextStream rt(&file);
557                if (!qstrcmp(vars[i+1], "INCLUDEPATH")) {
558                    QString opt = var("QMAKE_CFLAGS_INCDIR");
559                    rt << varGlue(vars[i+1], opt, "\n" + opt, "\n");
560                } else {
561                    rt << varGlue(vars[i+1], QString::null, "\n", "\n")
562                       << varGlue("PRL_EXPORT_DEFINES", "-D", "\n-D", "\n")
563                       << varGlue("DEFINES", "-D", "\n-D", "\n");
564                }
565                rt.flush();
566                file.close();
567            }
568            project->values("QMAKE_DISTCLEAN").append("$(" + rspVar + ")");
569        }
570    }
571}
572
573void GNUMakefileGenerator::createLinkerResponseFiles(QTextStream &t)
574{
575    /* see createCompilerResponseFiles() */
576    QString var = project->first("QMAKE_OBJECTS_RSP_VAR");
577    if (!var.isEmpty()) {
578        QString fileName = makeResponseFileName("OBJECTS");
579        t << var.leftJustified(14) << "= " << fileName << endl;
580        QFile file(fileName);
581        if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
582            QTextStream rt(&file);
583            rt << varGlue("OBJECTS", QString::null, "\n", "\n");
584            rt.flush();
585            file.close();
586        }
587        project->values("QMAKE_DISTCLEAN").append("$(" + var + ")");
588    }
589}
590
591QString GNUMakefileGenerator::escapeFileVars(const QString &vars)
592{
593    /* In DOS environment, we escape spaces and other illegal characters in
594     * filenames with double quotes. However, this is not appropriate for make
595     * rule definitions (targets/dependencies) where Unix escaping is
596     * expected. For this reason, we must convert escaping to Unix mode using
597     * the q function that we define in writeMakefile() */
598    if (isDosLikeShell()) {
599        QString ret = vars;
600        ret.replace(QRegExp("\\$\\((.+)\\)"), "$(call q,$(\\1))");
601        return ret;
602    }
603    return vars;
604}
605
606QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.