aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@digia.com>2014-01-10 17:16:32 +0100
committerChristian Kandeler <christian.kandeler@digia.com>2014-01-16 16:51:48 +0100
commitf4b6d84baa16440812127099f7b03ec79f87bd2a (patch)
tree2f0e8a7959cc357684e887297faa4792b11facad
parent008992106eea60f0a63efc0978399c454fdab2ca (diff)
Move knowledge about Qt modules into libsetupqt.
In addition, we make less hard-coded assumptions than before, instead generating almost all modules dynamically from the respective Qt installation when setup-qt is being run. This way, qbs does not have to know about all the modules beforehand, and only the Qt modules that are actually present will have qbs counterparts, making it possible for project file authors to make use of soft dependencies for Qt modules. Task-number: QBS-479 Change-Id: Ie20d2acf249cd159ce4caff2ede4721ab879fad2 Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
-rw-r--r--share/qbs/modules/Qt/axcontainer/axcontainer.qbs14
-rw-r--r--share/qbs/modules/Qt/axserver/axserver.qbs15
-rw-r--r--share/qbs/modules/Qt/concurrent/concurrent.qbs7
-rw-r--r--share/qbs/modules/Qt/core/moc.js19
-rw-r--r--share/qbs/modules/Qt/dbus/dbus.qbs7
-rw-r--r--share/qbs/modules/Qt/declarative/declarative.qbs16
-rw-r--r--share/qbs/modules/Qt/designer/designer.qbs8
-rw-r--r--share/qbs/modules/Qt/designercomponents/designercomponents.qbs7
-rw-r--r--share/qbs/modules/Qt/enginio/enginio.qbs12
-rw-r--r--share/qbs/modules/Qt/help/help.qbs8
-rw-r--r--share/qbs/modules/Qt/multimedia/multimedia.qbs8
-rw-r--r--share/qbs/modules/Qt/multimediawidgets/multimediawidgets.qbs8
-rw-r--r--share/qbs/modules/Qt/network/network.qbs7
-rw-r--r--share/qbs/modules/Qt/opengl/opengl.qbs12
-rw-r--r--share/qbs/modules/Qt/phonon/phonon.qbs8
-rw-r--r--share/qbs/modules/Qt/printsupport/printsupport.qbs6
-rw-r--r--share/qbs/modules/Qt/qml/qml.qbs13
-rw-r--r--share/qbs/modules/Qt/quick/quick.qbs15
-rw-r--r--share/qbs/modules/Qt/script/script.qbs8
-rw-r--r--share/qbs/modules/Qt/sql/sql.qbs7
-rw-r--r--share/qbs/modules/Qt/svg/svg.qbs8
-rw-r--r--share/qbs/modules/Qt/test/test.qbs7
-rw-r--r--share/qbs/modules/Qt/webkit/webkit.qbs9
-rw-r--r--share/qbs/modules/Qt/webkitwidgets/webkitwidgets.qbs10
-rw-r--r--share/qbs/modules/Qt/widgets/widgets.qbs7
-rw-r--r--share/qbs/modules/Qt/xml/xml.qbs7
-rw-r--r--share/qbs/modules/Qt/xmlpatterns/xmlpatterns.qbs7
-rw-r--r--src/app/qbs-setup-qt/setupqt.cpp57
-rw-r--r--src/lib/corelib/tools/settings.cpp5
-rw-r--r--src/lib/corelib/tools/settings.h2
-rw-r--r--src/lib/qtprofilesetup/qtprofilesetup.cpp194
-rw-r--r--src/lib/qtprofilesetup/qtprofilesetup.h1
-rw-r--r--src/lib/qtprofilesetup/qtprofilesetup.pro1
-rw-r--r--src/lib/qtprofilesetup/qtprofilesetup.qbs5
-rw-r--r--src/lib/qtprofilesetup/templates.qrc11
-rw-r--r--src/lib/qtprofilesetup/templates/QtModule.qbs (renamed from share/qbs/modules/Qt/QtModule.qbs)9
-rw-r--r--src/lib/qtprofilesetup/templates/core.qbs (renamed from share/qbs/modules/Qt/core/core.qbs)2
-rw-r--r--src/lib/qtprofilesetup/templates/gui.qbs (renamed from share/qbs/modules/Qt/gui/gui.qbs)2
-rw-r--r--src/lib/qtprofilesetup/templates/moc.js47
-rw-r--r--src/lib/qtprofilesetup/templates/module.qbs10
-rw-r--r--src/lib/qtprofilesetup/templates/qtfunctions.js (renamed from share/qbs/modules/Qt/qtfunctions.js)0
-rw-r--r--src/lib/qtprofilesetup/templates/utils.js214
-rw-r--r--tests/auto/api/tst_api.cpp8
43 files changed, 533 insertions, 295 deletions
diff --git a/share/qbs/modules/Qt/axcontainer/axcontainer.qbs b/share/qbs/modules/Qt/axcontainer/axcontainer.qbs
deleted file mode 100644
index 646731a51..000000000
--- a/share/qbs/modules/Qt/axcontainer/axcontainer.qbs
+++ /dev/null
@@ -1,14 +0,0 @@
-import qbs 1.0
-import "../QtModule.qbs" as QtModule
-import "../qtfunctions.js" as QtFunctions
-
-QtModule {
- qtModuleName: "AxContainer"
- repository: "qtactiveqt"
- includeDirName: "ActiveQt"
- cpp.dynamicLibraries: [
- internalLibraryName,
- QtFunctions.getQtLibraryName("AxBase" + qtLibInfix, Qt.core, qbs),
- "Ole32.lib", "OleAut32.lib", "Gdi32.lib", "User32.lib"
- ]
-}
diff --git a/share/qbs/modules/Qt/axserver/axserver.qbs b/share/qbs/modules/Qt/axserver/axserver.qbs
deleted file mode 100644
index 3275f5b8f..000000000
--- a/share/qbs/modules/Qt/axserver/axserver.qbs
+++ /dev/null
@@ -1,15 +0,0 @@
-import qbs 1.0
-import qbs.FileInfo
-import "../QtModule.qbs" as QtModule
-import "../qtfunctions.js" as QtFunctions
-
-QtModule {
- qtModuleName: "AxServer"
- repository: "qtactiveqt"
- includeDirName: "ActiveQt"
- cpp.dynamicLibraries: [
- internalLibraryName,
- QtFunctions.getQtLibraryName("AxBase" + qtLibInfix, Qt.core, qbs),
- "Ole32.lib", "OleAut32.lib", "Gdi32.lib", "User32.lib"
- ]
-}
diff --git a/share/qbs/modules/Qt/concurrent/concurrent.qbs b/share/qbs/modules/Qt/concurrent/concurrent.qbs
deleted file mode 100644
index 097a3403f..000000000
--- a/share/qbs/modules/Qt/concurrent/concurrent.qbs
+++ /dev/null
@@ -1,7 +0,0 @@
-import qbs 1.0
-import '../QtModule.qbs' as QtModule
-
-QtModule {
- qtModuleName: Qt.core.versionMajor >= 5 ? 'Concurrent' : undefined
-}
-
diff --git a/share/qbs/modules/Qt/core/moc.js b/share/qbs/modules/Qt/core/moc.js
deleted file mode 100644
index be3a8fd60..000000000
--- a/share/qbs/modules/Qt/core/moc.js
+++ /dev/null
@@ -1,19 +0,0 @@
-function args(product, input, outputFileName)
-{
- var defines = ModUtils.modulePropertiesFromArtifacts(product, [input], 'cpp', 'compilerDefines');
- defines = defines.concat(ModUtils.modulePropertiesFromArtifacts(product, [input], 'cpp', 'platformDefines'));
- defines = defines.concat(ModUtils.modulePropertiesFromArtifacts(product, [input], 'cpp', 'defines'));
- var includePaths = ModUtils.modulePropertiesFromArtifacts(product, [input], 'cpp', 'includePaths');
- var args = [];
- args = args.concat(
- defines.map(function(item) { return '-D' + item; }),
- includePaths.map(function(item) { return '-I' + item; }),
- '-o', outputFileName,
- input.fileName);
- return args;
-}
-
-function fullPath(product)
-{
- return ModUtils.moduleProperty(product, "binPath") + '/' + ModUtils.moduleProperty(product, "mocName");
-}
diff --git a/share/qbs/modules/Qt/dbus/dbus.qbs b/share/qbs/modules/Qt/dbus/dbus.qbs
deleted file mode 100644
index a429c7732..000000000
--- a/share/qbs/modules/Qt/dbus/dbus.qbs
+++ /dev/null
@@ -1,7 +0,0 @@
-import qbs 1.0
-import '../QtModule.qbs' as QtModule
-
-QtModule {
- qtModuleName: 'DBus'
-}
-
diff --git a/share/qbs/modules/Qt/declarative/declarative.qbs b/share/qbs/modules/Qt/declarative/declarative.qbs
deleted file mode 100644
index e8d9d81c5..000000000
--- a/share/qbs/modules/Qt/declarative/declarative.qbs
+++ /dev/null
@@ -1,16 +0,0 @@
-import qbs 1.0
-import '../QtModule.qbs' as QtModule
-
-QtModule {
- qtModuleName: "Declarative"
-
- property bool qmlDebugging: false
-
- Depends {
- name: "Qt"
- submodules: ["gui", "network", "script", "xmlpatterns"]
- }
-
- cpp.defines: qmlDebugging ? base.concat("QT_DECLARATIVE_DEBUG") : base
-}
-
diff --git a/share/qbs/modules/Qt/designer/designer.qbs b/share/qbs/modules/Qt/designer/designer.qbs
deleted file mode 100644
index 01bb0c24d..000000000
--- a/share/qbs/modules/Qt/designer/designer.qbs
+++ /dev/null
@@ -1,8 +0,0 @@
-import qbs 1.0
-import '../QtModule.qbs' as QtModule
-
-QtModule {
- qtModuleName: 'Designer'
- repository: Qt.core.versionMajor >= 5 ? 'qttools' : undefined
-}
-
diff --git a/share/qbs/modules/Qt/designercomponents/designercomponents.qbs b/share/qbs/modules/Qt/designercomponents/designercomponents.qbs
deleted file mode 100644
index b304e6efe..000000000
--- a/share/qbs/modules/Qt/designercomponents/designercomponents.qbs
+++ /dev/null
@@ -1,7 +0,0 @@
-import qbs 1.0
-import '../QtModule.qbs' as QtModule
-
-QtModule {
- qtModuleName: 'DesignerComponents'
-}
-
diff --git a/share/qbs/modules/Qt/enginio/enginio.qbs b/share/qbs/modules/Qt/enginio/enginio.qbs
deleted file mode 100644
index 350b0449f..000000000
--- a/share/qbs/modules/Qt/enginio/enginio.qbs
+++ /dev/null
@@ -1,12 +0,0 @@
-import qbs 1.0
-import "../QtModule.qbs" as QtModule
-import "../qtfunctions.js" as QtFunctions
-
-QtModule {
- qtModuleName: "Enginio"
- includeDirName: qtModuleName
- internalLibraryName: QtFunctions.getPlatformLibraryName(qtModuleName, Qt.core, qbs)
- repository: "enginio-qt"
- Depends { name: "Qt"; submodules: ["network", "gui"] }
-}
-
diff --git a/share/qbs/modules/Qt/help/help.qbs b/share/qbs/modules/Qt/help/help.qbs
deleted file mode 100644
index 595e9dd7e..000000000
--- a/share/qbs/modules/Qt/help/help.qbs
+++ /dev/null
@@ -1,8 +0,0 @@
-import qbs 1.0
-import '../QtModule.qbs' as QtModule
-
-QtModule {
- qtModuleName: 'Help'
- repository: Qt.core.versionMajor === 5 ? 'qttools' : undefined
-}
-
diff --git a/share/qbs/modules/Qt/multimedia/multimedia.qbs b/share/qbs/modules/Qt/multimedia/multimedia.qbs
deleted file mode 100644
index e2e75a62e..000000000
--- a/share/qbs/modules/Qt/multimedia/multimedia.qbs
+++ /dev/null
@@ -1,8 +0,0 @@
-import qbs 1.0
-import '../QtModule.qbs' as QtModule
-
-QtModule {
- qtModuleName: 'Multimedia'
- repository: Qt.core.versionMajor === 5 ? 'qtmultimedia' : undefined
-}
-
diff --git a/share/qbs/modules/Qt/multimediawidgets/multimediawidgets.qbs b/share/qbs/modules/Qt/multimediawidgets/multimediawidgets.qbs
deleted file mode 100644
index 583d1ace7..000000000
--- a/share/qbs/modules/Qt/multimediawidgets/multimediawidgets.qbs
+++ /dev/null
@@ -1,8 +0,0 @@
-import qbs 1.0
-import '../QtModule.qbs' as QtModule
-
-QtModule {
- qtModuleName: 'MultimediaWidgets'
- repository: Qt.core.versionMajor === 5 ? 'qtmultimedia' : undefined
-}
-
diff --git a/share/qbs/modules/Qt/network/network.qbs b/share/qbs/modules/Qt/network/network.qbs
deleted file mode 100644
index 3d7682322..000000000
--- a/share/qbs/modules/Qt/network/network.qbs
+++ /dev/null
@@ -1,7 +0,0 @@
-import qbs 1.0
-import '../QtModule.qbs' as QtModule
-
-QtModule {
- qtModuleName: 'Network'
-}
-
diff --git a/share/qbs/modules/Qt/opengl/opengl.qbs b/share/qbs/modules/Qt/opengl/opengl.qbs
deleted file mode 100644
index e7934802e..000000000
--- a/share/qbs/modules/Qt/opengl/opengl.qbs
+++ /dev/null
@@ -1,12 +0,0 @@
-import qbs 1.0
-import '../QtModule.qbs' as QtModule
-
-QtModule {
- qtModuleName: 'OpenGL'
- Properties {
- condition: Qt.core.staticBuild && qbs.targetOS.contains("ios")
- cpp.frameworks: base.concat(["OpenGLES", "QuartzCore", "CoreGraphics"])
- }
- cpp.frameworks: base
-}
-
diff --git a/share/qbs/modules/Qt/phonon/phonon.qbs b/share/qbs/modules/Qt/phonon/phonon.qbs
deleted file mode 100644
index d55355530..000000000
--- a/share/qbs/modules/Qt/phonon/phonon.qbs
+++ /dev/null
@@ -1,8 +0,0 @@
-import qbs 1.0
-import '../QtModule.qbs' as QtModule
-
-QtModule {
- qtModuleName: "Phonon"
- internalQtModuleName: "Phonon"
-}
-
diff --git a/share/qbs/modules/Qt/printsupport/printsupport.qbs b/share/qbs/modules/Qt/printsupport/printsupport.qbs
deleted file mode 100644
index a2dc81b0c..000000000
--- a/share/qbs/modules/Qt/printsupport/printsupport.qbs
+++ /dev/null
@@ -1,6 +0,0 @@
-import qbs 1.0
-import '../QtModule.qbs' as QtModule
-
-QtModule {
- qtModuleName: Qt.core.versionMajor >= 5 ? 'PrintSupport' : undefined
-}
diff --git a/share/qbs/modules/Qt/qml/qml.qbs b/share/qbs/modules/Qt/qml/qml.qbs
deleted file mode 100644
index 8f6109084..000000000
--- a/share/qbs/modules/Qt/qml/qml.qbs
+++ /dev/null
@@ -1,13 +0,0 @@
-import qbs 1.0
-import '../QtModule.qbs' as QtModule
-
-QtModule {
- qtModuleName: "Qml"
- condition: Qt.core.versionMajor === 5
- Depends {
- name: "Qt"
- submodules: ["widgets", "script"]
- }
- repository: 'qtdeclarative'
-}
-
diff --git a/share/qbs/modules/Qt/quick/quick.qbs b/share/qbs/modules/Qt/quick/quick.qbs
deleted file mode 100644
index 60d09800b..000000000
--- a/share/qbs/modules/Qt/quick/quick.qbs
+++ /dev/null
@@ -1,15 +0,0 @@
-import qbs 1.0
-import '../QtModule.qbs' as QtModule
-
-QtModule {
- qtModuleName: "Quick"
- condition: Qt.core.versionMajor === 5
-
- property bool qmlDebugging: false
-
- Depends { name: "Qt.qml" }
- repository: "qtdeclarative"
-
- cpp.defines: qmlDebugging ? base.concat("QT_QML_DEBUG") : base
-}
-
diff --git a/share/qbs/modules/Qt/script/script.qbs b/share/qbs/modules/Qt/script/script.qbs
deleted file mode 100644
index 418f09b29..000000000
--- a/share/qbs/modules/Qt/script/script.qbs
+++ /dev/null
@@ -1,8 +0,0 @@
-import qbs 1.0
-import '../QtModule.qbs' as QtModule
-
-QtModule {
- qtModuleName: 'Script'
- repository: Qt.core.versionMajor === 5 ? 'qtscript' : undefined
-}
-
diff --git a/share/qbs/modules/Qt/sql/sql.qbs b/share/qbs/modules/Qt/sql/sql.qbs
deleted file mode 100644
index 23e76aace..000000000
--- a/share/qbs/modules/Qt/sql/sql.qbs
+++ /dev/null
@@ -1,7 +0,0 @@
-import qbs 1.0
-import '../QtModule.qbs' as QtModule
-
-QtModule {
- qtModuleName: 'Sql'
-}
-
diff --git a/share/qbs/modules/Qt/svg/svg.qbs b/share/qbs/modules/Qt/svg/svg.qbs
deleted file mode 100644
index 39ce3d161..000000000
--- a/share/qbs/modules/Qt/svg/svg.qbs
+++ /dev/null
@@ -1,8 +0,0 @@
-import qbs 1.0
-import '../QtModule.qbs' as QtModule
-
-QtModule {
- qtModuleName: 'Svg'
- repository: Qt.core.versionMajor === 5 ? 'qtsvg' : undefined
-}
-
diff --git a/share/qbs/modules/Qt/test/test.qbs b/share/qbs/modules/Qt/test/test.qbs
deleted file mode 100644
index 5bb1d50c7..000000000
--- a/share/qbs/modules/Qt/test/test.qbs
+++ /dev/null
@@ -1,7 +0,0 @@
-import qbs 1.0
-import '../QtModule.qbs' as QtModule
-
-QtModule {
- qtModuleName: 'Test'
-}
-
diff --git a/share/qbs/modules/Qt/webkit/webkit.qbs b/share/qbs/modules/Qt/webkit/webkit.qbs
deleted file mode 100644
index fc7299511..000000000
--- a/share/qbs/modules/Qt/webkit/webkit.qbs
+++ /dev/null
@@ -1,9 +0,0 @@
-import qbs 1.0
-import '../QtModule.qbs' as QtModule
-
-QtModule {
- Depends { name: "Qt.gui"; condition: Qt.core.versionMajor === 4}
- qtModuleName: 'WebKit'
- repository: Qt.core.versionMajor === 5 ? 'qtwebkit' : undefined
-}
-
diff --git a/share/qbs/modules/Qt/webkitwidgets/webkitwidgets.qbs b/share/qbs/modules/Qt/webkitwidgets/webkitwidgets.qbs
deleted file mode 100644
index 1e78203b8..000000000
--- a/share/qbs/modules/Qt/webkitwidgets/webkitwidgets.qbs
+++ /dev/null
@@ -1,10 +0,0 @@
-import qbs 1.0
-import '../QtModule.qbs' as QtModule
-
-QtModule {
- condition: Qt.core.versionMajor >= 5
- Depends { name: "Qt.webkit" }
- Depends { name: "Qt.gui" }
- qtModuleName: 'WebKitWidgets'
- repository: 'qtwebkit'
-}
diff --git a/share/qbs/modules/Qt/widgets/widgets.qbs b/share/qbs/modules/Qt/widgets/widgets.qbs
deleted file mode 100644
index 31865dc49..000000000
--- a/share/qbs/modules/Qt/widgets/widgets.qbs
+++ /dev/null
@@ -1,7 +0,0 @@
-import qbs 1.0
-import '../QtModule.qbs' as QtModule
-
-QtModule {
- Depends { name: "Qt.gui" }
- qtModuleName: Qt.core.versionMajor >= 5 ? 'Widgets' : undefined
-}
diff --git a/share/qbs/modules/Qt/xml/xml.qbs b/share/qbs/modules/Qt/xml/xml.qbs
deleted file mode 100644
index 02f30e25d..000000000
--- a/share/qbs/modules/Qt/xml/xml.qbs
+++ /dev/null
@@ -1,7 +0,0 @@
-import qbs 1.0
-import '../QtModule.qbs' as QtModule
-
-QtModule {
- qtModuleName: 'Xml'
-}
-
diff --git a/share/qbs/modules/Qt/xmlpatterns/xmlpatterns.qbs b/share/qbs/modules/Qt/xmlpatterns/xmlpatterns.qbs
deleted file mode 100644
index a09dd8656..000000000
--- a/share/qbs/modules/Qt/xmlpatterns/xmlpatterns.qbs
+++ /dev/null
@@ -1,7 +0,0 @@
-import qbs 1.0
-import '../QtModule.qbs' as QtModule
-
-QtModule {
- qtModuleName: 'XmlPatterns'
-}
-
diff --git a/src/app/qbs-setup-qt/setupqt.cpp b/src/app/qbs-setup-qt/setupqt.cpp
index 0d180ae5e..c04011e01 100644
--- a/src/app/qbs-setup-qt/setupqt.cpp
+++ b/src/app/qbs-setup-qt/setupqt.cpp
@@ -162,37 +162,45 @@ static Version extractVersion(const QString &versionString)
return v;
}
+typedef QMap<QByteArray, QByteArray> QueryMap;
+
+static QString pathQueryValue(const QueryMap &queryMap, const QByteArray &key)
+{
+ return QDir::fromNativeSeparators(QString::fromLocal8Bit(queryMap.value(key)));
+}
+
QtEnvironment SetupQt::fetchEnvironment(const QString &qmakePath)
{
QtEnvironment qtEnvironment;
- QMap<QByteArray, QByteArray> queryOutput = qmakeQueryOutput(qmakePath);
-
- qtEnvironment.installPrefixPath =
- QString::fromLocal8Bit(queryOutput.value("QT_INSTALL_PREFIX"));
- qtEnvironment.documentationPath = QString::fromLocal8Bit(queryOutput.value("QT_INSTALL_DOCS"));
- qtEnvironment.includePath = QString::fromLocal8Bit(queryOutput.value("QT_INSTALL_HEADERS"));
- qtEnvironment.libraryPath = QString::fromLocal8Bit(queryOutput.value("QT_INSTALL_LIBS"));
- qtEnvironment.binaryPath = QString::fromLocal8Bit(queryOutput.value("QT_INSTALL_BINS"));
- qtEnvironment.documentationPath = QString::fromLocal8Bit(queryOutput.value("QT_INSTALL_DOCS"));
- qtEnvironment.pluginPath = QString::fromLocal8Bit(queryOutput.value("QT_INSTALL_PLUGINS"));
- qtEnvironment.qmlImportPath = QString::fromLocal8Bit(queryOutput.value("QT_INSTALL_IMPORTS"));
+ QueryMap queryOutput = qmakeQueryOutput(qmakePath);
+
+ qtEnvironment.installPrefixPath = pathQueryValue(queryOutput, "QT_INSTALL_PREFIX");
+ qtEnvironment.documentationPath = pathQueryValue(queryOutput, "QT_INSTALL_DOCS");
+ qtEnvironment.includePath = pathQueryValue(queryOutput, "QT_INSTALL_HEADERS");
+ qtEnvironment.libraryPath = pathQueryValue(queryOutput, "QT_INSTALL_LIBS");
+ qtEnvironment.binaryPath = pathQueryValue(queryOutput, "QT_INSTALL_BINS");
+ qtEnvironment.documentationPath = pathQueryValue(queryOutput, "QT_INSTALL_DOCS");
+ qtEnvironment.pluginPath = pathQueryValue(queryOutput, "QT_INSTALL_PLUGINS");
+ qtEnvironment.qmlImportPath = pathQueryValue(queryOutput, "QT_INSTALL_IMPORTS");
qtEnvironment.qtVersion = QString::fromLocal8Bit(queryOutput.value("QT_VERSION"));
const Version qtVersion = extractVersion(qtEnvironment.qtVersion);
- QByteArray mkspecsBasePath;
- QByteArray mkspecsBaseSrcPath;
+ QString mkspecsBaseSrcPath;
if (qtVersion.majorVersion >= 5) {
- mkspecsBasePath = queryOutput.value("QT_HOST_DATA") + "/mkspecs";
- mkspecsBaseSrcPath = queryOutput.value("QT_HOST_DATA/src") + "/mkspecs";
+ qtEnvironment.mkspecBasePath
+ = pathQueryValue(queryOutput, "QT_HOST_DATA") + QLatin1String("/mkspecs");
+ mkspecsBaseSrcPath
+ = pathQueryValue(queryOutput, "QT_HOST_DATA/src") + QLatin1String("/mkspecs");
} else {
- mkspecsBasePath = queryOutput.value("QT_INSTALL_DATA") + "/mkspecs";
+ qtEnvironment.mkspecBasePath
+ = pathQueryValue(queryOutput, "QT_INSTALL_DATA") + QLatin1String("/mkspecs");
}
- if (!QFile::exists(QString::fromLocal8Bit(mkspecsBasePath)))
+ if (!QFile::exists(qtEnvironment.mkspecBasePath))
throw ErrorInfo(tr("Cannot extract the mkspecs directory."));
- const QByteArray qconfigContent = readFileContent(QString::fromLocal8Bit(mkspecsBasePath)
+ const QByteArray qconfigContent = readFileContent(qtEnvironment.mkspecBasePath
+ QLatin1String("/qconfig.pri"));
qtEnvironment.qtMajorVersion = configVariable(qconfigContent,
QLatin1String("QT_MAJOR_VERSION")).toInt();
@@ -214,20 +222,18 @@ QtEnvironment SetupQt::fetchEnvironment(const QString &qmakePath)
if (qtVersion.majorVersion >= 5) {
const QString mkspecName = QString::fromLocal8Bit(queryOutput.value("QMAKE_XSPEC"));
qtEnvironment.mkspecName = mkspecName;
- qtEnvironment.mkspecPath = QString::fromLocal8Bit(mkspecsBasePath)
- + QLatin1Char('/') + mkspecName;
+ qtEnvironment.mkspecPath = qtEnvironment.mkspecBasePath + QLatin1Char('/') + mkspecName;
if (!mkspecsBaseSrcPath.isEmpty() && !QFile::exists(qtEnvironment.mkspecPath))
- qtEnvironment.mkspecPath = QString::fromLocal8Bit(mkspecsBaseSrcPath)
- + QLatin1Char('/') + mkspecName;
+ qtEnvironment.mkspecPath = mkspecsBaseSrcPath + QLatin1Char('/') + mkspecName;
} else {
if (HostOsInfo::isWindowsHost()) {
- const QByteArray fileContent = readFileContent(QString::fromLocal8Bit(mkspecsBasePath)
+ const QByteArray fileContent = readFileContent(qtEnvironment.mkspecBasePath
+ QLatin1String("/default/qmake.conf"));
qtEnvironment.mkspecPath = configVariable(fileContent,
QLatin1String("QMAKESPEC_ORIGINAL"));
} else {
- qtEnvironment.mkspecPath = QFileInfo(QString::fromLocal8Bit(mkspecsBasePath)
- + QLatin1String("/default")).symLinkTarget();
+ qtEnvironment.mkspecPath
+ = QFileInfo(qtEnvironment.mkspecBasePath + "/default").symLinkTarget();
}
qtEnvironment.mkspecName = qtEnvironment.mkspecPath;
int idx = qtEnvironment.mkspecName.lastIndexOf(QLatin1Char('/'));
@@ -286,7 +292,6 @@ QtEnvironment SetupQt::fetchEnvironment(const QString &qmakePath)
if (!QFileInfo(qtEnvironment.mkspecPath).exists())
throw ErrorInfo(tr("mkspec '%1' does not exist").arg(qtEnvironment.mkspecPath));
- qtEnvironment.mkspecPath = QDir::toNativeSeparators(qtEnvironment.mkspecPath);
return qtEnvironment;
}
diff --git a/src/lib/corelib/tools/settings.cpp b/src/lib/corelib/tools/settings.cpp
index f170930eb..50eb169fb 100644
--- a/src/lib/corelib/tools/settings.cpp
+++ b/src/lib/corelib/tools/settings.cpp
@@ -146,6 +146,11 @@ QStringList Settings::profiles() const
return result;
}
+QString Settings::fileName() const
+{
+ return m_settings->fileName();
+}
+
QString Settings::internalRepresentation(const QString &externalKey) const
{
QString internalKey = externalKey;
diff --git a/src/lib/corelib/tools/settings.h b/src/lib/corelib/tools/settings.h
index 2542df4fb..7d0102324 100644
--- a/src/lib/corelib/tools/settings.h
+++ b/src/lib/corelib/tools/settings.h
@@ -58,6 +58,8 @@ public:
QString defaultProfile() const;
QStringList profiles() const;
+ QString fileName() const;
+
private:
QString internalRepresentation(const QString &externalKey) const;
QString externalRepresentation(const QString &internalKey) const;
diff --git a/src/lib/qtprofilesetup/qtprofilesetup.cpp b/src/lib/qtprofilesetup/qtprofilesetup.cpp
index 0bc19d124..6bf191c36 100644
--- a/src/lib/qtprofilesetup/qtprofilesetup.cpp
+++ b/src/lib/qtprofilesetup/qtprofilesetup.cpp
@@ -31,16 +31,205 @@
#include <logging/translator.h>
#include <tools/error.h>
+#include <tools/fileinfo.h>
#include <tools/profile.h>
#include <tools/settings.h>
#include <QDir>
+#include <QDirIterator>
#include <QFile>
+#include <QFileInfo>
#include <QRegExp>
#include <QTextStream>
namespace qbs {
+struct QtModuleInfo
+{
+ QtModuleInfo(const QString &name, const QString &qbsName,
+ const QStringList &deps = QStringList(), bool hasLib = true)
+ : name(name), qbsName(qbsName), dependencies(deps), hasLibrary(hasLib)
+ {
+ const QString coreModule = QLatin1String("core");
+ if (qbsName != coreModule && !dependencies.contains(coreModule))
+ dependencies.prepend(coreModule);
+ }
+
+ QtModuleInfo() : hasLibrary(true) {}
+
+ QString name; // As in the path to the headers and ".name" in the pri files.
+ QString qbsName; // Lower-case version without "qt" prefix.
+ QStringList dependencies; // qbs names.
+ QStringList includePaths;
+ bool hasLibrary;
+};
+
+static void copyTemplateFile(const QString &fileName, const QString &targetDirectory,
+ const QString &profileName)
+{
+ if (!QDir::root().mkpath(targetDirectory)) {
+ throw ErrorInfo(Internal::Tr::tr("Setting up Qt profile '%1' failed: "
+ "Cannot create directory '%2'.")
+ .arg(profileName, targetDirectory));
+ }
+ QFile sourceFile(QLatin1String(":/templates/") + fileName);
+ const QString targetPath = targetDirectory + QLatin1Char('/') + fileName;
+ QFile::remove(targetPath); // QFile::copy() cannot overwrite.
+ if (!sourceFile.copy(targetPath)) {
+ throw ErrorInfo(Internal::Tr::tr("Setting up Qt profile '%1' failed: "
+ "Cannot copy file '%2' into directory '%3' (%4).")
+ .arg(profileName, fileName, targetDirectory, sourceFile.errorString()));
+ }
+ QFile targetFile(targetPath);
+ if (!targetFile.setPermissions(targetFile.permissions() | QFile::WriteUser)) {
+ throw ErrorInfo(Internal::Tr::tr("Setting up Qt profile '%1' failed: Cannot set write "
+ "permission on file '%2' (%3).")
+ .arg(profileName, targetPath, targetFile.errorString()));
+ }
+}
+
+static void replaceListPlaceholder(QByteArray &content, const QByteArray &placeHolder,
+ const QStringList &list)
+{
+ QByteArray listString;
+ foreach (const QString &elem, list)
+ listString += "'" + elem.toUtf8() + "', ";
+ content.replace(placeHolder, listString);
+}
+
+static void createModules(Profile &profile, Settings *settings,
+ const QtEnvironment &qtEnvironment)
+{
+ QList<QtModuleInfo> modules;
+ if (qtEnvironment.qtMajorVersion < 5) {
+ modules // as per http://qt-project.org/doc/qt-4.8/modules.html
+ << QtModuleInfo(QLatin1String("QtCore"), QLatin1String("core"))
+ << QtModuleInfo(QLatin1String("QtGui"), QLatin1String("gui"))
+ << QtModuleInfo(QLatin1String("QtMultimedia"), QLatin1String("multimedia"),
+ QStringList() << QLatin1String("gui") << QLatin1String("network"))
+ << QtModuleInfo(QLatin1String("QtNetwork"), QLatin1String("network"))
+ << QtModuleInfo(QLatin1String("QtOpenGL"), QLatin1String("opengl"),
+ QStringList() << QLatin1String("gui"))
+ << QtModuleInfo(QLatin1String("QtOpenVG"), QLatin1String("openvg"),
+ QStringList() << QLatin1String("gui"))
+ << QtModuleInfo(QLatin1String("QtScript"), QLatin1String("script"))
+ << QtModuleInfo(QLatin1String("QtScriptTools"), QLatin1String("scripttols"),
+ QStringList() << QLatin1String("script") << QLatin1String("gui"))
+ << QtModuleInfo(QLatin1String("QtSql"), QLatin1String("sql"))
+ << QtModuleInfo(QLatin1String("QtSvg"), QLatin1String("svg"),
+ QStringList() << QLatin1String("gui"))
+ << QtModuleInfo(QLatin1String("QtWebKit"), QLatin1String("webkit"),
+ QStringList() << QLatin1String("gui") << QLatin1String("network"))
+ << QtModuleInfo(QLatin1String("QtXml"), QLatin1String("xml"))
+ << QtModuleInfo(QLatin1String("QtXmlPatterns"), QLatin1String("xmlpatterns"),
+ QStringList() << "network")
+ << QtModuleInfo(QLatin1String("QtDeclarative"), QLatin1String("qtdeclarative"),
+ QStringList() << QLatin1String("gui") << QLatin1String("script"))
+ << QtModuleInfo(QLatin1String("Phonon"), QLatin1String("phonon"))
+ << QtModuleInfo(QLatin1String("QtDesigner"), QLatin1String("designer"),
+ QStringList() << QLatin1String("gui") << QLatin1String("xml"))
+ << QtModuleInfo(QLatin1String("QtUiTools"), QLatin1String("uitools"))
+ << QtModuleInfo(QLatin1String("QtHelp"), QLatin1String("help"),
+ QStringList() << QLatin1String("network") << QLatin1String("sql"))
+ << QtModuleInfo(QLatin1String("QtTest"), QLatin1String("testlib"))
+ << QtModuleInfo(QLatin1String("QAxContainer"), QLatin1String("axcontainer"))
+ << QtModuleInfo(QLatin1String("QAxServer"), QLatin1String("axserver"))
+ << QtModuleInfo(QLatin1String("QtDBus"), QLatin1String("dbus"));
+ } else {
+ QDirIterator dit(qtEnvironment.mkspecBasePath + QLatin1String("/modules"));
+ while (dit.hasNext()) {
+ const QString moduleFileNamePrefix = QLatin1String("qt_lib_");
+ const QString moduleFileNameSuffix = QLatin1String(".pri");
+ dit.next();
+ if (!dit.fileName().startsWith(moduleFileNamePrefix)
+ || !dit.fileName().endsWith(moduleFileNameSuffix)) {
+ continue;
+ }
+ QtModuleInfo moduleInfo;
+ moduleInfo.qbsName = dit.fileName().mid(moduleFileNamePrefix.count(),
+ dit.fileName().count() - moduleFileNamePrefix.count()
+ - moduleFileNameSuffix.count());
+ moduleInfo.qbsName.replace(QLatin1String("_private"), QLatin1String("-private"));
+ QFile priFile(dit.filePath());
+ if (!priFile.open(QIODevice::ReadOnly)) {
+ throw ErrorInfo(Internal::Tr::tr("Setting up Qt profile '%1' failed: Cannot open "
+ "file '%1' (%2).").arg(priFile.fileName(), priFile.errorString()));
+ }
+ const QByteArray priFileContents = priFile.readAll();
+ foreach (const QByteArray &line, priFileContents.split('\n')) {
+ const QByteArray simplifiedLine = line.simplified();
+ const QList<QByteArray> parts = simplifiedLine.split('=');
+ if (parts.count() != 2)
+ continue;
+ const QByteArray key = parts.first().simplified();
+ const QByteArray value = parts.last().simplified();
+ if (key.endsWith(".name")) {
+ moduleInfo.name = QString::fromLocal8Bit(value);
+ } else if (key.endsWith(".depends")) {
+ moduleInfo.dependencies = QString::fromLocal8Bit(value).split(QLatin1Char(' '));
+ for (int i = 0; i < moduleInfo.dependencies.count(); ++i) {
+ moduleInfo.dependencies[i].replace(QLatin1String("_private"),
+ QLatin1String("-private"));
+ }
+ } else if (key.endsWith(".module_config") && value.contains("no_link")) {
+ moduleInfo.hasLibrary = false;
+ } else if (key.endsWith(".includes")) {
+ moduleInfo.includePaths = QString::fromLocal8Bit(value).split(QLatin1Char(' '));
+ for (int i = 0; i < moduleInfo.includePaths.count(); ++i) {
+ moduleInfo.includePaths[i].replace(
+ QLatin1String("$$QT_MODULE_INCLUDE_BASE"),
+ qtEnvironment.includePath);
+ }
+ }
+ }
+ modules << moduleInfo;
+ }
+ }
+
+ const QString profileBaseDir = QString::fromLocal8Bit("%1/qbs/profiles/%2")
+ .arg(QFileInfo(settings->fileName()).dir().absolutePath(), profile.name());
+ const QString qbsQtModuleBaseDir = profileBaseDir + QLatin1String("/modules/Qt");
+ QString removeError;
+ if (!qbs::Internal::removeDirectoryWithContents(qbsQtModuleBaseDir, &removeError)) {
+ throw ErrorInfo(Internal::Tr::tr("Setting up Qt profile '%1' failed: Could not remove "
+ "the existing profile of the same name (%2).").arg(removeError));
+ }
+ copyTemplateFile(QLatin1String("QtModule.qbs"), qbsQtModuleBaseDir, profile.name());
+ copyTemplateFile(QLatin1String("qtfunctions.js"), qbsQtModuleBaseDir, profile.name());
+ copyTemplateFile(QLatin1String("utils.js"), qbsQtModuleBaseDir, profile.name());
+ foreach (const QtModuleInfo &module, modules) {
+ const QString qbsQtModuleDir = qbsQtModuleBaseDir + QLatin1Char('/') + module.qbsName;
+ if (module.qbsName == QLatin1String("core")) {
+ copyTemplateFile(QLatin1String("core.qbs"), qbsQtModuleDir, profile.name());
+ copyTemplateFile(QLatin1String("moc.js"), qbsQtModuleDir, profile.name());
+ } else if (module.qbsName == QLatin1String("gui")) {
+ copyTemplateFile(QLatin1String("gui.qbs"), qbsQtModuleDir, profile.name());
+ } else {
+ copyTemplateFile(QLatin1String("module.qbs"), qbsQtModuleDir, profile.name());
+ QFile moduleFile(qbsQtModuleDir + QLatin1String("/module.qbs"));
+ if (!moduleFile.open(QIODevice::ReadWrite)) {
+ throw ErrorInfo(Internal::Tr::tr("Setting up Qt profile '%1' failed: Cannot adapt "
+ "module file '%2' (%3).")
+ .arg(profile.name(), moduleFile.fileName(), moduleFile.errorString()));
+ }
+ QByteArray content = moduleFile.readAll();
+ content.replace("### name", '"' + module.name.mid(2).toUtf8() + '"'); // Strip off "Qt".
+ content.replace("### has library", module.hasLibrary ? "true" : "false");
+ replaceListPlaceholder(content, "### dependencies", module.dependencies);
+ replaceListPlaceholder(content, "### includes", module.includePaths);
+ QByteArray propertiesString;
+ if (module.qbsName == QLatin1String("declarative")
+ || module.qbsName == QLatin1String("quick")) {
+ propertiesString = "property bool qmlDebugging: false";
+ }
+ content.replace("### special properties", propertiesString);
+ moduleFile.resize(0);
+ moduleFile.write(content);
+ }
+ }
+ profile.setValue(QLatin1String("preferences.qbsSearchPaths"), profileBaseDir);
+}
+
static QString guessMinimumWindowsVersion(const QtEnvironment &qt)
{
if (qt.mkspecName.startsWith("winrt-"))
@@ -156,6 +345,11 @@ ErrorInfo setupQtProfile(const QString &profileName, Settings *settings,
if (!androidVersion.isEmpty())
profile.setValue(QLatin1String("cpp.minimumAndroidVersion"), androidVersion);
+ try {
+ createModules(profile, settings, qtEnvironment);
+ } catch (const ErrorInfo &e) {
+ return e;
+ }
return ErrorInfo();
}
diff --git a/src/lib/qtprofilesetup/qtprofilesetup.h b/src/lib/qtprofilesetup/qtprofilesetup.h
index 8d2e04568..df0c1fb1c 100644
--- a/src/lib/qtprofilesetup/qtprofilesetup.h
+++ b/src/lib/qtprofilesetup/qtprofilesetup.h
@@ -51,6 +51,7 @@ public:
QString qtNameSpace;
QString mkspecPath;
QString mkspecName;
+ QString mkspecBasePath;
QStringList buildVariant;
QStringList configItems;
QStringList qtConfigItems;
diff --git a/src/lib/qtprofilesetup/qtprofilesetup.pro b/src/lib/qtprofilesetup/qtprofilesetup.pro
index cedb66e2a..0856d1ed5 100644
--- a/src/lib/qtprofilesetup/qtprofilesetup.pro
+++ b/src/lib/qtprofilesetup/qtprofilesetup.pro
@@ -4,6 +4,7 @@ include(../corelib/use_corelib.pri)
HEADERS = qtprofilesetup.h
SOURCES = qtprofilesetup.cpp
+RESOURCES = templates.qrc
!qbs_no_dev_install {
header.files = qtprofilesetup.h
diff --git a/src/lib/qtprofilesetup/qtprofilesetup.qbs b/src/lib/qtprofilesetup/qtprofilesetup.qbs
index 59d2595c3..00b3fe10e 100644
--- a/src/lib/qtprofilesetup/qtprofilesetup.qbs
+++ b/src/lib/qtprofilesetup/qtprofilesetup.qbs
@@ -15,7 +15,10 @@ QbsLibrary {
qbs.installDir: headerInstallPrefix
}
- files: "qtprofilesetup.cpp"
+ files: [
+ "qtprofilesetup.cpp",
+ "templates.qrc"
+ ]
Export {
Depends { name: "qbscore" }
diff --git a/src/lib/qtprofilesetup/templates.qrc b/src/lib/qtprofilesetup/templates.qrc
new file mode 100644
index 000000000..7cb420320
--- /dev/null
+++ b/src/lib/qtprofilesetup/templates.qrc
@@ -0,0 +1,11 @@
+<RCC>
+ <qresource prefix="/">
+ <file>templates/core.qbs</file>
+ <file>templates/gui.qbs</file>
+ <file>templates/module.qbs</file>
+ <file>templates/QtModule.qbs</file>
+ <file>templates/moc.js</file>
+ <file>templates/qtfunctions.js</file>
+ <file>templates/utils.js</file>
+ </qresource>
+</RCC>
diff --git a/share/qbs/modules/Qt/QtModule.qbs b/src/lib/qtprofilesetup/templates/QtModule.qbs
index 2b38e92de..4694dbcb1 100644
--- a/share/qbs/modules/Qt/QtModule.qbs
+++ b/src/lib/qtprofilesetup/templates/QtModule.qbs
@@ -15,6 +15,7 @@ Module {
property string includeDirName: 'Qt' + qtModuleName
property string internalLibraryName: QtFunctions.getQtLibraryName(qtModuleName + qtLibInfix, Qt.core, qbs)
property string qtVersion: Qt.core.version
+ property bool hasLibrary: true
Properties {
condition: qtModuleName != undefined
@@ -29,8 +30,10 @@ Module {
return paths;
}
- cpp.dynamicLibraries: Qt.core.frameworkBuild ? undefined : [internalLibraryName]
- cpp.frameworks: Qt.core.frameworkBuild ? [internalLibraryName] : undefined
- cpp.defines: [ "QT_" + qtModuleName.toUpperCase() + "_LIB" ]
+ cpp.dynamicLibraries: Qt.core.frameworkBuild || !hasLibrary
+ ? undefined : [internalLibraryName]
+ cpp.frameworks: Qt.core.frameworkBuild && hasLibrary ? [internalLibraryName] : undefined
+ cpp.defines: qtModuleName.contains("private")
+ ? [] : [ "QT_" + qtModuleName.toUpperCase() + "_LIB" ]
}
}
diff --git a/share/qbs/modules/Qt/core/core.qbs b/src/lib/qtprofilesetup/templates/core.qbs
index c940a1bfe..33c2ba856 100644
--- a/share/qbs/modules/Qt/core/core.qbs
+++ b/src/lib/qtprofilesetup/templates/core.qbs
@@ -1,8 +1,8 @@
import qbs 1.0
import qbs.FileInfo
-import '../../utils.js' as ModUtils
import "moc.js" as Moc
import '../qtfunctions.js' as QtFunctions
+import '../utils.js' as ModUtils
Module {
id: qtcore
diff --git a/share/qbs/modules/Qt/gui/gui.qbs b/src/lib/qtprofilesetup/templates/gui.qbs
index a87d59cdc..24b8f4b59 100644
--- a/share/qbs/modules/Qt/gui/gui.qbs
+++ b/src/lib/qtprofilesetup/templates/gui.qbs
@@ -1,7 +1,7 @@
import qbs 1.0
import qbs.FileInfo
import '../QtModule.qbs' as QtModule
-import '../../utils.js' as ModUtils
+import '../utils.js' as ModUtils
QtModule {
qtModuleName: "Gui"
diff --git a/src/lib/qtprofilesetup/templates/moc.js b/src/lib/qtprofilesetup/templates/moc.js
new file mode 100644
index 000000000..e2f278491
--- /dev/null
+++ b/src/lib/qtprofilesetup/templates/moc.js
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+function args(product, input, outputFileName)
+{
+ var defines = ModUtils.modulePropertiesFromArtifacts(product, [input], 'cpp', 'compilerDefines');
+ defines = defines.concat(ModUtils.modulePropertiesFromArtifacts(product, [input], 'cpp', 'platformDefines'));
+ defines = defines.concat(ModUtils.modulePropertiesFromArtifacts(product, [input], 'cpp', 'defines'));
+ var includePaths = ModUtils.modulePropertiesFromArtifacts(product, [input], 'cpp', 'includePaths');
+ var args = [];
+ args = args.concat(
+ defines.map(function(item) { return '-D' + item; }),
+ includePaths.map(function(item) { return '-I' + item; }),
+ '-o', outputFileName,
+ input.fileName);
+ return args;
+}
+
+function fullPath(product)
+{
+ return ModUtils.moduleProperty(product, "binPath") + '/' + ModUtils.moduleProperty(product, "mocName");
+}
diff --git a/src/lib/qtprofilesetup/templates/module.qbs b/src/lib/qtprofilesetup/templates/module.qbs
new file mode 100644
index 000000000..0d6b87c2b
--- /dev/null
+++ b/src/lib/qtprofilesetup/templates/module.qbs
@@ -0,0 +1,10 @@
+import qbs 1.0
+import '../QtModule.qbs' as QtModule
+
+QtModule {
+ qtModuleName: ### name
+ Depends { name: "Qt"; submodules: [### dependencies] }
+ hasLibrary: ### has library
+ cpp.includePaths: base.concat([### includes])
+ ### special properties
+}
diff --git a/share/qbs/modules/Qt/qtfunctions.js b/src/lib/qtprofilesetup/templates/qtfunctions.js
index f50f847b4..f50f847b4 100644
--- a/share/qbs/modules/Qt/qtfunctions.js
+++ b/src/lib/qtprofilesetup/templates/qtfunctions.js
diff --git a/src/lib/qtprofilesetup/templates/utils.js b/src/lib/qtprofilesetup/templates/utils.js
new file mode 100644
index 000000000..66f7c30bf
--- /dev/null
+++ b/src/lib/qtprofilesetup/templates/utils.js
@@ -0,0 +1,214 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+//
+// utility functions for modules
+//
+
+/*!
+ * Given a list of file tags, returns the file tag (one of [c, cpp, objc, objcpp])
+ * corresponding to the C-family language the file should be compiled as.
+ *
+ * If no such tag is found, undefined is returned. If more than one match is
+ * found, an exception is thrown.
+ */
+function fileTagForTargetLanguage(fileTags)
+{
+ var srcTags = ["c", "cpp", "objc", "objcpp", "asm", "asm_cpp"];
+ var pchTags = ["c_pch", "cpp_pch", "objc_pch", "objcpp_pch"];
+
+ var canonicalTag = undefined;
+ var foundTagCount = 0;
+ for (var i = 0; i < fileTags.length; ++i) {
+ var idx = srcTags.indexOf(fileTags[i]);
+ if (idx === -1)
+ idx = pchTags.indexOf(fileTags[i]);
+
+ if (idx !== -1) {
+ canonicalTag = srcTags[idx];
+ if (++foundTagCount > 1)
+ break;
+ }
+ }
+
+ if (foundTagCount > 1)
+ throw ("source files cannot be identified as more than one language");
+
+ return foundTagCount == 1 ? canonicalTag : undefined;
+}
+
+/*
+ * Returns the name of a language-specific property given the file tag
+ * for that property, and the base property name.
+ *
+ * If \a fileTag is undefined, the language-agnostic property name is returned.
+ *
+ * \param propertyName flags, platformFlags, precompiledHeader
+ * \param fileTag c, cpp, objc, objcpp
+ */
+function languagePropertyName(propertyName, fileTag)
+{
+ if (!fileTag)
+ fileTag = 'common';
+
+ var map = {
+ 'c': {
+ 'flags': 'cFlags',
+ 'platformFlags': 'platformCFlags',
+ 'precompiledHeader': 'cPrecompiledHeader'
+ },
+ 'cpp': {
+ 'flags': 'cxxFlags',
+ 'platformFlags': 'platformCxxFlags',
+ 'precompiledHeader': 'cxxPrecompiledHeader'
+ },
+ 'objc': {
+ 'flags': 'objcFlags',
+ 'platformFlags': 'platformObjcFlags',
+ 'precompiledHeader': 'objcPrecompiledHeader'
+ },
+ 'objcpp': {
+ 'flags': 'objcxxFlags',
+ 'platformFlags': 'platformObjcxxFlags',
+ 'precompiledHeader': 'objcxxPrecompiledHeader'
+ },
+ 'common': {
+ 'flags': 'commonCompilerFlags',
+ 'platformFlags': 'platformCommonCompilerFlags',
+ 'precompiledHeader': 'precompiledHeader'
+ }
+ };
+
+ var lang = map[fileTag];
+ if (!lang)
+ return propertyName;
+
+ return lang[propertyName] || propertyName;
+}
+
+function moduleProperties(config, key, langFilter)
+{
+ return config.moduleProperties(config.moduleName, languagePropertyName(key, langFilter))
+}
+
+function modulePropertiesFromArtifacts(product, artifacts, moduleName, propertyName, langFilter)
+{
+ var result = product.moduleProperties(moduleName, languagePropertyName(propertyName, langFilter))
+ for (var i in artifacts)
+ result = result.concat(artifacts[i].moduleProperties(moduleName, languagePropertyName(propertyName, langFilter)))
+ return result
+}
+
+function moduleProperty(product, propertyName, langFilter)
+{
+ return product.moduleProperty(product.moduleName, languagePropertyName(propertyName, langFilter))
+}
+
+function dumpProperty(key, value, level)
+{
+ var indent = ''
+ for (var k=0; k < level; ++k)
+ indent += ' '
+ print(indent + key + ': ' + value)
+}
+
+function traverseObject(obj, func, level)
+{
+ if (!level)
+ level = 0
+ var i, children = {}
+ for (i in obj) {
+ if (typeof(obj[i]) === "object" && !(obj[i] instanceof Array))
+ children[i] = obj[i]
+ else
+ func.apply(this, [i, obj[i], level])
+ }
+ level++
+ for (i in children) {
+ func.apply(this, [i, children[i], level - 1])
+ traverseObject(children[i], func, level)
+ }
+ level--
+}
+
+function dumpObject(obj, description)
+{
+ if (!description)
+ description = 'object dump'
+ print('+++++++++ ' + description + ' +++++++++')
+ traverseObject(obj, dumpProperty)
+}
+
+function uniqueConcat(array1, array2)
+{
+ var result = array1;
+ for (i in array2) {
+ var elem = array2[i];
+ if (result.indexOf(elem) === -1)
+ result.push(elem);
+ }
+ return result;
+}
+
+
+//////////////////////////////////////////////////////////
+// The EnvironmentVariable class
+//
+function EnvironmentVariable(name, separator, convertPathSeparators)
+{
+ if (!name)
+ throw "EnvironmentVariable c'tor needs a name as first argument."
+ this.name = name
+ this.value = getEnv(name).toString()
+ this.separator = separator || ''
+ this.convertPathSeparators = convertPathSeparators || false
+}
+
+EnvironmentVariable.prototype.prepend = function(v)
+{
+ if (this.value.length > 0 && this.value.charAt(0) !== this.separator)
+ this.value = this.separator + this.value
+ if (this.convertPathSeparators)
+ v = FileInfo.toWindowsSeparators(v)
+ this.value = v + this.value
+}
+
+EnvironmentVariable.prototype.append = function(v)
+{
+ if (this.value.length > 0)
+ this.value += this.separator
+ if (this.convertPathSeparators)
+ v = FileInfo.toWindowsSeparators(v)
+ this.value += v
+}
+
+EnvironmentVariable.prototype.set = function()
+{
+ putEnv(this.name, this.value)
+}
+
diff --git a/tests/auto/api/tst_api.cpp b/tests/auto/api/tst_api.cpp
index dbe5237a8..c2b43980e 100644
--- a/tests/auto/api/tst_api.cpp
+++ b/tests/auto/api/tst_api.cpp
@@ -475,10 +475,12 @@ qbs::SetupProjectParameters TestApi::defaultSetupParameters() const
const QString qbsRootPath = QDir::cleanPath(QCoreApplication::applicationDirPath()
+ QLatin1String("/../"));
SettingsPtr settings = qbsSettings();
- setupParams.setSearchPaths(qbs::Preferences(settings.data()).searchPaths(qbsRootPath));
- setupParams.setPluginPaths(qbs::Preferences(settings.data()).pluginPaths(qbsRootPath));
+ const QString profileName = QLatin1String("qbs_autotests");
+ const qbs::Preferences prefs(settings.data(), profileName);
+ setupParams.setSearchPaths(prefs.searchPaths(qbsRootPath));
+ setupParams.setPluginPaths(prefs.pluginPaths(qbsRootPath));
QVariantMap buildConfig;
- buildConfig.insert(QLatin1String("qbs.profile"), QLatin1String("qbs_autotests"));
+ buildConfig.insert(QLatin1String("qbs.profile"), profileName);
buildConfig.insert(QLatin1String("qbs.buildVariant"), QLatin1String("debug"));
setupParams.setBuildConfiguration(buildConfig);
setupParams.expandBuildConfiguration(settings.data());