rewrite windows library handling

first, store the library's full name in the .prl file, like we do on
unix. this is not expected to have any side effects, as QMAKE_PRL_TARGET
was entirely unused under windows so far.

then, rewrite the mingw library handling: instead of letting the linker
resolve the actual libraries, do it ourselves like we do for msvc. we
could not do that before due to the partial file names in the .prl
files: if the library didn't exist at qmake execution time, we'd have to
guess the file extension (the msvc generators never had that problem, as
they know about only one possible extension for libraries anyway).

make use of processPrlFile()'s ability to replace the reference to
the .prl file with the actual library. that way we don't need to
re-assemble the file name from pieces, which was fragile and
inefficient.

QMAKE_*_VERSION_OVERRIDE does not affect libraries coming with .prl
files any more. additionally, it is now used literally (not
numerically), and values less or equal to zero lost their special
meaning as "none" - this isn't a problem, because that's the default
anyway, and there is no need to override bogus versions from .prl files
any more.
no changelog for that, as i found no public traces of that feature
outside qtbase.

[ChangeLog][qmake][Windows] Libraries coming with .prl files can now
have non-standard file extensions and a major version of zero.

[ChangeLog][qmake][Windows][Important Behavior Changes] The .prl files
written by earlier versions of Qt cannot be used any more. This will
affect you if you depend on 3rd party libraries which come with .prl
files. Patch up QMAKE_PRL_TARGET to contain the complete file name of
the library, and replace any /LIBPATH: in QMAKE_PRL_LIBS with -L.

(the part about /LIBPATH: actually refers to the next commit.)

Change-Id: I07399341bff0609cb6db9660cbc62b141fb2ad96
Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
This commit is contained in:
Oswald Buddenhagen 2015-09-25 14:21:44 +02:00
parent c00e11d573
commit dd9ec15640
5 changed files with 63 additions and 71 deletions

View File

@ -908,6 +908,9 @@ MakefileGenerator::processPrlFile(QString &file)
if (tgt.isEmpty()) {
fprintf(stderr, "Error: %s does not define QMAKE_PRL_TARGET\n",
meta_file.toLatin1().constData());
} else if (!tgt.contains('.')) {
fprintf(stderr, "Error: %s defines QMAKE_PRL_TARGET without extension\n",
meta_file.toLatin1().constData());
} else {
int off = qMax(file.lastIndexOf('/'), file.lastIndexOf('\\')) + 1;
debug_msg(1, " Replacing library reference %s with %s",
@ -954,10 +957,6 @@ qv(const ProStringList &val)
void
MakefileGenerator::writePrlFile(QTextStream &t)
{
ProString target = project->first("TARGET");
int slsh = target.lastIndexOf(Option::dir_sep);
if(slsh != -1)
target.chopFront(slsh + 1);
QString bdir = Option::output_dir;
if(bdir.isEmpty())
bdir = qmake_getpwd();
@ -967,7 +966,7 @@ MakefileGenerator::writePrlFile(QTextStream &t)
if(!project->isEmpty("QMAKE_ABSOLUTE_SOURCE_PATH"))
t << "QMAKE_PRL_SOURCE_DIR =" << qv(project->first("QMAKE_ABSOLUTE_SOURCE_PATH")) << endl;
t << "QMAKE_PRL_TARGET =" << qv(target) << endl;
t << "QMAKE_PRL_TARGET =" << qv(project->first("LIB_TARGET")) << endl;
if(!project->isEmpty("PRL_EXPORT_DEFINES"))
t << "QMAKE_PRL_DEFINES =" << qv(project->values("PRL_EXPORT_DEFINES")) << endl;
if(!project->isEmpty("PRL_EXPORT_CFLAGS"))

View File

@ -275,6 +275,11 @@ UnixMakefileGenerator::init()
init2();
project->values("QMAKE_INTERNAL_PRL_LIBS") << "QMAKE_LIBS";
ProString target = project->first("TARGET");
int slsh = target.lastIndexOf(Option::dir_sep);
if (slsh != -1)
target.chopFront(slsh + 1);
project->values("LIB_TARGET").prepend(target);
if(!project->isEmpty("QMAKE_MAX_FILES_PER_AR")) {
bool ok;
int max_files = project->first("QMAKE_MAX_FILES_PER_AR").toInt(&ok);

View File

@ -71,39 +71,48 @@ bool MingwMakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags)
{
QList<QMakeLocalFileName> dirs;
static const char * const lflags[] = { "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", 0 };
static const QLatin1String extens[] =
{ QLatin1String(".dll.a"), QLatin1String(".a"), QLatin1String(0) };
for (int i = 0; lflags[i]; i++) {
ProStringList &l = project->values(lflags[i]);
ProStringList::Iterator it = l.begin();
while (it != l.end()) {
if ((*it).startsWith("-l")) {
QString steam = (*it).mid(2).toQString();
QString out;
ProString verovr =
project->first(ProKey("QMAKE_" + steam.toUpper() + "_VERSION_OVERRIDE"));
for (QList<QMakeLocalFileName>::Iterator dir_it = dirs.begin(); dir_it != dirs.end(); ++dir_it) {
QString extension;
int ver = findHighestVersion((*dir_it).local(), steam);
if (ver > 0)
extension += QString::number(ver);
QString libBase = (*dir_it).local() + '/' + steam;
if ((linkPrl && processPrlFile(libBase))
|| exists(libBase + extension + ".a")
|| exists(libBase + extension + ".dll.a")) {
out = *it + extension;
break;
QString cand = (*dir_it).real() + Option::dir_sep + steam;
if (linkPrl && processPrlFile(cand)) {
(*it) = cand;
goto found;
}
QString libBase = (*dir_it).local() + '/' + steam + verovr;
for (int e = 0; extens[e].data(); e++) {
if (exists(libBase + extens[e])) {
(*it) = cand + verovr + extens[e];
goto found;
}
}
}
if (!out.isEmpty()) // We assume if it never finds it that its correct
(*it) = out;
// We assume if it never finds it that its correct
found: ;
} else if ((*it).startsWith("-L")) {
QMakeLocalFileName f((*it).mid(2).toQString());
dirs.append(f);
*it = "-L" + f.real();
} else if (linkPrl && !(*it).startsWith('-')) {
QString prl = (*it).toQString();
if (!processPrlFile(prl) && QDir::isRelativePath(prl)) {
if (fileInfo(prl).isAbsolute()) {
if (processPrlFile(prl))
(*it) = prl;
} else {
for (QList<QMakeLocalFileName>::Iterator dir_it = dirs.begin(); dir_it != dirs.end(); ++dir_it) {
prl = (*dir_it).local() + '/' + *it;
if (processPrlFile(prl))
QString cand = (*dir_it).real() + Option::dir_sep + prl;
if (processPrlFile(cand)) {
(*it) = cand;
break;
}
}
}
}

View File

@ -49,33 +49,6 @@ Win32MakefileGenerator::Win32MakefileGenerator() : MakefileGenerator()
{
}
int
Win32MakefileGenerator::findHighestVersion(const QString &d, const QString &stem)
{
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(libInfoRead
&& !libinfo.values("QMAKE_PRL_CONFIG").contains("staticlib")
&& !libinfo.isEmpty("QMAKE_PRL_VERSION"))
biggest = libinfo.first("QMAKE_PRL_VERSION").toQString().replace(".", "").toInt();
return biggest;
}
ProString Win32MakefileGenerator::fixLibFlag(const ProString &lib)
{
if (lib.startsWith("/LIBPATH:"))
@ -114,32 +87,38 @@ Win32MakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags)
dirs.append(lp);
(*it) = "/LIBPATH:" + lp.real();
} else if(opt.startsWith("-l") || opt.startsWith("/l")) {
QString lib = opt.right(opt.length() - 2), out;
if(!lib.isEmpty()) {
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 += ".lib";
QString libBase = (*it).local() + '/' + lib;
if ((linkPrl && processPrlFile(libBase))
|| exists(libBase + extension)) {
out = (*it).real() + Option::dir_sep + lib + extension;
QString lib = opt.mid(2);
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 extension = verovr + ".lib";
if (exists((*dir_it).local() + '/' + lib + extension)) {
(*it) = cand + extension;
goto found;
}
}
(*it) = lib + ".lib";
found: ;
} else if (linkPrl) {
if (fileInfo(opt).isAbsolute()) {
if (processPrlFile(opt))
(*it) = opt;
} else {
for (QList<QMakeLocalFileName>::Iterator dir_it = dirs.begin();
dir_it != dirs.end(); ++dir_it) {
QString cand = (*dir_it).real() + Option::dir_sep + opt;
if (processPrlFile(cand)) {
(*it) = cand;
break;
}
}
}
if(out.isEmpty())
out = lib + ".lib";
(*it) = out;
} else if (linkPrl && !processPrlFile(opt) && QDir::isRelativePath(opt)) {
for (QList<QMakeLocalFileName>::Iterator it = dirs.begin(); it != dirs.end(); ++it) {
QString prl = (*it).local() + '/' + opt;
if (processPrlFile(prl))
break;
}
}
ProStringList &prl_libs = project->values("QMAKE_CURRENT_PRL_LIBS");
@ -242,6 +221,7 @@ void Win32MakefileGenerator::fixTargetExt()
} 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
}
}

View File

@ -57,7 +57,6 @@ protected:
virtual void writeRcFilePart(QTextStream &t);
int findHighestVersion(const QString &dir, const QString &stem);
virtual bool findLibraries(bool linkPrl, bool mergeLflags);
virtual ProString fixLibFlag(const ProString &lib);