aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@digia.com>2014-10-17 16:22:52 +0200
committerChristian Kandeler <christian.kandeler@digia.com>2014-11-10 10:48:11 +0100
commit3957fb612ae250671df02af67da2123ff65af232 (patch)
tree9e271070b06c389559ffce6d2d0d243e2a6e5f5c
parent9f6b297ca49a5eb376d11d130b240a8c8629e250 (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.qdoc2
-rw-r--r--doc/reference/jsextensions/jsextensions-general.qdoc10
-rw-r--r--share/qbs/modules/cpp/GenericGCC.qbs2
-rw-r--r--share/qbs/modules/cpp/windows-mingw.qbs2
-rw-r--r--share/qbs/modules/cpp/windows-msvc.qbs8
-rw-r--r--share/qbs/modules/ib/IBModule.qbs2
-rw-r--r--share/qbs/modules/wix/WiXModule.qbs2
-rw-r--r--src/lib/corelib/language/evaluatorscriptclass.cpp15
-rw-r--r--src/lib/corelib/language/evaluatorscriptclass.h2
-rw-r--r--src/lib/corelib/language/scriptengine.cpp2
-rw-r--r--tests/auto/blackbox/tst_blackbox.cpp20
-rw-r--r--tests/auto/shared.h5
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.