From d8b2998daeab9bfb7bfb5182960ec09b94885b17 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 9 May 2012 12:47:02 +0200 Subject: Revert "move finding the makespec to Option" Needed for an upcoming revert. This reverts commit 74a6669fa7c0d6e2cb7d34d56332d620d2a07755. Conflicts: qmake/option.cpp qmake/project.cpp qmake/property.cpp Change-Id: I56088506d27bf1f095f9261c75224f4bee17ec60 Reviewed-by: Joerg Bornemann --- qmake/project.cpp | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index 3df80bc00d..612acda2f4 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -602,6 +602,26 @@ QStringList qmake_feature_paths(QMakeProperty *prop=0) return feature_roots; } +QStringList qmake_mkspec_paths() +{ + QStringList ret; + const QString concat = QLatin1String("/mkspecs"); + QByteArray qmakepath = qgetenv("QMAKEPATH"); + if (!qmakepath.isEmpty()) { + const QStringList lst = splitPathList(QString::fromLocal8Bit(qmakepath)); + for (QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it) + ret << ((*it) + concat); + } + if (!Option::mkfile::project_build_root.isEmpty()) + ret << Option::mkfile::project_build_root + concat; + if (!Option::mkfile::project_root.isEmpty()) + ret << Option::mkfile::project_root + concat; + ret << QLibraryInfo::location(QLibraryInfo::DataPath) + concat; + ret.removeDuplicates(); + + return ret; +} + QMakeProject::~QMakeProject() { if(own_prop) @@ -1285,6 +1305,29 @@ QMakeProject::read(uchar cmd) } { // parse mkspec QString qmakespec = Option::mkfile::qmakespec; + if (qmakespec.isEmpty()) + qmakespec = "default"; + if (QDir::isRelativePath(qmakespec)) { + QStringList mkspec_roots = qmake_mkspec_paths(); + debug_msg(2, "Looking for mkspec %s in (%s)", qmakespec.toLatin1().constData(), + mkspec_roots.join("::").toLatin1().constData()); + bool found_mkspec = false; + for (QStringList::ConstIterator it = mkspec_roots.begin(); it != mkspec_roots.end(); ++it) { + QString mkspec = (*it) + QLatin1Char('/') + qmakespec; + if (QFile::exists(mkspec)) { + found_mkspec = true; + Option::mkfile::qmakespec = qmakespec = mkspec; + break; + } + } + if (!found_mkspec) { + fprintf(stderr, "Could not find mkspecs for your QMAKESPEC(%s) after trying:\n\t%s\n", + qmakespec.toLatin1().constData(), mkspec_roots.join("\n\t").toLatin1().constData()); + return false; + } + } + + // parse qmake configuration while(qmakespec.endsWith(QLatin1Char('/'))) qmakespec.truncate(qmakespec.length()-1); QString spec = qmakespec + QLatin1String("/qmake.conf"); -- cgit v1.2.3 From 4e9cbfc90f6db09d865d9dc5bb40924fbe0d11a3 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 9 May 2012 15:14:37 +0200 Subject: Revert "move .qmake.cache search to Option" We are now moving in the exact opposite direction. This logically reverts commit 059200a44ba7177d0c9ec6bb5e6ee0b7e0c3f017. Some adjustments were necessary to maintain the project root stuff. Conflicts: qmake/main.cpp qmake/option.cpp qmake/option.h qmake/project.cpp Change-Id: Ic14fa571cbbfe9ac159f92493e49741d70a87eff Reviewed-by: Joerg Bornemann --- qmake/project.cpp | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 6 deletions(-) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index 612acda2f4..283dee13c8 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -164,6 +164,9 @@ struct parser_info { bool from_file; } parser; +static QString project_root; +static QString project_build_root; + static QString remove_quotes(const QString &arg) { const ushort SINGLEQUOTE = '\''; @@ -612,10 +615,10 @@ QStringList qmake_mkspec_paths() for (QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it) ret << ((*it) + concat); } - if (!Option::mkfile::project_build_root.isEmpty()) - ret << Option::mkfile::project_build_root + concat; - if (!Option::mkfile::project_root.isEmpty()) - ret << Option::mkfile::project_root + concat; + if (!project_build_root.isEmpty()) + ret << project_build_root + concat; + if (!project_root.isEmpty()) + ret << project_root + concat; ret << QLibraryInfo::location(QLibraryInfo::DataPath) + concat; ret.removeDuplicates(); @@ -1298,11 +1301,61 @@ QMakeProject::read(uchar cmd) if(!Option::user_template_prefix.isEmpty()) base_vars["TEMPLATE_PREFIX"] = QStringList(Option::user_template_prefix); + project_build_root.clear(); + if (Option::mkfile::do_cache) { // parse the cache - if (Option::output_dir.startsWith(Option::mkfile::project_build_root)) + if (Option::mkfile::cachefile.isEmpty()) { //find it as it has not been specified + QDir dir(Option::output_dir); + while (!dir.exists(QLatin1String(".qmake.cache"))) + if (dir.isRoot() || !dir.cdUp()) + goto no_cache; + Option::mkfile::cachefile = dir.filePath(QLatin1String(".qmake.cache")); + project_build_root = dir.path(); + } else { + QFileInfo fi(Option::mkfile::cachefile); + Option::mkfile::cachefile = QDir::cleanPath(fi.absoluteFilePath()); + project_build_root = QDir::cleanPath(fi.absolutePath()); + } + + QHash cache; + if (!read(Option::mkfile::cachefile, cache)) { + Option::mkfile::cachefile.clear(); + goto no_cache; + } + if (Option::mkfile::qmakespec.isEmpty() && !cache["QMAKESPEC"].isEmpty()) + Option::mkfile::qmakespec = cache["QMAKESPEC"].first(); + + if (Option::output_dir.startsWith(project_build_root)) Option::mkfile::cachefile_depth = - Option::output_dir.mid(Option::mkfile::project_build_root.length()).count('/'); + Option::output_dir.mid(project_build_root.length()).count('/'); + } + no_cache: + + if (qmake_getpwd() != Option::output_dir || project_build_root.isEmpty()) { + QDir srcdir(qmake_getpwd()); + QDir dstdir(Option::output_dir); + do { + if (!project_build_root.isEmpty()) { + // If we already know the build root, just match up the source root with it. + if (dstdir.path() == project_build_root) { + project_root = srcdir.path(); + break; + } + } else { + // Look for mkspecs/ in source and build. First to win determines the root. + if (dstdir.exists("mkspecs") || srcdir.exists("mkspecs")) { + project_build_root = dstdir.path(); + project_root = srcdir.path(); + if (project_root == project_build_root) + project_root.clear(); + break; + } + } + } while (!srcdir.isRoot() && srcdir.cdUp() && !dstdir.isRoot() && dstdir.cdUp()); + } else { + project_root.clear(); } + { // parse mkspec QString qmakespec = Option::mkfile::qmakespec; if (qmakespec.isEmpty()) -- cgit v1.2.3 From 528192a78b3250964ee99efab42b6683da02eb11 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 9 May 2012 18:39:05 +0200 Subject: Revert "make default_pro.prf advertize dynamically created .qmake.cache" ... and followup fixes. this is not needed any more due to the breaking patch being reverted. Change-Id: Ia3416fcc16ddece680efbd0322286a601879fa0a Reviewed-by: Joerg Bornemann --- qmake/project.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index 283dee13c8..4d4dfe955e 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -1187,8 +1187,6 @@ QMakeProject::parse(const QString &t, QHash &place, int nu } if(var == "REQUIRES") // special case to get communicated to backends! doProjectCheckReqs(vallist, place); - else if (var == "_QMAKE_CACHE_") - Option::mkfile::cachefile = varlist.isEmpty() ? QString() : varlist.at(0); } return true; } -- cgit v1.2.3 From 14bbab09c158e3eb54169b42c4a303d396a32f0e Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 31 Jan 2012 18:36:18 +0100 Subject: introduce ability to build projects for the host system when qmake runs into the new option(host_build) command, it will restart the project evaluation with a host spec. the new default host spec is called default-host (gasp!). it is overridden with the pre-exising -spec / -platform option, while the new -xspec / -xplatform option overrides the pre-existing default spec. specifying -spec but not -xspec will set the xspec, too, so the behavior is backwards-compatible. same for the XQMAKESPEC override read from .qmake.cache and the environment variable. the cleaner solution would be adding -hostspec, to be symmetrical with the override semantics, but that would deviate from configure in turn. Change-Id: I4297c873780af16ab7928421b434ce0f1d3820da Reviewed-by: Joerg Bornemann --- qmake/project.cpp | 81 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 57 insertions(+), 24 deletions(-) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index 4d4dfe955e..f3a3856d82 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -531,7 +531,7 @@ static void qmake_error_msg(const QString &msg) 1) features/(unix|win32|macx)/ 2) features/ */ -QStringList qmake_feature_paths(QMakeProperty *prop=0) +QStringList qmake_feature_paths(QMakeProperty *prop, bool host_build) { const QString mkspecs_concat = QLatin1String("/mkspecs"); const QString base_concat = QLatin1String("/features"); @@ -578,12 +578,13 @@ QStringList qmake_feature_paths(QMakeProperty *prop=0) feature_roots << ((*it) + mkspecs_concat + (*concat_it)); } } - if(!Option::mkfile::qmakespec.isEmpty()) { + QString *specp = host_build ? &Option::mkfile::qmakespec : &Option::mkfile::xqmakespec; + if (!specp->isEmpty()) { // The spec is already platform-dependent, so no subdirs here. - feature_roots << Option::mkfile::qmakespec + base_concat; + feature_roots << *specp + base_concat; // Also check directly under the root directory of the mkspecs collection - QFileInfo specfi(Option::mkfile::qmakespec); + QFileInfo specfi(*specp); QDir specrootdir(specfi.absolutePath()); while (!specrootdir.isRoot()) { const QString specrootpath = specrootdir.path(); @@ -629,16 +630,7 @@ QMakeProject::~QMakeProject() { if(own_prop) delete prop; - for(QHash::iterator it = replaceFunctions.begin(); it != replaceFunctions.end(); ++it) { - if(!it.value()->deref()) - delete it.value(); - } - replaceFunctions.clear(); - for(QHash::iterator it = testFunctions.begin(); it != testFunctions.end(); ++it) { - if(!it.value()->deref()) - delete it.value(); - } - testFunctions.clear(); + cleanup(); } @@ -653,14 +645,29 @@ QMakeProject::init(QMakeProperty *p) own_prop = false; } recursive = false; + host_build = false; reset(); } +void +QMakeProject::cleanup() +{ + for (QHash::iterator it = replaceFunctions.begin(); it != replaceFunctions.end(); ++it) + if (!it.value()->deref()) + delete it.value(); + replaceFunctions.clear(); + for (QHash::iterator it = testFunctions.begin(); it != testFunctions.end(); ++it) + if (!it.value()->deref()) + delete it.value(); + testFunctions.clear(); +} + // Duplicate project. It is *not* allowed to call the complex read() functions on the copy. QMakeProject::QMakeProject(QMakeProject *p, const QHash *_vars) { init(p->properties()); vars = _vars ? *_vars : p->variables(); + host_build = p->host_build; for(QHash::iterator it = p->replaceFunctions.begin(); it != p->replaceFunctions.end(); ++it) { it.value()->ref(); replaceFunctions.insert(it.key(), it.value()); @@ -680,6 +687,7 @@ QMakeProject::reset() iterator = 0; function = 0; backslashWarned = false; + need_restart = false; } bool @@ -1226,6 +1234,8 @@ QMakeProject::read(QTextStream &file, QHash &place) } s = ""; numLines = 0; + if (need_restart) + break; } } } @@ -1271,7 +1281,7 @@ QMakeProject::read(const QString &file, QHash &place) if(!using_stdin) qfile.close(); } - if(scope_blocks.count() != 1) { + if (!need_restart && scope_blocks.count() != 1) { qmake_error_msg("Unterminated conditional block at end of file"); ret = false; } @@ -1290,6 +1300,7 @@ QMakeProject::read(const QString &project, uchar cmd) bool QMakeProject::read(uchar cmd) { + again: if ((cmd & ReadSetup) && base_vars.isEmpty()) { // hack to get the Option stuff in there base_vars["QMAKE_EXT_CPP"] = Option::cpp_ext; @@ -1320,8 +1331,13 @@ QMakeProject::read(uchar cmd) Option::mkfile::cachefile.clear(); goto no_cache; } - if (Option::mkfile::qmakespec.isEmpty() && !cache["QMAKESPEC"].isEmpty()) + if (Option::mkfile::xqmakespec.isEmpty() && !cache["XQMAKESPEC"].isEmpty()) + Option::mkfile::xqmakespec = cache["XQMAKESPEC"].first(); + if (Option::mkfile::qmakespec.isEmpty() && !cache["QMAKESPEC"].isEmpty()) { Option::mkfile::qmakespec = cache["QMAKESPEC"].first(); + if (Option::mkfile::xqmakespec.isEmpty()) + Option::mkfile::xqmakespec = Option::mkfile::qmakespec; + } if (Option::output_dir.startsWith(project_build_root)) Option::mkfile::cachefile_depth = @@ -1355,9 +1371,10 @@ QMakeProject::read(uchar cmd) } { // parse mkspec - QString qmakespec = Option::mkfile::qmakespec; + QString *specp = host_build ? &Option::mkfile::qmakespec : &Option::mkfile::xqmakespec; + QString qmakespec = *specp; if (qmakespec.isEmpty()) - qmakespec = "default"; + qmakespec = host_build ? "default-host" : "default"; if (QDir::isRelativePath(qmakespec)) { QStringList mkspec_roots = qmake_mkspec_paths(); debug_msg(2, "Looking for mkspec %s in (%s)", qmakespec.toLatin1().constData(), @@ -1367,7 +1384,7 @@ QMakeProject::read(uchar cmd) QString mkspec = (*it) + QLatin1Char('/') + qmakespec; if (QFile::exists(mkspec)) { found_mkspec = true; - Option::mkfile::qmakespec = qmakespec = mkspec; + *specp = qmakespec = mkspec; break; } } @@ -1441,6 +1458,11 @@ QMakeProject::read(uchar cmd) pfile += Option::pro_ext; if(!read(pfile, vars)) return false; + if (need_restart) { + base_vars.clear(); + cleanup(); + goto again; + } } if (cmd & ReadSetup) { @@ -1537,7 +1559,7 @@ QMakeProject::resolveSpec(QString *spec, const QString &qmakespec) { if (spec->isEmpty()) { *spec = QFileInfo(qmakespec).fileName(); - if (*spec == "default") { + if (*spec == "default" || *spec == "default-host") { #ifdef Q_OS_UNIX char buffer[1024]; int l = readlink(qmakespec.toLatin1().constData(), buffer, 1023); @@ -1586,9 +1608,14 @@ QMakeProject::isActiveConfig(const QString &x, bool regex, QHash, (void**)&feature_roots); } debug_msg(2, "Looking for feature '%s' in (%s)", file.toLatin1().constData(), @@ -2742,6 +2770,11 @@ QMakeProject::doProjectTest(QString func, QList args_list, QHash Date: Tue, 3 Apr 2012 15:55:45 +0200 Subject: add "blob" and "lines" modes to $$cat() and $$system() this bypasses the otherwise done insane word splitting Change-Id: Ia9b8980bc0770de3999544a06d239f55fb34f801 Reviewed-by: Marius Storm-Olsen --- qmake/project.cpp | 88 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 63 insertions(+), 25 deletions(-) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index f3a3856d82..000c6300b7 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -1797,6 +1797,23 @@ QMakeProject::doProjectInclude(QString file, uchar flags, QHash &place) @@ -1940,19 +1957,33 @@ QMakeProject::doProjectExpand(QString func, QList args_list, } else { QString file = Option::normalizePath(args[0]); + bool blob = false; + bool lines = false; bool singleLine = true; - if(args.count() > 1) - singleLine = (args[1].toLower() == "true"); - + if (args.count() > 1) { + if (!args.at(1).compare(QLatin1String("false"), Qt::CaseInsensitive)) + singleLine = false; + else if (!args.at(1).compare(QLatin1String("blob"), Qt::CaseInsensitive)) + blob = true; + else if (!args.at(1).compare(QLatin1String("lines"), Qt::CaseInsensitive)) + lines = true; + } QFile qfile(file); if(qfile.open(QIODevice::ReadOnly)) { QTextStream stream(&qfile); - while(!stream.atEnd()) { - ret += split_value_list(stream.readLine().trimmed()); - if(!singleLine) - ret += "\n"; + if (blob) { + ret += stream.readAll(); + } else { + while (!stream.atEnd()) { + if (lines) { + ret += stream.readLine(); + } else { + ret += split_value_list(stream.readLine().trimmed()); + if (!singleLine) + ret += "\n"; + } + } } - qfile.close(); } } break; } @@ -2113,26 +2144,33 @@ QMakeProject::doProjectExpand(QString func, QList args_list, fprintf(stderr, "%s:%d system(execut) requires one argument.\n", parser.file.toLatin1().constData(), parser.line_no); } else { - char buff[256]; + bool blob = false; + bool lines = false; bool singleLine = true; - if(args.count() > 1) - singleLine = (args[1].toLower() == "true"); - QString output; - FILE *proc = QT_POPEN(args[0].toLatin1().constData(), "r"); - while(proc && !feof(proc)) { - int read_in = int(fread(buff, 1, 255, proc)); - if(!read_in) - break; - for(int i = 0; i < read_in; i++) { - if((singleLine && buff[i] == '\n') || buff[i] == '\t') - buff[i] = ' '; + if (args.count() > 1) { + if (!args.at(1).compare(QLatin1String("false"), Qt::CaseInsensitive)) + singleLine = false; + else if (!args.at(1).compare(QLatin1String("blob"), Qt::CaseInsensitive)) + blob = true; + else if (!args.at(1).compare(QLatin1String("lines"), Qt::CaseInsensitive)) + lines = true; + } + QByteArray bytes = getCommandOutput(args.at(0)); + if (lines) { + QTextStream stream(bytes); + while (!stream.atEnd()) + ret += stream.readLine(); + } else { + QString output = QString::fromLocal8Bit(bytes); + if (blob) { + ret += output; + } else { + output.replace(QLatin1Char('\t'), QLatin1Char(' ')); + if (singleLine) + output.replace(QLatin1Char('\n'), QLatin1Char(' ')); + ret += split_value_list(output); } - buff[read_in] = '\0'; - output += buff; } - ret += split_value_list(output); - if(proc) - QT_PCLOSE(proc); } break; } case E_UNIQUE: { -- cgit v1.2.3 From 2702f7637e7a2955d37dcd8e748dbf3faf477b2d Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 27 Apr 2012 18:34:09 +0200 Subject: add cache() function this function adds the current contents of the named variable to the cache. this comprises populating base_vars and appending an assignment to .qmake.cache. if no cache file exists yet, it will be created in the current output directory (and inherited by subdirs projects). if called without a variable name, only create the cache file if missing. Change-Id: I1e81c2238aa6a5817a6ebbfb022e2b995c349363 Reviewed-by: Marius Storm-Olsen --- qmake/project.cpp | 225 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 222 insertions(+), 3 deletions(-) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index 000c6300b7..2a03580260 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -119,7 +119,7 @@ enum TestFunc { T_REQUIRES=1, T_GREATERTHAN, T_LESSTHAN, T_EQUALS, T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM, T_RETURN, T_BREAK, T_NEXT, T_DEFINED, T_CONTAINS, T_INFILE, T_COUNT, T_ISEMPTY, T_INCLUDE, T_LOAD, T_DEBUG, T_ERROR, - T_MESSAGE, T_WARNING, T_IF, T_OPTION }; + T_MESSAGE, T_WARNING, T_IF, T_OPTION, T_CACHE }; QHash qmake_testFunctions() { static QHash *qmake_test_functions = 0; @@ -154,6 +154,7 @@ QHash qmake_testFunctions() qmake_test_functions->insert("message", T_MESSAGE); qmake_test_functions->insert("warning", T_WARNING); qmake_test_functions->insert("option", T_OPTION); + qmake_test_functions->insert("cache", T_CACHE); } return *qmake_test_functions; } @@ -167,6 +168,16 @@ struct parser_info { static QString project_root; static QString project_build_root; +static QStringList *all_feature_roots[2] = { 0, 0 }; + +static void +invalidateFeatureRoots() +{ + for (int i = 0; i < 2; i++) + if (all_feature_roots[i]) + all_feature_roots[i]->clear(); +} + static QString remove_quotes(const QString &arg) { const ushort SINGLEQUOTE = '\''; @@ -1673,12 +1684,13 @@ QMakeProject::doProjectInclude(QString file, uchar flags, QHash, (void**)&feature_roots); } + if (feature_roots->isEmpty()) + *feature_roots = qmake_feature_paths(prop, host_build); debug_msg(2, "Looking for feature '%s' in (%s)", file.toLatin1().constData(), feature_roots->join("::").toLatin1().constData()); int start_root = 0; @@ -1797,6 +1809,99 @@ QMakeProject::doProjectInclude(QString file, uchar flags, QHashremoveAll(dv); +} + +static QString +quoteValue(const QString &val) +{ + QString ret; + ret.reserve(val.length()); + bool quote = val.isEmpty(); + bool escaping = false; + for (int i = 0, l = val.length(); i < l; i++) { + QChar c = val.unicode()[i]; + ushort uc = c.unicode(); + if (uc < 32) { + if (!escaping) { + escaping = true; + ret += QLatin1String("$$escape_expand("); + } + switch (uc) { + case '\r': + ret += QLatin1String("\\\\r"); + break; + case '\n': + ret += QLatin1String("\\\\n"); + break; + case '\t': + ret += QLatin1String("\\\\t"); + break; + default: + ret += QString::fromLatin1("\\\\x%1").arg(uc, 2, 16, QLatin1Char('0')); + break; + } + } else { + if (escaping) { + escaping = false; + ret += QLatin1Char(')'); + } + switch (uc) { + case '\\': + ret += QLatin1String("\\\\"); + break; + case '"': + ret += QLatin1String("\\\""); + break; + case '\'': + ret += QLatin1String("\\'"); + break; + case '$': + ret += QLatin1String("\\$"); + break; + case '#': + ret += QLatin1String("$${LITERAL_HASH}"); + break; + case 32: + quote = true; + // fallthrough + default: + ret += c; + break; + } + } + } + if (escaping) + ret += QLatin1Char(')'); + if (quote) { + ret.prepend(QLatin1Char('"')); + ret.append(QLatin1Char('"')); + } + return ret; +} + +static bool +writeFile(const QString &name, QIODevice::OpenMode mode, const QString &contents, QString *errStr) +{ + QByteArray bytes = contents.toLocal8Bit(); + QFile cfile(name); + if (!cfile.open(mode | QIODevice::WriteOnly | QIODevice::Text)) { + *errStr = cfile.errorString(); + return false; + } + cfile.write(bytes); + cfile.close(); + if (cfile.error() != QFile::NoError) { + *errStr = cfile.errorString(); + return false; + } + return true; +} + static QByteArray getCommandOutput(const QString &args) { @@ -2820,6 +2925,120 @@ QMakeProject::doProjectTest(QString func, QList args_list, QHash 3) { + fprintf(stderr, "%s:%d: cache(var, [set|add|sub] [transient], [srcvar]) requires one to three arguments.\n", + parser.file.toLatin1().constData(), parser.line_no); + return false; + } + bool persist = true; + enum { CacheSet, CacheAdd, CacheSub } mode = CacheSet; + QString srcvar; + if (args.count() >= 2) { + foreach (const QString &opt, split_value_list(args.at(1))) { + if (opt == QLatin1String("transient")) { + persist = false; + } else if (opt == QLatin1String("set")) { + mode = CacheSet; + } else if (opt == QLatin1String("add")) { + mode = CacheAdd; + } else if (opt == QLatin1String("sub")) { + mode = CacheSub; + } else { + fprintf(stderr, "%s:%d: cache(): invalid flag %s.\n", + parser.file.toLatin1().constData(), parser.line_no, + opt.toLatin1().constData()); + return false; + } + } + if (args.count() >= 3) { + srcvar = args.at(2); + } else if (mode != CacheSet) { + fprintf(stderr, "%s:%d: cache(): modes other than 'set' require a source variable.\n", + parser.file.toLatin1().constData(), parser.line_no); + return false; + } + } + QString varstr; + QString dstvar = args.at(0); + if (!dstvar.isEmpty()) { + if (srcvar.isEmpty()) + srcvar = dstvar; + if (!place.contains(srcvar)) { + fprintf(stderr, "%s:%d: variable %s is not defined.\n", + parser.file.toLatin1().constData(), parser.line_no, + srcvar.toLatin1().constData()); + return false; + } + // The current ("native") value can differ from the cached value, e.g., the current + // CONFIG will typically have more values than the cached one. Therefore we deal with + // them separately. + const QStringList diffval = values(srcvar, place); + const QStringList oldval = base_vars.value(dstvar); + QStringList newval; + if (mode == CacheSet) { + newval = diffval; + } else { + newval = oldval; + if (mode == CacheAdd) + newval += diffval; + else + subAll(&newval, diffval); + } + // We assume that whatever got the cached value to be what it is now will do so + // the next time as well, so it is OK that the early exit here will skip the + // persisting as well. + if (oldval == newval) + return true; + base_vars[dstvar] = newval; + if (!persist) + return true; + varstr = dstvar; + if (mode == CacheAdd) + varstr += QLatin1String(" +="); + else if (mode == CacheSub) + varstr += QLatin1String(" -="); + else + varstr += QLatin1String(" ="); + if (diffval.count() == 1) { + varstr += QLatin1Char(' '); + varstr += quoteValue(diffval.at(0)); + } else if (!diffval.isEmpty()) { + foreach (const QString &vval, diffval) { + varstr += QLatin1String(" \\\n "); + varstr += quoteValue(vval); + } + } + varstr += QLatin1Char('\n'); + } + if (Option::mkfile::cachefile.isEmpty()) { + Option::mkfile::cachefile = Option::output_dir + QLatin1String("/.qmake.cache"); + printf("Info: creating cache file %s\n", + Option::mkfile::cachefile.toLatin1().constData()); + project_build_root = Option::output_dir; + project_root = values("_PRO_FILE_PWD_", place).first(); + if (project_root == project_build_root) + project_root.clear(); + invalidateFeatureRoots(); + } + QFileInfo qfi(Option::mkfile::cachefile); + if (!QDir::current().mkpath(qfi.path())) { + fprintf(stderr, "%s:%d: ERROR creating cache directory %s\n", + parser.file.toLatin1().constData(), parser.line_no, + qfi.path().toLatin1().constData()); + return false; + } + QString errStr; + if (!writeFile(Option::mkfile::cachefile, QIODevice::Append, varstr, &errStr)) { + fprintf(stderr, "ERROR writing cache file %s: %s\n", + Option::mkfile::cachefile.toLatin1().constData(), errStr.toLatin1().constData()); +#if defined(QT_BUILD_QMAKE_LIBRARY) + return false; +#else + exit(2); +#endif + } + return true; } default: fprintf(stderr, "%s:%d: Unknown test function: %s\n", parser.file.toLatin1().constData(), parser.line_no, func.toLatin1().constData()); -- cgit v1.2.3 From 84614cabfaaab5eb4be04688a84cef8d79493f75 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 27 Apr 2012 14:01:08 +0200 Subject: add write_file() function this dumps the contents of a variable into a file. each element of the variable is considered a line; line terminators are added. all missing directories are automatically created. Change-Id: Idafeb873cea64e6705c894b3ab0ef21df69e7170 Reviewed-by: Marius Storm-Olsen --- qmake/project.cpp | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index 2a03580260..643e5fda9e 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -119,7 +119,7 @@ enum TestFunc { T_REQUIRES=1, T_GREATERTHAN, T_LESSTHAN, T_EQUALS, T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM, T_RETURN, T_BREAK, T_NEXT, T_DEFINED, T_CONTAINS, T_INFILE, T_COUNT, T_ISEMPTY, T_INCLUDE, T_LOAD, T_DEBUG, T_ERROR, - T_MESSAGE, T_WARNING, T_IF, T_OPTION, T_CACHE }; + T_MESSAGE, T_WARNING, T_IF, T_OPTION, T_CACHE, T_WRITE_FILE }; QHash qmake_testFunctions() { static QHash *qmake_test_functions = 0; @@ -155,6 +155,7 @@ QHash qmake_testFunctions() qmake_test_functions->insert("warning", T_WARNING); qmake_test_functions->insert("option", T_OPTION); qmake_test_functions->insert("cache", T_CACHE); + qmake_test_functions->insert("write_file", T_WRITE_FILE); } return *qmake_test_functions; } @@ -1889,6 +1890,11 @@ writeFile(const QString &name, QIODevice::OpenMode mode, const QString &contents { QByteArray bytes = contents.toLocal8Bit(); QFile cfile(name); + if (!(mode & QIODevice::Append) && cfile.open(QIODevice::ReadOnly | QIODevice::Text)) { + if (cfile.readAll() == bytes) + return true; + cfile.close(); + } if (!cfile.open(mode | QIODevice::WriteOnly | QIODevice::Text)) { *errStr = cfile.errorString(); return false; @@ -3039,6 +3045,37 @@ QMakeProject::doProjectTest(QString func, QList args_list, QHash 3) { + fprintf(stderr, "%s:%d: write_file(name, [content var, [append]]) requires one to three arguments.\n", + parser.file.toLatin1().constData(), parser.line_no); + return false; + } + QIODevice::OpenMode mode = QIODevice::Truncate; + QString contents; + if (args.count() >= 2) { + QStringList vals = values(args.at(1), place); + if (!vals.isEmpty()) + contents = vals.join(QLatin1String("\n")) + QLatin1Char('\n'); + if (args.count() >= 3) + if (!args.at(2).compare(QLatin1String("append"), Qt::CaseInsensitive)) + mode = QIODevice::Append; + } + QFileInfo qfi(args.at(0)); + if (!QDir::current().mkpath(qfi.path())) { + fprintf(stderr, "%s:%d: ERROR creating directory %s\n", + parser.file.toLatin1().constData(), parser.line_no, + qfi.path().toLatin1().constData()); + return false; + } + QString errStr; + if (!writeFile(args.at(0), mode, contents, &errStr)) { + fprintf(stderr, "%s:%d ERROR writing %s: %s\n", + parser.file.toLatin1().constData(), parser.line_no, + args.at(0).toLatin1().constData(), errStr.toLatin1().constData()); + return false; + } + return true; } default: fprintf(stderr, "%s:%d: Unknown test function: %s\n", parser.file.toLatin1().constData(), parser.line_no, func.toLatin1().constData()); -- cgit v1.2.3 From 064a5a08d2af33cfcbfb037722dec25068490db0 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 2 Apr 2012 18:08:49 +0200 Subject: add touch() function this is equivalent to unix "touch --no-create --reference ". QFile has no setLastModified() (even though QFileInfo has lastModified()), so the implementation is low-level. Change-Id: I6783e8f2613e168ad0c24e79e7384d5b2e4901ee Reviewed-by: Marius Storm-Olsen --- qmake/project.cpp | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index 643e5fda9e..1acfc2ea2a 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -54,7 +54,11 @@ #include #include #ifdef Q_OS_UNIX +#include +#include +#include #include +#include #include #elif defined(Q_OS_WIN32) #include @@ -119,7 +123,7 @@ enum TestFunc { T_REQUIRES=1, T_GREATERTHAN, T_LESSTHAN, T_EQUALS, T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM, T_RETURN, T_BREAK, T_NEXT, T_DEFINED, T_CONTAINS, T_INFILE, T_COUNT, T_ISEMPTY, T_INCLUDE, T_LOAD, T_DEBUG, T_ERROR, - T_MESSAGE, T_WARNING, T_IF, T_OPTION, T_CACHE, T_WRITE_FILE }; + T_MESSAGE, T_WARNING, T_IF, T_OPTION, T_CACHE, T_WRITE_FILE, T_TOUCH }; QHash qmake_testFunctions() { static QHash *qmake_test_functions = 0; @@ -156,6 +160,7 @@ QHash qmake_testFunctions() qmake_test_functions->insert("option", T_OPTION); qmake_test_functions->insert("cache", T_CACHE); qmake_test_functions->insert("write_file", T_WRITE_FILE); + qmake_test_functions->insert("touch", T_TOUCH); } return *qmake_test_functions; } @@ -1925,6 +1930,23 @@ getCommandOutput(const QString &args) return out; } +#ifdef Q_OS_WIN +static QString windowsErrorCode() +{ + wchar_t *string = 0; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPWSTR)&string, + 0, + NULL); + QString ret = QString::fromWCharArray(string); + LocalFree((HLOCAL)string); + return ret; +} +#endif + QStringList QMakeProject::doProjectExpand(QString func, const QString ¶ms, QHash &place) @@ -3076,6 +3098,57 @@ QMakeProject::doProjectTest(QString func, QList args_list, QHash Date: Thu, 5 Apr 2012 12:26:15 +0200 Subject: add log() function this is a literal print to stderr. Change-Id: Ib0a2f53373ebbc4e0bda07a38d656bce145b31cf Reviewed-by: Marius Storm-Olsen --- qmake/project.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index 1acfc2ea2a..2aebd1e140 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -122,8 +122,9 @@ QHash qmake_expandFunctions() enum TestFunc { T_REQUIRES=1, T_GREATERTHAN, T_LESSTHAN, T_EQUALS, T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM, T_RETURN, T_BREAK, T_NEXT, T_DEFINED, T_CONTAINS, T_INFILE, - T_COUNT, T_ISEMPTY, T_INCLUDE, T_LOAD, T_DEBUG, T_ERROR, - T_MESSAGE, T_WARNING, T_IF, T_OPTION, T_CACHE, T_WRITE_FILE, T_TOUCH }; + T_COUNT, T_ISEMPTY, T_INCLUDE, T_LOAD, + T_DEBUG, T_ERROR, T_MESSAGE, T_WARNING, T_LOG, + T_IF, T_OPTION, T_CACHE, T_WRITE_FILE, T_TOUCH }; QHash qmake_testFunctions() { static QHash *qmake_test_functions = 0; @@ -157,6 +158,7 @@ QHash qmake_testFunctions() qmake_test_functions->insert("error", T_ERROR); qmake_test_functions->insert("message", T_MESSAGE); qmake_test_functions->insert("warning", T_WARNING); + qmake_test_functions->insert("log", T_LOG); qmake_test_functions->insert("option", T_OPTION); qmake_test_functions->insert("cache", T_CACHE); qmake_test_functions->insert("write_file", T_WRITE_FILE); @@ -2916,6 +2918,7 @@ QMakeProject::doProjectTest(QString func, QList args_list, QHash args_list, QHash Date: Thu, 5 Apr 2012 12:45:23 +0200 Subject: add mkpath() function Change-Id: I8809b9ee4e85fbe8cec95641d659f237c5f51a26 Reviewed-by: Marius Storm-Olsen --- qmake/project.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index 2aebd1e140..2a7094376f 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -124,7 +124,7 @@ enum TestFunc { T_REQUIRES=1, T_GREATERTHAN, T_LESSTHAN, T_EQUALS, T_RETURN, T_BREAK, T_NEXT, T_DEFINED, T_CONTAINS, T_INFILE, T_COUNT, T_ISEMPTY, T_INCLUDE, T_LOAD, T_DEBUG, T_ERROR, T_MESSAGE, T_WARNING, T_LOG, - T_IF, T_OPTION, T_CACHE, T_WRITE_FILE, T_TOUCH }; + T_IF, T_OPTION, T_CACHE, T_MKPATH, T_WRITE_FILE, T_TOUCH }; QHash qmake_testFunctions() { static QHash *qmake_test_functions = 0; @@ -161,6 +161,7 @@ QHash qmake_testFunctions() qmake_test_functions->insert("log", T_LOG); qmake_test_functions->insert("option", T_OPTION); qmake_test_functions->insert("cache", T_CACHE); + qmake_test_functions->insert("mkpath", T_MKPATH); qmake_test_functions->insert("write_file", T_WRITE_FILE); qmake_test_functions->insert("touch", T_TOUCH); } @@ -3074,6 +3075,19 @@ QMakeProject::doProjectTest(QString func, QList args_list, QHash 3) { fprintf(stderr, "%s:%d: write_file(name, [content var, [append]]) requires one to three arguments.\n", -- cgit v1.2.3 From 1388199d4ff041cbd382acf754edbfdb3d8da8a7 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 2 Apr 2012 15:41:15 +0200 Subject: make defined() support testing definedness of variables Change-Id: I58d2dd402d72ee5a19012a6b5a4ba111717d40cc Reviewed-by: Marius Storm-Olsen --- qmake/project.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index 2a7094376f..0df2169ad8 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -2744,6 +2744,8 @@ QMakeProject::doProjectTest(QString func, QList args_list, QHash Date: Thu, 1 Mar 2012 18:49:20 +0100 Subject: add $$enumerate_vars() function this simply returns the keys of all variables in the context. Change-Id: I0092f827744fcd257dfb9e7ca664c87c6f1cc763 Reviewed-by: Joerg Bornemann --- qmake/project.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index 0df2169ad8..85ba72acb9 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -81,7 +81,7 @@ enum ExpandFunc { E_MEMBER=1, E_FIRST, E_LAST, E_CAT, E_FROMFILE, E_EVAL, E_LIST E_SPRINTF, E_JOIN, E_SPLIT, E_BASENAME, E_DIRNAME, E_SECTION, E_FIND, E_SYSTEM, E_UNIQUE, E_QUOTE, E_ESCAPE_EXPAND, E_UPPER, E_LOWER, E_FILES, E_PROMPT, E_RE_ESCAPE, E_REPLACE, - E_SIZE, E_SORT_DEPENDS, E_RESOLVE_DEPENDS }; + E_SIZE, E_SORT_DEPENDS, E_RESOLVE_DEPENDS, E_ENUMERATE_VARS }; QHash qmake_expandFunctions() { static QHash *qmake_expand_functions = 0; @@ -115,6 +115,7 @@ QHash qmake_expandFunctions() qmake_expand_functions->insert("size", E_SIZE); qmake_expand_functions->insert("sort_depends", E_SORT_DEPENDS); qmake_expand_functions->insert("resolve_depends", E_RESOLVE_DEPENDS); + qmake_expand_functions->insert("enumerate_vars", E_ENUMERATE_VARS); } return *qmake_expand_functions; } @@ -2477,6 +2478,9 @@ QMakeProject::doProjectExpand(QString func, QList args_list, } } break; } + case E_ENUMERATE_VARS: + ret += place.keys(); + break; default: { fprintf(stderr, "%s:%d: Unknown replace function: %s\n", parser.file.toLatin1().constData(), parser.line_no, -- cgit v1.2.3 From 6a66fef520d0fb2b8d507c3e91e03338fc39a57e Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 13 Mar 2012 17:15:27 +0100 Subject: add $$val_escape() function this quotes the elements of a variable in a way suitable for re-parsing as qmake code. Change-Id: I0e6ea2478c43b5aeff45f485a48ac8c86705dd4a Reviewed-by: Marius Storm-Olsen --- qmake/project.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index 85ba72acb9..1df4bf0200 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -80,7 +80,7 @@ QT_BEGIN_NAMESPACE enum ExpandFunc { E_MEMBER=1, E_FIRST, E_LAST, E_CAT, E_FROMFILE, E_EVAL, E_LIST, E_SPRINTF, E_JOIN, E_SPLIT, E_BASENAME, E_DIRNAME, E_SECTION, E_FIND, E_SYSTEM, E_UNIQUE, E_QUOTE, E_ESCAPE_EXPAND, - E_UPPER, E_LOWER, E_FILES, E_PROMPT, E_RE_ESCAPE, E_REPLACE, + E_UPPER, E_LOWER, E_FILES, E_PROMPT, E_RE_ESCAPE, E_VAL_ESCAPE, E_REPLACE, E_SIZE, E_SORT_DEPENDS, E_RESOLVE_DEPENDS, E_ENUMERATE_VARS }; QHash qmake_expandFunctions() { @@ -109,6 +109,7 @@ QHash qmake_expandFunctions() qmake_expand_functions->insert("upper", E_UPPER); qmake_expand_functions->insert("lower", E_LOWER); qmake_expand_functions->insert("re_escape", E_RE_ESCAPE); + qmake_expand_functions->insert("val_escape", E_VAL_ESCAPE); qmake_expand_functions->insert("files", E_FILES); qmake_expand_functions->insert("prompt", E_PROMPT); qmake_expand_functions->insert("replace", E_REPLACE); @@ -2361,6 +2362,17 @@ QMakeProject::doProjectExpand(QString func, QList args_list, for(int i = 0; i < args.size(); ++i) ret += QRegExp::escape(args[i]); break; } + case E_VAL_ESCAPE: + if (args.count() != 1) { + fprintf(stderr, "%s:%d val_escape(var) requires one argument.\n", + parser.file.toLatin1().constData(), parser.line_no); + } else { + QStringList vals = values(args.at(0), place); + ret.reserve(vals.length()); + foreach (const QString &str, vals) + ret += quoteValue(str); + } + break; case E_UPPER: case E_LOWER: { for(int i = 0; i < args.size(); ++i) { -- cgit v1.2.3 From bf984d5f24741a52a70024f3f43432307281f0ae Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 9 May 2012 15:29:25 +0200 Subject: add $$shadowed() function return the build directory corresponding to a given source directory. this is the identity function if not shadow-building. if input lies outside the source directory, return empty value. Change-Id: I2d2a6b1112bd19989fe29cfe19a12d39a0d208c1 Reviewed-by: Marius Storm-Olsen --- qmake/project.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index 1df4bf0200..de010faeb8 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -81,7 +81,8 @@ enum ExpandFunc { E_MEMBER=1, E_FIRST, E_LAST, E_CAT, E_FROMFILE, E_EVAL, E_LIST E_SPRINTF, E_JOIN, E_SPLIT, E_BASENAME, E_DIRNAME, E_SECTION, E_FIND, E_SYSTEM, E_UNIQUE, E_QUOTE, E_ESCAPE_EXPAND, E_UPPER, E_LOWER, E_FILES, E_PROMPT, E_RE_ESCAPE, E_VAL_ESCAPE, E_REPLACE, - E_SIZE, E_SORT_DEPENDS, E_RESOLVE_DEPENDS, E_ENUMERATE_VARS }; + E_SIZE, E_SORT_DEPENDS, E_RESOLVE_DEPENDS, E_ENUMERATE_VARS, + E_SHADOWED }; QHash qmake_expandFunctions() { static QHash *qmake_expand_functions = 0; @@ -117,6 +118,7 @@ QHash qmake_expandFunctions() qmake_expand_functions->insert("sort_depends", E_SORT_DEPENDS); qmake_expand_functions->insert("resolve_depends", E_RESOLVE_DEPENDS); qmake_expand_functions->insert("enumerate_vars", E_ENUMERATE_VARS); + qmake_expand_functions->insert("shadowed", E_SHADOWED); } return *qmake_expand_functions; } @@ -2493,6 +2495,13 @@ QMakeProject::doProjectExpand(QString func, QList args_list, case E_ENUMERATE_VARS: ret += place.keys(); break; + case E_SHADOWED: { + QString val = QDir::cleanPath(QFileInfo(args.at(0)).absoluteFilePath()); + if (Option::mkfile::source_root.isEmpty()) + ret += val; + else if (val.startsWith(Option::mkfile::source_root)) + ret += Option::mkfile::build_root + val.mid(Option::mkfile::source_root.length()); + break; } default: { fprintf(stderr, "%s:%d: Unknown replace function: %s\n", parser.file.toLatin1().constData(), parser.line_no, -- cgit v1.2.3 From 1261c9b2f483a63894f629cc0400970bd036239d Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 3 Apr 2012 13:35:53 +0200 Subject: add $$format_number() function Change-Id: I04266c1f5fb72af94073f3f508cee59085e365b6 Reviewed-by: Marius Storm-Olsen --- qmake/project.cpp | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index de010faeb8..24ea3a0257 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -78,7 +78,7 @@ QT_BEGIN_NAMESPACE //expand functions enum ExpandFunc { E_MEMBER=1, E_FIRST, E_LAST, E_CAT, E_FROMFILE, E_EVAL, E_LIST, - E_SPRINTF, E_JOIN, E_SPLIT, E_BASENAME, E_DIRNAME, E_SECTION, + E_SPRINTF, E_FORMAT_NUMBER, E_JOIN, E_SPLIT, E_BASENAME, E_DIRNAME, E_SECTION, E_FIND, E_SYSTEM, E_UNIQUE, E_QUOTE, E_ESCAPE_EXPAND, E_UPPER, E_LOWER, E_FILES, E_PROMPT, E_RE_ESCAPE, E_VAL_ESCAPE, E_REPLACE, E_SIZE, E_SORT_DEPENDS, E_RESOLVE_DEPENDS, E_ENUMERATE_VARS, @@ -97,6 +97,7 @@ QHash qmake_expandFunctions() qmake_expand_functions->insert("eval", E_EVAL); qmake_expand_functions->insert("list", E_LIST); qmake_expand_functions->insert("sprintf", E_SPRINTF); + qmake_expand_functions->insert("format_number", E_FORMAT_NUMBER); qmake_expand_functions->insert("join", E_JOIN); qmake_expand_functions->insert("split", E_SPLIT); qmake_expand_functions->insert("basename", E_BASENAME); @@ -2190,6 +2191,79 @@ QMakeProject::doProjectExpand(QString func, QList args_list, ret = split_value_list(tmp); } break; } + case E_FORMAT_NUMBER: + if (args.count() > 2) { + fprintf(stderr, "%s:%d: format_number(number[, options...]) requires one or two arguments.\n", + parser.file.toLatin1().constData(), parser.line_no); + } else { + int ibase = 10; + int obase = 10; + int width = 0; + bool zeropad = false; + bool leftalign = false; + enum { DefaultSign, PadSign, AlwaysSign } sign = DefaultSign; + if (args.count() >= 2) { + foreach (const QString &opt, split_value_list(args.at(1))) { + if (opt.startsWith(QLatin1String("ibase="))) { + ibase = opt.mid(6).toInt(); + } else if (opt.startsWith(QLatin1String("obase="))) { + obase = opt.mid(6).toInt(); + } else if (opt.startsWith(QLatin1String("width="))) { + width = opt.mid(6).toInt(); + } else if (opt == QLatin1String("zeropad")) { + zeropad = true; + } else if (opt == QLatin1String("padsign")) { + sign = PadSign; + } else if (opt == QLatin1String("alwayssign")) { + sign = AlwaysSign; + } else if (opt == QLatin1String("leftalign")) { + leftalign = true; + } else { + fprintf(stderr, "%s:%d: format_number(): invalid format option %s.\n", + parser.file.toLatin1().constData(), parser.line_no, + opt.toLatin1().constData()); + goto formfail; + } + } + } + if (args.at(0).contains(QLatin1Char('.'))) { + fprintf(stderr, "%s:%d: format_number(): floats are currently not supported.\n", + parser.file.toLatin1().constData(), parser.line_no); + break; + } + bool ok; + qlonglong num = args.at(0).toLongLong(&ok, ibase); + if (!ok) { + fprintf(stderr, "%s:%d: format_number(): malformed number %s for base %d.\n", + parser.file.toLatin1().constData(), parser.line_no, + args.at(0).toLatin1().constData(), ibase); + break; + } + QString outstr; + if (num < 0) { + num = -num; + outstr = QLatin1Char('-'); + } else if (sign == AlwaysSign) { + outstr = QLatin1Char('+'); + } else if (sign == PadSign) { + outstr = QLatin1Char(' '); + } + QString numstr = QString::number(num, obase); + int space = width - outstr.length() - numstr.length(); + if (space <= 0) { + outstr += numstr; + } else if (leftalign) { + outstr += numstr + QString(space, QLatin1Char(' ')); + } else if (zeropad) { + outstr += QString(space, QLatin1Char('0')) + numstr; + } else { + outstr.prepend(QString(space, QLatin1Char(' '))); + outstr += numstr; + } + ret += outstr; + } + formfail: + break; case E_JOIN: { if(args.count() < 1 || args.count() > 4) { fprintf(stderr, "%s:%d: join(var, glue, before, after) requires four" -- cgit v1.2.3 From f97913f2da5b4c46056b7d16ca30a3ae7874bbf7 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 20 Apr 2012 15:37:25 +0200 Subject: add $$clean_path() function just QDir::cleanPath() Change-Id: I2d51e2385939d8926c00f296537ab7f6757d9a79 Reviewed-by: Marius Storm-Olsen --- qmake/project.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index 24ea3a0257..88d55aef7f 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -82,7 +82,7 @@ enum ExpandFunc { E_MEMBER=1, E_FIRST, E_LAST, E_CAT, E_FROMFILE, E_EVAL, E_LIST E_FIND, E_SYSTEM, E_UNIQUE, E_QUOTE, E_ESCAPE_EXPAND, E_UPPER, E_LOWER, E_FILES, E_PROMPT, E_RE_ESCAPE, E_VAL_ESCAPE, E_REPLACE, E_SIZE, E_SORT_DEPENDS, E_RESOLVE_DEPENDS, E_ENUMERATE_VARS, - E_SHADOWED }; + E_SHADOWED, E_CLEAN_PATH }; QHash qmake_expandFunctions() { static QHash *qmake_expand_functions = 0; @@ -120,6 +120,7 @@ QHash qmake_expandFunctions() qmake_expand_functions->insert("resolve_depends", E_RESOLVE_DEPENDS); qmake_expand_functions->insert("enumerate_vars", E_ENUMERATE_VARS); qmake_expand_functions->insert("shadowed", E_SHADOWED); + qmake_expand_functions->insert("clean_path", E_CLEAN_PATH); } return *qmake_expand_functions; } @@ -2576,6 +2577,13 @@ QMakeProject::doProjectExpand(QString func, QList args_list, else if (val.startsWith(Option::mkfile::source_root)) ret += Option::mkfile::build_root + val.mid(Option::mkfile::source_root.length()); break; } + case E_CLEAN_PATH: + if (args.count() != 1) + fprintf(stderr, "%s:%d clean_path(path) requires one argument.\n", + parser.file.toLatin1().constData(), parser.line_no); + else + ret += QDir::cleanPath(args.at(0)); + break; default: { fprintf(stderr, "%s:%d: Unknown replace function: %s\n", parser.file.toLatin1().constData(), parser.line_no, -- cgit v1.2.3 From d8e6c49bfafaa69a0bd4a36c8a8c9684a832a646 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 20 Apr 2012 15:38:43 +0200 Subject: add $$native_path() function more or less QDir::toNativeSeparators(QDir::cleanPath()) Change-Id: I52deee1e8086559eda5833b387a0cf64d21cbcd9 Reviewed-by: Marius Storm-Olsen --- qmake/project.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index 88d55aef7f..d4065a1450 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -82,7 +82,7 @@ enum ExpandFunc { E_MEMBER=1, E_FIRST, E_LAST, E_CAT, E_FROMFILE, E_EVAL, E_LIST E_FIND, E_SYSTEM, E_UNIQUE, E_QUOTE, E_ESCAPE_EXPAND, E_UPPER, E_LOWER, E_FILES, E_PROMPT, E_RE_ESCAPE, E_VAL_ESCAPE, E_REPLACE, E_SIZE, E_SORT_DEPENDS, E_RESOLVE_DEPENDS, E_ENUMERATE_VARS, - E_SHADOWED, E_CLEAN_PATH }; + E_SHADOWED, E_CLEAN_PATH, E_NATIVE_PATH }; QHash qmake_expandFunctions() { static QHash *qmake_expand_functions = 0; @@ -121,6 +121,7 @@ QHash qmake_expandFunctions() qmake_expand_functions->insert("enumerate_vars", E_ENUMERATE_VARS); qmake_expand_functions->insert("shadowed", E_SHADOWED); qmake_expand_functions->insert("clean_path", E_CLEAN_PATH); + qmake_expand_functions->insert("native_path", E_NATIVE_PATH); } return *qmake_expand_functions; } @@ -2584,6 +2585,13 @@ QMakeProject::doProjectExpand(QString func, QList args_list, else ret += QDir::cleanPath(args.at(0)); break; + case E_NATIVE_PATH: + if (args.count() != 1) + fprintf(stderr, "%s:%d native_path(path) requires one argument.\n", + parser.file.toLatin1().constData(), parser.line_no); + else + ret += Option::fixPathToTargetOS(args.at(0), false); + break; default: { fprintf(stderr, "%s:%d: Unknown replace function: %s\n", parser.file.toLatin1().constData(), parser.line_no, -- cgit v1.2.3 From 09e01856b08c1b5ffd537b51b9a012eeeea70c3c Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 26 Apr 2012 13:19:53 +0200 Subject: add $$absolute_path() and $$relative_path() just exposes QDir::fooFilePath() wrapped into QDir::cleanPath() Change-Id: I7a7644084825fd8092a9910ac20f695c4d9351f6 Reviewed-by: Marius Storm-Olsen --- qmake/project.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index d4065a1450..b26796bb1c 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -82,7 +82,7 @@ enum ExpandFunc { E_MEMBER=1, E_FIRST, E_LAST, E_CAT, E_FROMFILE, E_EVAL, E_LIST E_FIND, E_SYSTEM, E_UNIQUE, E_QUOTE, E_ESCAPE_EXPAND, E_UPPER, E_LOWER, E_FILES, E_PROMPT, E_RE_ESCAPE, E_VAL_ESCAPE, E_REPLACE, E_SIZE, E_SORT_DEPENDS, E_RESOLVE_DEPENDS, E_ENUMERATE_VARS, - E_SHADOWED, E_CLEAN_PATH, E_NATIVE_PATH }; + E_SHADOWED, E_ABSOLUTE_PATH, E_RELATIVE_PATH, E_CLEAN_PATH, E_NATIVE_PATH }; QHash qmake_expandFunctions() { static QHash *qmake_expand_functions = 0; @@ -120,6 +120,8 @@ QHash qmake_expandFunctions() qmake_expand_functions->insert("resolve_depends", E_RESOLVE_DEPENDS); qmake_expand_functions->insert("enumerate_vars", E_ENUMERATE_VARS); qmake_expand_functions->insert("shadowed", E_SHADOWED); + qmake_expand_functions->insert("absolute_path", E_ABSOLUTE_PATH); + qmake_expand_functions->insert("relative_path", E_RELATIVE_PATH); qmake_expand_functions->insert("clean_path", E_CLEAN_PATH); qmake_expand_functions->insert("native_path", E_NATIVE_PATH); } @@ -2578,6 +2580,22 @@ QMakeProject::doProjectExpand(QString func, QList args_list, else if (val.startsWith(Option::mkfile::source_root)) ret += Option::mkfile::build_root + val.mid(Option::mkfile::source_root.length()); break; } + case E_ABSOLUTE_PATH: + if (args.count() > 2) + fprintf(stderr, "%s:%d absolute_path(path[, base]) requires one or two arguments.\n", + parser.file.toLatin1().constData(), parser.line_no); + else + ret += QDir::cleanPath(QDir(args.count() > 1 ? args.at(1) : QString()) + .absoluteFilePath(args.at(0))); + break; + case E_RELATIVE_PATH: + if (args.count() > 2) + fprintf(stderr, "%s:%d relative_path(path[, base]) requires one or two arguments.\n", + parser.file.toLatin1().constData(), parser.line_no); + else + ret += QDir::cleanPath(QDir(args.count() > 1 ? args.at(1) : QString()) + .relativeFilePath(args.at(0))); + break; case E_CLEAN_PATH: if (args.count() != 1) fprintf(stderr, "%s:%d clean_path(path) requires one argument.\n", -- cgit v1.2.3 From 083f7c501fa3d71160f139a0f37fa659424b4d97 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 20 Apr 2012 15:40:11 +0200 Subject: add $$shell_quote() function to be used in system() calls and when assembling EXTRA_COMPILER and INSTALLS .commands by hand. Change-Id: Id706cd56aa267a9fb4b14e3416692b4716fafa5b Reviewed-by: Marius Storm-Olsen --- qmake/project.cpp | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index b26796bb1c..935400e281 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -82,7 +82,8 @@ enum ExpandFunc { E_MEMBER=1, E_FIRST, E_LAST, E_CAT, E_FROMFILE, E_EVAL, E_LIST E_FIND, E_SYSTEM, E_UNIQUE, E_QUOTE, E_ESCAPE_EXPAND, E_UPPER, E_LOWER, E_FILES, E_PROMPT, E_RE_ESCAPE, E_VAL_ESCAPE, E_REPLACE, E_SIZE, E_SORT_DEPENDS, E_RESOLVE_DEPENDS, E_ENUMERATE_VARS, - E_SHADOWED, E_ABSOLUTE_PATH, E_RELATIVE_PATH, E_CLEAN_PATH, E_NATIVE_PATH }; + E_SHADOWED, E_ABSOLUTE_PATH, E_RELATIVE_PATH, E_CLEAN_PATH, E_NATIVE_PATH, + E_SHELL_QUOTE }; QHash qmake_expandFunctions() { static QHash *qmake_expand_functions = 0; @@ -124,6 +125,7 @@ QHash qmake_expandFunctions() qmake_expand_functions->insert("relative_path", E_RELATIVE_PATH); qmake_expand_functions->insert("clean_path", E_CLEAN_PATH); qmake_expand_functions->insert("native_path", E_NATIVE_PATH); + qmake_expand_functions->insert("shell_quote", E_SHELL_QUOTE); } return *qmake_expand_functions; } @@ -1834,6 +1836,67 @@ subAll(QStringList *val, const QStringList &diffval) val->removeAll(dv); } +inline static +bool isSpecialChar(ushort c) +{ + // Chars that should be quoted (TM). This includes: +#ifdef Q_OS_WIN + // - control chars & space + // - the shell meta chars "&()<>^| + // - the potential separators ,;= + static const uchar iqm[] = { + 0xff, 0xff, 0xff, 0xff, 0x45, 0x13, 0x00, 0x78, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10 + }; +#else + static const uchar iqm[] = { + 0xff, 0xff, 0xff, 0xff, 0xdf, 0x07, 0x00, 0xd8, + 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x78 + }; // 0-32 \'"$`<>|;&(){}*?#!~[] +#endif + + return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7))); +} + +inline static +bool hasSpecialChars(const QString &arg) +{ + for (int x = arg.length() - 1; x >= 0; --x) + if (isSpecialChar(arg.unicode()[x].unicode())) + return true; + return false; +} + +static QString +shellQuote(const QString &arg) +{ + if (!arg.length()) + return QString::fromLatin1("\"\""); + + QString ret(arg); + if (hasSpecialChars(ret)) { +#ifdef Q_OS_WIN + // Quotes are escaped and their preceding backslashes are doubled. + // It's impossible to escape anything inside a quoted string on cmd + // level, so the outer quoting must be "suspended". + ret.replace(QRegExp(QLatin1String("(\\\\*)\"")), QLatin1String("\"\\1\\1\\^\"\"")); + // The argument must not end with a \ since this would be interpreted + // as escaping the quote -- rather put the \ behind the quote: e.g. + // rather use "foo"\ than "foo\" + int i = ret.length(); + while (i > 0 && ret.at(i - 1) == QLatin1Char('\\')) + --i; + ret.insert(i, QLatin1Char('"')); + ret.prepend(QLatin1Char('"')); +#else // Q_OS_WIN + ret.replace(QLatin1Char('\''), QLatin1String("'\\''")); + ret.prepend(QLatin1Char('\'')); + ret.append(QLatin1Char('\'')); +#endif // Q_OS_WIN + } + return ret; +} + static QString quoteValue(const QString &val) { @@ -2610,6 +2673,13 @@ QMakeProject::doProjectExpand(QString func, QList args_list, else ret += Option::fixPathToTargetOS(args.at(0), false); break; + case E_SHELL_QUOTE: + if (args.count() != 1) + fprintf(stderr, "%s:%d shell_quote(args) requires one argument.\n", + parser.file.toLatin1().constData(), parser.line_no); + else + ret += shellQuote(args.at(0)); + break; default: { fprintf(stderr, "%s:%d: Unknown replace function: %s\n", parser.file.toLatin1().constData(), parser.line_no, -- cgit v1.2.3 From c85dc033dc58b06f1fc3cef6c2667f6516ac12b4 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 27 Apr 2012 11:51:55 +0200 Subject: add $$reverse() function returns the list with the order of the elements reversed. one can easily implement this with existing functions, but this is way faster and more readable. Change-Id: I12d306eb9fe58fc332622274ea6b658192529491 Reviewed-by: Joerg Bornemann --- qmake/project.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index 935400e281..8508059e9c 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -79,7 +79,7 @@ QT_BEGIN_NAMESPACE //expand functions enum ExpandFunc { E_MEMBER=1, E_FIRST, E_LAST, E_CAT, E_FROMFILE, E_EVAL, E_LIST, E_SPRINTF, E_FORMAT_NUMBER, E_JOIN, E_SPLIT, E_BASENAME, E_DIRNAME, E_SECTION, - E_FIND, E_SYSTEM, E_UNIQUE, E_QUOTE, E_ESCAPE_EXPAND, + E_FIND, E_SYSTEM, E_UNIQUE, E_REVERSE, E_QUOTE, E_ESCAPE_EXPAND, E_UPPER, E_LOWER, E_FILES, E_PROMPT, E_RE_ESCAPE, E_VAL_ESCAPE, E_REPLACE, E_SIZE, E_SORT_DEPENDS, E_RESOLVE_DEPENDS, E_ENUMERATE_VARS, E_SHADOWED, E_ABSOLUTE_PATH, E_RELATIVE_PATH, E_CLEAN_PATH, E_NATIVE_PATH, @@ -107,6 +107,7 @@ QHash qmake_expandFunctions() qmake_expand_functions->insert("find", E_FIND); qmake_expand_functions->insert("system", E_SYSTEM); qmake_expand_functions->insert("unique", E_UNIQUE); + qmake_expand_functions->insert("reverse", E_REVERSE); qmake_expand_functions->insert("quote", E_QUOTE); qmake_expand_functions->insert("escape_expand", E_ESCAPE_EXPAND); qmake_expand_functions->insert("upper", E_UPPER); @@ -2466,6 +2467,17 @@ QMakeProject::doProjectExpand(QString func, QList args_list, } } break; } + case E_REVERSE: + if (args.count() != 1) { + fprintf(stderr, "%s:%d reverse(var) requires one argument.\n", + parser.file.toLatin1().constData(), parser.line_no); + } else { + QStringList var = values(args.first(), place); + for (int i = 0; i < var.size() / 2; i++) + var.swap(i, var.size() - i - 1); + ret += var; + } + break; case E_QUOTE: ret = args; break; -- cgit v1.2.3 From 6a8f64136e7c38fa4e94c916a57b83856ded3a8d Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 3 May 2012 15:36:03 +0200 Subject: introduce /get property variants properties are now split into a write location $$[FOO] and a read location $$[FOO/get]. the write locations are hard-coded and configurable via qt.conf/Paths as before, while the read locations are configured via qt.conf/EffectivePaths. this finally provides a clean solution to the problem that during the qt build itself tools and libraries need to be taken from somewhere else than they are installed to. Change-Id: I956c43bd082afd465e690fe75d0bee3c2c0f7c25 Reviewed-by: Joerg Bornemann Reviewed-by: Robin Burchell --- qmake/project.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index 8508059e9c..f7102162b8 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -632,7 +632,8 @@ QStringList qmake_feature_paths(QMakeProperty *prop, bool host_build) } for(QStringList::Iterator concat_it = concat.begin(); concat_it != concat.end(); ++concat_it) - feature_roots << (QLibraryInfo::location(QLibraryInfo::HostDataPath) + + feature_roots << (QLibraryInfo::rawLocation(QLibraryInfo::HostDataPath, + QLibraryInfo::EffectivePaths) + mkspecs_concat + (*concat_it)); feature_roots.removeDuplicates(); return feature_roots; @@ -652,7 +653,7 @@ QStringList qmake_mkspec_paths() ret << project_build_root + concat; if (!project_root.isEmpty()) ret << project_root + concat; - ret << QLibraryInfo::location(QLibraryInfo::DataPath) + concat; + ret << QLibraryInfo::rawLocation(QLibraryInfo::HostDataPath, QLibraryInfo::EffectivePaths) + concat; ret.removeDuplicates(); return ret; @@ -3802,7 +3803,8 @@ QStringList &QMakeProject::values(const QString &_var, QHash Date: Mon, 12 Mar 2012 17:24:47 +0100 Subject: make splitPathList() return an empty list for an empty string this makes the user code a bit cleaner Change-Id: I3713c73c5c19cf69341be65480917eda0b967b77 Reviewed-by: Joerg Bornemann --- qmake/project.cpp | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index f7102162b8..768a1c2922 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -586,10 +586,7 @@ QStringList qmake_feature_paths(QMakeProperty *prop, bool host_build) concat << base_concat; } - QStringList feature_roots; - QByteArray mkspec_path = qgetenv("QMAKEFEATURES"); - if(!mkspec_path.isNull()) - feature_roots += splitPathList(QString::fromLocal8Bit(mkspec_path)); + QStringList feature_roots = splitPathList(QString::fromLocal8Bit(qgetenv("QMAKEFEATURES"))); if(prop) feature_roots += splitPathList(prop->value("QMAKEFEATURES")); if(!Option::mkfile::cachefile.isEmpty()) { @@ -601,15 +598,10 @@ QStringList qmake_feature_paths(QMakeProperty *prop, bool host_build) concat_it != concat.end(); ++concat_it) feature_roots << (path + (*concat_it)); } - QByteArray qmakepath = qgetenv("QMAKEPATH"); - if (!qmakepath.isNull()) { - const QStringList lst = splitPathList(QString::fromLocal8Bit(qmakepath)); - for(QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it) { - for(QStringList::Iterator concat_it = concat.begin(); - concat_it != concat.end(); ++concat_it) - feature_roots << ((*it) + mkspecs_concat + (*concat_it)); - } - } + QStringList qmakepath = splitPathList(QString::fromLocal8Bit(qgetenv("QMAKEPATH"))); + foreach (const QString &path, qmakepath) + foreach (const QString &cat, concat) + feature_roots << (path + mkspecs_concat + cat); QString *specp = host_build ? &Option::mkfile::qmakespec : &Option::mkfile::xqmakespec; if (!specp->isEmpty()) { // The spec is already platform-dependent, so no subdirs here. @@ -643,12 +635,10 @@ QStringList qmake_mkspec_paths() { QStringList ret; const QString concat = QLatin1String("/mkspecs"); - QByteArray qmakepath = qgetenv("QMAKEPATH"); - if (!qmakepath.isEmpty()) { - const QStringList lst = splitPathList(QString::fromLocal8Bit(qmakepath)); - for (QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it) - ret << ((*it) + concat); - } + + QStringList qmakepath = splitPathList(QString::fromLocal8Bit(qgetenv("QMAKEPATH"))); + foreach (const QString &path, qmakepath) + ret << (path + concat); if (!project_build_root.isEmpty()) ret << project_build_root + concat; if (!project_root.isEmpty()) -- cgit v1.2.3 From 7d44bd0646dd18cfa67e11fae7d9368d318ed5f6 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 18 Apr 2012 12:09:48 +0200 Subject: remove last traces of js support don't even complain about trying to use js-based feature files. we have been doing that for long enough. Change-Id: Ib58ec204322442c488e8d780989f26b1e32595ed Reviewed-by: Joerg Bornemann --- qmake/project.cpp | 35 ++++++++++------------------------- 1 file changed, 10 insertions(+), 25 deletions(-) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index 768a1c2922..b6d2143f62 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -1690,7 +1690,6 @@ QMakeProject::doProjectTest(QString func, const QString ¶ms, QMakeProject::IncludeStatus QMakeProject::doProjectInclude(QString file, uchar flags, QHash &place) { - enum { UnknownFormat, ProFormat, JSFormat } format = UnknownFormat; if(flags & IncludeFlagFeature) { if(!file.endsWith(Option::prf_ext)) file += Option::prf_ext; @@ -1722,18 +1721,13 @@ QMakeProject::doProjectInclude(QString file, uchar flags, QHashsize(); ++root) { QString prf(feature_roots->at(root) + QLatin1Char('/') + file); - if(QFile::exists(prf + Option::js_ext)) { - format = JSFormat; - file = prf + Option::js_ext; - break; - } else if(QFile::exists(prf)) { - format = ProFormat; + if (QFile::exists(prf)) { file = prf; - break; + goto foundf; } } - if(format == UnknownFormat) - return IncludeNoExist; + return IncludeNoExist; + foundf: ; } if(place["QMAKE_INTERNAL_INCLUDED_FEATURES"].indexOf(file) != -1) return IncludeFeatureAlreadyLoaded; @@ -1751,19 +1745,13 @@ QMakeProject::doProjectInclude(QString file, uchar flags, QHash Date: Fri, 27 Apr 2012 18:14:56 +0200 Subject: don't duplicate project_build_root's calculation needlessly Change-Id: Id2f343c450149b13b52c2cae8eb6eb4bfd73fc03 Reviewed-by: Joerg Bornemann --- qmake/project.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index b6d2143f62..42967df461 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -589,15 +589,10 @@ QStringList qmake_feature_paths(QMakeProperty *prop, bool host_build) QStringList feature_roots = splitPathList(QString::fromLocal8Bit(qgetenv("QMAKEFEATURES"))); if(prop) feature_roots += splitPathList(prop->value("QMAKEFEATURES")); - if(!Option::mkfile::cachefile.isEmpty()) { - QString path; - int last_slash = Option::mkfile::cachefile.lastIndexOf(QLatin1Char('/')); - if(last_slash != -1) - path = Option::normalizePath(Option::mkfile::cachefile.left(last_slash), false); + if (!project_build_root.isEmpty()) for(QStringList::Iterator concat_it = concat.begin(); concat_it != concat.end(); ++concat_it) - feature_roots << (path + (*concat_it)); - } + feature_roots << (project_build_root + (*concat_it)); QStringList qmakepath = splitPathList(QString::fromLocal8Bit(qgetenv("QMAKEPATH"))); foreach (const QString &path, qmakepath) foreach (const QString &cat, concat) -- cgit v1.2.3 From c80697cfbe9071152e49559e9f375352cd205029 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 7 Jun 2012 12:48:40 +0200 Subject: allow setting QMAKEPATH and QMAKEFEATURES in .qmake.cache Change-Id: Ie383abb57c06cb49d38345d64750837b8fe14c70 Reviewed-by: Joerg Bornemann --- qmake/project.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index 42967df461..b141860556 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -189,6 +189,9 @@ struct parser_info { static QString project_root; static QString project_build_root; +static QStringList cached_qmakepath; +static QStringList cached_qmakefeatures; + static QStringList *all_feature_roots[2] = { 0, 0 }; static void @@ -587,6 +590,7 @@ QStringList qmake_feature_paths(QMakeProperty *prop, bool host_build) } QStringList feature_roots = splitPathList(QString::fromLocal8Bit(qgetenv("QMAKEFEATURES"))); + feature_roots += cached_qmakefeatures; if(prop) feature_roots += splitPathList(prop->value("QMAKEFEATURES")); if (!project_build_root.isEmpty()) @@ -594,6 +598,7 @@ QStringList qmake_feature_paths(QMakeProperty *prop, bool host_build) concat_it != concat.end(); ++concat_it) feature_roots << (project_build_root + (*concat_it)); QStringList qmakepath = splitPathList(QString::fromLocal8Bit(qgetenv("QMAKEPATH"))); + qmakepath += cached_qmakepath; foreach (const QString &path, qmakepath) foreach (const QString &cat, concat) feature_roots << (path + mkspecs_concat + cat); @@ -632,6 +637,7 @@ QStringList qmake_mkspec_paths() const QString concat = QLatin1String("/mkspecs"); QStringList qmakepath = splitPathList(QString::fromLocal8Bit(qgetenv("QMAKEPATH"))); + qmakepath += cached_qmakepath; foreach (const QString &path, qmakepath) ret << (path + concat); if (!project_build_root.isEmpty()) @@ -1330,6 +1336,8 @@ QMakeProject::read(uchar cmd) project_build_root.clear(); + QStringList qmakepath; + QStringList qmakefeatures; if (Option::mkfile::do_cache) { // parse the cache if (Option::mkfile::cachefile.isEmpty()) { //find it as it has not been specified QDir dir(Option::output_dir); @@ -1356,6 +1364,13 @@ QMakeProject::read(uchar cmd) if (Option::mkfile::xqmakespec.isEmpty()) Option::mkfile::xqmakespec = Option::mkfile::qmakespec; } + qmakepath = cache.value(QLatin1String("QMAKEPATH")); + qmakefeatures = cache.value(QLatin1String("QMAKEFEATURES")); + if (qmakepath != cached_qmakepath || qmakefeatures != cached_qmakefeatures) { + cached_qmakepath = qmakepath; + cached_qmakefeatures = qmakefeatures; + invalidateFeatureRoots(); + } if (Option::output_dir.startsWith(project_build_root)) Option::mkfile::cachefile_depth = @@ -3215,6 +3230,15 @@ QMakeProject::doProjectTest(QString func, QList args_list, QHash Date: Thu, 10 May 2012 10:41:54 +0200 Subject: find .qmake.cache for subprojects independently this allows the creation of aggregator projects, like, say, qt5. this is not expected to have a negative impact, as no project could reasonably expect a nested .qmake.cache to *not* take effect - in fact, if the project was processed stand-alone, it would already use it. Change-Id: I33f2935d309baba7e95465f2fefb8231c4f03eda Reviewed-by: Joerg Bornemann --- qmake/project.cpp | 85 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 47 insertions(+), 38 deletions(-) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index b141860556..88535bd0e8 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -186,9 +186,8 @@ struct parser_info { bool from_file; } parser; -static QString project_root; -static QString project_build_root; - +static QString cached_source_root; +static QString cached_build_root; static QStringList cached_qmakepath; static QStringList cached_qmakefeatures; @@ -593,10 +592,10 @@ QStringList qmake_feature_paths(QMakeProperty *prop, bool host_build) feature_roots += cached_qmakefeatures; if(prop) feature_roots += splitPathList(prop->value("QMAKEFEATURES")); - if (!project_build_root.isEmpty()) + if (!cached_build_root.isEmpty()) for(QStringList::Iterator concat_it = concat.begin(); concat_it != concat.end(); ++concat_it) - feature_roots << (project_build_root + (*concat_it)); + feature_roots << (cached_build_root + (*concat_it)); QStringList qmakepath = splitPathList(QString::fromLocal8Bit(qgetenv("QMAKEPATH"))); qmakepath += cached_qmakepath; foreach (const QString &path, qmakepath) @@ -640,10 +639,10 @@ QStringList qmake_mkspec_paths() qmakepath += cached_qmakepath; foreach (const QString &path, qmakepath) ret << (path + concat); - if (!project_build_root.isEmpty()) - ret << project_build_root + concat; - if (!project_root.isEmpty()) - ret << project_root + concat; + if (!cached_build_root.isEmpty()) + ret << cached_build_root + concat; + if (!cached_source_root.isEmpty()) + ret << cached_source_root + concat; ret << QLibraryInfo::rawLocation(QLibraryInfo::HostDataPath, QLibraryInfo::EffectivePaths) + concat; ret.removeDuplicates(); @@ -1334,27 +1333,34 @@ QMakeProject::read(uchar cmd) if(!Option::user_template_prefix.isEmpty()) base_vars["TEMPLATE_PREFIX"] = QStringList(Option::user_template_prefix); - project_build_root.clear(); - + QString project_root; + QString project_build_root; QStringList qmakepath; QStringList qmakefeatures; if (Option::mkfile::do_cache) { // parse the cache if (Option::mkfile::cachefile.isEmpty()) { //find it as it has not been specified - QDir dir(Option::output_dir); - while (!dir.exists(QLatin1String(".qmake.cache"))) - if (dir.isRoot() || !dir.cdUp()) + QString dir = Option::output_dir; + forever { + QFileInfo qfi(dir, QLatin1String(".qmake.cache")); + if (qfi.exists()) { + cachefile = qfi.filePath(); + project_build_root = dir; + break; + } + QFileInfo qdfi(dir); + if (qdfi.isRoot()) goto no_cache; - Option::mkfile::cachefile = dir.filePath(QLatin1String(".qmake.cache")); - project_build_root = dir.path(); + dir = qdfi.path(); + } } else { QFileInfo fi(Option::mkfile::cachefile); - Option::mkfile::cachefile = QDir::cleanPath(fi.absoluteFilePath()); + cachefile = QDir::cleanPath(fi.absoluteFilePath()); project_build_root = QDir::cleanPath(fi.absolutePath()); } QHash cache; - if (!read(Option::mkfile::cachefile, cache)) { - Option::mkfile::cachefile.clear(); + if (!read(cachefile, cache)) { + cachefile.clear(); goto no_cache; } if (Option::mkfile::xqmakespec.isEmpty() && !cache["XQMAKESPEC"].isEmpty()) @@ -1366,11 +1372,6 @@ QMakeProject::read(uchar cmd) } qmakepath = cache.value(QLatin1String("QMAKEPATH")); qmakefeatures = cache.value(QLatin1String("QMAKEFEATURES")); - if (qmakepath != cached_qmakepath || qmakefeatures != cached_qmakefeatures) { - cached_qmakepath = qmakepath; - cached_qmakefeatures = qmakefeatures; - invalidateFeatureRoots(); - } if (Option::output_dir.startsWith(project_build_root)) Option::mkfile::cachefile_depth = @@ -1403,6 +1404,15 @@ QMakeProject::read(uchar cmd) project_root.clear(); } + if (qmakepath != cached_qmakepath || qmakefeatures != cached_qmakefeatures + || project_build_root != cached_build_root) { // No need to check source dir, as it goes in sync + cached_source_root = project_root; + cached_build_root = project_build_root; + cached_qmakepath = qmakepath; + cached_qmakefeatures = qmakefeatures; + invalidateFeatureRoots(); + } + { // parse mkspec QString *specp = host_build ? &Option::mkfile::qmakespec : &Option::mkfile::xqmakespec; QString qmakespec = *specp; @@ -1439,9 +1449,9 @@ QMakeProject::read(uchar cmd) } validateModes(); - if(Option::mkfile::do_cache && !Option::mkfile::cachefile.isEmpty()) { - debug_msg(1, "QMAKECACHE file: reading %s", Option::mkfile::cachefile.toLatin1().constData()); - read(Option::mkfile::cachefile, base_vars); + if (!cachefile.isEmpty()) { + debug_msg(1, "QMAKECACHE file: reading %s", cachefile.toLatin1().constData()); + read(cachefile, base_vars); } } } @@ -3259,14 +3269,13 @@ QMakeProject::doProjectTest(QString func, QList args_list, QHash args_list, QHash Date: Thu, 10 May 2012 11:22:07 +0200 Subject: look for .qmake.conf files this is the source dir equivalent of .qmake.cache and can be checked into the repository. it can be used to make project-wide settings, or just to signal the presence of an mkspecs/ directory. Change-Id: I5f1cebad2aa2a89e78089341b2051613b6b7a613 Reviewed-by: Joerg Bornemann --- qmake/project.cpp | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index 88535bd0e8..a60c168ef4 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -1338,31 +1338,45 @@ QMakeProject::read(uchar cmd) QStringList qmakepath; QStringList qmakefeatures; if (Option::mkfile::do_cache) { // parse the cache + QHash cache; if (Option::mkfile::cachefile.isEmpty()) { //find it as it has not been specified + QString sdir = qmake_getpwd(); QString dir = Option::output_dir; forever { + QFileInfo qsfi(sdir, QLatin1String(".qmake.conf")); + if (qsfi.exists()) { + conffile = qsfi.filePath(); + if (!read(conffile, cache)) + return false; + } QFileInfo qfi(dir, QLatin1String(".qmake.cache")); if (qfi.exists()) { cachefile = qfi.filePath(); + if (!read(cachefile, cache)) + return false; + } + if (!conffile.isEmpty() || !cachefile.isEmpty()) { + project_root = sdir; project_build_root = dir; break; } + QFileInfo qsdfi(sdir); QFileInfo qdfi(dir); - if (qdfi.isRoot()) + if (qsdfi.isRoot() || qdfi.isRoot()) goto no_cache; + sdir = qsdfi.path(); dir = qdfi.path(); } } else { QFileInfo fi(Option::mkfile::cachefile); cachefile = QDir::cleanPath(fi.absoluteFilePath()); + if (!read(cachefile, cache)) + return false; project_build_root = QDir::cleanPath(fi.absolutePath()); + // This intentionally bypasses finding a source root, + // as the result would be more or less arbitrary. } - QHash cache; - if (!read(cachefile, cache)) { - cachefile.clear(); - goto no_cache; - } if (Option::mkfile::xqmakespec.isEmpty() && !cache["XQMAKESPEC"].isEmpty()) Option::mkfile::xqmakespec = cache["XQMAKESPEC"].first(); if (Option::mkfile::qmakespec.isEmpty() && !cache["QMAKESPEC"].isEmpty()) { @@ -1379,17 +1393,10 @@ QMakeProject::read(uchar cmd) } no_cache: - if (qmake_getpwd() != Option::output_dir || project_build_root.isEmpty()) { + if (project_build_root.isEmpty()) { QDir srcdir(qmake_getpwd()); QDir dstdir(Option::output_dir); do { - if (!project_build_root.isEmpty()) { - // If we already know the build root, just match up the source root with it. - if (dstdir.path() == project_build_root) { - project_root = srcdir.path(); - break; - } - } else { // Look for mkspecs/ in source and build. First to win determines the root. if (dstdir.exists("mkspecs") || srcdir.exists("mkspecs")) { project_build_root = dstdir.path(); @@ -1398,10 +1405,7 @@ QMakeProject::read(uchar cmd) project_root.clear(); break; } - } } while (!srcdir.isRoot() && srcdir.cdUp() && !dstdir.isRoot() && dstdir.cdUp()); - } else { - project_root.clear(); } if (qmakepath != cached_qmakepath || qmakefeatures != cached_qmakefeatures @@ -1449,6 +1453,10 @@ QMakeProject::read(uchar cmd) } validateModes(); + if (!conffile.isEmpty()) { + debug_msg(1, "Project config file: reading %s", conffile.toLatin1().constData()); + read(conffile, base_vars); + } if (!cachefile.isEmpty()) { debug_msg(1, "QMAKECACHE file: reading %s", cachefile.toLatin1().constData()); read(cachefile, base_vars); -- cgit v1.2.3 From 1f83f0cf2ad077733fe783879ae16e293a2ceaee Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 10 May 2012 12:59:14 +0200 Subject: add support for a super cache qmake will now look for .qmake.super, just like it looks for .qmake.cache, and the cache() function has a mode to write this super cache. this allows the creation of aggregator projects like, say, qt5. a notable difference to the normal cache is that this file is *not* added as a dependency of the Makefile. this means that modifications done by later sub-projects will not cause a re-processing of earlier projects, and consequently that one should be cautious regarding what information to store there. another notable difference is that this file is read *before* the spec, so the spec can use the variables from the cache without resorting to $$fromfile() & co. Change-Id: I4807b6d34014261fa9eebd6f0ae128b802d86691 Reviewed-by: Joerg Bornemann --- qmake/project.cpp | 69 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 56 insertions(+), 13 deletions(-) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index a60c168ef4..58c2b8cb86 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -1333,12 +1333,28 @@ QMakeProject::read(uchar cmd) if(!Option::user_template_prefix.isEmpty()) base_vars["TEMPLATE_PREFIX"] = QStringList(Option::user_template_prefix); + QString superdir; QString project_root; QString project_build_root; QStringList qmakepath; QStringList qmakefeatures; if (Option::mkfile::do_cache) { // parse the cache QHash cache; + QString rdir = Option::output_dir; + forever { + QFileInfo qfi(rdir, QLatin1String(".qmake.super")); + if (qfi.exists()) { + superfile = qfi.filePath(); + if (!read(superfile, cache)) + return false; + superdir = rdir; + break; + } + QFileInfo qdfi(rdir); + if (qdfi.isRoot()) + break; + rdir = qdfi.path(); + } if (Option::mkfile::cachefile.isEmpty()) { //find it as it has not been specified QString sdir = qmake_getpwd(); QString dir = Option::output_dir; @@ -1360,6 +1376,8 @@ QMakeProject::read(uchar cmd) project_build_root = dir; break; } + if (dir == superdir) + goto no_cache; QFileInfo qsdfi(sdir); QFileInfo qdfi(dir); if (qsdfi.isRoot() || qdfi.isRoot()) @@ -1405,7 +1423,8 @@ QMakeProject::read(uchar cmd) project_root.clear(); break; } - } while (!srcdir.isRoot() && srcdir.cdUp() && !dstdir.isRoot() && dstdir.cdUp()); + } while (!srcdir.isRoot() && srcdir.cdUp() + && dstdir != superdir && !dstdir.isRoot() && dstdir.cdUp()); } if (qmakepath != cached_qmakepath || qmakefeatures != cached_qmakefeatures @@ -1442,6 +1461,13 @@ QMakeProject::read(uchar cmd) } } + // We do this before reading the spec, so it can use module and feature paths from + // here without resorting to tricks. This is the only planned use case anyway. + if (!superfile.isEmpty()) { + debug_msg(1, "Project super cache file: reading %s", superfile.toLatin1().constData()); + read(superfile, base_vars); + } + // parse qmake configuration while(qmakespec.endsWith(QLatin1Char('/'))) qmakespec.truncate(qmakespec.length()-1); @@ -3184,17 +3210,20 @@ QMakeProject::doProjectTest(QString func, QList args_list, QHash 3) { - fprintf(stderr, "%s:%d: cache(var, [set|add|sub] [transient], [srcvar]) requires one to three arguments.\n", + fprintf(stderr, "%s:%d: cache(var, [set|add|sub] [transient] [super], [srcvar]) requires one to three arguments.\n", parser.file.toLatin1().constData(), parser.line_no); return false; } bool persist = true; + bool super = false; enum { CacheSet, CacheAdd, CacheSub } mode = CacheSet; QString srcvar; if (args.count() >= 2) { foreach (const QString &opt, split_value_list(args.at(1))) { if (opt == QLatin1String("transient")) { persist = false; + } else if (opt == QLatin1String("super")) { + super = true; } else if (opt == QLatin1String("set")) { mode = CacheSet; } else if (opt == QLatin1String("add")) { @@ -3277,16 +3306,26 @@ QMakeProject::doProjectTest(QString func, QList args_list, QHash args_list, QHash Date: Wed, 6 Jun 2012 22:14:41 +0200 Subject: look for mkspecs/ even below .qmake.cache/.conf-determined root otherwise a cache/config in an aggregator project may unduly hide the mkspecs/ of the aggregated project from qmake's view. Change-Id: Idb0b124de071822f8f55463d9f8a4d194ef3130e --- qmake/project.cpp | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index 58c2b8cb86..fb4d439bef 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -1411,20 +1411,25 @@ QMakeProject::read(uchar cmd) } no_cache: - if (project_build_root.isEmpty()) { - QDir srcdir(qmake_getpwd()); - QDir dstdir(Option::output_dir); - do { - // Look for mkspecs/ in source and build. First to win determines the root. - if (dstdir.exists("mkspecs") || srcdir.exists("mkspecs")) { - project_build_root = dstdir.path(); - project_root = srcdir.path(); - if (project_root == project_build_root) - project_root.clear(); - break; - } - } while (!srcdir.isRoot() && srcdir.cdUp() - && dstdir != superdir && !dstdir.isRoot() && dstdir.cdUp()); + // Look for mkspecs/ in source and build. First to win determines the root. + QString sdir = qmake_getpwd(); + QString dir = Option::output_dir; + while (dir != project_build_root) { + if ((dir != sdir && QFileInfo(sdir, QLatin1String("mkspecs")).isDir()) + || QFileInfo(dir, QLatin1String("mkspecs")).isDir()) { + if (dir != sdir) + project_root = sdir; + project_build_root = dir; + break; + } + if (dir == superdir) + break; + QFileInfo qsdfi(sdir); + QFileInfo qdfi(dir); + if (qsdfi.isRoot() || qdfi.isRoot()) + break; + sdir = qsdfi.path(); + dir = qdfi.path(); } if (qmakepath != cached_qmakepath || qmakefeatures != cached_qmakefeatures @@ -3317,11 +3322,13 @@ QMakeProject::doProjectTest(QString func, QList args_list, QHash Date: Mon, 23 Apr 2012 12:44:40 +0200 Subject: normalize $$QMAKE_QMAKE everything in the projects should be normalized. only the makefile generators need to adjust it to the native form. Change-Id: I06a4e997f32134d13949ec4a9dd1b44367aab7cb Reviewed-by: Joerg Bornemann Reviewed-by: Oswald Buddenhagen --- qmake/project.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'qmake/project.cpp') diff --git a/qmake/project.cpp b/qmake/project.cpp index fb4d439bef..3a34aef1a9 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -3861,12 +3861,11 @@ QStringList &QMakeProject::values(const QString &_var, QHash