diff options
Diffstat (limited to 'share/qbs')
33 files changed, 1757 insertions, 0 deletions
diff --git a/share/qbs/imports/qbs/base/Application.qbs b/share/qbs/imports/qbs/base/Application.qbs new file mode 100644 index 000000000..5865e6a99 --- /dev/null +++ b/share/qbs/imports/qbs/base/Application.qbs @@ -0,0 +1,3 @@ +Product { + type: qbs.targetOS == 'mac' ? "applicationbundle" : "application" +} diff --git a/share/qbs/imports/qbs/base/DynamicLibrary.qbs b/share/qbs/imports/qbs/base/DynamicLibrary.qbs new file mode 100644 index 000000000..bf71dc8d5 --- /dev/null +++ b/share/qbs/imports/qbs/base/DynamicLibrary.qbs @@ -0,0 +1,3 @@ +Product { + type: "dynamiclibrary" +} diff --git a/share/qbs/imports/qbs/base/QmlApp.qbs b/share/qbs/imports/qbs/base/QmlApp.qbs new file mode 100644 index 000000000..2d1ce228c --- /dev/null +++ b/share/qbs/imports/qbs/base/QmlApp.qbs @@ -0,0 +1,22 @@ +import qbs.base 1.0 + +Product { + type: ["application", "installed_content"] + Depends { name: "qt.declarative" } + Depends { name: "cpp" } + property string appViewerPath: localPath + "/qmlapplicationviewer" + cpp.includePaths: [appViewerPath] + + Group { + files: [ + appViewerPath + "/qmlapplicationviewer.h", + appViewerPath + "/qmlapplicationviewer.cpp" + ] + } + + FileTagger { + pattern: "*.qml" + fileTags: ["install"] + } +} + diff --git a/share/qbs/imports/qbs/base/StaticLibrary.qbs b/share/qbs/imports/qbs/base/StaticLibrary.qbs new file mode 100644 index 000000000..da0416bee --- /dev/null +++ b/share/qbs/imports/qbs/base/StaticLibrary.qbs @@ -0,0 +1,3 @@ +Product { + type: "staticlibrary" +} diff --git a/share/qbs/imports/qbs/base/qmlapplicationviewer/qmlapplicationviewer.cpp b/share/qbs/imports/qbs/base/qmlapplicationviewer/qmlapplicationviewer.cpp new file mode 100644 index 000000000..997bbfcc7 --- /dev/null +++ b/share/qbs/imports/qbs/base/qmlapplicationviewer/qmlapplicationviewer.cpp @@ -0,0 +1,174 @@ +// checksum 0xee24 version 0x70013 +/* + This file was generated by the Qt Quick Application wizard of Qt Creator. + QmlApplicationViewer is a convenience class containing mobile device specific + code such as screen orientation handling. Also QML paths and debugging are + handled here. + It is recommended not to modify this file, since newer versions of Qt Creator + may offer an updated version of it. +*/ + +#include "qmlapplicationviewer.h" + +#include <QtCore/QDir> +#include <QtCore/QFileInfo> +#include <QtGui/QApplication> +#include <QtDeclarative/QDeclarativeComponent> +#include <QtDeclarative/QDeclarativeEngine> +#include <QtDeclarative/QDeclarativeContext> + +#include <qplatformdefs.h> // MEEGO_EDITION_HARMATTAN + +#ifdef HARMATTAN_BOOSTER +#include <MDeclarativeCache> +#endif + +#if defined(QMLJSDEBUGGER) && QT_VERSION < 0x040800 + +#include <qt_private/qdeclarativedebughelper_p.h> + +#if !defined(NO_JSDEBUGGER) +#include <jsdebuggeragent.h> +#endif +#if !defined(NO_QMLOBSERVER) +#include <qdeclarativeviewobserver.h> +#endif + +// Enable debugging before any QDeclarativeEngine is created +struct QmlJsDebuggingEnabler +{ + QmlJsDebuggingEnabler() + { + QDeclarativeDebugHelper::enableDebugging(); + } +}; + +// Execute code in constructor before first QDeclarativeEngine is instantiated +static QmlJsDebuggingEnabler enableDebuggingHelper; + +#endif // QMLJSDEBUGGER + +class QmlApplicationViewerPrivate +{ + QString mainQmlFile; + friend class QmlApplicationViewer; + static QString adjustPath(const QString &path); +}; + +QString QmlApplicationViewerPrivate::adjustPath(const QString &path) +{ +#ifdef Q_OS_UNIX +#ifdef Q_OS_MAC + if (!QDir::isAbsolutePath(path)) + return QString::fromLatin1("%1/../Resources/%2") + .arg(QCoreApplication::applicationDirPath(), path); +#else + const QString pathInInstallDir = + QString::fromLatin1("%1/../%2").arg(QCoreApplication::applicationDirPath(), path); + if (QFileInfo(pathInInstallDir).exists()) + return pathInInstallDir; +#endif +#endif + return path; +} + +QmlApplicationViewer::QmlApplicationViewer(QWidget *parent) + : QDeclarativeView(parent) + , d(new QmlApplicationViewerPrivate()) +{ + connect(engine(), SIGNAL(quit()), SLOT(close())); + setResizeMode(QDeclarativeView::SizeRootObjectToView); + // Qt versions prior to 4.8.0 don't have QML/JS debugging services built in +#if defined(QMLJSDEBUGGER) && QT_VERSION < 0x040800 +#if !defined(NO_JSDEBUGGER) + new QmlJSDebugger::JSDebuggerAgent(engine()); +#endif +#if !defined(NO_QMLOBSERVER) + new QmlJSDebugger::QDeclarativeViewObserver(this, this); +#endif +#endif +} + +QmlApplicationViewer::~QmlApplicationViewer() +{ + delete d; +} + +QmlApplicationViewer *QmlApplicationViewer::create() +{ + return new QmlApplicationViewer(); +} + +void QmlApplicationViewer::setMainQmlFile(const QString &file) +{ + d->mainQmlFile = QmlApplicationViewerPrivate::adjustPath(file); + setSource(QUrl::fromLocalFile(d->mainQmlFile)); +} + +void QmlApplicationViewer::addImportPath(const QString &path) +{ + engine()->addImportPath(QmlApplicationViewerPrivate::adjustPath(path)); +} + +void QmlApplicationViewer::setOrientation(ScreenOrientation orientation) +{ +#if defined(Q_OS_SYMBIAN) + // If the version of Qt on the device is < 4.7.2, that attribute won't work + if (orientation != ScreenOrientationAuto) { + const QStringList v = QString::fromAscii(qVersion()).split(QLatin1Char('.')); + if (v.count() == 3 && (v.at(0).toInt() << 16 | v.at(1).toInt() << 8 | v.at(2).toInt()) < 0x040702) { + qWarning("Screen orientation locking only supported with Qt 4.7.2 and above"); + return; + } + } +#endif // Q_OS_SYMBIAN + + Qt::WidgetAttribute attribute; + switch (orientation) { +#if QT_VERSION < 0x040702 + // Qt < 4.7.2 does not yet have the Qt::WA_*Orientation attributes + case ScreenOrientationLockPortrait: + attribute = static_cast<Qt::WidgetAttribute>(128); + break; + case ScreenOrientationLockLandscape: + attribute = static_cast<Qt::WidgetAttribute>(129); + break; + default: + case ScreenOrientationAuto: + attribute = static_cast<Qt::WidgetAttribute>(130); + break; +#else // QT_VERSION < 0x040702 + case ScreenOrientationLockPortrait: + attribute = Qt::WA_LockPortraitOrientation; + break; + case ScreenOrientationLockLandscape: + attribute = Qt::WA_LockLandscapeOrientation; + break; + default: + case ScreenOrientationAuto: + attribute = Qt::WA_AutoOrientation; + break; +#endif // QT_VERSION < 0x040702 + }; + setAttribute(attribute, true); +} + +void QmlApplicationViewer::showExpanded() +{ +#if defined(Q_OS_SYMBIAN) || defined(MEEGO_EDITION_HARMATTAN) || defined(Q_WS_SIMULATOR) + showFullScreen(); +#elif defined(Q_WS_MAEMO_5) + showMaximized(); +#else + show(); +#endif +} + +QApplication *createApplication(int &argc, char **argv) +{ +#ifdef HARMATTAN_BOOSTER + return MDeclarativeCache::qApplication(argc, argv); +#else + return new QApplication(argc, argv); +#endif +} diff --git a/share/qbs/imports/qbs/base/qmlapplicationviewer/qmlapplicationviewer.h b/share/qbs/imports/qbs/base/qmlapplicationviewer/qmlapplicationviewer.h new file mode 100644 index 000000000..b01cc886f --- /dev/null +++ b/share/qbs/imports/qbs/base/qmlapplicationviewer/qmlapplicationviewer.h @@ -0,0 +1,46 @@ +// checksum 0x898f version 0x70013 +/* + This file was generated by the Qt Quick Application wizard of Qt Creator. + QmlApplicationViewer is a convenience class containing mobile device specific + code such as screen orientation handling. Also QML paths and debugging are + handled here. + It is recommended not to modify this file, since newer versions of Qt Creator + may offer an updated version of it. +*/ + +#ifndef QMLAPPLICATIONVIEWER_H +#define QMLAPPLICATIONVIEWER_H + +#include <QtDeclarative/QDeclarativeView> + +class QmlApplicationViewer : public QDeclarativeView +{ + Q_OBJECT + +public: + enum ScreenOrientation { + ScreenOrientationLockPortrait, + ScreenOrientationLockLandscape, + ScreenOrientationAuto + }; + + explicit QmlApplicationViewer(QWidget *parent = 0); + virtual ~QmlApplicationViewer(); + + static QmlApplicationViewer *create(); + + void setMainQmlFile(const QString &file); + void addImportPath(const QString &path); + + // Note that this will only have an effect on Symbian and Fremantle. + void setOrientation(ScreenOrientation orientation); + + void showExpanded(); + +private: + class QmlApplicationViewerPrivate *d; +}; + +QApplication *createApplication(int &argc, char **argv); + +#endif // QMLAPPLICATIONVIEWER_H diff --git a/share/qbs/imports/qbs/fileinfo/fileinfo.js b/share/qbs/imports/qbs/fileinfo/fileinfo.js new file mode 100644 index 000000000..b65e4073c --- /dev/null +++ b/share/qbs/imports/qbs/fileinfo/fileinfo.js @@ -0,0 +1,62 @@ +function path(fp) { + if (fp[fp.length -1] == '/') + return fp; + var last = fp.lastIndexOf('/'); + if (last < 0) + return '.'; + return fp.slice(0, last); +} + +function fileName(fph) { + var fp = fph.toString(); + if (fp[fp.length -1] == '/') + return fp; + var last = fp.lastIndexOf('/'); + if (last < 0) + return '.'; + return fp.slice(last + 1); +} + +function baseName(fph) { + var fn = fileName(fph); + return fn.split('.')[0]; +} + +function relativePath(base, rel) +{ + var basel = base.split('/'); + var rell = rel.split('/'); + var i = 0; + + while (i < basel.length && i < rell.length && basel[i] == rell[i]) + i++; + + var j = i; + var r = []; + + for (; i < basel.length; i++) + r.push('..'); + + for (; j < rell.length; j++) + r.push(rell[j]); + + return r.join('/'); +} + +function isAbsolutePath(path) +{ + if (!path) + return false; + return (path.charAt(0) == '/'); +} + +function toWindowsSeparators(str) +{ + return str.toString().replace(/\//g, '\\'); +} + +function fromWindowsSeparators(str) +{ + return str.toString().replace(/\\/g, '/'); +} + diff --git a/share/qbs/modules/cpp/CppModule.qbs b/share/qbs/modules/cpp/CppModule.qbs new file mode 100644 index 000000000..f4204dad1 --- /dev/null +++ b/share/qbs/modules/cpp/CppModule.qbs @@ -0,0 +1,75 @@ +// base for Cpp modules + +Module { + condition: false + additionalProductFileTags: ["hpp"] // to include all rules that generate hpp files + + property string warningLevel : 'all' // 'none', 'all' + property bool treatWarningsAsErrors : false + property string architecture: qbs.architecture + property string optimization: qbs.optimization + property bool debugInformation: qbs.debugInformation + property string precompiledHeader + property paths precompiledHeaderDir: [product.buildDirectory] + property var defines + property paths includePaths + property paths libraryPaths + property paths frameworkPaths + property var compilerFlags + property string compilerPath + // ### same separation in msvc? + property var dynamicLibraries // list of names, will be linked with -lname + property var staticLibraries // list of static library files + property var frameworks // list of frameworks, will be linked with '-framework <name>' + property var rpaths + + FileTagger { + pattern: "*.c" + fileTags: ["c"] + } + + FileTagger { + pattern: "*.C" + fileTags: ["c"] + } + + FileTagger { + pattern: "*.cpp" + fileTags: ["cpp"] + } + + FileTagger { + pattern: "*.cxx" + fileTags: ["cpp"] + } + + FileTagger { + pattern: "*.c++" + fileTags: ["cpp"] + } + + FileTagger { + pattern: "*.h" + fileTags: ["hpp"] + } + + FileTagger { + pattern: "*.H" + fileTags: ["hpp"] + } + + FileTagger { + pattern: "*.hpp" + fileTags: ["hpp"] + } + + FileTagger { + pattern: "*.hxx" + fileTags: ["hpp"] + } + + FileTagger { + pattern: "*.h++" + fileTags: ["hpp"] + } +} diff --git a/share/qbs/modules/cpp/GenericGCC.qbs b/share/qbs/modules/cpp/GenericGCC.qbs new file mode 100644 index 000000000..14ee2753f --- /dev/null +++ b/share/qbs/modules/cpp/GenericGCC.qbs @@ -0,0 +1,300 @@ +import qbs.base 1.0 +import qbs.fileinfo 1.0 as FileInfo +import 'gcc.js' as Gcc +import '../utils.js' as ModUtils + +CppModule { + condition: false + + property var transitiveSOs + property string toolchainPrefix + property string toolchainInstallPath + property string compilerName: 'g++' + + property string compilerPath: { + var path = '' + if (toolchainInstallPath) { + path += toolchainInstallPath + if (path.substr(-1) !== '/') + path += '/' + } + if (toolchainPrefix) + path += toolchainPrefix + path += compilerName + return path + } + + Rule { + id: dynamicLibraryLinker + multiplex: true + inputs: ["obj"] + usings: ['dynamiclibrary', 'staticlibrary'] + + Artifact { + fileName: product.destinationDirectory + "/lib" + product.name + ".so" + fileTags: ["dynamiclibrary"] + cpp.transitiveSOs: { + var result = [] + for (var i in inputs.dynamiclibrary) { + var lib = inputs.dynamiclibrary[i] + result.push(lib.fileName) + var impliedLibs = ModUtils.appendAll(lib, 'transitiveSOs') + result = result.concat(impliedLibs) + } + return result + } + } + + TransformProperties { + property var libraryPaths: ModUtils.appendAll(product, 'libraryPaths') + property var dynamicLibraries: ModUtils.appendAll(product, 'dynamicLibraries') + property var staticLibraries: ModUtils.appendAll(product, 'staticLibraries') + property var rpaths: ModUtils.appendAll(product, 'rpaths') + } + + prepare: { + var args = Gcc.configFlags(product); + if (product.modules.qbs.targetOS == 'linux') + args = args.concat([ + '-Wl,--hash-style=gnu', + '-Wl,--as-needed', + '-Wl,--allow-shlib-undefined', + '-Wl,--no-undefined', + '-Wl,-soname=' + FileInfo.fileName(output.fileName) + ]); + args = args.concat([ + '-Wl,-rpath,\$ORIGIN', + '-shared' + ]); + for (var i in inputs.obj) + args.push(inputs.obj[i].fileName); + + var staticLibrariesI = []; + for (i in inputs.staticlibrary) { + staticLibrariesI.push(inputs.staticlibrary[i].fileName); + } + staticLibrariesI = staticLibrariesI.concat(staticLibraries); + + var dynamicLibrariesI = []; + for (i in inputs.dynamiclibrary) { + libraryPaths.push(FileInfo.path(inputs.dynamiclibrary[i].fileName)) + var fileName = FileInfo.fileName(inputs.dynamiclibrary[i].fileName) + fileName = fileName.substr(3, fileName.length - 6) + dynamicLibrariesI.push(fileName) + } + dynamicLibrariesI = dynamicLibrariesI.concat(dynamicLibraries); + + args.push('-o'); + args.push(output.fileName); + args = args.concat(Gcc.libs(libraryPaths, rpaths, dynamicLibrariesI, staticLibrariesI)); + var cmd = new Command(product.module.compilerPath, args); + Gcc.linkEnv(cmd) + cmd.description = 'linking ' + FileInfo.fileName(output.fileName); + cmd.highlight = 'linker'; + return cmd; + } + } + + Rule { + id: staticLibraryLinker + multiplex: true + inputs: ["obj"] + usings: ['dynamiclibrary', 'staticlibrary'] + + Artifact { + fileName: product.destinationDirectory + "/lib" + product.name + ".a" + fileTags: ["staticlibrary"] + cpp.staticLibraries: { + var result = [] + for (var i in inputs.staticlibrary) { + var lib = inputs.staticlibrary[i] + result.push(lib.fileName) + var impliedLibs = ModUtils.appendAll(lib, 'staticLibraries') + result.concat(impliedLibs) + } + return result + } + cpp.dynamicLibraries: { + var result = [] + for (var i in inputs.dynamiclibrary) { + var lib = inputs.dynamiclibrary[i] + result.push(lib.fileName) + var impliedLibs = ModUtils.appendAll(lib, 'dynamicLibraries') + result.concat(impliedLibs) + } + return result + } + } + + prepare: { + var args = ['rcs', output.fileName]; + for (var i in inputs.obj) + args.push(inputs.obj[i].fileName); + var cmd = new Command('ar', args); + cmd.description = 'creating ' + FileInfo.fileName(output.fileName); + cmd.highlight = 'linker' + return cmd; + } + } + + Rule { + id: applicationLinker + multiplex: true + inputs: ["obj"] + usings: ['dynamiclibrary', 'staticlibrary'] + + Artifact { + fileName: product.destinationDirectory + "/" + product.name + fileTags: ["application"] + } + + TransformProperties { + property var libraryPaths: ModUtils.appendAll(product, 'libraryPaths') + property var dynamicLibraries: ModUtils.appendAllFromArtifacts(product, inputs.dynamiclibrary, 'cpp', 'dynamicLibraries') + property var staticLibraries: ModUtils.appendAllFromArtifacts(product, inputs.staticlibrary, 'cpp', 'staticLibraries') + property var rpaths: ModUtils.appendAll(product, 'rpaths') + } + + prepare: { + var args = Gcc.configFlags(product); + for (var i in inputs.obj) + args.push(inputs.obj[i].fileName) + args.push('-Wl,-rpath,\$ORIGIN'); + args.push('-o'); + args.push(output.fileName); + + var staticLibrariesI = []; + for (i in inputs.staticlibrary) { + staticLibrariesI.push(inputs.staticlibrary[i].fileName); + } + staticLibrariesI = staticLibrariesI.concat(staticLibraries); + + var dynamicLibrariesI = []; + for (i in dynamicLibraries) { + if (dynamicLibraries[i].match("lib.*\\.so$") != null) { + // shared object filename found + var libDir = FileInfo.path(dynamicLibraries[i]) + var libName = FileInfo.fileName(dynamicLibraries[i]) + libName = libName.substr(3, libName.length - 6) + libraryPaths.push(libDir) + dynamicLibrariesI.push(libName) + } else { + // shared object libname found + dynamicLibrariesI.push(dynamicLibraries[i]) + } + } + + if (product.modules.qbs.targetOS === 'linux') { + var transitiveSOs = ModUtils.appendAllFromArtifacts(product, inputs.dynamiclibrary, 'cpp', 'transitiveSOs') + for (i in transitiveSOs) { + args.push("-Wl,-rpath-link=" + FileInfo.path(transitiveSOs[i])) + } + } + + for (i in inputs.dynamiclibrary) { + libraryPaths.push(FileInfo.path(inputs.dynamiclibrary[i].fileName)) + var fileName = FileInfo.fileName(inputs.dynamiclibrary[i].fileName) + fileName = fileName.substr(3, fileName.length - 6) + dynamicLibrariesI.push(fileName) + } + + args = args.concat(Gcc.libs(libraryPaths, rpaths, dynamicLibrariesI, staticLibrariesI)); + var cmd = new Command(product.module.compilerPath, args); + Gcc.linkEnv(cmd, product) + cmd.description = 'linking ' + FileInfo.fileName(output.fileName); + cmd.highlight = 'linker' + return cmd; + } + } + + Rule { + id: compiler + inputs: ["cpp", "c"] + explicitlyDependsOn: ["c++_pch"] + + Artifact { + fileTags: ["obj"] + // ### make it possible to override ".obj" in a project file + fileName: ".obj/" + product.name + "/" + input.baseDir + "/" + input.baseName + ".o" + } + + TransformProperties { + property var defines: ModUtils.appendAll(input, 'defines') + property var includePaths: ModUtils.appendAll(input, 'includePaths') + property var compilerFlags: ModUtils.appendAll(input, 'compilerFlags') + } + + prepare: { + var args = Gcc.configFlags(input); + + // ### what we actually need here is something like product.usedFileTags + // that contains all fileTags that have been used when applying the rules. + if (product.type.indexOf('staticlibrary') >= 0 || product.type.indexOf('dynamiclibrary') >= 0) { + args.push('-fPIC'); + } else if (product.type.indexOf('application') < 0) { + throw ("OK, now we got a problem... The product's type must be in {staticlibrary, dynamiclibrary, application}. But it is " + product.type + '.'); + } + + for (var i in defines) + args.push('-D' + defines[i]); + for (var i in includePaths) + args.push('-I' + includePaths[i]); + if (product.module.precompiledHeader) { + args.push('-include') + args.push(product.name) + var pchPath = product.module.precompiledHeaderDir[0] + var pchPathIncluded = false + for (var i in includePaths) { + if (includePaths[i] == pchPath) { + pchPathIncluded = true + break + } + } + if (!pchPathIncluded) + args.push('-I' + pchPath) + } + if (input.fileTags.indexOf("c") >= 0) { + args.push('-x') + args.push('c') + } + args.push('-c'); + args.push(input.fileName); + args.push('-o'); + args.push(output.fileName); + args = args.concat(compilerFlags); + var cmd = new Command(product.module.compilerPath, args); + cmd.description = 'compiling '; + Gcc.describe(cmd, input.fileName, output.fileName); + cmd.highlight = "compiler"; + return cmd; + } + } + + Transformer { + condition: precompiledHeader != null + inputs: precompiledHeader + Artifact { + fileName: product.name + ".gch" + fileTags: "c++_pch" + } + prepare: { + var args = Gcc.configFlags(product); + for (var i in product.module.defines) + args.push('-D' + defines[i]); + for (var i in product.module.includePaths) + args.push('-I' + includePaths[i]); + args.push('-x'); + args.push('c++-header'); + args.push('-c'); + args.push(product.module.precompiledHeader); + args.push('-o'); + args.push(output.fileName); + if (product.module.compilerFlags) + args = args.concat(product.module.compilerFlags); + var cmd = new Command(product.module.compilerPath, args); + cmd.description = 'precompiling ' + FileInfo.fileName(input.fileName); + return cmd; + } + } +} + diff --git a/share/qbs/modules/cpp/gcc.js b/share/qbs/modules/cpp/gcc.js new file mode 100644 index 000000000..a4155ad9b --- /dev/null +++ b/share/qbs/modules/cpp/gcc.js @@ -0,0 +1,113 @@ +function collectDynamicLinkPaths(config) { + var paths = [] + + var linkProducts = config.linkProducts || [] + for (var libPath in linkProducts) { + var linkedConfig = linkProducts[libPath] + var fileTags = linkedConfig['fileTags'] + if (fileTags.indexOf('dynamiclibrary') >= 0) { + paths.push(FileInfo.path(libPath)) + paths = paths.concat(collectDynamicLinkPaths(linkedConfig)) + } + } + return paths +} + +function linkEnv(cmd) { + // ### setup LD_LIBRARY_PATH for ProductModule dynamiclibrary depends +// var paths = [] +// for (var i in config.linkProducts) { +// var linkedConfig = config.linkProducts[i] +// var fileTags = linkedConfig['fileTags'] +// if (fileTags.indexOf('dynamiclibrary') >= 0) { +// paths = paths.concat(collectDynamicLinkPaths(linkedConfig)) +// } +// } + +// if (paths.length) { +// var envdef = newEnvironmentDefinition("LD_LIBRARY_PATH") +// envdef.pathNames = true +// envdef.separator = ':' +// envdef.prepend = paths +// cmd.addEnvironmentDefinition(envdef) +// } +} + +function libs(libraryPaths, rpaths, dynamicLibraries, staticLibraries) { + + var args = []; + if (rpaths && rpaths.length) + args.push('-Wl,-rpath,' + rpaths.join(':')); + for (var i in libraryPaths) { + args.push('-L' + libraryPaths[i]); + } + for (var i in staticLibraries) { + args.push(staticLibraries[i]); + } + for (var i in dynamicLibraries) { + if (FileInfo.isAbsolutePath(dynamicLibraries[i])) { + args.push(dynamicLibraries[i]); + } else { + args.push('-l' + dynamicLibraries[i]); + } + } + return args; +} + +function macLibs(libraryPaths, rpaths, dynamicLibraries, staticLibraries, frameworks) +{ + var args = libs(libraryPaths, rpaths, dynamicLibraries, staticLibraries); + for (var i in libraryPaths) { + args.push('-F' + libraryPaths[i]); + } + for (var i in frameworks) { + args.push('-framework'); + args.push(frameworks[i]); + } + return args; +} + +function configFlags(config) { + var args = []; + // optimization: + if (config.module.debugInformation === 'on') + args.push('-g'); + if (config.module.optimization === 'fast') + args.push('-O2'); + if (config.module.optimization === 'small') + args.push('-Os'); + // warnings: + if (config.module.warningLevel === 'none') + args.push('-w'); + if (config.module.warningLevel === 'all') { + args.push('-Wall'); + args.push('-W'); + } + if (config.module.treatWarningsAsErrors) + args.push('-Werror'); + + return args; +} + +function frameworkPaths(config) { + var args = []; + for (var i in config.frameworkPaths) { + args.push('-F' + config.frameworkPaths[i]); + } + return args; +} + +function frameworks(config) { + var args = []; + for (var i in config.frameworks) { + args.push('-framework'); + args.push(config.frameworks[i] + .replace(/.framework$/,'')); + } + return args; +} + +function describe(cmd, input, output) +{ + cmd.description += FileInfo.fileName(input); +} diff --git a/share/qbs/modules/cpp/linux-gcc.qbs b/share/qbs/modules/cpp/linux-gcc.qbs new file mode 100644 index 000000000..ff1827ebb --- /dev/null +++ b/share/qbs/modules/cpp/linux-gcc.qbs @@ -0,0 +1,6 @@ +import qbs.base 1.0 + +GenericGCC { + condition: qbs.hostOS == 'linux' && qbs.targetOS == 'linux' && qbs.toolchain == 'gcc' +} + diff --git a/share/qbs/modules/cpp/mac-gcc.qbs b/share/qbs/modules/cpp/mac-gcc.qbs new file mode 100644 index 000000000..fda5da3f2 --- /dev/null +++ b/share/qbs/modules/cpp/mac-gcc.qbs @@ -0,0 +1,69 @@ +import qbs.base 1.0 + +GenericGCC { + condition: qbs.hostOS == 'mac' && qbs.targetOS == 'mac' && qbs.toolchain == 'gcc' + + Rule { + multiplex: true + inputs: ["qbs"] + + Artifact { + fileName: product.name + ".app/Info.plist" + fileTags: ["infoplist"] + } + + prepare: { + var cmd = new JavaScriptCommand(); + cmd.description = "generating Info.plist"; + cmd.highlight = "codegen"; + cmd.sourceCode = function() { + var infoplist = new TextFile(outputs.infoplist[0].fileName, TextFile.WriteOnly); + infoplist.write("<foobar>"); + infoplist.close(); + } + return cmd; + } + } + + Rule { + multiplex: true + inputs: ["qbs"] + + Artifact { + fileName: product.name + ".app/PkgInfo" + fileTags: ["pkginfo"] + } + + prepare: { + var cmd = new JavaScriptCommand(); + cmd.description = "generating PkgInfo"; + cmd.highlight = "codegen"; + cmd.sourceCode = function() { + var pkginfo = new TextFile(outputs.pkginfo[0].fileName, TextFile.WriteOnly); + pkginfo.write("FOO"); + pkginfo.close(); + } + return cmd; + } + } + + Rule { + multiplex: true + inputs: ["application", "infoplist", "pkginfo"] + + Artifact { + fileName: product.name + ".app/Contents/MacOS/" + product.name + fileTags: ["applicationbundle"] + } + + prepare: { + var cmd = new JavaScriptCommand(); + cmd.description = "generating app bundle"; + cmd.highlight = "codegen"; + cmd.sourceCode = function() { + File.copy(inputs.application[0].fileName, outputs.applicationbundle[0].fileName); + } + return cmd; + } + } +} diff --git a/share/qbs/modules/cpp/msvc.js b/share/qbs/modules/cpp/msvc.js new file mode 100644 index 000000000..0f306eced --- /dev/null +++ b/share/qbs/modules/cpp/msvc.js @@ -0,0 +1,173 @@ +function prepareCompiler(product, input, outputs, defines, includePaths, compilerFlags) +{ + var optimization = input.module.optimization + var debugInformation = input.module.debugInformation + var architecture = input.module.architecture + var toolchainInstallPath = product.module.toolchainInstallPath + + var args = ['/nologo', '/c', '/Zm200', '/Zc:wchar_t-'] + + // C or C++ + if (input.fileTags.indexOf('c') >= 0) { + args.push('/TC') + } + + // enable unwind semantics + args.push("/EHsc") + // optimization: + if (optimization === 'small') + args.push('/Os') + else if (optimization === 'fast') + args.push('/O2') + if (debugInformation) { + args.push('/Zi') + args.push('/MDd') + } else { + args.push('/MD') + } + // warnings: + var warningLevel = input.module.warningLevel + if (warningLevel === 'none') + args.push('/w') + if (warningLevel === 'all') + args.push('/Wall') + for (var i in includePaths) + args.push('/I' + FileInfo.toWindowsSeparators(includePaths[i])) + for (i in defines) + args.push('/D' + defines[i]) + + var objOutput = outputs.obj ? outputs.obj[0] : undefined + var pchOutput = outputs["c++_pch"] ? outputs["c++_pch"][0] : undefined + + // precompiled header file + if (product.module.precompiledHeader) { + if (pchOutput) { + // create pch + args.push('/Yc') + args.push('/Fp' + FileInfo.toWindowsSeparators(pchOutput.fileName)) + args.push('/Fo' + FileInfo.toWindowsSeparators(objOutput.fileName)) + args.push('/TP') + args.push(FileInfo.toWindowsSeparators(input.fileName)) + } else { + // use pch + var pchHeaderName = FileInfo.toWindowsSeparators(product.module.precompiledHeader) + var pchName = FileInfo.toWindowsSeparators(product.module.precompiledHeaderDir[0] + "\\.obj\\" + product.name + "\\" + product.name + ".pch") + args.push("/FI" + pchHeaderName) + args.push("/Yu" + pchHeaderName) + args.push("/Fp" + pchName) + } + } + args.push('/Fo' + FileInfo.toWindowsSeparators(objOutput.fileName)) + args.push(FileInfo.toWindowsSeparators(input.fileName)) + + var clPath = toolchainInstallPath + '/VC/bin/' + var is64bit = (architecture === "x86_64") + if (is64bit) + clPath += 'amd64/' + clPath += 'cl.exe' + + for (var i in compilerFlags) { + args.push(i) + } + + var cmd = new Command(clPath, args) + cmd.description = (pchOutput ? 'pre' : '') + 'compiling ' + FileInfo.fileName(input.fileName) + cmd.highlight = "compiler"; + cmd.workingDirectory = FileInfo.path(objOutput.fileName) + cmd.responseFileThreshold = product.module.responseFileThreshold + cmd.responseFileUsagePrefix = '@'; + // cl.exe outputs the cpp file name. We filter that out. + cmd.stdoutFilterFunction = "function(output) {"; + cmd.stdoutFilterFunction += "return output.replace('" + FileInfo.fileName(input.fileName) + "\\r\\n', '');"; + cmd.stdoutFilterFunction += "}"; + return cmd; +} + +function prepareLinker(product, inputs, outputs, libraryPaths, dynamicLibraries, staticLibraries) +{ + var linkDLL = (outputs.dynamiclibrary ? true : false) + var primaryOutput = (linkDLL ? outputs.dynamiclibrary[0] : outputs.application[0]) + var optimization = product.module.optimization + var debugInformation = product.module.debugInformation + var architecture = product.module.architecture + var windowsSDKPath = product.module.windowsSDKPath + var generateManifestFiles = !linkDLL && product.module.generateManifestFiles + var toolchainInstallPath = product.module.toolchainInstallPath + + var args = ['/nologo'] + if (linkDLL) { + args.push('/DLL'); + args.push('/IMPLIB:' + FileInfo.toWindowsSeparators(outputs.dynamiclibrary_import[0].fileName)); + } + + if (debugInformation) + args.push('/DEBUG') + else + args.push('/INCREMENTAL:NO') + + var manifestFileName + if (generateManifestFiles) { + manifestFileName = FileInfo.toWindowsSeparators(primaryOutput.fileName) + manifestFileName += '.intermediate.manifest' + args.push('/MANIFEST', '/MANIFESTFILE:' + manifestFileName) + } + + var allInputs = inputs.obj.concat(inputs.staticlibrary || []) + if (inputs.dynamiclibrary_import) + allInputs = inputs.obj.concat(inputs.dynamiclibrary_import) + for (var i in allInputs) { + var fileName = FileInfo.toWindowsSeparators(allInputs[i].fileName) + args.push(fileName) + } + for (var i in staticLibraries) { + var staticLibrary = staticLibraries[i]; + if (!staticLibrary.match(/\.lib$/i)) + staticLibrary += ".lib"; + args.push(staticLibrary) + } + for (var i in dynamicLibraries) { + var dynamicLibrary = dynamicLibraries[i]; + if (!dynamicLibrary.match(/\.lib$/i)) + dynamicLibrary += ".lib"; + args.push(dynamicLibrary) + } + + var nativeOutputFileName = FileInfo.toWindowsSeparators(primaryOutput.fileName) + args.push('/OUT:' + nativeOutputFileName) + for (var i in libraryPaths) { + args.push('/LIBPATH:' + FileInfo.toWindowsSeparators(libraryPaths[i])) + } + args = args.concat(dynamicLibraries) + var is64bit = (architecture == "x86_64") + + var linkerPath = toolchainInstallPath + '/VC/bin/' + if (is64bit) + linkerPath += 'amd64/' + linkerPath += 'link.exe' + + var commands = []; + var cmd = new Command(linkerPath, args) + cmd.description = 'linking ' + FileInfo.fileName(primaryOutput.fileName) + cmd.highlight = 'linker'; + cmd.workingDirectory = FileInfo.path(primaryOutput.fileName) + cmd.responseFileThreshold = product.module.responseFileThreshold + cmd.responseFileUsagePrefix = '@'; + commands.push(cmd); + + if (generateManifestFiles) { + // embed the generated manifest files + var args = [ + '/nologo', '/manifest', manifestFileName, + '/outputresource:' + nativeOutputFileName + ';1' + ] + var mtPath = windowsSDKPath + '/bin/mt.exe' + var cmd = new Command(mtPath, args) + cmd.description = 'embedding manifest into ' + FileInfo.fileName(primaryOutput.fileName) + cmd.highlight = 'linker'; + cmd.workingDirectory = FileInfo.path(primaryOutput.fileName) + commands.push(cmd); + } + + return commands; +} + diff --git a/share/qbs/modules/cpp/ponyphone.qbs b/share/qbs/modules/cpp/ponyphone.qbs new file mode 100644 index 000000000..e7ea9dfe4 --- /dev/null +++ b/share/qbs/modules/cpp/ponyphone.qbs @@ -0,0 +1,28 @@ +/* + Giddyup, pony pony pony! + + How to setup this crazy horsey platform? + - install the pony SDK + - call the following + qbs config --global ponyphone/substitute theLittlePrancingPony + qbs config --global ponyphone/sdkInstallPath ~/theLittlePrancingPonySDK + - stand up and sing the Mr. Ed theme song! +*/ + +import qbs.base 1.0 + +GenericGCC { + property string substitute: qbs.configurationValue('ponyphone/substitute') + + condition: qbs.hostOS == 'linux' && qbs.targetOS == 'linux' && qbs.toolchain == 'gcc' && qbs.platform == 'ponyphone' + + toolchainPrefix: { + if (architecture == 'i586') + return architecture + '-' + substitute + '-linux-' + else if (architecture == 'armv7hl') + return architecture + '-' + substitute + '-linux-gnueabi-' + throw "unknown target architecture: " + architecture + } + toolchainInstallPath: qbs.configurationValue('ponyphone/sdkInstallPath') + "/" + substitute + "/" + architecture + "/toolchain/bin" +} + diff --git a/share/qbs/modules/cpp/windows-msvc.qbs b/share/qbs/modules/cpp/windows-msvc.qbs new file mode 100644 index 000000000..535df9491 --- /dev/null +++ b/share/qbs/modules/cpp/windows-msvc.qbs @@ -0,0 +1,199 @@ +import qbs.base 1.0 +import qbs.fileinfo 1.0 as FileInfo +import '../utils.js' as ModUtils +import 'msvc.js' as MSVC + +CppModule { + condition: qbs.hostOS == 'windows' && qbs.targetOS == 'windows' && qbs.toolchain == 'msvc' + + id: module + + defines: ['UNICODE', 'WIN32'] + warningLevel: "default" + + property bool generateManifestFiles: true + property string toolchainInstallPath: "UNKNOWN" + property string windowsSDKPath: "UNKNOWN" + property string architecture: "x86" + property int responseFileThreshold: 32000 + + setupBuildEnvironment: { + var v = new ModUtils.EnvironmentVariable("INCLUDE", ";", true) + v.prepend(toolchainInstallPath + "/VC/ATLMFC/INCLUDE") + v.prepend(toolchainInstallPath + "/VC/INCLUDE") + v.prepend(windowsSDKPath + "/include") + v.set() + + if (architecture == 'x86') { + v = new ModUtils.EnvironmentVariable("PATH", ";", true) + v.prepend(toolchainInstallPath + "/Common7/IDE") + v.prepend(toolchainInstallPath + "/VC/bin") + v.prepend(toolchainInstallPath + "/Common7/Tools") + v.set() + + v = new ModUtils.EnvironmentVariable("LIB", ";", true) + v.prepend(toolchainInstallPath + "/VC/ATLMFC/LIB") + v.prepend(toolchainInstallPath + "/VC/LIB") + v.prepend(windowsSDKPath + "/lib") + v.set() + } else if (architecture == 'x86_64') { + v = new ModUtils.EnvironmentVariable("PATH", ";", true) + v.prepend(toolchainInstallPath + "/Common7/IDE") + v.prepend(toolchainInstallPath + "/VC/bin/amd64") + v.prepend(toolchainInstallPath + "/Common7/Tools") + v.set() + + v = new ModUtils.EnvironmentVariable("LIB", ";", true) + v.prepend(toolchainInstallPath + "/VC/ATLMFC/LIB/amd64") + v.prepend(toolchainInstallPath + "/VC/LIB/amd64") + v.prepend(windowsSDKPath + "/lib/x64") + v.set() + } + } + + Artifact { + // This adds the filename in precompiledHeader to the set of source files. + // If its already in there, then this makes sure it has the right file tag. + condition: precompiledHeader != null + fileName: precompiledHeader + fileTags: ["hpp_pch"] + } + + Rule { + id: pchCompiler + inputs: ["hpp_pch"] + Artifact { + fileTags: ['obj'] + // ### make the object file dir overridable + fileName: ".obj/" + product.name + "/" + input.baseName + '.obj' + } + Artifact { + fileTags: ['c++_pch'] + // ### make the object file dir overridable + fileName: ".obj/" + product.name + "/" + product.name + '.pch' + } + TransformProperties { + property var defines: ModUtils.appendAll(input, 'defines') + property var includePaths: ModUtils.appendAll(input, 'includePaths') + property var compilerFlags: ModUtils.appendAll(input, 'compilerFlags') + } + prepare: { + return MSVC.prepareCompiler(product, input, outputs) + } + } + + Rule { + id: compiler + inputs: ["cpp", "c"] + explicitlyDependsOn: ["c++_pch"] + Artifact { + fileTags: ['obj'] + // ### make the object file dir overridable + fileName: ".obj/" + product.name + "/" + input.baseDir + "/" + input.baseName + ".obj" + } + + TransformProperties { + property var defines: ModUtils.appendAll(input, 'defines') + property var includePaths: ModUtils.appendAll(input, 'includePaths') + property var compilerFlags: ModUtils.appendAll(input, 'compilerFlags') + } + + prepare: { + return MSVC.prepareCompiler(product, input, outputs, defines, includePaths, compilerFlags) + } + } + + Rule { + id: applicationLinker + multiplex: true + inputs: ['obj'] + usings: ['staticlibrary', 'dynamiclibrary_import'] + Artifact { + fileTags: ["application"] + fileName: product.destinationDirectory + "/" + product.name + ".exe" + } + + TransformProperties { + property var libraryPaths: ModUtils.appendAll(product, 'libraryPaths') + property var dynamicLibraries: ModUtils.appendAllFromArtifacts(product, inputs.dynamiclibrary_import, 'cpp', 'dynamicLibraries') + property var staticLibraries: ModUtils.appendAllFromArtifacts(product, (inputs.staticlibrary || []).concat(inputs.obj), 'cpp', 'staticLibraries') + } + + prepare: { + return MSVC.prepareLinker(product, inputs, outputs, libraryPaths, dynamicLibraries, staticLibraries) + } + } + + Rule { + id: dynamicLibraryLinker + multiplex: true + inputs: ['obj'] + usings: ['staticlibrary', 'dynamiclibrary_import'] + + Artifact { + fileTags: ["dynamiclibrary"] + fileName: product.destinationDirectory + "/" + product.name + ".dll" + } + + Artifact { + fileTags: ["dynamiclibrary_import"] + fileName: product.destinationDirectory + "/" + product.name + "_imp.lib" + } + + TransformProperties { + property var libraryPaths: ModUtils.appendAll(product, 'libraryPaths') + property var dynamicLibraries: ModUtils.appendAll(product, 'dynamicLibraries') + property var staticLibraries: ModUtils.appendAllFromArtifacts(product, (inputs.staticlibrary || []).concat(inputs.obj), 'cpp', 'staticLibraries') + } + + prepare: { + return MSVC.prepareLinker(product, inputs, outputs, libraryPaths, dynamicLibraries, staticLibraries) + } + } + + Rule { + id: libtool + multiplex: true + inputs: ["obj"] + usings: ["staticlibrary"] + + Artifact { + fileTags: ["staticlibrary"] + fileName: product.destinationDirectory + "/" + product.name + ".lib" + cpp.staticLibraries: { + var result = [] + for (var i in inputs.staticlibrary) { + var lib = inputs.staticlibrary[i] + result.push(lib.fileName) + var impliedLibs = ModUtils.appendAll(lib, 'staticLibraries') + result.concat(impliedLibs) + } + return result + } + } + + prepare: { + var toolchainInstallPath = product.module.toolchainInstallPath + + var args = ['/nologo'] + var nativeOutputFileName = FileInfo.toWindowsSeparators(output.fileName) + args.push('/OUT:' + nativeOutputFileName) + for (var i in inputs.obj) { + var fileName = FileInfo.toWindowsSeparators(inputs.obj[i].fileName) + args.push(fileName) + } + var is64bit = (product.module.architecture == "x86_64") + var linkerPath = toolchainInstallPath + '/VC/bin/' + if (is64bit) + linkerPath += 'amd64/' + linkerPath += 'lib.exe' + var cmd = new Command(linkerPath, args) + cmd.description = 'creating ' + FileInfo.fileName(output.fileName) + cmd.highlight = 'linker'; + cmd.workingDirectory = FileInfo.path(output.fileName) + cmd.responseFileThreshold = product.module.responseFileThreshold + cmd.responseFileUsagePrefix = '@'; + return cmd; + } + } +} diff --git a/share/qbs/modules/qbs/common.qbs b/share/qbs/modules/qbs/common.qbs new file mode 100644 index 000000000..e9e311e93 --- /dev/null +++ b/share/qbs/modules/qbs/common.qbs @@ -0,0 +1,50 @@ +import qbs.base 1.0 +import qbs.fileinfo 1.0 as FileInfo + +Module { + property list<string> references; + property string buildVariant: "debug" + property bool debugInformation: (buildVariant == "debug") + property string optimization: (buildVariant == "debug" ? "none" : "fast") + property string platform: null + property string hostOS: getHostOS() + property string hostArchitecture: getHostDefaultArchitecture() + property string targetOS: null + property string targetName: null + property string toolchain: null + property string architecture: null + property string endianness: null + property string installDir: '.' + + PropertyOptions { + name: "buildVariant" + allowedValues: ['debug', 'release'] + description: "Defines the consistence of your ice cream sandwich" + } + + PropertyOptions { + name: "optimization" + allowedValues: ['none', 'fast', 'small'] + description: "optimization level" + } + + Rule { + inputs: ["install"] + Artifact { + fileTags: ["installed_content"] + fileName: input.modules.qbs.installDir + "/" + input.fileName + } + + prepare: { + var cmd = new JavaScriptCommand(); + cmd.sourceCode = function() { + File.remove(output.fileName); + File.copy(input.fileName, output.fileName); + } + cmd.description = "installing " + FileInfo.fileName(output.fileName); + cmd.highlight = "linker"; + return cmd; + } + + } +} diff --git a/share/qbs/modules/qt/QtModule.qbs b/share/qbs/modules/qt/QtModule.qbs new file mode 100644 index 000000000..b1a03d4c2 --- /dev/null +++ b/share/qbs/modules/qt/QtModule.qbs @@ -0,0 +1,19 @@ +import qbs.base 1.0 +import qbs.fileinfo 1.0 as FileInfo +import 'qtfunctions.js' as QtFunctions + +Module { + condition: false + + Depends { name: "cpp" } + Depends { id: qtcore; name: "Qt.core" } + + property string binPath: qtcore.binPath + property string incPath: qtcore.incPath + property string libPath: qtcore.libPath + property string qtModuleName: '' + property string internalQtModuleName: 'Qt' + qtModuleName + cpp.includePaths: [incPath + '/' + internalQtModuleName] + cpp.dynamicLibraries: [QtFunctions.getLibraryName(internalQtModuleName, qbs.targetOS, cpp.debugInformation)] + cpp.frameworks: [QtFunctions.getLibraryName(internalQtModuleName, qbs.targetOS, cpp.debugInformation)] +} diff --git a/share/qbs/modules/qt/core/moc.js b/share/qbs/modules/qt/core/moc.js new file mode 100644 index 000000000..c0845220c --- /dev/null +++ b/share/qbs/modules/qt/core/moc.js @@ -0,0 +1,15 @@ +function args(input, output, config) { + var args = []; + + // ### fixme + var defines = ModUtils.appendAll_internal(config.modules, 'cpp', 'defines') //config.modules.cpp.compiler.defines + var includePaths = ModUtils.appendAll_internal(config.modules, 'cpp', 'includePaths') //config.modules.cpp.compiler.includePaths + for (var i in defines) + args.push('-D' + defines[i]); + for (var i in includePaths) + args.push('-I' + includePaths[i]); + args.push('-o', output); + args.push(input); + return args; +} + diff --git a/share/qbs/modules/qt/core/qtcore.qbs b/share/qbs/modules/qt/core/qtcore.qbs new file mode 100644 index 000000000..075b462b6 --- /dev/null +++ b/share/qbs/modules/qt/core/qtcore.qbs @@ -0,0 +1,130 @@ +import qbs.base 1.0 +import qbs.fileinfo 1.0 as FileInfo +import '../../utils.js' as ModUtils +import "moc.js" 1.0 as Moc +import '../qtfunctions.js' as QtFunctions + +Module { + Depends { name: "cpp" } + + property string qtVersionName: "default" + property string configKey: "qt/" + qtVersionName + "/" + property string qtNamespace: qbs.configurationValue(configKey + "namespace", undefined) + property string qtPath: qbs.configurationValue(configKey + "path", undefined) + property string binPath: qtPath ? qtPath + "/bin" : qbs.configurationValue(configKey + "binPath", undefined) + property string incPath: qtPath ? qtPath + "/include" : qbs.configurationValue(configKey + "incPath", undefined) + property string libPath: qtPath ? qtPath + "/lib" : qbs.configurationValue(configKey + "libPath", undefined) + property string mkspecsPath: qtPath ? qtPath + "/mkspecs" : qbs.configurationValue(configKey + "mkspecsPath", undefined) + property string generatedFilesDir: 'GeneratedFiles/' + product.name // ### TODO: changing this property does not change the path in the rule ATM. + property string libraryInfix: cpp.debugInformation ? 'd' : '' + cpp.defines: { + if (!qtNamespace) + return undefined; + return ["QT_NAMESPACE=" + qtNamespace] + } + cpp.includePaths: [ + mkspecsPath + '/default', + incPath + '/QtCore', + incPath, + product.buildDirectory + '/' + generatedFilesDir + ] + cpp.libraryPaths: [libPath] + cpp.dynamicLibraries: qbs.targetOS != 'mac' ? [QtFunctions.getLibraryName('QtCore', qbs.targetOS, cpp.debugInformation)] : [] + cpp.frameworkPaths: [libPath] + cpp.frameworks: [QtFunctions.getLibraryName('QtCore', qbs.targetOS, cpp.debugInformation)] + cpp.rpaths: [libPath] + + setupBuildEnvironment: { + // Not really a setup in this case. Just some sanity checks. + if (!binPath) + throw "qt/core.binPath not set. Set the configuration values qt/default/binPath or qt/default/path."; + if (!incPath) + throw "qt/core.incPath not set. Set the configuration values qt/default/incPath or qt/default/path."; + if (!libPath) + throw "qt/core.libPath not set. Set the configuration values qt/default/libPath or qt/default/path."; + if (!mkspecsPath) + throw "qt/core.mkspecsPath not set. Set the configuration values qt/default/mkspecsPath or qt/default/path."; + } + + setupRunEnvironment: { + var v = getenv('PATH') || '' + if (v.length > 0 && v.charAt(0) != ';') + v = ';' + v + var y = binPath + if (qbs.targetOS === 'windows') + v = FileInfo.toWindowsSeparators(y) + v + else + v = y + v + putenv('PATH', v) + } + + FileTagger { + pattern: "*.qrc" + fileTags: ["qrc"] + } + + Rule { + inputs: ["moc_cpp"] + + Artifact { + fileName: 'GeneratedFiles/' + product.name + '/' + input.baseName + '.moc' +// fileName: input.baseDir + '/' + input.baseName + '.moc' + fileTags: ["hpp"] + } + + prepare: { + var cmd = new Command(product.module.binPath + '/moc', Moc.args(input.fileName, output.fileName, input)); + cmd.description = 'moc ' + FileInfo.fileName(input.fileName); + cmd.highlight = 'codegen'; + return cmd; + } + } + + Rule { + inputs: ["moc_hpp"] + + Artifact { + fileName: 'GeneratedFiles/' + product.name + '/moc_' + input.baseName + '.cpp' + fileTags: [ "cpp" ] + } + + prepare: { + var cmd = new Command(product.module.binPath + '/moc', Moc.args(input.fileName, output.fileName, input)); + cmd.description = 'moc ' + FileInfo.fileName(input.fileName); + cmd.highlight = 'codegen'; + return cmd; + } + } + + Rule { + inputs: ["moc_hpp_inc"] + + Artifact { + fileName: 'GeneratedFiles/' + product.name + '/moc_' + input.baseName + '.cpp' + fileTags: [ "hpp" ] + } + + prepare: { + var cmd = new Command(product.module.binPath + '/moc', Moc.args(input.fileName, output.fileName, input)); + cmd.description = 'moc ' + FileInfo.fileName(input.fileName); + cmd.highlight = 'codegen'; + return cmd; + } + } + + Rule { + inputs: ["qrc"] + + Artifact { +// ### TODO we want to access the module's property "generatedFilesDir" here. But without evaluating all available properties a priori. + fileName: 'GeneratedFiles/' + product.name + '/qrc_' + input.baseName + '.cpp' + fileTags: ["cpp"] + } + prepare: { + var cmd = new Command(product.module.binPath + '/rcc', [input.fileName, '-name', FileInfo.baseName(input.fileName), '-o', output.fileName]); + cmd.description = 'rcc ' + FileInfo.fileName(input.fileName); + cmd.highlight = 'codegen'; + return cmd; + } + } +} diff --git a/share/qbs/modules/qt/declarative/module.qbs b/share/qbs/modules/qt/declarative/module.qbs new file mode 100644 index 000000000..3f4bf5b0f --- /dev/null +++ b/share/qbs/modules/qt/declarative/module.qbs @@ -0,0 +1,9 @@ +import qbs.base 1.0 +import '../QtModule.qbs' as QtModule + +QtModule { + condition: true + qtModuleName: "Declarative" + Depends { name: "Qt.gui" } +} + diff --git a/share/qbs/modules/qt/designer/module.qbs b/share/qbs/modules/qt/designer/module.qbs new file mode 100644 index 000000000..c2e319d88 --- /dev/null +++ b/share/qbs/modules/qt/designer/module.qbs @@ -0,0 +1,8 @@ +import qbs.base 1.0 +import '../QtModule.qbs' as QtModule + +QtModule { + condition: true + qtModuleName: 'Designer' +} + diff --git a/share/qbs/modules/qt/designercomponents/module.qbs b/share/qbs/modules/qt/designercomponents/module.qbs new file mode 100644 index 000000000..eb700eb7f --- /dev/null +++ b/share/qbs/modules/qt/designercomponents/module.qbs @@ -0,0 +1,8 @@ +import qbs.base 1.0 +import '../QtModule.qbs' as QtModule + +QtModule { + condition: true + qtModuleName: 'DesignerComponents' +} + diff --git a/share/qbs/modules/qt/gui/qtgui.qbs b/share/qbs/modules/qt/gui/qtgui.qbs new file mode 100644 index 000000000..2a300a00c --- /dev/null +++ b/share/qbs/modules/qt/gui/qtgui.qbs @@ -0,0 +1,33 @@ +import qbs.base 1.0 +import qbs.fileinfo 1.0 as FileInfo +import '../QtModule.qbs' as QtModule + +QtModule { + qtModuleName: "Gui" + + Depends { id: qtcore; name: "Qt.core" } + + FileTagger { + pattern: "*.ui" + fileTags: ["ui"] + } + + Rule { + inputs: ["ui"] + + Artifact { +// ### TODO we want to access the module's property "qtcore.generatedFilesDir" here. But without evaluating all available properties a priori. +// fileName: input.baseDir + '/qrc_' + input.baseName + '.cpp' + fileName: 'GeneratedFiles/' + product.name + '/ui_' + input.baseName + '.h' + fileTags: ["hpp"] + } + + prepare: { + var cmd = new Command(product.module.binPath + '/uic', [input.fileName, '-o', output.fileName]) + cmd.description = 'uic ' + FileInfo.fileName(input.fileName); + cmd.highlight = 'codegen'; + return cmd; + } + } +} + diff --git a/share/qbs/modules/qt/help/module.qbs b/share/qbs/modules/qt/help/module.qbs new file mode 100644 index 000000000..6bf5616f9 --- /dev/null +++ b/share/qbs/modules/qt/help/module.qbs @@ -0,0 +1,8 @@ +import qbs.base 1.0 +import '../QtModule.qbs' as QtModule + +QtModule { + condition: true + qtModuleName: 'Help' +} + diff --git a/share/qbs/modules/qt/network/module.qbs b/share/qbs/modules/qt/network/module.qbs new file mode 100644 index 000000000..00aa5386a --- /dev/null +++ b/share/qbs/modules/qt/network/module.qbs @@ -0,0 +1,8 @@ +import qbs.base 1.0 +import '../QtModule.qbs' as QtModule + +QtModule { + condition: true + qtModuleName: 'Network' +} + diff --git a/share/qbs/modules/qt/opengl/module.qbs b/share/qbs/modules/qt/opengl/module.qbs new file mode 100644 index 000000000..fed343603 --- /dev/null +++ b/share/qbs/modules/qt/opengl/module.qbs @@ -0,0 +1,8 @@ +import qbs.base 1.0 +import '../QtModule.qbs' as QtModule + +QtModule { + condition: true + qtModuleName: 'OpenGL' +} + diff --git a/share/qbs/modules/qt/qtfunctions.js b/share/qbs/modules/qt/qtfunctions.js new file mode 100644 index 000000000..c6dbf4de5 --- /dev/null +++ b/share/qbs/modules/qt/qtfunctions.js @@ -0,0 +1,12 @@ +// helper functions for the Qt modules + +function getLibraryName(qtModule, targetOS, debugInfo) +{ + var isUnix = (targetOS == 'linux' || targetOS == 'mac') + var libName + if (isUnix) + libName = qtModule + else if (targetOS == 'windows') + libName = qtModule + (debugInfo ? 'd' : '') + '4.lib' + return libName +} diff --git a/share/qbs/modules/qt/script/module.qbs b/share/qbs/modules/qt/script/module.qbs new file mode 100644 index 000000000..96e292bb4 --- /dev/null +++ b/share/qbs/modules/qt/script/module.qbs @@ -0,0 +1,8 @@ +import qbs.base 1.0 +import '../QtModule.qbs' as QtModule + +QtModule { + condition: true + qtModuleName: 'Script' +} + diff --git a/share/qbs/modules/qt/sql/module.qbs b/share/qbs/modules/qt/sql/module.qbs new file mode 100644 index 000000000..23892e162 --- /dev/null +++ b/share/qbs/modules/qt/sql/module.qbs @@ -0,0 +1,8 @@ +import qbs.base 1.0 +import '../QtModule.qbs' as QtModule + +QtModule { + condition: true + qtModuleName: 'Sql' +} + diff --git a/share/qbs/modules/qt/svg/module.qbs b/share/qbs/modules/qt/svg/module.qbs new file mode 100644 index 000000000..e06e9277a --- /dev/null +++ b/share/qbs/modules/qt/svg/module.qbs @@ -0,0 +1,8 @@ +import qbs.base 1.0 +import '../QtModule.qbs' as QtModule + +QtModule { + condition: true + qtModuleName: 'Svg' +} + diff --git a/share/qbs/modules/qt/webkit/module.qbs b/share/qbs/modules/qt/webkit/module.qbs new file mode 100644 index 000000000..ea598d61f --- /dev/null +++ b/share/qbs/modules/qt/webkit/module.qbs @@ -0,0 +1,8 @@ +import qbs.base 1.0 +import '../QtModule.qbs' as QtModule + +QtModule { + condition: true + qtModuleName: 'WebKit' +} + diff --git a/share/qbs/modules/qt/xml/module.qbs b/share/qbs/modules/qt/xml/module.qbs new file mode 100644 index 000000000..5b4a462a7 --- /dev/null +++ b/share/qbs/modules/qt/xml/module.qbs @@ -0,0 +1,8 @@ +import qbs.base 1.0 +import '../QtModule.qbs' as QtModule + +QtModule { + condition: true + qtModuleName: 'Xml' +} + diff --git a/share/qbs/modules/utils.js b/share/qbs/modules/utils.js new file mode 100644 index 000000000..4d1e08418 --- /dev/null +++ b/share/qbs/modules/utils.js @@ -0,0 +1,133 @@ +// +// utility functions for modules +// + +function appendAll_internal2(modules, name, property, seenValues) +{ + var result = [] + for (var m in modules) { + if (m == name) { + var value = modules[m][property] + if (value) { + if (!seenValues[value]) { + seenValues[value] = true + result = result.concat(value) + } + } + } else { + var values = appendAll_internal2(modules[m].modules, name, property, seenValues) + if (values && values.length > 0) + result = result.concat(values) + } + } + return result +} + +function appendAll_internal(modules, name, property) +{ + var seenValues = [] + return appendAll_internal2(modules, name, property, seenValues) +} + +function appendAll(config, property) +{ + return appendAll_internal(config.modules, config.module.name, property) +} + +function appendAllFromArtifacts(product, artifacts, moduleName, propertyName) +{ + var seenValues = [] + var result = appendAll_internal2(product.modules, moduleName, propertyName, seenValues) + for (var i in artifacts) + result = result.concat(appendAll_internal2(artifacts[i].modules, moduleName, propertyName, seenValues)) + return result +} + +function findFirst(modules, name, property) +{ + for (var m in modules) { + if (m == name) { + var value = modules[m][property] + if (value) + return value + } else { + var value = findFirst(m.modules, name, property) + if (value) + return value + } + } + return null +} + +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 children = {} + for (var 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 (var 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) +} + + +////////////////////////////////////////////////////////// +// 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) +} + |