/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the qmake application of the Qt Toolkit. ** ** Copyright (C) 2009 netlabs.org. OS/2 parts. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain ** additional rights. These rights are described in the Nokia Qt LGPL ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "gnumake.h" #include "option.h" #include "meta.h" #include #include #include #include QT_BEGIN_NAMESPACE GNUMakefileGenerator::GNUMakefileGenerator() : Win32MakefileGenerator(), init_flag(false) { if (isDosLikeShell()) quote = "\""; else quote = "'"; } bool GNUMakefileGenerator::isDosLikeShell() const { #ifdef Q_OS_OS2 return Option::shellPath.isEmpty(); #else return Win32MakefileGenerator::isDosLikeShell(); #endif } QString GNUMakefileGenerator::escapeFilePath(const QString &path) const { QString ret = path; if (!isDosLikeShell()) { ret.remove('\"'); ret.replace('\\', "/"); ret.replace(' ', "\\ "); } else { ret = Option::fixPathToTargetOS(ret, false); ret.replace(QRegExp("\""), ""); ret.replace(QRegExp("[\\\\/]$"), ""); if (ret.contains(QRegExp("[ +&;%]"))) ret = quote + ret + quote; } return ret; } QString GNUMakefileGenerator::escapeDependencyPath(const QString &path) const { // dependency escaping is always done Unix-way since this is a requirement // of GNU make which allows " and ' to be part of the file name. // Note that if the string is a make variable reference, we don't eascape! QString ret = path; QString trimmed = path.trimmed(); if (!trimmed.startsWith("$(") || !trimmed.endsWith(")")) { ret.remove('\"'); ret.replace(' ', "\\ "); } return ret; } QString GNUMakefileGenerator::findBestVersion(const QString &d, const QString &stem, const QString &ext) { QString bd = Option::fixPathToLocalOS(d, true); if(!exists(bd)) return QString(); QString dllStem = stem + QTDLL_POSTFIX; QString versionOverride; if(!project->values("QMAKE_" + stem.toUpper() + "_VERSION_OVERRIDE").isEmpty()) versionOverride = project->values("QMAKE_" + stem.toUpper() + "_VERSION_OVERRIDE").first(); if (project->isActiveConfig("link_prl")) { QMakeMetaInfo libinfo; QString libfile = QMakeMetaInfo::findLib(bd + Option::dir_sep + dllStem); if (project->values("QMAKE_PRL_INTERNAL_FILES").contains(libfile)) { // already processed, return emtpy string to discard this lib return QString(""); } if (libinfo.readLib(libfile)) { project->values("QMAKE_PRL_INTERNAL_FILES") += libfile; QString target = libinfo.first("QMAKE_PRL_TARGET"); if (target == project->first("TARGET")) { // circular reference to ourselves, return emtpy string to discard this lib return QString(""); } if (target.isEmpty()) target = dllStem; if (!versionOverride.isEmpty()) target += versionOverride; else if (!libinfo.values("QMAKE_PRL_CONFIG").contains("staticlib") && !libinfo.isEmpty("QMAKE_PRL_VERSION")) target += libinfo.first("QMAKE_PRL_VERSION").replace(".", ""); const QStringList &in = libinfo.values("QMAKE_PRL_LIBS"); QStringList &out = project->values("QMAKE_PRL_LIBS"); for (QStringList::ConstIterator it = in.begin(); it != in.end(); ++it) { if (!out.contains(*it)) out.append((*it)); } return target; } } if (!versionOverride.isEmpty()) return stem + versionOverride; int biggest = -1; if(!project->isActiveConfig("no_versionlink")) { QDir dir(bd); QStringList entries = dir.entryList(); QRegExp regx(QString("((lib)?%1([0-9]*))(%2)$").arg(dllStem).arg(ext), Qt::CaseInsensitive); for(QStringList::Iterator it = entries.begin(); it != entries.end(); ++it) { if(regx.exactMatch((*it))) { if (!regx.cap(3).isEmpty()) { bool ok = true; int num = regx.cap(3).toInt(&ok); biggest = qMax(biggest, (!ok ? -1 : num)); } } } } if (biggest != -1) return stem + QString::number(biggest); return QString(); } bool GNUMakefileGenerator::findLibraries() { QStringList &l = project->values("QMAKE_LIBS"); QList dirs; { QStringList &libpaths = project->values("QMAKE_LIBDIR"); for(QStringList::Iterator libpathit = libpaths.begin(); libpathit != libpaths.end(); ++libpathit) dirs.append(QMakeLocalFileName((*libpathit))); } QStringList::Iterator it = l.begin(); do { project->values("QMAKE_PRL_LIBS").clear(); bool erase = false; for (; it != l.end(); erase ? (erase = false, it = l.erase(it)) : ++it) { if((*it).startsWith("-L")) { dirs.append(QMakeLocalFileName((*it).mid(2))); } else { QString stem = *it, out; if (stem.startsWith("-l")) stem = stem.mid(2); QString suffix; if (!project->isEmpty("QMAKE_" + stem.toUpper() + "_SUFFIX")) suffix = project->first("QMAKE_" + stem.toUpper() + "_SUFFIX"); for (QList::Iterator dir_it = dirs.begin(); dir_it != dirs.end(); ++dir_it) { QString best = findBestVersion((*dir_it).local(), stem, QString("%1.lib").arg(suffix)); if (!best.isNull()) { if (best.isEmpty()) { // we are asked to discard this lib, do it erase = true; break; } out = best.prepend("-l"); break; } } if (!out.isEmpty()) // We assume if it never finds it then its correct if (!project->values("QMAKE_LIBS").contains(out)) (*it) = out; } } // add the libraries from PRL and process them normally QStringList l2 = project->values("QMAKE_PRL_LIBS"); int oldSize = l.size(); for (QStringList::ConstIterator it2 = l2.begin(); it2 != l2.end(); ++it2) { if (!l.contains(*it2)) l.append(*it2); } it = l.begin() + oldSize; } while(it != l.end()); return true; } bool GNUMakefileGenerator::writeMakefile(QTextStream &t) { writeHeader(t); /* function to convert from DOS-like to Unix-like space escaping in file * names */ t << "null :=" << endl << "space := $(null) # end of the line" << endl; t << "# function to change DOS-like space escaping to Unix-like" << endl; t << "q = $(subst %,\\%,$(subst ;,\\;,$(subst &,\\&," "$(subst +,\\+,$(subst $(space),\\ ,$(subst \",,$(1)))))))" << endl << endl; if(!project->values("QMAKE_FAILED_REQUIREMENTS").isEmpty()) { t << "all clean:" << "\n\t" << "@echo \"Some of the required modules (" << var("QMAKE_FAILED_REQUIREMENTS") << ") are not available.\"" << "\n\t" << "@echo \"Skipped.\"" << endl << endl; writeMakeQmake(t); return true; } if(project->first("TEMPLATE") == "app" || project->first("TEMPLATE") == "lib") { if(Option::mkfile::do_stub_makefile) { t << "QMAKE = " << (project->isEmpty("QMAKE_QMAKE") ? QString("qmake") : var("QMAKE_QMAKE")) << endl; QStringList &qut = project->values("QMAKE_EXTRA_TARGETS"); for(QStringList::ConstIterator it = qut.begin(); it != qut.end(); ++it) t << *it << " "; t << "first all clean install distclean uninstall: qmake" << endl << "qmake_all:" << endl; writeMakeQmake(t); if(project->isEmpty("QMAKE_NOFORCE")) t << "FORCE:" << endl << endl; return true; } writeGNUParts(t); return MakefileGenerator::writeMakefile(t); } else if(project->first("TEMPLATE") == "subdirs") { writeSubDirs(t); return true; } return false; } void GNUMakefileGenerator::writeGNUParts(QTextStream &t) { t << "QMAKESPECDIR = " << escapeFilePath(specdir()) << endl; QString ofile = escapeFilePath(Option::output.fileName()); if(ofile.lastIndexOf(Option::dir_sep) != -1) ofile = ofile.right(ofile.length() - ofile.lastIndexOf(Option::dir_sep) -1); t << "MAKEFILE = " << ofile << endl << endl; writeStandardParts(t); if (!preCompHeaderOut.isEmpty()) { QString header = project->first("PRECOMPILED_HEADER"); QString cHeader = preCompHeaderOut + Option::dir_sep + "c"; t << escapeDependencyPath(cHeader) << ": " << escapeDependencyPath(header) << " " << escapeDependencyPaths(findDependencies(header)).join(" \\\n\t\t") << "\n\t" << mkdir_p_asstring(preCompHeaderOut) << "\n\t" << "$(CC) -x c-header -c $(CFLAGS) $(INCPATH) -o " << cHeader << " " << header << endl << endl; QString cppHeader = preCompHeaderOut + Option::dir_sep + "c++"; t << escapeDependencyPath(cppHeader) << ": " << escapeDependencyPath(header) << " " << escapeDependencyPaths(findDependencies(header)).join(" \\\n\t\t") << "\n\t" << mkdir_p_asstring(preCompHeaderOut) << "\n\t" << "$(CXX) -x c++-header -c $(CXXFLAGS) $(INCPATH) -o " << cppHeader << " " << header << endl << endl; } } void GNUMakefileGenerator::init() { if(init_flag) return; init_flag = true; if(project->first("TEMPLATE") == "app") { mode = App; project->values("QMAKE_APP_FLAG").append("1"); } else if(project->first("TEMPLATE") == "lib") { mode = project->isActiveConfig("staticlib") ? StaticLib : DLL; project->values("QMAKE_LIB_FLAG").append("1"); } else if(project->first("TEMPLATE") == "subdirs") { MakefileGenerator::init(); if(project->isEmpty("QMAKE_COPY_FILE")) project->values("QMAKE_COPY_FILE").append("$(COPY)"); if(project->isEmpty("QMAKE_COPY_DIR")) project->values("QMAKE_COPY_DIR").append("$(COPY)"); if(project->isEmpty("QMAKE_INSTALL_FILE")) project->values("QMAKE_INSTALL_FILE").append("$(COPY_FILE)"); if(project->isEmpty("QMAKE_INSTALL_PROGRAM")) project->values("QMAKE_INSTALL_PROGRAM").append("$(COPY_FILE)"); if(project->isEmpty("QMAKE_INSTALL_DIR")) project->values("QMAKE_INSTALL_DIR").append("$(COPY_DIR)"); if(project->values("MAKEFILE").isEmpty()) project->values("MAKEFILE").append("Makefile"); if(project->values("QMAKE_QMAKE").isEmpty()) project->values("QMAKE_QMAKE").append("qmake"); return; } project->values("TARGET_PRL").append(project->first("TARGET")); processVars(); // LIBS defined in Profile comes first for gcc project->values("QMAKE_LIBS") += escapeFilePaths(project->values("LIBS")); QStringList &configs = project->values("CONFIG"); if(project->isActiveConfig("qt_dll")) if(configs.indexOf("qt") == -1) configs.append("qt"); if(project->isActiveConfig("dll")) { QString destDir = ""; if(!project->first("DESTDIR").isEmpty()) destDir = Option::fixPathToTargetOS(project->first("DESTDIR") + Option::dir_sep, false, false); } MakefileGenerator::init(); // precomp if (!project->first("PRECOMPILED_HEADER").isEmpty() && project->isActiveConfig("precompile_header")) { QString preCompHeader = var("PRECOMPILED_DIR") + QFileInfo(project->first("PRECOMPILED_HEADER")).fileName(); preCompHeaderOut = preCompHeader + ".gch"; project->values("QMAKE_CLEAN").append(preCompHeaderOut + Option::dir_sep + "c"); project->values("QMAKE_CLEAN").append(preCompHeaderOut + Option::dir_sep + "c++"); project->values("QMAKE_RUN_CC").clear(); project->values("QMAKE_RUN_CC").append("$(CC) -c -include " + preCompHeader + " $(CFLAGS) $(INCPATH) -o $obj $src"); project->values("QMAKE_RUN_CC_IMP").clear(); project->values("QMAKE_RUN_CC_IMP").append("$(CC) -c -include " + preCompHeader + " $(CFLAGS) $(INCPATH) -o $@ $<"); project->values("QMAKE_RUN_CXX").clear(); project->values("QMAKE_RUN_CXX").append("$(CXX) -c -include " + preCompHeader + " $(CXXFLAGS) $(INCPATH) -o $obj $src"); project->values("QMAKE_RUN_CXX_IMP").clear(); project->values("QMAKE_RUN_CXX_IMP").append("$(CXX) -c -include " + preCompHeader + " $(CXXFLAGS) $(INCPATH) -o $@ $<"); } } void GNUMakefileGenerator::fixTargetExt() { if (mode == App) project->values("TARGET_EXT").append(".exe"); else if (mode == DLL) project->values("TARGET_EXT").append(project->first("TARGET_VERSION_EXT") + ".dll"); else project->values("TARGET_EXT").append(".lib"); } void GNUMakefileGenerator::writeIncPart(QTextStream &t) { t << "INCPATH ="; QString opt = var("QMAKE_CFLAGS_INCDIR"); QStringList &incs = project->values("INCLUDEPATH"); QString incsSemicolon; for(QStringList::Iterator incit = incs.begin(); incit != incs.end(); ++incit) { QString inc = escapeFilePath(*incit); t << " " << opt << inc; incsSemicolon += inc + Option::dirlist_sep; } t << " " << opt << "$(QMAKESPECDIR)" << endl; incsSemicolon += "$(QMAKESPECDIR)"; t << "INCLUDEPATH = " << incsSemicolon << endl; /* createCompilerResponseFiles() will need QAKESPECDIR expanded) */ project->values("INCLUDEPATH").append(specdir()); } void GNUMakefileGenerator::writeLibsPart(QTextStream &t) { if (mode == StaticLib) { t << "LIB = " << var("QMAKE_LIB") << endl; } else { t << "LINK = " << var("QMAKE_LINK") << endl; t << "LFLAGS = " << var("QMAKE_LFLAGS") << endl; t << "LIBS ="; if(!project->values("QMAKE_LIBDIR").isEmpty()) writeLibDirPart(t); QString opt = var("QMAKE_LFLAGS_LIB"); QString optL = var("QMAKE_LFLAGS_LIBDIR"); QStringList libs = project->values("QMAKE_LIBS"); for(QStringList::Iterator it = libs.begin(); it != libs.end(); ++it) { QString lib = escapeFilePath(*it); /* lib may be prefixed with -l which is commonly used in e.g. PRF * (feature) files on all platforms; remove it before prepending * the compiler-specific option. There is even more weird case * when LIBS contains library paths prefixed with -L; we detect * this as well and replace it with the proper option. */ if (lib.startsWith("-L")) { lib = lib.mid(2); t << " " << optL << lib; } else { if (lib.startsWith("-l")) lib = lib.mid(2); t << " " << opt << lib; } } t << endl; } } void GNUMakefileGenerator::writeLibDirPart(QTextStream &t) { QString opt = var("QMAKE_LFLAGS_LIBDIR"); QStringList libDirs = project->values("QMAKE_LIBDIR"); for(QStringList::Iterator it = libDirs.begin(); it != libDirs.end(); ++it) { QString libDir = escapeFilePath(*it); /* libDir may be prefixed with -L which is commonly used in e.g. PRF * (feature) files on all platforms; remove it before prepending * the compiler-specific option */ if (libDir.startsWith("-L")) libDir = libDir.mid(2); t << " " << opt << libDir; } } void GNUMakefileGenerator::writeObjectsPart(QTextStream &t) { Win32MakefileGenerator::writeObjectsPart(t); createLinkerResponseFiles(t); /* this function is a nice place to also handle compiler options response * files */ createCompilerResponseFiles(t); } void GNUMakefileGenerator::writeBuildRulesPart(QTextStream &t) { t << "first: all" << endl; t << "all: " << escapeDependencyPath(fileFixify(Option::output.fileName())) << " " << valGlue(escapeDependencyPaths(project->values("ALL_DEPS"))," "," "," ") << escapeFileVars(" $(DESTDIR_TARGET)") << endl << endl; t << escapeFileVars("$(DESTDIR_TARGET): ") << var("PRE_TARGETDEPS") << " $(OBJECTS) " << var("POST_TARGETDEPS"); if (!project->isEmpty("QMAKE_PRE_LINK")) t << "\n\t" <isEmpty("RES_FILE") && !project->isEmpty("QMAKE_RUN_RC2EXE")) { t << "\n\t" << var("QMAKE_RUN_RC2EXE"); } } if(!project->isEmpty("QMAKE_POST_LINK")) t << "\n\t" <isEmpty("RC_FILE")) { t << "RC_FILE = " << escapeFilePath(var("RC_FILE")) << endl; } if (!project->isEmpty("RES_FILE")) { t << "RES_FILE = " << valList(escapeFilePaths(project->values("RES_FILE"))) << endl; } if (project->isEmpty("DEF_FILE")) { /* no DEF file supplied, we will generate one */ if (mode == DLL) { t << "DEF_FILE = $(basename $(DESTDIR_TARGET)).def" << endl; project->values("QMAKE_CLEAN").append("$(DEF_FILE)"); project->values("POST_TARGETDEPS") += escapeFileVars("$(DEF_FILE)"); if (!project->isEmpty("DEF_FILE_TEMPLATE")) { t << "DEF_FILE_TEMPLATE = " << escapeFilePath(var("DEF_FILE_TEMPLATE")) << endl; project->values("QMAKE_GENDEF_DEPS") += escapeFileVars("$(DEF_FILE_TEMPLATE)"); } if (!project->isEmpty("DEF_FILE_MAP")) { t << "DEF_FILE_MAP = " << escapeFilePath(var("DEF_FILE_MAP")) << endl; project->values("QMAKE_GENDEF_DEPS") += escapeFileVars("$(DEF_FILE_MAP)"); } } } else { if (!project->isEmpty("DEF_FILE_TEMPLATE")) { fprintf(stderr, "Both DEF_FILE and DEF_FILE_TEMPLATE are specified.\n"); fprintf(stderr, "Please specify one of them, not both."); exit(1); } t << "DEF_FILE = " << escapeFilePath(var("DEF_FILE")) << endl; project->values("POST_TARGETDEPS") += escapeFileVars("$(DEF_FILE)"); } if (mode == DLL && !project->isEmpty("QMAKE_RUN_IMPLIB")) { t << "TARGET_IMPLIB = $(basename $(DESTDIR_TARGET)).lib" << endl; project->values("QMAKE_CLEAN").append("$(TARGET_IMPLIB)"); project->values("POST_TARGETDEPS") += escapeFileVars("$(TARGET_IMPLIB)"); } } void GNUMakefileGenerator::writeRcAndDefPart(QTextStream &t) { if (!project->isEmpty("RC_FILE") && !project->isEmpty("RES_FILE") && !project->isEmpty("QMAKE_RUN_RC2RES")) { t << escapeFileVars("$(RES_FILE): $(RC_FILE)\n\t"); t << var("QMAKE_RUN_RC2RES") << endl; } if (mode == DLL) { if (project->isEmpty("DEF_FILE")) { /* generate a DEF file for the DLL when not supplied */ t << escapeFileVars("$(DEF_FILE): ") << var("QMAKE_GENDEF_DEPS"); t << valGlue(var("QMAKE_RUN_GENDEF").split(";;"), "\n\t", "\n\t", "") << endl; } if (!project->isEmpty("QMAKE_RUN_IMPLIB")) { /* generate the import library */ t << escapeFileVars("$(TARGET_IMPLIB): ") << escapeFileVars("$(DEF_FILE)"); t << "\n\t" << var("QMAKE_RUN_IMPLIB") << endl; } } } void GNUMakefileGenerator::processRcFileVar() { if (Option::qmake_mode == Option::QMAKE_GENERATE_NOTHING) return; if (!project->isEmpty("RC_FILE")) { if (!project->isEmpty("RES_FILE")) { fprintf(stderr, "Both rc and res file specified.\n"); fprintf(stderr, "Please specify one of them, not both."); exit(1); } project->values("RES_FILE").prepend(escapeFilePath(QString("$(OBJECTS_DIR)") + QDir::separator() + QFileInfo(var("RC_FILE")).baseName() + ".res")); project->values("CLEAN_FILES") += "$(RES_FILE)"; } if (!project->isEmpty("RES_FILE")) project->values("POST_TARGETDEPS") += escapeFileVars("$(RES_FILE)"); } void GNUMakefileGenerator::processPrlVariable(const QString &var, const QStringList &l) { // we don't do any processing here; everything we need is done in // GNUMakefileGenerator::findLibraries() return; } void GNUMakefileGenerator::processPrlFiles() { // we don't do any processing here; everything we need is done in // GNUMakefileGenerator::findLibraries() return; } QStringList &GNUMakefileGenerator::findDependencies(const QString &file) { QStringList &aList = MakefileGenerator::findDependencies(file); // Note: The QMAKE_IMAGE_COLLECTION file have all images // as dependency, so don't add precompiled header then if (file == project->first("QMAKE_IMAGE_COLLECTION") || preCompHeaderOut.isEmpty()) return aList; for (QStringList::Iterator it = Option::c_ext.begin(); it != Option::c_ext.end(); ++it) { if (file.endsWith(*it)) { QString cHeader = preCompHeaderOut + Option::dir_sep + "c"; if (!aList.contains(cHeader)) aList += cHeader; break; } } for (QStringList::Iterator it = Option::cpp_ext.begin(); it != Option::cpp_ext.end(); ++it) { if (file.endsWith(*it)) { QString cppHeader = preCompHeaderOut + Option::dir_sep + "c++"; if (!aList.contains(cppHeader)) aList += cppHeader; break; } } return aList; } void GNUMakefileGenerator::writeProjectVarToStream(QTextStream &t, const QString &var) { QStringList &list = project->values(var); for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { t << (*it) << endl; } } QString GNUMakefileGenerator::makeResponseFileName(const QString &base) { QString fileName = base + "." + var("TARGET"); if (!var("BUILD_NAME").isEmpty()) { fileName += "." + var("BUILD_NAME"); } fileName += ".rsp"; QString filePath = project->first("OBJECTS_DIR"); if (filePath.isEmpty()) filePath = Option::output_dir; filePath = Option::fixPathToTargetOS(filePath + QDir::separator() + fileName); return filePath; } void GNUMakefileGenerator::createCompilerResponseFiles(QTextStream &t) { static const char *vars[] = { "CFLAGS", "CXXFLAGS", "DEFINES", "INCPATH" }; /* QMAKE_XXX_RSP_VAR is used as a flag whether it is necessary to * generate response files to overcome the 1024 chars CMD.EXE limitation. * When this variable is defined, a response file with the relevant * information will be generated and its full path will be stored in an * environment variable with the given name which can then be referred to in * other places of qmake.conf (e.g. rules) */ for (size_t i = 0; i < sizeof(vars)/sizeof(vars[0]); ++i) { QString rspVar = project->first(QString().sprintf("QMAKE_%s_RSP_VAR", vars[i])); if (!rspVar.isEmpty()) { QString fileName = makeResponseFileName(vars[i]); t << rspVar.leftJustified(14) << "= " << fileName << endl; QFile file(fileName); if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream rt(&file); if (!qstrcmp(vars[i], "CFLAGS")) { rt << varGlue("QMAKE_CFLAGS", QString::null, "\n", "\n"); } else if (!qstrcmp(vars[i], "CXXFLAGS")) { rt << varGlue("QMAKE_CXXFLAGS", QString::null, "\n", "\n"); } else if (!qstrcmp(vars[i], "DEFINES")) { rt << varGlue("PRL_EXPORT_DEFINES", "-D", "\n-D", "\n") << varGlue("DEFINES", "-D", "\n-D", "\n"); } else if (!qstrcmp(vars[i], "INCPATH")) { QString opt = var("QMAKE_CFLAGS_INCDIR"); rt << varGlue("INCLUDEPATH", opt, "\n" + opt, "\n"); } else { Q_ASSERT(false); } rt.flush(); file.close(); } project->values("QMAKE_DISTCLEAN").append("$(" + rspVar + ")"); } } } void GNUMakefileGenerator::createLinkerResponseFiles(QTextStream &t) { /* see createCompilerResponseFiles() */ QString var = project->first("QMAKE_OBJECTS_RSP_VAR"); if (!var.isEmpty()) { QString fileName = makeResponseFileName("OBJECTS"); t << var.leftJustified(14) << "= " << fileName << endl; QFile file(fileName); if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream rt(&file); rt << varGlue("OBJECTS", QString::null, "\n", "\n"); rt.flush(); file.close(); } project->values("QMAKE_DISTCLEAN").append("$(" + var + ")"); } } QString GNUMakefileGenerator::escapeFileVars(const QString &vars) { /* In DOS environment, we escape spaces and other illegal characters in * filenames with double quotes. However, this is not appropriate for make * rule definitions (targets/dependencies) where Unix escaping is * expected. If we'd deal only with immediate strings, we could provide * necessary escaping in place, but we often use make variables instead of * direct file names so we must perform such escaping on the fly. This is * what we do here using the q function that we define in writeMakefile().*/ if (isDosLikeShell()) { QString ret = vars; QRegExp rx = QRegExp("\\$\\((.+)\\)"); rx.setMinimal(true); ret.replace(rx, "$(call q,$(\\1))"); return ret; } return vars; } QT_END_NAMESPACE