diff options
Diffstat (limited to 'qmake/generators/win32/winmakefile.cpp')
-rw-r--r-- | qmake/generators/win32/winmakefile.cpp | 315 |
1 files changed, 107 insertions, 208 deletions
diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp index 386e2865fa..1fba7057ab 100644 --- a/qmake/generators/win32/winmakefile.cpp +++ b/qmake/generators/win32/winmakefile.cpp @@ -49,215 +49,125 @@ Win32MakefileGenerator::Win32MakefileGenerator() : MakefileGenerator() { } -int -Win32MakefileGenerator::findHighestVersion(const QString &d, const QString &stem, const QString &ext) +ProString Win32MakefileGenerator::fixLibFlag(const ProString &lib) { - QString bd = Option::normalizePath(d); - if(!exists(bd)) - return -1; - - QMakeMetaInfo libinfo(project); - bool libInfoRead = libinfo.readLib(bd + '/' + stem); - - // If the library, for which we're trying to find the highest version - // number, is a static library - if (libInfoRead && libinfo.values("QMAKE_PRL_CONFIG").contains("staticlib")) - return -1; - - const ProStringList &vover = project->values(ProKey("QMAKE_" + stem.toUpper() + "_VERSION_OVERRIDE")); - if (!vover.isEmpty()) - return vover.first().toInt(); - - int biggest=-1; - if (project->isActiveConfig("link_highest_lib_version")) { - static QHash<QString, QStringList> dirEntryListCache; - QStringList entries = dirEntryListCache.value(bd); - if (entries.isEmpty()) { - QDir dir(bd); - entries = dir.entryList(); - dirEntryListCache.insert(bd, entries); - } - - QRegExp regx(QString("((lib)?%1([0-9]*)).(%2|prl)$").arg(stem).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(libInfoRead - && !libinfo.values("QMAKE_PRL_CONFIG").contains("staticlib") - && !libinfo.isEmpty("QMAKE_PRL_VERSION")) - biggest = qMax(biggest, libinfo.first("QMAKE_PRL_VERSION").toQString().replace(".", "").toInt()); - return biggest; + if (lib.startsWith("-l")) // Fallback for unresolved -l libs. + return escapeFilePath(lib.mid(2) + QLatin1String(".lib")); + if (lib.startsWith("-L")) // Lib search path. Needed only by -l above. + return QLatin1String("/LIBPATH:") + + escapeFilePath(Option::fixPathToTargetOS(lib.mid(2).toQString(), false)); + return escapeFilePath(Option::fixPathToTargetOS(lib.toQString(), false)); } -ProString Win32MakefileGenerator::fixLibFlag(const ProString &lib) +MakefileGenerator::LibFlagType +Win32MakefileGenerator::parseLibFlag(const ProString &flag, ProString *arg) { - if (lib.startsWith('/')) { - if (lib.startsWith("/LIBPATH:")) - return QLatin1String("/LIBPATH:") - + escapeFilePath(Option::fixPathToTargetOS(lib.mid(9).toQString(), false)); - // This appears to be a user-supplied flag. Assume sufficient quoting. - return lib; + LibFlagType ret = MakefileGenerator::parseLibFlag(flag, arg); + if (ret != LibFlagFile) + return ret; + // MSVC compatibility. This should be deprecated. + if (flag.startsWith("/LIBPATH:")) { + *arg = flag.mid(9); + return LibFlagPath; } - // This must be a fully resolved library path. - return escapeFilePath(Option::fixPathToTargetOS(lib.toQString(), false)); + // These are pure qmake inventions. They *really* should be deprecated. + if (flag.startsWith("/L")) { + *arg = flag.mid(2); + return LibFlagPath; + } + if (flag.startsWith("/l")) { + *arg = flag.mid(2); + return LibFlagLib; + } + return LibFlagFile; } bool -Win32MakefileGenerator::findLibraries() +Win32MakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags) { + ProStringList impexts = project->values("QMAKE_LIB_EXTENSIONS"); + if (impexts.isEmpty()) + impexts = project->values("QMAKE_EXTENSION_STATICLIB"); QList<QMakeLocalFileName> dirs; static const char * const lflags[] = { "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", 0 }; for (int i = 0; lflags[i]; i++) { ProStringList &l = project->values(lflags[i]); for (ProStringList::Iterator it = l.begin(); it != l.end();) { - bool remove = false; - QString opt = (*it).trimmed().toQString(); - if(opt.startsWith("/LIBPATH:")) { - QString libpath = opt.mid(9); - QMakeLocalFileName l(libpath); - if (!dirs.contains(l)) { - dirs.append(l); - (*it) = "/LIBPATH:" + l.real(); - } else { - remove = true; - } - } else if(opt.startsWith("-L") || opt.startsWith("/L")) { - QString libpath = Option::fixPathToTargetOS(opt.mid(2), false, false); - QMakeLocalFileName l(libpath); - if(!dirs.contains(l)) { - dirs.append(l); - (*it) = "/LIBPATH:" + l.real(); - } else { - remove = true; + const ProString &opt = *it; + ProString arg; + LibFlagType type = parseLibFlag(opt, &arg); + if (type == LibFlagPath) { + QMakeLocalFileName lp(arg.toQString()); + if (dirs.contains(lp)) { + it = l.erase(it); + continue; } - } else if(opt.startsWith("-l") || opt.startsWith("/l")) { - QString lib = opt.right(opt.length() - 2), out; - if(!lib.isEmpty()) { - ProString suffix = project->first(ProKey("QMAKE_" + lib.toUpper() + "_SUFFIX")); - for(QList<QMakeLocalFileName>::Iterator it = dirs.begin(); - it != dirs.end(); ++it) { - QString extension; - int ver = findHighestVersion((*it).local(), lib); - if(ver > 0) - extension += QString::number(ver); - extension += suffix; - extension += ".lib"; - if (QMakeMetaInfo::libExists((*it).local() + '/' + lib) - || exists((*it).local() + '/' + lib + extension)) { - out = (*it).real() + Option::dir_sep + lib + extension; - break; + dirs.append(lp); + (*it) = "-L" + lp.real(); + } else if (type == LibFlagLib) { + QString lib = arg.toQString(); + ProString verovr = + project->first(ProKey("QMAKE_" + lib.toUpper() + "_VERSION_OVERRIDE")); + for (QList<QMakeLocalFileName>::Iterator dir_it = dirs.begin(); + dir_it != dirs.end(); ++dir_it) { + QString cand = (*dir_it).real() + Option::dir_sep + lib; + if (linkPrl && processPrlFile(cand)) { + (*it) = cand; + goto found; + } + QString libBase = (*dir_it).local() + '/' + lib + verovr; + for (ProStringList::ConstIterator extit = impexts.begin(); + extit != impexts.end(); ++extit) { + if (exists(libBase + '.' + *extit)) { + (*it) = cand + verovr + '.' + *extit; + goto found; } } } - if(out.isEmpty()) - out = lib + ".lib"; - (*it) = out; - } else if (!exists(Option::normalizePath(opt))) { - QList<QMakeLocalFileName> lib_dirs; - QString file = Option::fixPathToTargetOS(opt); - int slsh = file.lastIndexOf(Option::dir_sep); - if(slsh != -1) { - lib_dirs.append(QMakeLocalFileName(file.left(slsh+1))); - file = file.right(file.length() - slsh - 1); + // We assume if it never finds it that it's correct + found: ; + } else if (linkPrl && type == LibFlagFile) { + QString lib = opt.toQString(); + if (fileInfo(lib).isAbsolute()) { + if (processPrlFile(lib)) + (*it) = lib; } else { - lib_dirs = dirs; - } - if(file.endsWith(".lib")) { - file = file.left(file.length() - 4); - if(!file.at(file.length()-1).isNumber()) { - ProString suffix = project->first(ProKey("QMAKE_" + file.toUpper() + "_SUFFIX")); - for(QList<QMakeLocalFileName>::Iterator dep_it = lib_dirs.begin(); dep_it != lib_dirs.end(); ++dep_it) { - QString lib_tmpl(file + "%1" + suffix + ".lib"); - int ver = findHighestVersion((*dep_it).local(), file); - if(ver != -1) { - if(ver) - lib_tmpl = lib_tmpl.arg(ver); - else - lib_tmpl = lib_tmpl.arg(""); - if(slsh != -1) { - QString dir = (*dep_it).real(); - if(!dir.endsWith(Option::dir_sep)) - dir += Option::dir_sep; - lib_tmpl.prepend(dir); - } - (*it) = lib_tmpl; - break; - } + for (QList<QMakeLocalFileName>::Iterator dir_it = dirs.begin(); + dir_it != dirs.end(); ++dir_it) { + QString cand = (*dir_it).real() + Option::dir_sep + lib; + if (processPrlFile(cand)) { + (*it) = cand; + break; } } } } - if(remove) { - it = l.erase(it); - } else { - ++it; - } - } - } - return true; -} -void -Win32MakefileGenerator::processPrlFiles() -{ - const QString libArg = project->first("QMAKE_L_FLAG").toQString(); - QList<QMakeLocalFileName> libdirs; - static const char * const lflags[] = { "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", 0 }; - for (int i = 0; lflags[i]; i++) { - ProStringList &l = project->values(lflags[i]); + ProStringList &prl_libs = project->values("QMAKE_CURRENT_PRL_LIBS"); + for (int prl = 0; prl < prl_libs.size(); ++prl) + it = l.insert(++it, prl_libs.at(prl)); + prl_libs.clear(); + ++it; + } + if (mergeLflags) { + ProStringList lopts; for (int lit = 0; lit < l.size(); ++lit) { - QString opt = l.at(lit).trimmed().toQString(); - if (opt.startsWith(libArg)) { - QMakeLocalFileName l(opt.mid(libArg.length())); - if (!libdirs.contains(l)) - libdirs.append(l); - } else if (!opt.startsWith("/")) { - if (!processPrlFile(opt) && (QDir::isRelativePath(opt) || opt.startsWith("-l"))) { - QString tmp; - if (opt.startsWith("-l")) - tmp = opt.mid(2); - else - tmp = opt; - for(QList<QMakeLocalFileName>::Iterator it = libdirs.begin(); it != libdirs.end(); ++it) { - QString prl = (*it).local() + '/' + tmp; - if (processPrlFile(prl)) - break; - } - } - } - ProStringList &prl_libs = project->values("QMAKE_CURRENT_PRL_LIBS"); - for (int prl = 0; prl < prl_libs.size(); ++prl) - l.insert(++lit, prl_libs.at(prl)); - prl_libs.clear(); - } - - // Merge them into a logical order - if (!project->isActiveConfig("no_smart_library_merge") && !project->isActiveConfig("no_lflags_merge")) { - ProStringList lflags; - for (int lit = 0; lit < l.size(); ++lit) { - ProString opt = l.at(lit).trimmed(); - if (opt.startsWith(libArg)) { - if (!lflags.contains(opt)) - lflags.append(opt); - } else { - // Make sure we keep the dependency-order of libraries - lflags.removeAll(opt); - lflags.append(opt); - } + ProString opt = l.at(lit); + if (opt.startsWith(QLatin1String("-L"))) { + if (!lopts.contains(opt)) + lopts.append(opt); + } else { + // Make sure we keep the dependency order of libraries + lopts.removeAll(opt); + lopts.append(opt); } - l = lflags; } + l = lopts; } + } + return true; } - void Win32MakefileGenerator::processVars() { project->values("QMAKE_ORIG_TARGET") = project->values("TARGET"); @@ -286,7 +196,6 @@ void Win32MakefileGenerator::processVars() fixTargetExt(); processRcFileVar(); - ProString libArg = project->first("QMAKE_L_FLAG"); ProStringList libs; ProStringList &libDir = project->values("QMAKE_LIBDIR"); for (ProStringList::Iterator libDir_it = libDir.begin(); libDir_it != libDir.end(); ++libDir_it) { @@ -294,7 +203,7 @@ void Win32MakefileGenerator::processVars() if (!lib.isEmpty()) { if (lib.endsWith('\\')) lib.chop(1); - libs << libArg + Option::fixPathToTargetOS(lib, false, false); + libs << QLatin1String("-L") + lib; } } project->values("QMAKE_LIBS") += libs + project->values("LIBS"); @@ -321,20 +230,19 @@ void Win32MakefileGenerator::processVars() void Win32MakefileGenerator::fixTargetExt() { - if (project->isEmpty("QMAKE_EXTENSION_STATICLIB")) - project->values("QMAKE_EXTENSION_STATICLIB").append("lib"); - if (project->isEmpty("QMAKE_EXTENSION_SHLIB")) - project->values("QMAKE_EXTENSION_SHLIB").append("dll"); - if (!project->values("QMAKE_APP_FLAG").isEmpty()) { project->values("TARGET_EXT").append(".exe"); } else if (project->isActiveConfig("shared")) { + project->values("LIB_TARGET").prepend(project->first("QMAKE_PREFIX_STATICLIB") + + project->first("TARGET") + project->first("TARGET_VERSION_EXT") + + '.' + project->first("QMAKE_EXTENSION_STATICLIB")); project->values("TARGET_EXT").append(project->first("TARGET_VERSION_EXT") + "." + project->first("QMAKE_EXTENSION_SHLIB")); project->values("TARGET").first() = project->first("QMAKE_PREFIX_SHLIB") + project->first("TARGET"); } else { project->values("TARGET_EXT").append("." + project->first("QMAKE_EXTENSION_STATICLIB")); project->values("TARGET").first() = project->first("QMAKE_PREFIX_STATICLIB") + project->first("TARGET"); + project->values("LIB_TARGET").prepend(project->first("TARGET") + project->first("TARGET_EXT")); // for the .prl only } } @@ -662,7 +570,6 @@ void Win32MakefileGenerator::writeStandardParts(QTextStream &t) t << "DESTDIR_TARGET = " << fileVar("DEST_TARGET") << endl; t << endl; - t << "####### Implicit rules\n\n"; writeImplicitRulesPart(t); t << "####### Build rules\n\n"; @@ -734,16 +641,6 @@ void Win32MakefileGenerator::writeObjectsPart(QTextStream &t) void Win32MakefileGenerator::writeImplicitRulesPart(QTextStream &t) { - t << ".SUFFIXES:"; - for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) - t << " " << (*cppit); - for(QStringList::Iterator cit = Option::c_ext.begin(); cit != Option::c_ext.end(); ++cit) - t << " " << (*cit); - t << endl << endl; - for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) - t << (*cppit) << Option::obj_ext << ":\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl; - for(QStringList::Iterator cit = Option::c_ext.begin(); cit != Option::c_ext.end(); ++cit) - t << (*cit) << Option::obj_ext << ":\n\t" << var("QMAKE_RUN_CC_IMP") << endl << endl; } void Win32MakefileGenerator::writeBuildRulesPart(QTextStream &) @@ -755,10 +652,6 @@ void Win32MakefileGenerator::writeRcFilePart(QTextStream &t) if(!project->values("RC_FILE").isEmpty()) { const ProString res_file = project->first("RES_FILE"); const QString rc_file = fileFixify(project->first("RC_FILE").toQString()); - // The resource tool needs to have the same defines passed in as the compiler, since you may - // use these defines in the .rc file itself. Also, we need to add the _DEBUG define manually - // since the compiler defines this symbol by itself, and we use it in the automatically - // created rc file when VERSION is define the .pro file. const ProStringList rcIncPaths = project->values("RC_INCLUDEPATH"); QString incPathStr; @@ -770,19 +663,25 @@ void Win32MakefileGenerator::writeRcFilePart(QTextStream &t) incPathStr += escapeFilePath(path); } + // The resource tool may use defines. This might be the same defines passed in as the + // compiler, since you may use these defines in the .rc file itself. + // As the escape syntax for the command line defines for RC is different from that for CL, + // we might have to set specific defines for RC. + ProString defines = varGlue("RC_DEFINES", " -D", " -D", ""); + if (defines.isEmpty()) + defines = ProString(" $(DEFINES)"); + + // Also, we need to add the _DEBUG define manually since the compiler defines this symbol + // by itself, and we use it in the automatically created rc file when VERSION is defined + // in the .pro file. t << escapeDependencyPath(res_file) << ": " << escapeDependencyPath(rc_file) << "\n\t" << var("QMAKE_RC") << (project->isActiveConfig("debug") ? " -D_DEBUG" : "") - << " $(DEFINES)" << incPathStr << " -fo " << escapeFilePath(res_file) + << defines << incPathStr << " -fo " << escapeFilePath(res_file) << ' ' << escapeFilePath(rc_file); t << endl << endl; } } -QString Win32MakefileGenerator::getLibTarget() -{ - return QString(project->first("TARGET") + project->first("TARGET_VERSION_EXT") + ".lib"); -} - QString Win32MakefileGenerator::defaultInstall(const QString &t) { if((t != "target" && t != "dlltarget") || @@ -829,7 +728,7 @@ QString Win32MakefileGenerator::defaultInstall(const QString &t) } } if(project->isActiveConfig("shared") && !project->isActiveConfig("plugin")) { - QString lib_target = getLibTarget(); + ProString lib_target = project->first("LIB_TARGET"); QString src_targ = escapeFilePath( (project->isEmpty("DESTDIR") ? QString("$(DESTDIR)") : project->first("DESTDIR")) + lib_target); |