diff options
author | Christian Kandeler <christian.kandeler@digia.com> | 2014-10-17 16:22:52 +0200 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@digia.com> | 2014-11-10 10:48:11 +0100 |
commit | 3957fb612ae250671df02af67da2123ff65af232 (patch) | |
tree | 9e271070b06c389559ffce6d2d0d243e2a6e5f5c | |
parent | 9f6b297ca49a5eb376d11d130b240a8c8629e250 (diff) |
Use a hashing function to construct output artfact file paths.
Modules like cpp need a way to construct unique locations
for output artifacts, but the current approach of duplicating
the path to the input file in the build directory can lead
to excessively long file paths that hit the limit on Windows.
So let's hash the path to the input file instead.
Change-Id: I47dcd242d0ee90c377f2a6df8e270bbefbaf082f
Reviewed-by: Thomas Epting <thomas.epting@stryker.com>
Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
-rw-r--r-- | doc/reference/items/rule.qdoc | 2 | ||||
-rw-r--r-- | doc/reference/jsextensions/jsextensions-general.qdoc | 10 | ||||
-rw-r--r-- | share/qbs/modules/cpp/GenericGCC.qbs | 2 | ||||
-rw-r--r-- | share/qbs/modules/cpp/windows-mingw.qbs | 2 | ||||
-rw-r--r-- | share/qbs/modules/cpp/windows-msvc.qbs | 8 | ||||
-rw-r--r-- | share/qbs/modules/ib/IBModule.qbs | 2 | ||||
-rw-r--r-- | share/qbs/modules/wix/WiXModule.qbs | 2 | ||||
-rw-r--r-- | src/lib/corelib/language/evaluatorscriptclass.cpp | 15 | ||||
-rw-r--r-- | src/lib/corelib/language/evaluatorscriptclass.h | 2 | ||||
-rw-r--r-- | src/lib/corelib/language/scriptengine.cpp | 2 | ||||
-rw-r--r-- | tests/auto/blackbox/tst_blackbox.cpp | 20 | ||||
-rw-r--r-- | tests/auto/shared.h | 5 |
12 files changed, 53 insertions, 19 deletions
diff --git a/doc/reference/items/rule.qdoc b/doc/reference/items/rule.qdoc index 00b065f2b..5d3ae4533 100644 --- a/doc/reference/items/rule.qdoc +++ b/doc/reference/items/rule.qdoc @@ -52,7 +52,7 @@ Artifact { fileTags: ['obj'] - filePath: '.obj/' + input.baseDir + '/' + input.fileName + '.o' + filePath: '.obj/' + qbs.getHash(input.baseDir) + '/' + input.fileName + '.o' } prepare: { diff --git a/doc/reference/jsextensions/jsextensions-general.qdoc b/doc/reference/jsextensions/jsextensions-general.qdoc index 9582772fc..2bbd2f7ac 100644 --- a/doc/reference/jsextensions/jsextensions-general.qdoc +++ b/doc/reference/jsextensions/jsextensions-general.qdoc @@ -49,6 +49,16 @@ Tries to find a variable with the given name in the build environment and returns its value. If no such variable could be found, \c undefined is returned. + \section2 qbs.getHash + \code + qbs.getHash(key: string): string + \endcode + Calculates a 16-byte hash of the input and returns it. + Rules in modules should use this function to find unique locations for output + artifacts in the build directory without duplicating the whole directory structure of + the respective input file (to deal with the case of two files with the same name in different + subdirectories of the same product). + \section2 qbs.rfc1034Identifier \code qbs.rfc1034Identifier(str: string): string diff --git a/share/qbs/modules/cpp/GenericGCC.qbs b/share/qbs/modules/cpp/GenericGCC.qbs index 7c5ef6e30..2e1394bb0 100644 --- a/share/qbs/modules/cpp/GenericGCC.qbs +++ b/share/qbs/modules/cpp/GenericGCC.qbs @@ -180,7 +180,7 @@ CppModule { Artifact { fileTags: ["obj"] - filePath: ".obj/" + input.baseDir + "/" + input.fileName + ".o" + filePath: ".obj/" + qbs.getHash(input.baseDir) + "/" + input.fileName + ".o" } prepare: { diff --git a/share/qbs/modules/cpp/windows-mingw.qbs b/share/qbs/modules/cpp/windows-mingw.qbs index 809485b78..b680eb681 100644 --- a/share/qbs/modules/cpp/windows-mingw.qbs +++ b/share/qbs/modules/cpp/windows-mingw.qbs @@ -39,7 +39,7 @@ GenericGCC { inputs: ["rc"] Artifact { - filePath: ".obj/" + input.baseDir.replace(':', '') + "/" + input.completeBaseName + "_res.o" + filePath: ".obj/" + qbs.getHash(input.baseDir) + "/" + input.completeBaseName + "_res.o" fileTags: ["obj"] } diff --git a/share/qbs/modules/cpp/windows-msvc.qbs b/share/qbs/modules/cpp/windows-msvc.qbs index bad42b62a..74272774e 100644 --- a/share/qbs/modules/cpp/windows-msvc.qbs +++ b/share/qbs/modules/cpp/windows-msvc.qbs @@ -38,7 +38,7 @@ CppModule { filePath: { var completeBaseName = FileInfo.completeBaseName(product.moduleProperty("cpp", "cPrecompiledHeader")); - return ".obj/" + completeBaseName + '_c.obj' + return ".obj/" + qbs.getHash(completeBaseName) + '_c.obj' } } Artifact { @@ -59,7 +59,7 @@ CppModule { filePath: { var completeBaseName = FileInfo.completeBaseName(product.moduleProperty("cpp", "cxxPrecompiledHeader")); - return ".obj/" + completeBaseName + '_cpp.obj' + return ".obj/" + qbs.getHash(completeBaseName) + '_cpp.obj' } } Artifact { @@ -79,7 +79,7 @@ CppModule { Artifact { fileTags: ['obj'] - filePath: ".obj/" + input.baseDir.replace(':', '') + "/" + input.fileName + ".obj" + filePath: ".obj/" + qbs.getHash(input.baseDir) + "/" + input.fileName + ".obj" } prepare: { @@ -171,7 +171,7 @@ CppModule { inputs: ["rc"] Artifact { - filePath: ".obj/" + input.baseDir.replace(':', '') + "/" + input.completeBaseName + ".res" + filePath: ".obj/" + qbs.getHash(input.baseDir) + "/" + input.completeBaseName + ".res" fileTags: ["obj"] } diff --git a/share/qbs/modules/ib/IBModule.qbs b/share/qbs/modules/ib/IBModule.qbs index 85856f144..274e9e86f 100644 --- a/share/qbs/modules/ib/IBModule.qbs +++ b/share/qbs/modules/ib/IBModule.qbs @@ -122,7 +122,7 @@ Module { path += '/' + subPath; } else { path += '/' + BundleTools.unlocalizedResourcesFolderPath(product); - path += '/' + input.baseDir; + path += '/' + qbs.getHash(input.baseDir); } var suffix = ""; diff --git a/share/qbs/modules/wix/WiXModule.qbs b/share/qbs/modules/wix/WiXModule.qbs index 24f3082d0..34708d1cc 100644 --- a/share/qbs/modules/wix/WiXModule.qbs +++ b/share/qbs/modules/wix/WiXModule.qbs @@ -152,7 +152,7 @@ Module { Artifact { fileTags: ["wixobj"] - filePath: FileInfo.joinPaths(".obj", input.baseDir.replace(':', ''), + filePath: FileInfo.joinPaths(".obj", qbs.getHash(input.baseDir), FileInfo.baseName(input.fileName) + ".wixobj") } diff --git a/src/lib/corelib/language/evaluatorscriptclass.cpp b/src/lib/corelib/language/evaluatorscriptclass.cpp index c91adf59b..27ba4e0e7 100644 --- a/src/lib/corelib/language/evaluatorscriptclass.cpp +++ b/src/lib/corelib/language/evaluatorscriptclass.cpp @@ -42,6 +42,8 @@ #include <tools/qbsassert.h> #include <tools/scripttools.h> +#include <QByteArray> +#include <QCryptographicHash> #include <QScriptString> #include <QScriptValue> #include <QDebug> @@ -259,6 +261,7 @@ EvaluatorScriptClass::EvaluatorScriptClass(ScriptEngine *scriptEngine, const Log m_getEnvBuiltin = scriptEngine->newFunction(js_getEnv, 1); m_canonicalArchitectureBuiltin = scriptEngine->newFunction(js_canonicalArchitecture, 1); m_rfc1034identifierBuiltin = scriptEngine->newFunction(js_rfc1034identifier, 1); + m_getHashBuiltin = scriptEngine->newFunction(js_getHash, 1); } QScriptClass::QueryFlags EvaluatorScriptClass::queryProperty(const QScriptValue &object, @@ -486,5 +489,17 @@ QScriptValue EvaluatorScriptClass::js_rfc1034identifier(QScriptContext *context, return engine->toScriptValue(HostOsInfo::rfc1034Identifier(identifier)); } +QScriptValue EvaluatorScriptClass::js_getHash(QScriptContext *context, QScriptEngine *engine) +{ + if (Q_UNLIKELY(context->argumentCount() < 1)) { + return context->throwError(QScriptContext::SyntaxError, + QLatin1String("getHash expects 1 argument")); + } + const QByteArray input = context->argument(0).toString().toLatin1(); + const QByteArray hash + = QCryptographicHash::hash(input, QCryptographicHash::Sha1).toHex().left(16); + return engine->toScriptValue(QString::fromLatin1(hash)); +} + } // namespace Internal } // namespace qbs diff --git a/src/lib/corelib/language/evaluatorscriptclass.h b/src/lib/corelib/language/evaluatorscriptclass.h index 9769dc85b..30537e7d5 100644 --- a/src/lib/corelib/language/evaluatorscriptclass.h +++ b/src/lib/corelib/language/evaluatorscriptclass.h @@ -63,6 +63,7 @@ public: static QScriptValue js_getEnv(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_canonicalArchitecture(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_rfc1034identifier(QScriptContext *context, QScriptEngine *engine); + static QScriptValue js_getHash(QScriptContext *context, QScriptEngine *engine); private: QueryFlags queryItemProperty(const EvaluationData *data, @@ -92,6 +93,7 @@ private: QScriptValue m_getEnvBuiltin; QScriptValue m_canonicalArchitectureBuiltin; QScriptValue m_rfc1034identifierBuiltin; + QScriptValue m_getHashBuiltin; }; } // namespace Internal diff --git a/src/lib/corelib/language/scriptengine.cpp b/src/lib/corelib/language/scriptengine.cpp index aaa113c32..691a13a2e 100644 --- a/src/lib/corelib/language/scriptengine.cpp +++ b/src/lib/corelib/language/scriptengine.cpp @@ -505,6 +505,8 @@ void ScriptEngine::installQbsBuiltins() EvaluatorScriptClass::js_canonicalArchitecture); installQbsFunction(QLatin1String("rfc1034Identifier"), EvaluatorScriptClass::js_rfc1034identifier); + installQbsFunction(QLatin1String("getHash"), + EvaluatorScriptClass::js_getHash); } void ScriptEngine::extendJavaScriptBuiltins() diff --git a/tests/auto/blackbox/tst_blackbox.cpp b/tests/auto/blackbox/tst_blackbox.cpp index 07b9f30b9..1458bd8e2 100644 --- a/tests/auto/blackbox/tst_blackbox.cpp +++ b/tests/auto/blackbox/tst_blackbox.cpp @@ -318,11 +318,11 @@ static bool symlinkExists(const QString &linkFilePath) void TestBlackbox::clean() { - const QString appObjectFilePath = relativeProductBuildDir("app") - + objectFileName("/.obj/main.cpp", profileName()); + const QString appObjectFilePath = relativeProductBuildDir("app") + "/.obj/" + inputDirHash(".") + + objectFileName("/main.cpp", profileName()); const QString appExeFilePath = relativeExecutableFilePath("app"); - const QString depObjectFilePath = relativeProductBuildDir("dep") - + objectFileName("/.obj/dep.cpp", profileName()); + const QString depObjectFilePath = relativeProductBuildDir("dep") + "/.obj/" + inputDirHash(".") + + objectFileName("/dep.cpp", profileName()); const QString depLibBase = relativeProductBuildDir("dep") + '/' + QBS_HOST_DYNAMICLIB_PREFIX + "dep"; QString depLibFilePath; @@ -464,8 +464,8 @@ void TestBlackbox::track_qobject_change() QCOMPARE(runQbs(), 0); const QString productFilePath = relativeExecutableFilePath("i"); QVERIFY2(regularFileExists(productFilePath), qPrintable(productFilePath)); - QString moc_bla_objectFileName = relativeProductBuildDir("i") - + objectFileName("/.obj/GeneratedFiles/moc_bla.cpp", profileName()); + QString moc_bla_objectFileName = relativeProductBuildDir("i") + "/.obj/" + + inputDirHash("GeneratedFiles") + objectFileName("/moc_bla.cpp", profileName()); QVERIFY2(regularFileExists(moc_bla_objectFileName), qPrintable(moc_bla_objectFileName)); waitForNewTimestamp(); @@ -681,8 +681,8 @@ void TestBlackbox::trackRemoveFileTag() QCOMPARE(runQbs(), 0); // check if the artifacts are here that will become stale in the 2nd step - QVERIFY(regularFileExists(relativeProductBuildDir("someapp") - + objectFileName("/.obj/main_foo.cpp", profileName()))); + QVERIFY(regularFileExists(relativeProductBuildDir("someapp") + "/.obj/" + inputDirHash(".") + + objectFileName("/main_foo.cpp", profileName()))); QVERIFY(regularFileExists(relativeProductBuildDir("someapp") + "/main_foo.cpp")); QVERIFY(regularFileExists(relativeProductBuildDir("someapp") + "/main.foo")); @@ -707,8 +707,8 @@ void TestBlackbox::trackRemoveFileTag() QCOMPARE(output.takeFirst().trimmed().constData(), "there's no foo here"); // check if stale artifacts have been removed - QCOMPARE(regularFileExists(relativeProductBuildDir("someapp") - + objectFileName("/.obj/main_foo.cpp", profileName())), false); + QCOMPARE(regularFileExists(relativeProductBuildDir("someapp") + "/.obj/" + inputDirHash(".") + + objectFileName("/main_foo.cpp", profileName())), false); QCOMPARE(regularFileExists(relativeProductBuildDir("someapp") + "/main_foo.cpp"), false); QCOMPARE(regularFileExists(relativeProductBuildDir("someapp") + "/main.foo"), false); } diff --git a/tests/auto/shared.h b/tests/auto/shared.h index 67ea19128..193327e21 100644 --- a/tests/auto/shared.h +++ b/tests/auto/shared.h @@ -119,4 +119,9 @@ inline QString objectFileName(const QString &baseName, const QString &profileNam return baseName + '.' + suffix; } +inline QString inputDirHash(const QString &dir) +{ + return QCryptographicHash::hash(dir.toLatin1(), QCryptographicHash::Sha1).toHex().left(16); +} + #endif // Include guard. |