diff options
-rw-r--r-- | mkspecs/features/configure.prf | 4 | ||||
-rw-r--r-- | mkspecs/features/default_post.prf | 4 | ||||
-rw-r--r-- | mkspecs/features/incredibuild_xge.prf | 2 | ||||
-rw-r--r-- | mkspecs/features/qt_functions.prf | 4 | ||||
-rw-r--r-- | mkspecs/features/testcocoon.prf | 2 | ||||
-rw-r--r-- | mkspecs/features/win32/embed_manifest_dll.prf | 2 | ||||
-rw-r--r-- | mkspecs/features/win32/embed_manifest_exe.prf | 2 | ||||
-rw-r--r-- | qmake/option.cpp | 1 | ||||
-rw-r--r-- | qmake/project.cpp | 96 | ||||
-rw-r--r-- | tests/auto/tools/qmake/testdata/functions/functions.pro | 16 |
10 files changed, 84 insertions, 49 deletions
diff --git a/mkspecs/features/configure.prf b/mkspecs/features/configure.prf index 651f0ad256..ff52c6b373 100644 --- a/mkspecs/features/configure.prf +++ b/mkspecs/features/configure.prf @@ -44,7 +44,7 @@ defineTest(qtCompileTest) { test_dir = $$QMAKE_CONFIG_TESTS_DIR/$$1 test_out_dir = $$shadowed($$test_dir) - test_cmd_base = "cd $$shell_quote($$native_path($$test_out_dir)) &&" + test_cmd_base = "cd $$system_quote($$system_path($$test_out_dir)) &&" # Disable qmake features which are typically counterproductive for tests qmake_configs = "\"CONFIG -= qt debug_and_release app_bundle lib_bundle\"" @@ -54,7 +54,7 @@ defineTest(qtCompileTest) { mkpath($$test_out_dir)|error("Aborting.") - qtRunLoggedCommand("$$test_cmd_base $$shell_quote($$native_path($$QMAKE_QMAKE)) $$qmake_configs $$shell_quote($$test_dir)") { + qtRunLoggedCommand("$$test_cmd_base $$system_quote($$system_path($$QMAKE_QMAKE)) $$qmake_configs $$shell_quote($$test_dir)") { qtRunLoggedCommand("$$test_cmd_base $$QMAKE_MAKE") { log("yes$$escape_expand(\\n)") msg = "test $$1 succeeded" diff --git a/mkspecs/features/default_post.prf b/mkspecs/features/default_post.prf index 63daff64bc..d0a2d61607 100644 --- a/mkspecs/features/default_post.prf +++ b/mkspecs/features/default_post.prf @@ -31,8 +31,8 @@ breakpad { load(resolve_target) win32: QMAKE_CLEAN += $$replace(QMAKE_RESOLVED_TARGET, ...$, pdb) # for the debug case it is hardcoded in qmake - DEBUGFILENAME = $$shell_quote($$native_path($$QMAKE_RESOLVED_TARGET)) - PROJECTPATH = $$shell_quote($$native_path($$OUT_PWD)) + DEBUGFILENAME = $$shell_quote($$shell_path($$QMAKE_RESOLVED_TARGET)) + PROJECTPATH = $$shell_quote($$shell_path($$OUT_PWD)) !isEmpty(QMAKE_POST_LINK):QMAKE_POST_LINK = $$QMAKE_POST_LINK$$escape_expand(\\n\\t) QMAKE_POST_LINK = $$QMAKE_POST_LINK$$quote($${QT_BREAKPAD_ROOT_PATH}$${QMAKE_DIR_SEP}qtbreakpadsymbols $$DEBUGFILENAME $$PROJECTPATH) diff --git a/mkspecs/features/incredibuild_xge.prf b/mkspecs/features/incredibuild_xge.prf index 28a58cafce..028f39d7b6 100644 --- a/mkspecs/features/incredibuild_xge.prf +++ b/mkspecs/features/incredibuild_xge.prf @@ -6,6 +6,6 @@ contains(TEMPLATE, "vc.*") { win32-msvc2*|wince*msvc*: EOC = $$escape_expand(\\r\\h) for(xge, INCREDIBUILD_XGE) { - $${xge}.commands = Rem IncrediBuild_AllowRemote $$EOC Rem IncrediBuild_OutputFile $$native_path($${xge}.output) $$EOC $$eval($${xge}.commands) + $${xge}.commands = Rem IncrediBuild_AllowRemote $$EOC Rem IncrediBuild_OutputFile $$shell_path($${xge}.output) $$EOC $$eval($${xge}.commands) } } diff --git a/mkspecs/features/qt_functions.prf b/mkspecs/features/qt_functions.prf index 649bea0f80..b6a3b0ada4 100644 --- a/mkspecs/features/qt_functions.prf +++ b/mkspecs/features/qt_functions.prf @@ -137,12 +137,12 @@ defineTest(qtPrepareTool) { } } } - $$1 = $$native_path($$eval($$1)) + $$1 = $$shell_path($$eval($$1)) deps = $$resolve_depends(QT_TOOL.$${2}.depends, "QT.") !isEmpty(deps) { for(dep, deps): \ - deppath += $$native_path($$eval(QT.$${dep}.libs)) + deppath += $$shell_path($$eval(QT.$${dep}.libs)) deppath = $$unique(deppath) equals(QMAKE_DIR_SEP, /) { equals(QMAKE_HOST.os, Windows): \ diff --git a/mkspecs/features/testcocoon.prf b/mkspecs/features/testcocoon.prf index bf7e3dd463..efa33ecb08 100644 --- a/mkspecs/features/testcocoon.prf +++ b/mkspecs/features/testcocoon.prf @@ -25,7 +25,7 @@ TESTCOCOON_COVERAGE_OPTIONS = \ # is built directly in target.path and there is no need to move the csmes. !isEmpty(DESTDIR):contains(TEMPLATE, lib) { !isEmpty(QMAKE_POST_LINK):QMAKE_POST_LINK = $$escape_expand(\\n\\t)$$QMAKE_POST_LINK - QMAKE_POST_LINK = -$(MOVE) $${TARGET_BASENAME}.csmes $$native_path($${QMAKE_RESOLVED_TARGET}.csmes)$$QMAKE_POST_LINK + QMAKE_POST_LINK = -$(MOVE) $${TARGET_BASENAME}.csmes $$shell_path($${QMAKE_RESOLVED_TARGET}.csmes)$$QMAKE_POST_LINK } QMAKE_CLEAN += *.csexe *.csmes diff --git a/mkspecs/features/win32/embed_manifest_dll.prf b/mkspecs/features/win32/embed_manifest_dll.prf index 783dc6708d..e50783d20a 100644 --- a/mkspecs/features/win32/embed_manifest_dll.prf +++ b/mkspecs/features/win32/embed_manifest_dll.prf @@ -7,6 +7,6 @@ NOPATH_TARGET ~= s,^(.*/)+,, # Remove all paths QMAKE_LFLAGS += /MANIFEST $$quote(/MANIFESTFILE:\"$${MANIFEST_DIR}\\$${NOPATH_TARGET}.intermediate.manifest\") !isEmpty(QMAKE_POST_LINK):QMAKE_POST_LINK = $$escape_expand(\\n\\t)$$QMAKE_POST_LINK - QMAKE_POST_LINK = $$quote(mt.exe -nologo -manifest $$shell_quote($$native_path($$MANIFEST_DIR/$${NOPATH_TARGET}.intermediate.manifest)) -outputresource:$(DESTDIR_TARGET);2)$$QMAKE_POST_LINK + QMAKE_POST_LINK = $$quote(mt.exe -nologo -manifest $$shell_quote($$shell_path($$MANIFEST_DIR/$${NOPATH_TARGET}.intermediate.manifest)) -outputresource:$(DESTDIR_TARGET);2)$$QMAKE_POST_LINK QMAKE_CLEAN += $$MANIFEST_DIR/$${NOPATH_TARGET}.intermediate.manifest } diff --git a/mkspecs/features/win32/embed_manifest_exe.prf b/mkspecs/features/win32/embed_manifest_exe.prf index c496a53f91..526fc009d9 100644 --- a/mkspecs/features/win32/embed_manifest_exe.prf +++ b/mkspecs/features/win32/embed_manifest_exe.prf @@ -7,6 +7,6 @@ if(win32-msvc2005*|win32-msvc2008*|win32-msvc2010*):equals(TEMPLATE, "app") { NOPATH_TARGET ~= s,^(.*/)+,, # Remove all paths QMAKE_LFLAGS += /MANIFEST $$quote(/MANIFESTFILE:\"$${MANIFEST_DIR}\\$${NOPATH_TARGET}.intermediate.manifest\") !isEmpty(QMAKE_POST_LINK):QMAKE_POST_LINK = $$escape_expand(\\n\\t)$$QMAKE_POST_LINK - QMAKE_POST_LINK = $$quote(mt.exe -nologo -manifest $$shell_quote($$native_path($$MANIFEST_DIR/$${NOPATH_TARGET}.intermediate.manifest)) -outputresource:$(DESTDIR_TARGET);1)$$QMAKE_POST_LINK + QMAKE_POST_LINK = $$quote(mt.exe -nologo -manifest $$shell_quote($$shell_path($$MANIFEST_DIR/$${NOPATH_TARGET}.intermediate.manifest)) -outputresource:$(DESTDIR_TARGET);1)$$QMAKE_POST_LINK QMAKE_CLEAN += $$MANIFEST_DIR/$${NOPATH_TARGET}.intermediate.manifest } diff --git a/qmake/option.cpp b/qmake/option.cpp index b01b4eded5..3bfec96087 100644 --- a/qmake/option.cpp +++ b/qmake/option.cpp @@ -555,7 +555,6 @@ bool Option::postProcessProject(QMakeProject *project) Option::h_moc_mod = project->first("QMAKE_H_MOD_MOC"); Option::lex_mod = project->first("QMAKE_MOD_LEX"); Option::yacc_mod = project->first("QMAKE_MOD_YACC"); - Option::dir_sep = project->first("QMAKE_DIR_SEP"); if (Option::output_dir.startsWith(project->buildRoot())) Option::mkfile::cachefile_depth = diff --git a/qmake/project.cpp b/qmake/project.cpp index 26ab0d0f35..0681697a96 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -82,8 +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_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, - E_SHELL_QUOTE }; + E_SHADOWED, E_ABSOLUTE_PATH, E_RELATIVE_PATH, E_CLEAN_PATH, + E_SYSTEM_PATH, E_SHELL_PATH, E_SYSTEM_QUOTE, E_SHELL_QUOTE }; QHash<QString, ExpandFunc> qmake_expandFunctions() { static QHash<QString, ExpandFunc> *qmake_expand_functions = 0; @@ -125,7 +125,9 @@ QHash<QString, ExpandFunc> qmake_expandFunctions() 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); + qmake_expand_functions->insert("system_path", E_SYSTEM_PATH); + qmake_expand_functions->insert("shell_path", E_SHELL_PATH); + qmake_expand_functions->insert("system_quote", E_SYSTEM_QUOTE); qmake_expand_functions->insert("shell_quote", E_SHELL_QUOTE); } return *qmake_expand_functions; @@ -1498,6 +1500,8 @@ QMakeProject::read(uchar cmd) doProjectInclude("spec_post", IncludeFlagFeature, vars); // The spec extends the feature search path, so invalidate the cache. invalidateFeatureRoots(); + // The MinGW and x-build specs may change the separator; $$shell_{path,quote}() need it + Option::dir_sep = first(QLatin1String("QMAKE_DIR_SEP")); if (!conffile.isEmpty()) { debug_msg(1, "Project config file: reading %s", conffile.toLatin1().constData()); @@ -1895,45 +1899,54 @@ subAll(QStringList *val, const QStringList &diffval) } inline static -bool isSpecialChar(ushort c) +bool hasSpecialChars(const QString &arg, const uchar (&iqm)[16]) +{ + for (int x = arg.length() - 1; x >= 0; --x) { + ushort c = arg.unicode()[x].unicode(); + if ((c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)))) + return true; + } + return false; +} + +static QString +shellQuoteUnix(const QString &arg) { // 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))); -} + if (!arg.length()) + return QString::fromLatin1("\"\""); -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; + QString ret(arg); + if (hasSpecialChars(ret, iqm)) { + ret.replace(QLatin1Char('\''), QLatin1String("'\\''")); + ret.prepend(QLatin1Char('\'')); + ret.append(QLatin1Char('\'')); + } + return ret; } static QString -shellQuote(const QString &arg) +shellQuoteWin(const QString &arg) { + // Chars that should be quoted (TM). This includes: + // - 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 + }; + if (!arg.length()) return QString::fromLatin1("\"\""); QString ret(arg); - if (hasSpecialChars(ret)) { -#ifdef Q_OS_WIN + if (hasSpecialChars(ret, iqm)) { // 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". @@ -1946,11 +1959,6 @@ shellQuote(const QString &arg) --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; } @@ -2738,19 +2746,39 @@ QMakeProject::doProjectExpand(QString func, QList<QStringList> args_list, else ret += QDir::cleanPath(args.at(0)); break; - case E_NATIVE_PATH: + case E_SYSTEM_PATH: if (args.count() != 1) - fprintf(stderr, "%s:%d native_path(path) requires one argument.\n", + fprintf(stderr, "%s:%d system_path(path) requires one argument.\n", + parser.file.toLatin1().constData(), parser.line_no); + else + ret += Option::fixPathToLocalOS(args.at(0), false); + break; + case E_SHELL_PATH: + if (args.count() != 1) + fprintf(stderr, "%s:%d shell_path(path) requires one argument.\n", parser.file.toLatin1().constData(), parser.line_no); else ret += Option::fixPathToTargetOS(args.at(0), false); break; + case E_SYSTEM_QUOTE: + if (args.count() != 1) + fprintf(stderr, "%s:%d system_quote(args) requires one argument.\n", + parser.file.toLatin1().constData(), parser.line_no); + else +#ifdef Q_OS_WIN + ret += shellQuoteWin(args.at(0)); +#else + ret += shellQuoteUnix(args.at(0)); +#endif + 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 if (Option::dir_sep.at(0) != QLatin1Char('/')) + ret += shellQuoteWin(args.at(0)); else - ret += shellQuote(args.at(0)); + ret += shellQuoteUnix(args.at(0)); break; default: { fprintf(stderr, "%s:%d: Unknown replace function: %s\n", diff --git a/tests/auto/tools/qmake/testdata/functions/functions.pro b/tests/auto/tools/qmake/testdata/functions/functions.pro index 884113b95a..98e12b7650 100644 --- a/tests/auto/tools/qmake/testdata/functions/functions.pro +++ b/tests/auto/tools/qmake/testdata/functions/functions.pro @@ -131,7 +131,8 @@ testReplace($$format_number(13, width=5 padsign zeropad), " 0013", "zero-padded testReplace($$clean_path("c:$${DIR_SEPARATOR}crazy//path/../trolls"), "c:/crazy/trolls", "clean_path") -testReplace($$native_path("/crazy/trolls"), "$${DIR_SEPARATOR}crazy$${DIR_SEPARATOR}trolls", "native_path") +testReplace($$shell_path("/crazy/trolls"), "$${QMAKE_DIR_SEP}crazy$${QMAKE_DIR_SEP}trolls", "shell_path") +testReplace($$system_path("/crazy/trolls"), "$${DIR_SEPARATOR}crazy$${DIR_SEPARATOR}trolls", "system_path") testReplace($$absolute_path("crazy/trolls"), "$$PWD/crazy/trolls", "absolute_path") testReplace($$absolute_path("crazy/trolls", "/fake/path"), "/fake/path/crazy/trolls", "absolute_path with base") @@ -142,10 +143,17 @@ testReplace($$relative_path(""), "", "relative_path of empty") #this test is very rudimentary. the backend function is thoroughly tested in qt creator in = "some nasty\" path\\" -win32: \ - out = "\"some nasty\"\\^\"\" path\"\\" +out_cmd = "\"some nasty\"\\^\"\" path\"\\" +out_sh = "'some nasty\" path\\'" +equals(QMAKE_HOST.os, Windows): \ + out = $$out_cmd else: \ - out = "'some nasty\" path\\'" + out = $$out_sh +testReplace($$system_quote($$in), $$out, "system_quote") +!equals(QMAKE_DIR_SEP, /): \ + out = $$out_cmd +else: \ + out = $$out_sh testReplace($$shell_quote($$in), $$out, "shell_quote") testReplace($$reverse($$list(one two three)), three two one, "reverse") |