summaryrefslogtreecommitdiffstats
path: root/qmake/generators
diff options
context:
space:
mode:
Diffstat (limited to 'qmake/generators')
-rw-r--r--qmake/generators/mac/pbuilder_pbx.cpp2
-rw-r--r--qmake/generators/makefile.cpp141
-rw-r--r--qmake/generators/makefile.h4
-rw-r--r--qmake/generators/projectgenerator.cpp10
-rw-r--r--qmake/generators/unix/unixmake.cpp23
-rw-r--r--qmake/generators/unix/unixmake2.cpp8
-rw-r--r--qmake/generators/win32/msbuild_objectmodel.cpp23
-rw-r--r--qmake/generators/win32/msvc_nmake.cpp244
-rw-r--r--qmake/generators/win32/msvc_nmake.h1
-rw-r--r--qmake/generators/win32/msvc_objectmodel.cpp98
-rw-r--r--qmake/generators/win32/msvc_objectmodel.h5
-rw-r--r--qmake/generators/win32/msvc_vcproj.cpp106
-rw-r--r--qmake/generators/win32/msvc_vcproj.h6
-rw-r--r--qmake/generators/win32/registry.cpp158
-rw-r--r--qmake/generators/win32/registry_p.h73
-rw-r--r--qmake/generators/win32/winmakefile.cpp14
16 files changed, 300 insertions, 616 deletions
diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp
index 5407ed6c69..07832041a7 100644
--- a/qmake/generators/mac/pbuilder_pbx.cpp
+++ b/qmake/generators/mac/pbuilder_pbx.cpp
@@ -856,7 +856,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
QString lib_file = QMakeMetaInfo::checkLib(Option::normalizePath(
(*lit) + Option::dir_sep + lib + Option::prl_ext));
if (!lib_file.isEmpty()) {
- QMakeMetaInfo libinfo(project);
+ QMakeMetaInfo libinfo;
if(libinfo.readLib(lib_file)) {
if(!libinfo.isEmpty("QMAKE_PRL_TARGET")) {
library = (*lit) + Option::dir_sep + libinfo.first("QMAKE_PRL_TARGET");
diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp
index e41e391cad..b634ec622b 100644
--- a/qmake/generators/makefile.cpp
+++ b/qmake/generators/makefile.cpp
@@ -81,8 +81,8 @@ bool MakefileGenerator::canExecute(const QStringList &cmdline, int *a) const
QString MakefileGenerator::mkdir_p_asstring(const QString &dir, bool escape) const
{
- QString edir = escape ? escapeFilePath(Option::fixPathToTargetOS(dir, false, false)) : dir;
- return "@" + makedir.arg(edir);
+ return "@" + makedir.arg(
+ escape ? escapeFilePath(Option::fixPathToTargetOS(dir, false, false)) : dir);
}
bool MakefileGenerator::mkdir(const QString &in_path) const
@@ -424,6 +424,9 @@ MakefileGenerator::init()
}
incs.append(project->specDir());
+ const auto platform = v["QMAKE_PLATFORM"];
+ resolveDependenciesInFrameworks = platform.contains("darwin");
+
const char * const cacheKeys[] = { "_QMAKE_STASH_", "_QMAKE_SUPER_CACHE_", nullptr };
for (int i = 0; cacheKeys[i]; ++i) {
if (v[cacheKeys[i]].isEmpty())
@@ -529,7 +532,7 @@ MakefileGenerator::init()
QStack<int> state;
enum { IN_CONDITION, MET_CONDITION, PENDING_CONDITION };
for (int count = 1; !in.atEnd(); ++count) {
- QString line = QString::fromUtf8(in.readLine());
+ QString line = QString::fromLatin1(in.readLine());
if (line.startsWith("!!IF ")) {
if (state.isEmpty() || state.top() == IN_CONDITION) {
QString test = line.mid(5, line.length()-(5+1));
@@ -575,7 +578,7 @@ MakefileGenerator::init()
contents += project->expand(line, in.fileName(), count);
}
}
- contentBytes = contents.toUtf8();
+ contentBytes = contents.toLatin1();
}
QFile out(outn);
QFileInfo outfi(out);
@@ -624,7 +627,7 @@ MakefileGenerator::init()
compiler.flags |= Compiler::CompilerNoCheckDeps;
compilers.append(compiler);
}
- for (ProStringList::ConstIterator it = quc.begin(); it != quc.end(); ++it) {
+ for (ProStringList::ConstIterator it = quc.cbegin(); it != quc.cend(); ++it) {
const ProStringList &inputs = v[ProKey(*it + ".input")];
for(x = 0; x < inputs.size(); ++x) {
Compiler compiler;
@@ -909,7 +912,7 @@ MakefileGenerator::processPrlFileCore(QString &origFile, const QStringRef &origN
const QString meta_file = QMakeMetaInfo::checkLib(fixedFile);
if (meta_file.isEmpty())
return false;
- QMakeMetaInfo libinfo(project);
+ QMakeMetaInfo libinfo;
debug_msg(1, "Processing PRL file: %s", meta_file.toLatin1().constData());
if (!libinfo.readLib(meta_file)) {
fprintf(stderr, "Error processing meta file %s\n", meta_file.toLatin1().constData());
@@ -1101,8 +1104,6 @@ QString
MakefileGenerator::prlFileName(bool fixify)
{
QString ret = project->first("PRL_TARGET") + Option::prl_ext;
- if(!project->isEmpty("QMAKE_BUNDLE"))
- ret.prepend(project->first("QMAKE_BUNDLE") + Option::dir_sep);
if(fixify) {
if(!project->isEmpty("DESTDIR"))
ret.prepend(project->first("DESTDIR").toQString());
@@ -1291,6 +1292,7 @@ MakefileGenerator::writeInstalls(QTextStream &t, bool noBuild)
}
}
bool is_target = (wild == fileFixify(var("TARGET"), FileFixifyAbsolute));
+ const bool noStrip = installConfigValues.contains("nostrip");
if(is_target || exists(wild)) { //real file or target
QFileInfo fi(fileInfo(wild));
QString dst_file = filePrefixRoot(root, dst_dir);
@@ -1304,7 +1306,7 @@ MakefileGenerator::writeInstalls(QTextStream &t, bool noBuild)
cmd = QLatin1String("-$(QINSTALL)");
cmd += " " + escapeFilePath(wild) + " " + escapeFilePath(dst_file);
inst << cmd;
- if (!project->isActiveConfig("debug_info") && !project->isActiveConfig("nostrip") &&
+ if (!noStrip && !project->isActiveConfig("debug_info") && !project->isActiveConfig("nostrip") &&
!fi.isDir() && fi.isExecutable() && !project->isEmpty("QMAKE_STRIP"))
inst << QString("-") + var("QMAKE_STRIP") + " " +
escapeFilePath(filePrefixRoot(root, fileFixify(dst_dir + filestr, FileFixifyAbsolute, false)));
@@ -1339,7 +1341,7 @@ MakefileGenerator::writeInstalls(QTextStream &t, bool noBuild)
QString cmd = QLatin1String("-$(QINSTALL) ") +
escapeFilePath(dirstr + file) + " " + escapeFilePath(dst_file);
inst << cmd;
- if (!project->isActiveConfig("debug_info") && !project->isActiveConfig("nostrip") &&
+ if (!noStrip && !project->isActiveConfig("debug_info") && !project->isActiveConfig("nostrip") &&
!fi.isDir() && fi.isExecutable() && !project->isEmpty("QMAKE_STRIP"))
inst << QString("-") + var("QMAKE_STRIP") + " " +
escapeFilePath(filePrefixRoot(root, fileFixify(dst_dir + file, FileFixifyAbsolute, false)));
@@ -1840,6 +1842,33 @@ static QStringList splitDeps(const QString &indeps, bool lineMode)
return deps;
}
+QString MakefileGenerator::resolveDependency(const QDir &outDir, const QString &file)
+{
+ const QList<QMakeLocalFileName> &depdirs = QMakeSourceFileInfo::dependencyPaths();
+ for (const auto &depdir : depdirs) {
+ const QString &local = depdir.local();
+ QString lf = outDir.absoluteFilePath(local + '/' + file);
+ if (exists(lf))
+ return lf;
+
+ if (resolveDependenciesInFrameworks) {
+ // Given a file like "QtWidgets/QWidget", try to resolve it
+ // as framework header "QtWidgets.framework/Headers/QWidget".
+ int cut = file.indexOf('/');
+ if (cut < 0 || cut + 1 >= file.size())
+ continue;
+ QStringRef framework = file.leftRef(cut);
+ QStringRef include = file.midRef(cut + 1);
+ if (local.endsWith('/' + framework + ".framework/Headers")) {
+ lf = outDir.absoluteFilePath(local + '/' + include);
+ if (exists(lf))
+ return lf;
+ }
+ }
+ }
+ return {};
+}
+
void
MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
{
@@ -1877,12 +1906,14 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
if (config.indexOf("combine") != -1) {
// compilers with a combined input only have one output
QString input = project->first(ProKey(*it + ".output")).toQString();
- t << ' ' << escapeDependencyPath(Option::fixPathToTargetOS(
- replaceExtraCompilerVariables(tmp_out, input, QString(), NoShell)));
+ t << ' ' << escapeDependencyPath(fileFixify(
+ replaceExtraCompilerVariables(tmp_out, input, QString(), NoShell),
+ FileFixifyFromOutdir));
} else {
- for (ProStringList::ConstIterator input = tmp_inputs.begin(); input != tmp_inputs.end(); ++input) {
- t << ' ' << escapeDependencyPath(Option::fixPathToTargetOS(
- replaceExtraCompilerVariables(tmp_out, (*input).toQString(), QString(), NoShell)));
+ for (ProStringList::ConstIterator input = tmp_inputs.cbegin(); input != tmp_inputs.cend(); ++input) {
+ t << ' ' << escapeDependencyPath(fileFixify(
+ replaceExtraCompilerVariables(tmp_out, (*input).toQString(), QString(), NoShell),
+ FileFixifyFromOutdir));
}
}
t << endl;
@@ -1914,12 +1945,13 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
const QString del_statement("-$(DEL_FILE)");
if(!wrote_clean) {
QStringList dels;
- for (ProStringList::ConstIterator input = tmp_inputs.begin(); input != tmp_inputs.end(); ++input) {
+ for (ProStringList::ConstIterator input = tmp_inputs.cbegin(); input != tmp_inputs.cend(); ++input) {
QString tinp = (*input).toQString();
QString out = replaceExtraCompilerVariables(tmp_out, tinp, QString(), NoShell);
for (const QString &rc : qAsConst(raw_clean)) {
- dels << ' ' + escapeFilePath(Option::fixPathToTargetOS(
- replaceExtraCompilerVariables(rc, tinp, out, NoShell), false));
+ dels << ' ' + escapeFilePath(fileFixify(
+ replaceExtraCompilerVariables(rc, tinp, out, NoShell),
+ FileFixifyFromOutdir));
}
}
if(project->isActiveConfig("no_delete_multiple_files")) {
@@ -1942,7 +1974,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
if(!cleans.isEmpty())
t << valGlue(cleans, "\n\t" + del_statement, "\n\t" + del_statement, "");
if(!wrote_clean_cmds) {
- for (ProStringList::ConstIterator input = tmp_inputs.begin(); input != tmp_inputs.end(); ++input) {
+ for (ProStringList::ConstIterator input = tmp_inputs.cbegin(); input != tmp_inputs.cend(); ++input) {
QString tinp = (*input).toQString();
t << "\n\t" << replaceExtraCompilerVariables(tmp_clean_cmds, tinp,
replaceExtraCompilerVariables(tmp_out, tinp, QString(), NoShell), TargetShell);
@@ -1961,7 +1993,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
QStringList deps, inputs;
if(!tmp_dep.isEmpty())
deps += fileFixify(tmp_dep, FileFixifyFromOutdir);
- for (ProStringList::ConstIterator input = tmp_inputs.begin(); input != tmp_inputs.end(); ++input) {
+ for (ProStringList::ConstIterator input = tmp_inputs.cbegin(); input != tmp_inputs.cend(); ++input) {
QString inpf = (*input).toQString();
deps += findDependencies(inpf);
inputs += Option::fixPathToTargetOS(inpf, false);
@@ -1989,16 +2021,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
} else if (exists(absFile)) {
file = absFile;
} else {
- QString localFile;
- QList<QMakeLocalFileName> depdirs = QMakeSourceFileInfo::dependencyPaths();
- for (QList<QMakeLocalFileName>::Iterator dit = depdirs.begin();
- dit != depdirs.end(); ++dit) {
- QString lf = outDir.absoluteFilePath((*dit).local() + '/' + file);
- if (exists(lf)) {
- localFile = lf;
- break;
- }
- }
+ QString localFile = resolveDependency(outDir, file);
if (localFile.isEmpty()) {
if (exists(file))
warn_msg(WarnDeprecated, ".depend_command for extra compiler %s"
@@ -2035,7 +2058,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
QString out = replaceExtraCompilerVariables(tmp_out, QString(), QString(), NoShell);
QString cmd = replaceExtraCompilerVariables(tmp_cmd, inputs, QStringList() << out, TargetShell);
- t << escapeDependencyPath(Option::fixPathToTargetOS(out)) << ":";
+ t << escapeDependencyPath(fileFixify(out, FileFixifyFromOutdir)) << ":";
// compiler.CONFIG+=explicit_dependencies means that ONLY compiler.depends gets to cause Makefile dependencies
if (config.indexOf("explicit_dependencies") != -1) {
t << " " << valList(escapeDependencyPaths(fileFixify(tmp_dep, FileFixifyFromOutdir)));
@@ -2045,16 +2068,18 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
t << "\n\t" << cmd << endl << endl;
continue;
}
- for (ProStringList::ConstIterator input = tmp_inputs.begin(); input != tmp_inputs.end(); ++input) {
+ for (ProStringList::ConstIterator input = tmp_inputs.cbegin(); input != tmp_inputs.cend(); ++input) {
QString inpf = (*input).toQString();
- QString in = Option::fixPathToTargetOS(inpf, false);
- QStringList deps = findDependencies(inpf);
- deps << in;
- QString out = Option::fixPathToTargetOS(replaceExtraCompilerVariables(tmp_out, inpf, QString(), NoShell));
+ QStringList deps;
+ deps << fileFixify(inpf, FileFixifyFromOutdir);
+ deps += findDependencies(inpf);
+ QString out = fileFixify(replaceExtraCompilerVariables(tmp_out, inpf, QString(), NoShell),
+ FileFixifyFromOutdir);
if(!tmp_dep.isEmpty()) {
QStringList pre_deps = fileFixify(tmp_dep, FileFixifyFromOutdir);
for(int i = 0; i < pre_deps.size(); ++i)
- deps << replaceExtraCompilerVariables(pre_deps.at(i), inpf, out, NoShell);
+ deps << fileFixify(replaceExtraCompilerVariables(pre_deps.at(i), inpf, out, NoShell),
+ FileFixifyFromOutdir);
}
QString cmd = replaceExtraCompilerVariables(tmp_cmd, inpf, out, TargetShell);
// NOTE: The var -> QMAKE_COMP_var replace feature is unsupported, do not use!
@@ -2084,16 +2109,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
} else if (exists(absFile)) {
file = absFile;
} else {
- QString localFile;
- QList<QMakeLocalFileName> depdirs = QMakeSourceFileInfo::dependencyPaths();
- for (QList<QMakeLocalFileName>::Iterator dit = depdirs.begin();
- dit != depdirs.end(); ++dit) {
- QString lf = outDir.absoluteFilePath((*dit).local() + '/' + file);
- if (exists(lf)) {
- localFile = lf;
- break;
- }
- }
+ QString localFile = resolveDependency(outDir, file);
if (localFile.isEmpty()) {
if (exists(file))
warn_msg(WarnDeprecated, ".depend_command for extra compiler %s"
@@ -2114,7 +2130,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
//use the depend system to find includes of these included files
QStringList inc_deps;
for(int i = 0; i < deps.size(); ++i) {
- const QString dep = deps.at(i);
+ const QString dep = fileFixify(deps.at(i), FileFixifyFromOutdir | FileFixifyAbsolute);
if(QFile::exists(dep)) {
SourceFileType type = TYPE_UNKNOWN;
if(type == TYPE_UNKNOWN) {
@@ -2151,11 +2167,10 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
}
}
}
- deps += inc_deps;
+ deps += fileFixify(inc_deps, FileFixifyFromOutdir);
}
for(int i = 0; i < deps.size(); ) {
QString &dep = deps[i];
- dep = Option::fixPathToTargetOS(dep, false);
if(out == dep)
deps.removeAt(i);
else
@@ -2209,6 +2224,25 @@ MakefileGenerator::writeExtraVariables(QTextStream &t)
}
}
+// This is a more powerful alternative to the above function.
+// It's meant to be internal, as one can make quite a mess with it.
+void
+MakefileGenerator::writeExportedVariables(QTextStream &t)
+{
+ const auto &vars = project->values("QMAKE_EXPORTED_VARIABLES");
+ if (vars.isEmpty())
+ return;
+ for (const auto &exp : vars) {
+ const ProString &name = project->first(ProKey(exp + ".name"));
+ const ProString &value = project->first(ProKey(exp + ".value"));
+ if (!value.isEmpty())
+ t << name << " = " << value << endl;
+ else
+ t << name << " =\n";
+ }
+ t << endl;
+}
+
bool
MakefileGenerator::writeDummyMakefile(QTextStream &t)
{
@@ -2327,6 +2361,7 @@ MakefileGenerator::writeHeader(QTextStream &t)
if (ofile.lastIndexOf(Option::dir_sep) != -1)
ofile.remove(0, ofile.lastIndexOf(Option::dir_sep) +1);
t << "MAKEFILE = " << escapeFilePath(ofile) << endl << endl;
+ t << "EQ = =\n\n";
}
QList<MakefileGenerator::SubTarget*>
@@ -2550,6 +2585,9 @@ MakefileGenerator::writeSubTargets(QTextStream &t, QList<MakefileGenerator::SubT
{ //actually compile
t << subtarget->target << ":";
+ auto extraDeps = extraSubTargetDependencies();
+ if (!extraDeps.isEmpty())
+ t << " " << valList(extraDeps);
if(!subtarget->depends.isEmpty())
t << " " << valList(subtarget->depends);
t << " FORCE";
@@ -2871,6 +2909,7 @@ MakefileGenerator::escapeDependencyPath(const QString &path) const
static const QRegExp criticalChars(QStringLiteral("([\t #])"));
#endif
ret.replace(criticalChars, QStringLiteral("\\\\1"));
+ ret.replace(QLatin1Char('='), QStringLiteral("$(EQ)"));
debug_msg(2, "escapeDependencyPath: %s -> %s", path.toLatin1().constData(), ret.toLatin1().constData());
}
return ret;
@@ -3352,7 +3391,7 @@ MakefileGenerator::writePkgConfigFile()
libs << "QMAKE_LIBS_PRIVATE";
libs << "QMAKE_LFLAGS_THREAD"; //not sure about this one, but what about things like -pthread?
t << "Libs.private:";
- for (ProStringList::ConstIterator it = libs.begin(); it != libs.end(); ++it)
+ for (ProStringList::ConstIterator it = libs.cbegin(); it != libs.cend(); ++it)
t << ' ' << fixLibFlags((*it).toKey()).join(' ');
t << endl;
}
diff --git a/qmake/generators/makefile.h b/qmake/generators/makefile.h
index b5c150e1cb..350ebd377a 100644
--- a/qmake/generators/makefile.h
+++ b/qmake/generators/makefile.h
@@ -55,6 +55,7 @@ class MakefileGenerator : protected QMakeSourceFileInfo
{
QString spec;
bool no_io;
+ bool resolveDependenciesInFrameworks = false;
QHash<QString, bool> init_compiler_already;
QString makedir, chkexists;
QString build_args();
@@ -79,8 +80,10 @@ protected:
void writeHeader(QTextStream &t);
void writeSubDirs(QTextStream &t);
void writeMakeQmake(QTextStream &t, bool noDummyQmakeAll = false);
+ void writeExportedVariables(QTextStream &t);
void writeExtraVariables(QTextStream &t);
void writeExtraTargets(QTextStream &t);
+ QString resolveDependency(const QDir &outDir, const QString &file);
void writeExtraCompilerTargets(QTextStream &t);
void writeExtraCompilerVariables(QTextStream &t);
bool writeDummyMakefile(QTextStream &t);
@@ -116,6 +119,7 @@ protected:
virtual void writeSubMakeCall(QTextStream &t, const QString &outDirectory_cdin,
const QString &makeFileIn);
virtual void writeSubTargets(QTextStream &t, QList<SubTarget*> subtargets, int flags);
+ virtual ProStringList extraSubTargetDependencies() { return {}; }
//extra compiler interface
bool verifyExtraCompiler(const ProString &c, const QString &f);
diff --git a/qmake/generators/projectgenerator.cpp b/qmake/generators/projectgenerator.cpp
index f45a90b851..ef34955eb1 100644
--- a/qmake/generators/projectgenerator.cpp
+++ b/qmake/generators/projectgenerator.cpp
@@ -345,14 +345,10 @@ ProjectGenerator::writeMakefile(QTextStream &t)
<< getWritableVar("CONFIG_REMOVE", false)
<< getWritableVar("INCLUDEPATH") << endl;
- t << "# The following define makes your compiler warn you if you use any\n"
- "# feature of Qt which has been marked as deprecated (the exact warnings\n"
- "# depend on your compiler). Please consult the documentation of the\n"
- "# deprecated API in order to know how to port your code away from it.\n"
- "DEFINES += QT_DEPRECATED_WARNINGS\n"
- "\n"
- "# You can also make your code fail to compile if you use deprecated APIs.\n"
+ t << "# You can make your code fail to compile if you use deprecated APIs.\n"
"# In order to do so, uncomment the following line.\n"
+ "# Please consult the documentation of the deprecated API in order to know\n"
+ "# how to port your code away from it.\n"
"# You can also select to disable deprecated APIs only up to a certain version of Qt.\n"
"#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0\n\n";
diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp
index 50ec8db79e..7f42fbe09e 100644
--- a/qmake/generators/unix/unixmake.cpp
+++ b/qmake/generators/unix/unixmake.cpp
@@ -399,6 +399,8 @@ UnixMakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags)
libdirs.append(QMakeLocalFileName(dlib.toQString()));
frameworkdirs.append(QMakeLocalFileName("/System/Library/Frameworks"));
frameworkdirs.append(QMakeLocalFileName("/Library/Frameworks"));
+ ProStringList extens;
+ extens << project->first("QMAKE_EXTENSION_SHLIB") << "a";
static const char * const lflags[] = { "LIBS", "LIBS_PRIVATE",
"QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", nullptr };
for (int i = 0; lflags[i]; i++) {
@@ -417,8 +419,6 @@ UnixMakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags)
libdirs.insert(libidx++, f);
} else if(opt.startsWith("-l")) {
QString lib = opt.mid(2);
- ProStringList extens;
- extens << project->first("QMAKE_EXTENSION_SHLIB") << "a";
for (QList<QMakeLocalFileName>::Iterator dep_it = libdirs.begin();
dep_it != libdirs.end(); ++dep_it) {
QString libBase = (*dep_it).local() + '/'
@@ -506,23 +506,30 @@ UnixMakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags)
if (opt.startsWith("-Xarch"))
opt = l.at(++lit); // The user has done the right thing and prefixed each part
}
- bool found = false;
for(int x = 0; x < lflags[arch].size(); ++x) {
if (lflags[arch].at(x) == "-framework" && lflags[arch].at(++x) == opt) {
- found = true;
+ lflags[arch].remove(x - 1, 2);
break;
}
}
- if(!found) {
- lflags[arch].append("-framework");
- lflags[arch].append(opt);
- }
+ lflags[arch].append("-framework");
+ lflags[arch].append(opt);
} else {
lflags[arch].append(opt);
}
} else if(!opt.isNull()) {
+ for (const ProString &ext : extens) {
+ if (opt.size() > ext.size() && opt.endsWith(ext)
+ && opt.at(opt.size() - ext.size() - 1) == '.') {
+ // Make sure we keep the dependency order of libraries
+ lflags[arch].removeAll(opt);
+ lflags[arch].append(opt);
+ goto found2;
+ }
+ }
if(!lflags[arch].contains(opt))
lflags[arch].append(opt);
+ found2: ;
}
}
diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp
index 976751b02c..7d8c70ec3b 100644
--- a/qmake/generators/unix/unixmake2.cpp
+++ b/qmake/generators/unix/unixmake2.cpp
@@ -180,6 +180,8 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
ProStringList &bundledFiles = project->values("QMAKE_BUNDLED_FILES");
+ writeExportedVariables(t);
+
t << "####### Compiler, tools and options\n\n";
t << "CC = " << var("QMAKE_CC") << endl;
t << "CXX = " << var("QMAKE_CXX") << endl;
@@ -405,7 +407,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
const ProStringList &l = project->values("QMAKE_PRL_INTERNAL_FILES");
ProStringList::ConstIterator it;
for(it = l.begin(); it != l.end(); ++it) {
- QMakeMetaInfo libinfo(project);
+ QMakeMetaInfo libinfo;
if (libinfo.readLib((*it).toQString()) && !libinfo.isEmpty("QMAKE_PRL_BUILD_DIR")) {
ProString dir;
int slsh = (*it).lastIndexOf(Option::dir_sep);
@@ -1225,6 +1227,8 @@ void UnixMakefileGenerator::init2()
else
ar_cmd.append("$(AR) $(TARGETA) $(OBJECTS)");
if (!project->isEmpty("QMAKE_BUNDLE")) {
+ project->values("PRL_TARGET").prepend(
+ project->first("QMAKE_BUNDLE") + Option::dir_sep + project->first("TARGET"));
ProString bundle_loc = project->first("QMAKE_BUNDLE_LOCATION");
if(!bundle_loc.isEmpty() && !bundle_loc.startsWith("/"))
bundle_loc.prepend("/");
@@ -1483,7 +1487,7 @@ UnixMakefileGenerator::writeLibtoolFile()
ProStringList libs;
libs << "LIBS" << "QMAKE_LIBS";
t << "dependency_libs='";
- for (ProStringList::ConstIterator it = libs.begin(); it != libs.end(); ++it)
+ for (ProStringList::ConstIterator it = libs.cbegin(); it != libs.cend(); ++it)
t << fixLibFlags((*it).toKey()).join(' ') << ' ';
t << "'\n\n";
diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp
index ad2976aa01..0e95766f8e 100644
--- a/qmake/generators/win32/msbuild_objectmodel.cpp
+++ b/qmake/generators/win32/msbuild_objectmodel.cpp
@@ -34,7 +34,6 @@
#include <qscopedpointer.h>
#include <qstringlist.h>
#include <qfileinfo.h>
-#include <qversionnumber.h>
QT_BEGIN_NAMESPACE
@@ -625,31 +624,17 @@ void VCXProjectWriter::write(XmlOutput &xml, VCProject &tool)
<< tagValue("RootNamespace", tool.Name)
<< tagValue("Keyword", tool.Keyword);
- QString windowsTargetPlatformVersion;
if (isWinRT) {
xml << tagValue("MinimumVisualStudioVersion", tool.Version)
<< tagValue("DefaultLanguage", "en")
<< tagValue("AppContainerApplication", "true")
<< tagValue("ApplicationType", "Windows Store")
<< tagValue("ApplicationTypeRevision", tool.SdkVersion);
- if (tool.SdkVersion == "10.0")
- windowsTargetPlatformVersion = qgetenv("UCRTVERSION");
- } else {
- QByteArray winSDKVersionStr = qgetenv("WindowsSDKVersion").trimmed();
-
- // This environment variable might end with a backslash due to a VS bug.
- if (winSDKVersionStr.endsWith('\\'))
- winSDKVersionStr.chop(1);
-
- QVersionNumber winSDKVersion = QVersionNumber::fromString(
- QString::fromLocal8Bit(winSDKVersionStr));
- if (!winSDKVersion.isNull())
- windowsTargetPlatformVersion = winSDKVersionStr;
- }
- if (!windowsTargetPlatformVersion.isEmpty()) {
- xml << tagValue("WindowsTargetPlatformVersion", windowsTargetPlatformVersion)
- << tagValue("WindowsTargetPlatformMinVersion", windowsTargetPlatformVersion);
}
+ if (!tool.WindowsTargetPlatformVersion.isEmpty())
+ xml << tagValue("WindowsTargetPlatformVersion", tool.WindowsTargetPlatformVersion);
+ if (!tool.WindowsTargetPlatformMinVersion.isEmpty())
+ xml << tagValue("WindowsTargetPlatformMinVersion", tool.WindowsTargetPlatformMinVersion);
xml << closetag();
diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp
index f2cd7c633b..63d89a5388 100644
--- a/qmake/generators/win32/msvc_nmake.cpp
+++ b/qmake/generators/win32/msvc_nmake.cpp
@@ -34,23 +34,10 @@
#include <qdiriterator.h>
#include <qset.h>
-#include <registry_p.h>
-
#include <time.h>
QT_BEGIN_NAMESPACE
-static QString nmakePathList(const QStringList &list)
-{
- QStringList pathList;
- pathList.reserve(list.size());
- for (const QString &path : list)
- pathList.append(QDir::cleanPath(path));
-
- return QDir::toNativeSeparators(pathList.join(QLatin1Char(';')))
- .replace('#', QLatin1String("^#")).replace('$', QLatin1String("$$"));
-}
-
NmakeMakefileGenerator::NmakeMakefileGenerator() : usePCH(false), usePCHC(false)
{
@@ -70,180 +57,6 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t)
if(Option::mkfile::do_stub_makefile)
return MakefileGenerator::writeStubMakefile(t);
#endif
- if (!project->isHostBuild()) {
- if (project->isActiveConfig(QStringLiteral("winrt"))) {
- QString arch = project->first("VCPROJ_ARCH").toQString().toLower();
- QString compiler;
- QString compilerArch;
- const QString msvcVer = project->first("MSVC_VER").toQString();
- if (msvcVer.isEmpty()) {
- fprintf(stderr, "Mkspec does not specify MSVC_VER. Cannot continue.\n");
- return false;
- }
-
- if (msvcVer == QStringLiteral("15.0")) {
- const ProStringList hostArch = project->values("QMAKE_TARGET.arch");
- if (hostArch.contains("x86_64"))
- compiler = QStringLiteral("HostX64/");
- else
- compiler = QStringLiteral("HostX86/");
- if (arch == QLatin1String("arm")) {
- compiler += QStringLiteral("arm");
- compilerArch = QStringLiteral("arm");
- } else if (arch == QLatin1String("x64")) {
- compiler += QStringLiteral("x64");
- compilerArch = QStringLiteral("amd64");
- } else {
- arch = QStringLiteral("x86");
- compiler += QStringLiteral("x86");
- }
- } else {
- if (arch == QLatin1String("arm")) {
- compiler = QStringLiteral("x86_arm");
- compilerArch = QStringLiteral("arm");
- } else if (arch == QLatin1String("x64")) {
- const ProStringList hostArch = project->values("QMAKE_TARGET.arch");
- if (hostArch.contains("x86_64"))
- compiler = QStringLiteral("amd64");
- else
- compiler = QStringLiteral("x86_amd64");
- compilerArch = QStringLiteral("amd64");
- } else {
- arch = QStringLiteral("x86");
- }
- }
-
- const QString winsdkVer = project->first("WINSDK_VER").toQString();
- if (winsdkVer.isEmpty()) {
- fprintf(stderr, "Mkspec does not specify WINSDK_VER. Cannot continue.\n");
- return false;
- }
- const QString targetVer = project->first("WINTARGET_VER").toQString();
- if (targetVer.isEmpty()) {
- fprintf(stderr, "Mkspec does not specify WINTARGET_VER. Cannot continue.\n");
- return false;
- }
-
-#ifdef Q_OS_WIN
- QString regKey;
- if (msvcVer == QStringLiteral("15.0"))
- regKey = QStringLiteral("Software\\Microsoft\\VisualStudio\\SxS\\VS7\\") + msvcVer;
- else
- regKey = QStringLiteral("Software\\Microsoft\\VisualStudio\\") + msvcVer + ("\\Setup\\VC\\ProductDir");
- const QString vcInstallDir = qt_readRegistryKey(HKEY_LOCAL_MACHINE, regKey, KEY_WOW64_32KEY);
- if (vcInstallDir.isEmpty()) {
- fprintf(stderr, "Failed to find the Visual Studio installation directory.\n");
- return false;
- }
-
- const QString windowsPath = "Software\\Microsoft\\Microsoft SDKs\\Windows\\v";
-
- regKey = windowsPath + winsdkVer + QStringLiteral("\\InstallationFolder");
- const QString kitDir = qt_readRegistryKey(HKEY_LOCAL_MACHINE, regKey, KEY_WOW64_32KEY);
- if (kitDir.isEmpty()) {
- fprintf(stderr, "Failed to find the Windows Kit installation directory.\n");
- return false;
- }
-#else
- const QString vcInstallDir = "/fake/vc_install_dir";
- const QString kitDir = "/fake/sdk_install_dir";
-#endif // Q_OS_WIN
- QStringList incDirs;
- QStringList libDirs;
- QStringList binDirs;
- if (msvcVer == QStringLiteral("15.0")) {
- const QString toolsInstallDir = qgetenv("VCToolsInstallDir");
- if (toolsInstallDir.isEmpty()) {
- fprintf(stderr, "Failed to access tools installation dir.\n");
- return false;
- }
-
- binDirs << toolsInstallDir + QStringLiteral("bin/") + compiler;
- if (arch == QStringLiteral("x64"))
- binDirs << toolsInstallDir + QStringLiteral("bin/HostX86/X86");
- binDirs << kitDir + QStringLiteral("bin/x86");
- binDirs << vcInstallDir + QStringLiteral("Common7/Tools");
- binDirs << vcInstallDir + QStringLiteral("Common7/ide");
- binDirs << vcInstallDir + QStringLiteral("MSBuild/15.0/bin");
-
- incDirs << toolsInstallDir + QStringLiteral("include");
- incDirs << vcInstallDir + QStringLiteral("VC/Auxiliary/VS/include");
-
- const QString crtVersion = qgetenv("UCRTVersion");
- if (crtVersion.isEmpty()) {
- fprintf(stderr, "Failed to access CRT version.\n");
- return false;
- }
- const QString crtInclude = kitDir + QStringLiteral("Include/") + crtVersion;
- const QString crtLib = kitDir + QStringLiteral("Lib/") + crtVersion;
- incDirs << crtInclude + QStringLiteral("/ucrt");
- incDirs << crtInclude + QStringLiteral("/um");
- incDirs << crtInclude + QStringLiteral("/shared");
- incDirs << crtInclude + QStringLiteral("/winrt");
-
- incDirs << kitDir + QStringLiteral("Extension SDKs/WindowsMobile/")
- + crtVersion + QStringLiteral("/Include/WinRT");
-
- libDirs << toolsInstallDir + QStringLiteral("lib/") + arch + QStringLiteral("/store");
-
- libDirs << vcInstallDir + QStringLiteral("VC/Auxiliary/VS/lib/") + arch;
-
- libDirs << crtLib + QStringLiteral("/ucrt/") + arch;
- libDirs << crtLib + QStringLiteral("/um/") + arch;
- } else if (msvcVer == QStringLiteral("14.0")) {
- binDirs << vcInstallDir + QStringLiteral("bin/") + compiler;
- binDirs << vcInstallDir + QStringLiteral("bin/"); // Maybe remove for x86 again?
- binDirs << kitDir + QStringLiteral("bin/") + (arch == QStringLiteral("arm") ? QStringLiteral("x86") : arch);
- binDirs << vcInstallDir + QStringLiteral("../Common7/Tools/bin");
- binDirs << vcInstallDir + QStringLiteral("../Common7/Tools");
- binDirs << vcInstallDir + QStringLiteral("../Common7/ide");
- binDirs << kitDir + QStringLiteral("Windows Performance Toolkit/");
-
- incDirs << vcInstallDir + QStringLiteral("include");
- incDirs << vcInstallDir + QStringLiteral("atlmfc/include");
-
- const QString crtVersion = qgetenv("UCRTVersion");
- if (crtVersion.isEmpty()) {
- fprintf(stderr, "Failed to access CRT version.\n");
- return false;
- }
- const QString crtInclude = kitDir + QStringLiteral("Include/") + crtVersion;
- const QString crtLib = kitDir + QStringLiteral("Lib/") + crtVersion;
- incDirs << crtInclude + QStringLiteral("/ucrt");
- incDirs << crtInclude + QStringLiteral("/um");
- incDirs << crtInclude + QStringLiteral("/shared");
- incDirs << crtInclude + QStringLiteral("/winrt");
-
- incDirs << kitDir + QStringLiteral("Extension SDKs/WindowsMobile/")
- + crtVersion + QStringLiteral("/Include/WinRT");
-
- libDirs << vcInstallDir + QStringLiteral("lib/store/") + compilerArch;
- libDirs << vcInstallDir + QStringLiteral("atlmfc/lib") + compilerArch;
-
- libDirs << crtLib + QStringLiteral("/ucrt/") + arch;
- libDirs << crtLib + QStringLiteral("/um/") + arch;
- } else {
- incDirs << vcInstallDir + QStringLiteral("/include");
- libDirs << vcInstallDir + QStringLiteral("/lib/store/") + compilerArch
- << vcInstallDir + QStringLiteral("/lib/") + compilerArch;
- binDirs << vcInstallDir + QStringLiteral("/bin/") + compiler
- << vcInstallDir + QStringLiteral("/../Common7/IDE");
- libDirs << kitDir + QStringLiteral("/Lib/") + targetVer + ("/um/") + arch;
- incDirs << kitDir + QStringLiteral("/include/um")
- << kitDir + QStringLiteral("/include/shared")
- << kitDir + QStringLiteral("/include/winrt");
- }
-
- binDirs << vcInstallDir + QStringLiteral("/bin");
-
- // Inherit PATH
- binDirs << QString::fromLocal8Bit(qgetenv("PATH")).split(QLatin1Char(';'));
-
- t << "\nINCLUDE = " << nmakePathList(incDirs);
- t << "\nLIB = " << nmakePathList(libDirs);
- t << "\nPATH = " << nmakePathList(binDirs) << '\n';
- }
- }
writeNmakeParts(t);
return MakefileGenerator::writeMakefile(t);
}
@@ -263,6 +76,11 @@ void NmakeMakefileGenerator::writeSubMakeCall(QTextStream &t, const QString &cal
Win32MakefileGenerator::writeSubMakeCall(t, callPrefix, makeArguments);
}
+ProStringList NmakeMakefileGenerator::extraSubTargetDependencies()
+{
+ return { "$(MAKEFILE)" };
+}
+
QString NmakeMakefileGenerator::defaultInstall(const QString &t)
{
QString ret = Win32MakefileGenerator::defaultInstall(t);
@@ -277,7 +95,9 @@ QString NmakeMakefileGenerator::defaultInstall(const QString &t)
if (project->isActiveConfig("debug_info")) {
if (t == "dlltarget" || project->values(ProKey(t + ".CONFIG")).indexOf("no_dll") == -1) {
- QString pdb_target = project->first("TARGET") + project->first("TARGET_VERSION_EXT") + ".pdb";
+ const QFileInfo targetFileInfo = project->first("DESTDIR") + project->first("TARGET")
+ + project->first("TARGET_EXT");
+ const QString pdb_target = targetFileInfo.completeBaseName() + ".pdb";
QString src_targ = (project->isEmpty("DESTDIR") ? QString("$(DESTDIR)") : project->first("DESTDIR")) + pdb_target;
QString dst_targ = filePrefixRoot(root, fileFixify(targetdir + pdb_target, FileFixifyAbsolute));
if(!ret.isEmpty())
@@ -345,21 +165,17 @@ QString NmakeMakefileGenerator::var(const ProKey &value) const
|| value == "QMAKE_RUN_CXX_IMP"
|| value == "QMAKE_RUN_CXX");
if ((isRunCpp && usePCH) || (isRunC && usePCHC)) {
- QFileInfo precompHInfo(fileInfo(precompH));
- QString precompH_f = escapeFilePath(precompHInfo.fileName());
+ QString precompH_f = escapeFilePath(fileFixify(precompH, FileFixifyBackwards));
QString precompRule = QString("-c -FI%1 -Yu%2 -Fp%3")
.arg(precompH_f, precompH_f, escapeFilePath(isRunC ? precompPchC : precompPch));
+ // ### For clang_cl 8 we force inline methods to be compiled here instead
+ // linking them from a pch.o file. We do this by pretending we are also doing
+ // the pch.o generation step.
+ if (project->isActiveConfig("clang_cl"))
+ precompRule += QString(" -Xclang -building-pch-with-obj");
QString p = MakefileGenerator::var(value);
p.replace(QLatin1String("-c"), precompRule);
- // Cannot use -Gm with -FI & -Yu, as this gives an
- // internal compiler error, on the newer compilers
- // ### work-around for a VS 2003 bug. Move to some prf file or remove completely.
- p.remove("-Gm");
return p;
- } else if (value == "QMAKE_CXXFLAGS") {
- // Remove internal compiler error option
- // ### work-around for a VS 2003 bug. Move to some prf file or remove completely.
- return MakefileGenerator::var(value).remove("-Gm");
}
}
@@ -418,7 +234,10 @@ void NmakeMakefileGenerator::init()
precompObj = var("PRECOMPILED_DIR") + project->first("TARGET") + "_pch" + Option::obj_ext;
precompPch = var("PRECOMPILED_DIR") + project->first("TARGET") + "_pch.pch";
// Add linking of precompObj (required for whole precompiled classes)
- project->values("OBJECTS") += precompObj;
+ // ### For clang_cl we currently let inline methods be generated in the normal objects,
+ // since the PCH object is buggy (as of clang 8.0.0)
+ if (!project->isActiveConfig("clang_cl"))
+ project->values("OBJECTS") += precompObj;
// Add pch file to cleanup
project->values("QMAKE_CLEAN") += precompPch;
// Return to variable pool
@@ -428,21 +247,23 @@ void NmakeMakefileGenerator::init()
if (usePCHC) {
precompObjC = var("PRECOMPILED_DIR") + project->first("TARGET") + "_pch_c" + Option::obj_ext;
precompPchC = var("PRECOMPILED_DIR") + project->first("TARGET") + "_pch_c.pch";
- project->values("OBJECTS") += precompObjC;
+ if (!project->isActiveConfig("clang_cl"))
+ project->values("OBJECTS") += precompObjC;
project->values("QMAKE_CLEAN") += precompPchC;
project->values("PRECOMPILED_OBJECT_C") = ProStringList(precompObjC);
project->values("PRECOMPILED_PCH_C") = ProStringList(precompPchC);
}
- ProString tgt = project->first("DESTDIR")
- + project->first("TARGET") + project->first("TARGET_VERSION_EXT");
- if(project->isActiveConfig("shared")) {
- project->values("QMAKE_CLEAN").append(tgt + ".exp");
- project->values("QMAKE_DISTCLEAN").append(tgt + ".lib");
+ const QFileInfo targetFileInfo = project->first("DESTDIR") + project->first("TARGET")
+ + project->first("TARGET_EXT");
+ const ProString targetBase = targetFileInfo.path() + '/' + targetFileInfo.completeBaseName();
+ if (project->first("TEMPLATE") == "lib" && project->isActiveConfig("shared")) {
+ project->values("QMAKE_CLEAN").append(targetBase + ".exp");
+ project->values("QMAKE_DISTCLEAN").append(targetBase + ".lib");
}
if (project->isActiveConfig("debug_info")) {
QString pdbfile;
- QString distPdbFile = tgt + ".pdb";
+ QString distPdbFile = targetBase + ".pdb";
if (project->isActiveConfig("staticlib")) {
// For static libraries, the compiler's pdb file and the dist pdb file are the same.
pdbfile = distPdbFile;
@@ -458,8 +279,8 @@ void NmakeMakefileGenerator::init()
project->values("QMAKE_DISTCLEAN").append(distPdbFile);
}
if (project->isActiveConfig("debug")) {
- project->values("QMAKE_CLEAN").append(tgt + ".ilk");
- project->values("QMAKE_CLEAN").append(tgt + ".idb");
+ project->values("QMAKE_CLEAN").append(targetBase + ".ilk");
+ project->values("QMAKE_CLEAN").append(targetBase + ".idb");
} else {
ProStringList &defines = project->values("DEFINES");
if (!defines.contains("NDEBUG"))
@@ -531,12 +352,13 @@ void NmakeMakefileGenerator::writeImplicitRulesPart(QTextStream &t)
QDirIterator dit(sourceDir, sourceFilesFilter, QDir::Files | QDir::NoDotAndDotDot);
while (dit.hasNext()) {
dit.next();
- QString &duplicate = fileNames[dit.fileName()];
+ const QFileInfo fi = dit.fileInfo();
+ QString &duplicate = fileNames[fi.completeBaseName()];
if (duplicate.isNull()) {
- duplicate = dit.filePath();
+ duplicate = fi.filePath();
} else {
warn_msg(WarnLogic, "%s conflicts with %s", qPrintable(duplicate),
- qPrintable(dit.filePath()));
+ qPrintable(fi.filePath()));
duplicatesFound = true;
}
}
diff --git a/qmake/generators/win32/msvc_nmake.h b/qmake/generators/win32/msvc_nmake.h
index 67a56c7813..5bfdba2bbc 100644
--- a/qmake/generators/win32/msvc_nmake.h
+++ b/qmake/generators/win32/msvc_nmake.h
@@ -48,6 +48,7 @@ class NmakeMakefileGenerator : public Win32MakefileGenerator
protected:
void writeSubMakeCall(QTextStream &t, const QString &callPrefix,
const QString &makeArguments) override;
+ ProStringList extraSubTargetDependencies() override;
QString defaultInstall(const QString &t) override;
QStringList &findDependencies(const QString &file) override;
QString var(const ProKey &value) const override;
diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp
index 4f0cee65e1..cf0b96ec9f 100644
--- a/qmake/generators/win32/msvc_objectmodel.cpp
+++ b/qmake/generators/win32/msvc_objectmodel.cpp
@@ -55,7 +55,8 @@ static DotNET vsVersionFromString(const char *versionString)
{ "11.0", NET2012 },
{ "12.0", NET2013 },
{ "14.0", NET2015 },
- { "15.0", NET2017 }
+ { "15.0", NET2017 },
+ { "16.0", NET2019 }
};
DotNET result = NETUnknown;
for (const auto entry : mapping) {
@@ -2213,8 +2214,49 @@ void VCFilter::addFiles(const ProStringList& fileList)
void VCFilter::modifyPCHstage(QString str)
{
- bool autogenSourceFile = Project->autogenPrecompCPP;
- bool pchThroughSourceFile = !Project->precompCPP.isEmpty();
+ const bool isHFile = (str == Project->precompH);
+ const bool pchThroughSourceFile = !Project->precompSource.isEmpty();
+ if (isHFile && pchThroughSourceFile && Project->autogenPrecompSource) {
+ useCustomBuildTool = true;
+ QString toFile(Project->precompSource);
+ CustomBuildTool.Description = "Generating precompiled header source file '" + toFile + "' ...";
+ CustomBuildTool.Outputs += toFile;
+
+ QStringList lines;
+ CustomBuildTool.CommandLine +=
+ "echo /*-------------------------------------------------------------------- >" + toFile;
+ lines << "* Precompiled header source file used by Visual Studio.NET to generate";
+ lines << "* the .pch file.";
+ lines << "*";
+ lines << "* Due to issues with the dependencies checker within the IDE, it";
+ lines << "* sometimes fails to recompile the PCH file, if we force the IDE to";
+ lines << "* create the PCH file directly from the header file.";
+ lines << "*";
+ lines << "* This file is auto-generated by qmake since no PRECOMPILED_SOURCE was";
+ lines << "* specified, and is used as the common stdafx.cpp. The file is only";
+ lines << QLatin1String("* generated when creating ")
+ + (Config->CompilerVersion < NET2010 ? ".vcproj" : ".vcxproj")
+ + " project files, and is not used for";
+ lines << "* command line compilations by nmake.";
+ lines << "*";
+ lines << "* WARNING: All changes made in this file will be lost.";
+ lines << "--------------------------------------------------------------------*/";
+ lines << "#include \"" + Project->precompHFilename + "\"";
+ for (const QString &line : qAsConst(lines))
+ CustomBuildTool.CommandLine += "echo " + line + ">>" + toFile;
+ return;
+ }
+
+ useCompilerTool = true;
+ const bool isPrecompSource = pchThroughSourceFile && (str == Project->precompSource);
+ if (isPrecompSource) {
+ CompilerTool.UsePrecompiledHeader = pchCreateUsingSpecific;
+ if (Project->autogenPrecompSource)
+ CompilerTool.PrecompiledHeaderThrough = Project->precompHFilename;
+ CompilerTool.ForcedIncludeFiles = QStringList("$(NOINHERIT)");
+ return;
+ }
+
bool isCFile = false;
for (QStringList::Iterator it = Option::c_ext.begin(); it != Option::c_ext.end(); ++it) {
if (str.endsWith(*it)) {
@@ -2222,53 +2264,13 @@ void VCFilter::modifyPCHstage(QString str)
break;
}
}
- const bool isHFile = (str == Project->precompH);
- bool isCPPFile = pchThroughSourceFile && (str == Project->precompCPP);
-
- if(!isCFile && !isHFile && !isCPPFile)
- return;
-
- if(isHFile && pchThroughSourceFile) {
- if (autogenSourceFile) {
- useCustomBuildTool = true;
- QString toFile(Project->precompCPP);
- CustomBuildTool.Description = "Generating precompiled header source file '" + toFile + "' ...";
- CustomBuildTool.Outputs += toFile;
-
- QStringList lines;
- CustomBuildTool.CommandLine +=
- "echo /*-------------------------------------------------------------------- >" + toFile;
- lines << "* Precompiled header source file used by Visual Studio.NET to generate";
- lines << "* the .pch file.";
- lines << "*";
- lines << "* Due to issues with the dependencies checker within the IDE, it";
- lines << "* sometimes fails to recompile the PCH file, if we force the IDE to";
- lines << "* create the PCH file directly from the header file.";
- lines << "*";
- lines << "* This file is auto-generated by qmake since no PRECOMPILED_SOURCE was";
- lines << "* specified, and is used as the common stdafx.cpp. The file is only";
- lines << QLatin1String("* generated when creating ")
- + (Config->CompilerVersion < NET2010 ? ".vcproj" : ".vcxproj")
- + " project files, and is not used for";
- lines << "* command line compilations by nmake.";
- lines << "*";
- lines << "* WARNING: All changes made in this file will be lost.";
- lines << "--------------------------------------------------------------------*/";
- lines << "#include \"" + Project->precompHFilename + "\"";
- for (const QString &line : qAsConst(lines))
- CustomBuildTool.CommandLine += "echo " + line + ">>" + toFile;
- }
- return;
- }
- useCompilerTool = true;
- // Setup PCH options
- CompilerTool.UsePrecompiledHeader = (isCFile ? pchNone : pchCreateUsingSpecific);
- if (isCFile)
+ bool pchCompatible = (isCFile == Project->pchIsCFile);
+ if (!pchCompatible) {
+ CompilerTool.UsePrecompiledHeader = pchNone;
CompilerTool.PrecompiledHeaderThrough = QLatin1String("$(NOINHERIT)");
- else if (autogenSourceFile)
- CompilerTool.PrecompiledHeaderThrough = Project->precompHFilename;
- CompilerTool.ForcedIncludeFiles = QStringList("$(NOINHERIT)");
+ CompilerTool.ForcedIncludeFiles = QStringList("$(NOINHERIT)");
+ }
}
VCFilterFile VCFilter::findFile(const QString &filePath, bool *found) const
diff --git a/qmake/generators/win32/msvc_objectmodel.h b/qmake/generators/win32/msvc_objectmodel.h
index 9d1a170489..33a96bf85e 100644
--- a/qmake/generators/win32/msvc_objectmodel.h
+++ b/qmake/generators/win32/msvc_objectmodel.h
@@ -52,7 +52,8 @@ enum DotNET {
NET2012 = 0xb0,
NET2013 = 0xc0,
NET2015 = 0xd0,
- NET2017 = 0xe0
+ NET2017 = 0xe0,
+ NET2019
};
DotNET vsVersionFromString(const ProString &versionString);
@@ -1123,6 +1124,8 @@ public:
QString SccLocalPath;
QString PlatformName;
QString SdkVersion;
+ QString WindowsTargetPlatformVersion;
+ QString WindowsTargetPlatformMinVersion;
// Single projects
QList<VCProjectSingleConfig> SingleProjects;
diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp
index f7837fc1b4..fd53ec2a6e 100644
--- a/qmake/generators/win32/msvc_vcproj.cpp
+++ b/qmake/generators/win32/msvc_vcproj.cpp
@@ -73,7 +73,9 @@ const char _slnHeader120[] = "Microsoft Visual Studio Solution File, Format
const char _slnHeader140[] = "Microsoft Visual Studio Solution File, Format Version 12.00"
"\n# Visual Studio 2015";
const char _slnHeader141[] = "Microsoft Visual Studio Solution File, Format Version 12.00"
- "\n# Visual Studio 2017";
+ "\n# Visual Studio 15";
+const char _slnHeader142[] = "Microsoft Visual Studio Solution File, Format Version 12.00"
+ "\n# Visual Studio Version 16";
// The following UUID _may_ change for later servicepacks...
// If so we need to search through the registry at
// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\7.0\Projects
@@ -191,6 +193,10 @@ bool VcprojGenerator::writeProjectMakefile()
mergedProject.SccProjectName = mergedProjects.at(0)->vcProject.SccProjectName;
mergedProject.SccLocalPath = mergedProjects.at(0)->vcProject.SccLocalPath;
mergedProject.PlatformName = mergedProjects.at(0)->vcProject.PlatformName;
+ mergedProject.WindowsTargetPlatformVersion =
+ project->first("WINDOWS_TARGET_PLATFORM_VERSION").toQString();
+ mergedProject.WindowsTargetPlatformMinVersion =
+ project->first("WINDOWS_TARGET_PLATFORM_MIN_VERSION").toQString();
XmlOutput xmlOut(t);
projectWriter->write(xmlOut, mergedProject);
@@ -208,6 +214,16 @@ struct VcsolutionDepend {
QStringList dependencies;
};
+/* Disable optimization in getProjectUUID() due to a compiler
+ * bug in MSVC 2015 that causes ASSERT: "&other != this" in the QString
+ * copy constructor for non-empty file names at:
+ * filename.isEmpty()?project->first("QMAKE_MAKEFILE"):filename */
+
+#if defined(Q_CC_MSVC) && !defined(Q_CC_CLANG)
+# pragma optimize( "g", off )
+# pragma warning ( disable : 4748 )
+#endif
+
QUuid VcprojGenerator::getProjectUUID(const QString &filename)
{
bool validUUID = true;
@@ -239,6 +255,10 @@ QUuid VcprojGenerator::getProjectUUID(const QString &filename)
return uuid;
}
+#if defined(Q_CC_MSVC) && !defined(Q_CC_CLANG)
+# pragma optimize( "g", on )
+#endif
+
QUuid VcprojGenerator::increaseUUID(const QUuid &id)
{
QUuid result(id);
@@ -287,6 +307,8 @@ QString VcprojGenerator::retrievePlatformToolSet() const
return QStringLiteral("v140");
case NET2017:
return QStringLiteral("v141");
+ case NET2019:
+ return QStringLiteral("v142");
default:
return QString();
}
@@ -459,8 +481,8 @@ ProStringList VcprojGenerator::collectDependencies(QMakeProject *proj, QHash<QSt
// Add all unknown libs to the deps
QStringList where = QStringList() << "LIBS" << "LIBS_PRIVATE"
<< "QMAKE_LIBS" << "QMAKE_LIBS_PRIVATE";
- for (QStringList::ConstIterator wit = where.begin();
- wit != where.end(); ++wit) {
+ for (QStringList::ConstIterator wit = where.cbegin();
+ wit != where.cend(); ++wit) {
const ProStringList &l = tmp_proj.values(ProKey(*wit));
for (ProStringList::ConstIterator it = l.begin(); it != l.end(); ++it) {
const QString opt = fixLibFlag(*it).toQString();
@@ -513,6 +535,9 @@ void VcprojGenerator::writeSubDirs(QTextStream &t)
}
switch (vcProject.Configuration.CompilerVersion) {
+ case NET2019:
+ t << _slnHeader142;
+ break;
case NET2017:
t << _slnHeader141;
break;
@@ -757,8 +782,9 @@ void VcprojGenerator::init()
// Setup PCH variables
precompH = project->first("PRECOMPILED_HEADER").toQString();
- precompCPP = project->first("PRECOMPILED_SOURCE").toQString();
- usePCH = !precompH.isEmpty() && project->isActiveConfig("precompile_header");
+ precompSource = project->first("PRECOMPILED_SOURCE").toQString();
+ pchIsCFile = project->isActiveConfig("precompile_header_c");
+ usePCH = !precompH.isEmpty() && (pchIsCFile || project->isActiveConfig("precompile_header"));
if (usePCH) {
precompHFilename = fileInfo(precompH).fileName();
// Created files
@@ -772,13 +798,15 @@ void VcprojGenerator::init()
project->values("PRECOMPILED_OBJECT") = ProStringList(precompObj);
project->values("PRECOMPILED_PCH") = ProStringList(precompPch);
- autogenPrecompCPP = precompCPP.isEmpty() && project->isActiveConfig("autogen_precompile_source");
- if (autogenPrecompCPP) {
- precompCPP = precompH
- + (Option::cpp_ext.count() ? Option::cpp_ext.at(0) : QLatin1String(".cpp"));
- project->values("GENERATED_SOURCES") += precompCPP;
- } else if (!precompCPP.isEmpty()) {
- project->values("SOURCES") += precompCPP;
+ autogenPrecompSource = precompSource.isEmpty() && project->isActiveConfig("autogen_precompile_source");
+ if (autogenPrecompSource) {
+ precompSource = precompH
+ + (pchIsCFile
+ ? (Option::c_ext.count() ? Option::c_ext.at(0) : QLatin1String(".c"))
+ : (Option::cpp_ext.count() ? Option::cpp_ext.at(0) : QLatin1String(".cpp")));
+ project->values("GENERATED_SOURCES") += precompSource;
+ } else if (!precompSource.isEmpty()) {
+ project->values("SOURCES") += precompSource;
}
}
@@ -860,6 +888,9 @@ void VcprojGenerator::initProject()
// Own elements -----------------------------
vcProject.Name = project->first("QMAKE_ORIG_TARGET").toQString();
switch (vcProject.Configuration.CompilerVersion) {
+ case NET2019:
+ vcProject.Version = "16.00";
+ break;
case NET2017:
vcProject.Version = "15.00";
break;
@@ -1032,16 +1063,6 @@ void VcprojGenerator::initCompilerTool()
conf.compiler.PrecompiledHeaderFile = "$(IntDir)\\" + precompPch;
conf.compiler.PrecompiledHeaderThrough = project->first("PRECOMPILED_HEADER").toQString();
conf.compiler.ForcedIncludeFiles = project->values("PRECOMPILED_HEADER").toQStringList();
-
- if (conf.CompilerVersion <= NET2003) {
- // Minimal build option triggers an Internal Compiler Error
- // when used in conjunction with /FI and /Yu, so remove it
- // ### work-around for a VS 2003 bug. Move to some prf file or remove completely.
- project->values("QMAKE_CFLAGS_DEBUG").removeAll("-Gm");
- project->values("QMAKE_CFLAGS_DEBUG").removeAll("/Gm");
- project->values("QMAKE_CXXFLAGS_DEBUG").removeAll("-Gm");
- project->values("QMAKE_CXXFLAGS_DEBUG").removeAll("/Gm");
- }
}
conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS"));
@@ -1326,7 +1347,7 @@ void VcprojGenerator::initWinDeployQtTool()
// structure manually by invoking windeployqt a second time, so that
// the MDILXapCompile call succeeds and deployment continues.
conf.windeployqt.CommandLine += commandLine
- + QStringLiteral(" -list relative -dir \"$(MSBuildProjectDirectory)\" \"$(OutDir)\\$(TargetName).exe\" > ")
+ + QStringLiteral(" -list relative -dir \"$(MSBuildProjectDirectory)\" \"$(OutDir)\\$(TargetFileName)\" > ")
+ MakefileGenerator::shellQuote(conf.windeployqt.Record);
conf.windeployqt.config = &vcProject.Configuration;
conf.windeployqt.ExcludedFromBuild = false;
@@ -1423,6 +1444,7 @@ void VcprojGenerator::initTranslationFiles()
vcProject.TranslationFiles.Guid = _GUIDTranslationFiles;
vcProject.TranslationFiles.addFiles(project->values("TRANSLATIONS"));
+ vcProject.TranslationFiles.addFiles(project->values("EXTRA_TRANSLATIONS"));
vcProject.TranslationFiles.Project = this;
vcProject.TranslationFiles.Config = &(vcProject.Configuration);
@@ -1527,14 +1549,14 @@ void VcprojGenerator::initExtraCompilerOutputs()
extraCompile.Filter = "";
extraCompile.Guid = QString(_GUIDExtraCompilerFiles) + "-" + (*it);
- // If the extra compiler has a variable_out set the output file
- // is added to an other file list, and does not need its own..
bool addOnInput = hasBuiltinCompiler(firstExpandedOutputFileName(*it));
- const ProString &tmp_other_out = project->first(ProKey(*it + ".variable_out"));
- if (!tmp_other_out.isEmpty() && !addOnInput)
- continue;
-
if (!addOnInput) {
+ // If the extra compiler has a variable_out set that is already handled
+ // some other place, ignore it.
+ const ProString &outputVar = project->first(ProKey(*it + ".variable_out"));
+ if (!outputVar.isEmpty() && otherFilters.contains(outputVar))
+ continue;
+
QString tmp_out = project->first(ProKey(*it + ".output")).toQString();
if (project->values(ProKey(*it + ".CONFIG")).indexOf("combine") != -1) {
// Combined output, only one file result
@@ -1545,7 +1567,7 @@ void VcprojGenerator::initExtraCompilerOutputs()
const ProStringList &tmp_in = project->values(project->first(ProKey(*it + ".input")).toKey());
for (int i = 0; i < tmp_in.count(); ++i) {
const QString &filename = tmp_in.at(i).toQString();
- if (extraCompilerSources.contains(filename))
+ if (extraCompilerSources.contains(filename) && !otherFiltersContain(filename))
extraCompile.addFile(Option::fixPathToTargetOS(
replaceExtraCompilerVariables(filename, tmp_out, QString(), NoShell), false));
}
@@ -1561,7 +1583,7 @@ void VcprojGenerator::initExtraCompilerOutputs()
const ProStringList &tmp_in = project->values(inputVar.toKey());
for (int i = 0; i < tmp_in.count(); ++i) {
const QString &filename = tmp_in.at(i).toQString();
- if (extraCompilerSources.contains(filename))
+ if (extraCompilerSources.contains(filename) && !otherFiltersContain(filename))
extraCompile.addFile(Option::fixPathToTargetOS(
replaceExtraCompilerVariables(filename, QString(), QString(), NoShell), false));
}
@@ -1575,6 +1597,28 @@ void VcprojGenerator::initExtraCompilerOutputs()
}
}
+bool VcprojGenerator::otherFiltersContain(const QString &fileName) const
+{
+ auto filterFileMatches = [&fileName] (const VCFilterFile &ff)
+ {
+ return ff.file == fileName;
+ };
+ for (const VCFilter *filter : { &vcProject.RootFiles,
+ &vcProject.SourceFiles,
+ &vcProject.HeaderFiles,
+ &vcProject.GeneratedFiles,
+ &vcProject.LexYaccFiles,
+ &vcProject.TranslationFiles,
+ &vcProject.FormFiles,
+ &vcProject.ResourceFiles,
+ &vcProject.DeploymentFiles,
+ &vcProject.DistributionFiles}) {
+ if (std::any_of(filter->Files.cbegin(), filter->Files.cend(), filterFileMatches))
+ return true;
+ }
+ return false;
+}
+
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
diff --git a/qmake/generators/win32/msvc_vcproj.h b/qmake/generators/win32/msvc_vcproj.h
index 6af5ec7007..55d36c3762 100644
--- a/qmake/generators/win32/msvc_vcproj.h
+++ b/qmake/generators/win32/msvc_vcproj.h
@@ -57,15 +57,16 @@ public:
~VcprojGenerator();
QString defaultMakefile() const;
- QString precompH, precompHFilename, precompCPP,
+ QString precompH, precompHFilename, precompSource,
precompObj, precompPch;
- bool autogenPrecompCPP;
+ bool autogenPrecompSource;
static bool hasBuiltinCompiler(const QString &file);
QHash<QString, QStringList> extraCompilerSources;
QHash<QString, QString> extraCompilerOutputs;
const QString customBuildToolFilterFileSuffix;
bool usePCH;
+ bool pchIsCFile = false;
VCProjectWriter *projectWriter;
protected:
@@ -131,6 +132,7 @@ private:
ProString firstInputFileName(const ProString &extraCompilerName) const;
QString firstExpandedOutputFileName(const ProString &extraCompilerName);
void createCustomBuildToolFakeFile(const QString &cbtFilePath, const QString &realOutFilePath);
+ bool otherFiltersContain(const QString &fileName) const;
friend class VCFilter;
};
diff --git a/qmake/generators/win32/registry.cpp b/qmake/generators/win32/registry.cpp
deleted file mode 100644
index 3391ab9512..0000000000
--- a/qmake/generators/win32/registry.cpp
+++ /dev/null
@@ -1,158 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the qmake application of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtCore/qstringlist.h>
-#include "registry_p.h"
-
-QT_BEGIN_NAMESPACE
-
-#ifdef Q_OS_WIN32
-/*
- Returns the path part of a registry key.
- e.g.
- For a key
- "Software\\Microsoft\\VisualStudio\\8.0\\Setup\\VC\\ProductDir"
- it returns
- "Software\\Microsoft\\VisualStudio\\8.0\\Setup\\VC\\"
-*/
-static QString keyPath(const QString &rKey)
-{
- int idx = rKey.lastIndexOf(QLatin1Char('\\'));
- if (idx == -1)
- return QString();
- return rKey.left(idx + 1);
-}
-
-/*
- Returns the name part of a registry key.
- e.g.
- For a key
- "Software\\Microsoft\\VisualStudio\\8.0\\Setup\\VC\\ProductDir"
- it returns
- "ProductDir"
-*/
-static QString keyName(const QString &rKey)
-{
- int idx = rKey.lastIndexOf(QLatin1Char('\\'));
- if (idx == -1)
- return rKey;
-
- QString res(rKey.mid(idx + 1));
- if (res == QLatin1String("Default") || res == QLatin1String("."))
- res = QString();
- return res;
-}
-#endif
-
-QString qt_readRegistryKey(HKEY parentHandle, const QString &rSubkey, unsigned long options)
-{
- QString result;
-
-#ifdef Q_OS_WIN32
- QString rSubkeyName = keyName(rSubkey);
- QString rSubkeyPath = keyPath(rSubkey);
-
- HKEY handle = nullptr;
- LONG res = RegOpenKeyEx(parentHandle, (wchar_t*)rSubkeyPath.utf16(), 0,
- KEY_READ | options, &handle);
-
- if (res != ERROR_SUCCESS)
- return QString();
-
- // get the size and type of the value
- DWORD dataType;
- DWORD dataSize;
- res = RegQueryValueEx(handle, (wchar_t*)rSubkeyName.utf16(), nullptr, &dataType, nullptr, &dataSize);
- if (res != ERROR_SUCCESS) {
- RegCloseKey(handle);
- return QString();
- }
-
- // get the value
- QByteArray data(dataSize, 0);
- res = RegQueryValueEx(handle, (wchar_t*)rSubkeyName.utf16(), nullptr, nullptr,
- reinterpret_cast<unsigned char*>(data.data()), &dataSize);
- if (res != ERROR_SUCCESS) {
- RegCloseKey(handle);
- return QString();
- }
-
- switch (dataType) {
- case REG_EXPAND_SZ:
- case REG_SZ: {
- result = QString::fromWCharArray(((const wchar_t *)data.constData()));
- break;
- }
-
- case REG_MULTI_SZ: {
- QStringList l;
- int i = 0;
- for (;;) {
- QString s = QString::fromWCharArray((const wchar_t *)data.constData() + i);
- i += s.length() + 1;
-
- if (s.isEmpty())
- break;
- l.append(s);
- }
- result = l.join(QLatin1String(", "));
- break;
- }
-
- case REG_NONE:
- case REG_BINARY: {
- result = QString::fromWCharArray((const wchar_t *)data.constData(), data.size() / 2);
- break;
- }
-
- case REG_DWORD_BIG_ENDIAN:
- case REG_DWORD: {
- Q_ASSERT(data.size() == sizeof(int));
- int i;
- memcpy((char*)&i, data.constData(), sizeof(int));
- result = QString::number(i);
- break;
- }
-
- default:
- qWarning("QSettings: unknown data %u type in windows registry", quint32(dataType));
- break;
- }
-
- RegCloseKey(handle);
-#else
- Q_UNUSED(parentHandle);
- Q_UNUSED(rSubkey)
- Q_UNUSED(options);
-#endif
-
- return result;
-}
-
-QT_END_NAMESPACE
-
diff --git a/qmake/generators/win32/registry_p.h b/qmake/generators/win32/registry_p.h
deleted file mode 100644
index 3526dffd45..0000000000
--- a/qmake/generators/win32/registry_p.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the qmake application of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QT_WINDOWS_REGISTRY_H
-#define QT_WINDOWS_REGISTRY_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-QT_BEGIN_NAMESPACE
-
-#include <QtCore/qglobal.h>
-
-#ifdef Q_OS_WIN32
- #include <QtCore/qt_windows.h>
-#else
- typedef void* HKEY;
-#endif
-
-#include <QtCore/qstring.h>
-
-/**
- * Read a value from the Windows registry.
- *
- * If the key is not found, or the registry cannot be accessed (for example
- * if this code is compiled for a platform other than Windows), a null
- * string is returned.
- *
- * 32-bit code reads from the registry's 32 bit view (Wow6432Node),
- * 64 bit code reads from the 64 bit view.
- * Pass KEY_WOW64_32KEY to access the 32 bit view regardless of the
- * application's architecture, KEY_WOW64_64KEY respectively.
- */
-QString qt_readRegistryKey(HKEY parentHandle, const QString &rSubkey,
- unsigned long options = 0);
-
-QT_END_NAMESPACE
-
-#endif // QT_WINDOWS_REGISTRY_H
-
diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp
index e0d03ccc1c..16f9361d13 100644
--- a/qmake/generators/win32/winmakefile.cpp
+++ b/qmake/generators/win32/winmakefile.cpp
@@ -84,6 +84,9 @@ Win32MakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags)
if (impexts.isEmpty())
impexts = project->values("QMAKE_EXTENSION_STATICLIB");
QList<QMakeLocalFileName> dirs;
+ int libidx = 0;
+ for (const ProString &dlib : project->values("QMAKE_DEFAULT_LIBDIRS"))
+ dirs.append(QMakeLocalFileName(dlib.toQString()));
static const char * const lflags[] = { "LIBS", "LIBS_PRIVATE",
"QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", nullptr };
for (int i = 0; lflags[i]; i++) {
@@ -94,11 +97,12 @@ Win32MakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags)
LibFlagType type = parseLibFlag(opt, &arg);
if (type == LibFlagPath) {
QMakeLocalFileName lp(arg.toQString());
- if (dirs.contains(lp)) {
+ int idx = dirs.indexOf(lp);
+ if (idx >= 0 && idx < libidx) {
it = l.erase(it);
continue;
}
- dirs.append(lp);
+ dirs.insert(libidx++, lp);
(*it) = "-L" + lp.real();
} else if (type == LibFlagLib) {
QString lib = arg.toQString();
@@ -112,8 +116,8 @@ Win32MakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags)
goto found;
}
QString libBase = (*dir_it).local() + '/' + lib + verovr;
- for (ProStringList::ConstIterator extit = impexts.begin();
- extit != impexts.end(); ++extit) {
+ for (ProStringList::ConstIterator extit = impexts.cbegin();
+ extit != impexts.cend(); ++extit) {
if (exists(libBase + '.' + *extit)) {
(*it) = cand + verovr + '.' + *extit;
goto found;
@@ -520,6 +524,8 @@ void Win32MakefileGenerator::writeIncPart(QTextStream &t)
void Win32MakefileGenerator::writeStandardParts(QTextStream &t)
{
+ writeExportedVariables(t);
+
t << "####### Compiler, tools and options\n\n";
t << "CC = " << var("QMAKE_CC") << endl;
t << "CXX = " << var("QMAKE_CXX") << endl;