diff options
23 files changed, 292 insertions, 670 deletions
diff --git a/doc/qbs.qdoc b/doc/qbs.qdoc index 0ab69f287..277948537 100644 --- a/doc/qbs.qdoc +++ b/doc/qbs.qdoc @@ -161,7 +161,7 @@ \title Configuring Qbs - When you run Qbs from an in-source build most paths are set up + When you run Qbs from an in-source build, most paths are set up automatically. If you do not build in-source, configure the following paths: @@ -178,13 +178,13 @@ Now open a build shell (on Windows open an MSVC command prompt, on other platforms the default shell is usually ok): \code - qbs platforms probe + qbs detect-toolchains \endcode - The platform prober will automatically choose a name for the detected - platforms. You can list the detected platforms by running + The toolchain detector will automatically set up a profile for each detected toolchain. + You can list the existing profiles by running \code - qbs platforms list + qbs config --list profiles \endcode Now you should be ready to build your first project with qbs. @@ -255,7 +255,7 @@ You can set the default Qt build you want to use like this: \code - qbs config profile qt5 + qbs config defaultProfile qt5 \endcode To choose a Qt build that's different from the default, use: @@ -264,15 +264,19 @@ qbs build profile:qt48 \endcode - You can set other properties in a profile not just Qt ones, in the same way + You can set other properties in a profile (not just Qt ones), in the same way you could override them from the command-line. For example: \code qbs setup-qt C:\Qt\5.0.0\qtbase\bin\qmake.exe qt5 qbs config profiles.qt5.qbs.architecture x86_64 - qbs config profiles.qt5.qbs.platform msvc2010 + qbs config profiles.qt5.qbs.baseProfile msvc2010 \endcode + The last example uses the inheritance feature of profiles: All settings in the profile + set as "baseProfile" are known in the derived profile as well. + They can of course be overridden there. + \section1 Customized Qt Settings If you have built your Qt with the option -qtnamespace MyNamespace diff --git a/share/qbs/modules/qbs/common.qbs b/share/qbs/modules/qbs/common.qbs index aad8d7041..6a0f7b0ed 100644 --- a/share/qbs/modules/qbs/common.qbs +++ b/share/qbs/modules/qbs/common.qbs @@ -6,7 +6,6 @@ Module { property bool enableDebugCode: buildVariant == "debug" property bool debugInformation: (buildVariant == "debug") property string optimization: (buildVariant == "debug" ? "none" : "fast") - property string platform property string hostOS: getHostOS() property string hostArchitecture: getHostDefaultArchitecture() property string pathListSeparator: hostOS === "windows" ? ";" : ":" diff --git a/src/app/app.pro b/src/app/app.pro index e1f741f8e..839898686 100644 --- a/src/app/app.pro +++ b/src/app/app.pro @@ -1,7 +1,7 @@ TEMPLATE = subdirs SUBDIRS =\ qbs\ - platforms \ + detect-toolchains \ setupmaddeplatforms \ qbs-setup-qt \ config \ diff --git a/src/app/config/configcommandexecutor.cpp b/src/app/config/configcommandexecutor.cpp index 62045f0c1..ba03c2023 100644 --- a/src/app/config/configcommandexecutor.cpp +++ b/src/app/config/configcommandexecutor.cpp @@ -49,7 +49,7 @@ void ConfigCommandExecutor::execute(const ConfigCommand &command) { switch (command.command) { case ConfigCommand::CfgList: - printSettings(); + printSettings(command); break; case ConfigCommand::CfgGet: puts(qPrintable(m_settings.value(command.varNames.first()).toString())); @@ -67,10 +67,10 @@ void ConfigCommandExecutor::execute(const ConfigCommand &command) case ConfigCommand::CfgImport: // Display old and new settings, in case import fails or user accidentally nukes everything printf("old "); // Will end up as "old settings:" - printSettings(); + printSettings(command); importSettings(command.fileName); printf("\nnew "); - printSettings(); + printSettings(command); break; case ConfigCommand::CfgNone: qFatal("%s: Impossible command value.", Q_FUNC_INFO); @@ -78,14 +78,28 @@ void ConfigCommandExecutor::execute(const ConfigCommand &command) } } -void ConfigCommandExecutor::printSettings() +void ConfigCommandExecutor::printSettings(const ConfigCommand &command) { - foreach (const QString &key, m_settings.allKeys()) { - printf("%s: %s\n", qPrintable(key), - qPrintable(m_settings.value(key).toString())); + if (command.varNames.isEmpty()) { + foreach (const QString &key, m_settings.allKeys()) + printOneSetting(key); + } else { + foreach (const QString &parentKey, command.varNames) { + if (m_settings.value(parentKey).isValid()) { // Key is a leaf. + printOneSetting(parentKey); + } else { // Key is a node. + foreach (const QString &key, m_settings.allKeysWithPrefix(parentKey)) + printOneSetting(parentKey + QLatin1Char('.') + key); + } + } } } +void ConfigCommandExecutor::printOneSetting(const QString &key) +{ + printf("%s: %s\n", qPrintable(key), qPrintable(m_settings.value(key).toString())); + } + void ConfigCommandExecutor::exportSettings(const QString &filename) { QFile file(filename); diff --git a/src/app/config/configcommandexecutor.h b/src/app/config/configcommandexecutor.h index c03a56c65..e85bf17c0 100644 --- a/src/app/config/configcommandexecutor.h +++ b/src/app/config/configcommandexecutor.h @@ -44,7 +44,8 @@ public: void execute(const ConfigCommand &command); private: - void printSettings(); + void printSettings(const ConfigCommand &command); + void printOneSetting(const QString &key); void exportSettings(const QString &filename); void importSettings(const QString &filename); diff --git a/src/app/config/configcommandlineparser.cpp b/src/app/config/configcommandlineparser.cpp index 30c6c0ac0..20e318334 100644 --- a/src/app/config/configcommandlineparser.cpp +++ b/src/app/config/configcommandlineparser.cpp @@ -91,6 +91,9 @@ void ConfigCommandLineParser::parse(const QStringList &commandLine) throw Error("Need name of file from which to import."); m_command.fileName = args.first(); break; + case ConfigCommand::CfgList: + m_command.varNames = args; + break; default: break; } @@ -108,8 +111,8 @@ void ConfigCommandLineParser::printHelp() const puts("usage: qbs config [options]\n" "\n" "Options:\n" - " --list list all variables\n" - " --unset <name> remove variable with given name\n" - " --import <file> import settings from given file\n" - " --export <file> export settings to given file\n"); + " --list [<root> ...] list variables under key <root> or all variables\n" + " --unset <name> remove variable with given name\n" + " --import <file> import settings from given file\n" + " --export <file> export settings to given file\n"); } diff --git a/src/app/platforms/platforms.pro b/src/app/detect-toolchains/detect-toolchains.pro index 7f0df7edd..b9aacd9a2 100644 --- a/src/app/platforms/platforms.pro +++ b/src/app/detect-toolchains/detect-toolchains.pro @@ -1,13 +1,13 @@ QT = core script gui TEMPLATE = app -TARGET = qbs-platforms +TARGET = qbs-detect-toolchains DESTDIR = ../../../bin/ CONFIG += console CONFIG -= app_bundle -HEADERS = msvcprobe.h +HEADERS = probe.h msvcprobe.h SOURCES += main.cpp probe.cpp msvcprobe.cpp include(../../lib/use.pri) diff --git a/src/app/detect-toolchains/main.cpp b/src/app/detect-toolchains/main.cpp new file mode 100644 index 000000000..d45f35597 --- /dev/null +++ b/src/app/detect-toolchains/main.cpp @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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. +** +****************************************************************************/ + +#include "probe.h" + +#include <logging/consolelogger.h> +#include <logging/translator.h> +#include <tools/error.h> + +#include <QCoreApplication> + +#include <cstdlib> + +using namespace qbs; + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + + ConsoleLogger cl; + if (app.arguments().count() > 1) { + qbsWarning() << Internal::Tr::tr("You supplied command-line arguments, " + "but this tool does not use any."); + } + + try { + probe(); + return EXIT_SUCCESS; + } catch (const Error &error) { + qbsError() << Tr::tr("Probing for toolchains failed: %1").arg(error.toString()); + return EXIT_FAILURE; + } +} diff --git a/src/app/platforms/msvcprobe.cpp b/src/app/detect-toolchains/msvcprobe.cpp index 50d071f6b..f8c307eeb 100644 --- a/src/app/platforms/msvcprobe.cpp +++ b/src/app/detect-toolchains/msvcprobe.cpp @@ -29,6 +29,11 @@ #include "msvcprobe.h" +#include <logging/logger.h> +#include <logging/translator.h> +#include <tools/profile.h> +#include <tools/settings.h> + #include <QDir> #include <QFileInfo> #include <QSettings> @@ -56,25 +61,22 @@ Q_DECLARE_TYPEINFO(WinSDK, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(MSVC, Q_MOVABLE_TYPE); QT_END_NAMESPACE -static void addMSVCPlatform(const QString &settingsPath, QHash<QString, Platform::Ptr> &platforms, const QString &platformName, const QString &installPath, const QString &winSDKPath) +static void addMSVCPlatform(Settings *settings, QList<Profile> &profiles, const QString &name, + const QString &installPath, const QString &winSDKPath) { - Platform::Ptr platform = platforms.value(platformName); - if (!platform) { - platform = Platform::Ptr(new Platform(platformName, settingsPath + "/" + platformName)); - platforms.insert(platform->name, platform); - } - platform->settings.setValue("targetOS", "windows"); - platform->settings.setValue("cpp/toolchainInstallPath", installPath); - platform->settings.setValue("toolchain", "msvc"); - platform->settings.setValue("cpp/windowsSDKPath", winSDKPath); - QTextStream qstdout(stdout); - qstdout << "Setting up platform " << platformName << endl; + qbsInfo() << DontPrintLogLevel << Tr::tr("Setting up profile '%1'.").arg(name); + Profile p(name, settings); + p.removeProfile(); + p.setValue("qbs.targetOS", "windows"); + p.setValue("cpp.toolchainInstallPath", installPath); + p.setValue("qbs.toolchain", "msvc"); + p.setValue("cpp.windowsSDKPath", winSDKPath); + profiles << p; } -void msvcProbe(const QString &settingsPath, QHash<QString, Platform::Ptr> &platforms) +void msvcProbe(Settings *settings, QList<Profile> &profiles) { - QTextStream qstdout(stdout); - qstdout << "Detecting MSVC toolchains..." << endl; + qbsInfo() << DontPrintLogLevel << Tr::tr("Detecting MSVC toolchains..."); // 1) Installed SDKs preferred over standalone Visual studio QVector<WinSDK> winSDKs; @@ -100,13 +102,13 @@ void msvcProbe(const QString &settingsPath, QHash<QString, Platform::Ptr> &platf } foreach (const WinSDK &sdk, winSDKs) { - qstdout << " Windows SDK detected:\n" - << " version " << sdk.version << endl - << " installed in " << sdk.installPath << endl; + qbsInfo() << DontPrintLogLevel << Tr::tr(" Windows SDK detected:\n" + " version %1\n" + " installed in %2").arg(sdk.version, sdk.installPath); if (sdk.hasCompiler) - qstdout << " This SDK contains C++ compiler(s)." << endl; + qbsInfo() << DontPrintLogLevel << Tr::tr(" This SDK contains C++ compiler(s)."); if (sdk.isDefault) - qstdout << " This is the default SDK on this machine." << endl; + qbsInfo() << DontPrintLogLevel << Tr::tr(" This is the default SDK on this machine."); } // 2) Installed MSVCs @@ -148,7 +150,7 @@ void msvcProbe(const QString &settingsPath, QHash<QString, Platform::Ptr> &platf } if (msvc.version.isEmpty()) { - qstdout << " Unknown MSVC version " << nVersion << " found." << endl; + qbsInfo() << DontPrintLogLevel << Tr::tr(" Unknown MSVC version %1 found.").arg(nVersion); continue; } @@ -160,20 +162,27 @@ void msvcProbe(const QString &settingsPath, QHash<QString, Platform::Ptr> &platf msvcs += msvc; } - foreach (const MSVC &msvc, msvcs) - qstdout << " MSVC detected:\n" - << " version " << msvc.version << endl - << " installed in " << msvc.installPath << endl; + foreach (const MSVC &msvc, msvcs) { + qbsInfo() << DontPrintLogLevel << Tr::tr(" MSVC detected:\n" + " version %1\n" + " installed in %2").arg(msvc.version, msvc.installPath); + } if (winSDKs.isEmpty() && msvcs.isEmpty()) { - qstdout << "Could not detect an installation of the Windows SDK nor Visual Studio." << endl; + qbsInfo() << DontPrintLogLevel << Tr::tr("Could not detect an installation of " + "the Windows SDK or Visual Studio."); return; } - foreach (const WinSDK &sdk, winSDKs) - if (sdk.hasCompiler) - addMSVCPlatform(settingsPath, platforms, QLatin1String("WinSDK") + sdk.version, sdk.installPath, defaultWinSDK.installPath); + foreach (const WinSDK &sdk, winSDKs) { + if (sdk.hasCompiler) { + addMSVCPlatform(settings, profiles, QLatin1String("WinSDK") + sdk.version, + sdk.installPath, defaultWinSDK.installPath); + } + } - foreach (const MSVC &msvc, msvcs) - addMSVCPlatform(settingsPath, platforms, QLatin1String("MSVC") + msvc.version, msvc.installPath, defaultWinSDK.installPath); + foreach (const MSVC &msvc, msvcs) { + addMSVCPlatform(settings, profiles, QLatin1String("MSVC") + msvc.version, + msvc.installPath, defaultWinSDK.installPath); + } } diff --git a/src/app/platforms/msvcprobe.h b/src/app/detect-toolchains/msvcprobe.h index 8756697df..30f067c36 100644 --- a/src/app/platforms/msvcprobe.h +++ b/src/app/detect-toolchains/msvcprobe.h @@ -30,8 +30,13 @@ #ifndef MSVCPROBE_H #define MSVCPROBE_H -#include <tools/platform.h> +#include <QList> -void msvcProbe(const QString &settingsPath, QHash<QString, qbs::Platform::Ptr> &platforms); +namespace qbs { +class Profile; +class Settings; +} + +void msvcProbe(qbs::Settings *settings, QList<qbs::Profile> &profiles); #endif // MSVCPROBE_H diff --git a/src/app/platforms/probe.cpp b/src/app/detect-toolchains/probe.cpp index 3739cc8c4..40020512b 100644 --- a/src/app/platforms/probe.cpp +++ b/src/app/detect-toolchains/probe.cpp @@ -26,19 +26,21 @@ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ +#include "probe.h" + +#include "msvcprobe.h" #include <logging/logger.h> +#include <logging/translator.h> #include <tools/hostosinfo.h> -#include <tools/platform.h> -#include "msvcprobe.h" +#include <tools/profile.h> +#include <tools/settings.h> #include <QCoreApplication> #include <QDir> #include <QDirIterator> #include <QProcess> -#include <QSettings> #include <QStringList> -#include <QTextStream> using namespace qbs; @@ -62,15 +64,12 @@ static QString qsystem(const QString &exe, const QStringList &args = QStringList return QString::fromLocal8Bit(p.readAll()); } -static void specific_probe(const QString &settingsPath, - QHash<QString, Platform::Ptr> &platforms, - QString cc) +static void specific_probe(Settings *settings, QList<Profile> &profiles, QString cc) { - QTextStream qstdout(stdout); - qstdout << "Trying to detect " << cc << "..." << endl; + qbsInfo() << DontPrintLogLevel << Tr::tr("Trying to detect %1...").arg(cc); QString toolchainType; - if(cc.contains("clang")) + if (cc.contains("clang")) toolchainType = "clang"; else if (cc.contains("gcc")) toolchainType = "gcc"; @@ -78,9 +77,6 @@ static void specific_probe(const QString &settingsPath, QString path = QString::fromLocal8Bit(qgetenv("PATH")); QString cxx = QString::fromLocal8Bit(qgetenv("CXX")); QString ld = QString::fromLocal8Bit(qgetenv("LD")); - QString cflags = QString::fromLocal8Bit(qgetenv("CFLAGS")); - QString cxxflags = QString::fromLocal8Bit(qgetenv("CXXFLAGS")); - QString ldflags = QString::fromLocal8Bit(qgetenv("LDFLAGS")); QString cross = QString::fromLocal8Bit(qgetenv("CROSS_COMPILE")); QString arch = QString::fromLocal8Bit(qgetenv("ARCH")); @@ -88,9 +84,6 @@ static void specific_probe(const QString &settingsPath, QString architecture; QString endianness; - QString name; - QString sysroot; - QString uname = qsystem("uname", QStringList() << "-m").simplified(); if (arch.isEmpty()) @@ -125,30 +118,19 @@ static void specific_probe(const QString &settingsPath, pathToGcc = searchPath(path, cc); if (!QFileInfo(pathToGcc).exists()) { - qstdout << cc << " not found." << endl; + qbsInfo() << DontPrintLogLevel << Tr::tr("%1 not found.").arg(cc); return; } - Platform::Ptr s; - foreach (Platform::Ptr p, platforms.values()) { - QString path = p->settings.value(Platform::internalKey() + "/completeccpath").toString(); - if (path == pathToGcc) { - name = p->name; - s = p; - name = s->name; - break; - } - } - QString compilerTriplet = qsystem(pathToGcc, QStringList() << "-dumpmachine").simplified(); QStringList compilerTripletl = compilerTriplet.split('-'); if (compilerTripletl.count() < 2 || !(compilerTripletl.at(0).contains(QRegExp(".86")) || compilerTripletl.at(0).contains("arm") ) ) { - qbs::qbsError("Detected '%s', but I don't understand its architecture '%s'.", + qbsError("Detected '%s', but I don't understand its architecture '%s'.", qPrintable(pathToGcc), qPrintable(compilerTriplet)); - return; + return; } architecture = compilerTripletl.at(0); @@ -161,88 +143,44 @@ static void specific_probe(const QString &settingsPath, QStringList pathToGccL = pathToGcc.split('/'); QString compilerName = pathToGccL.takeLast().replace(cc, cxx); - if (cflags.contains("--sysroot")) { - QStringList flagl = cflags.split(' '); - - bool nextitis = false; - foreach (const QString &flag, flagl) { - if (nextitis) { - sysroot = flag; - break; - } - if (flag == "--sysroot") { - nextitis = true; - } - } - } - - qstdout << "==> " << (s?"reconfiguring " + name :"detected") - << " " << pathToGcc << "\n" - << " triplet: " << compilerTriplet << "\n" - << " arch: " << architecture << "\n" - << " bin: " << pathToGccL.join("/") << "\n" - << " cc: " << cc << "\n" - ; - + qbsInfo() << DontPrintLogLevel << Tr::tr("Toolchain detected:\n" + " binary: %1\n" + " triplet: %2\n" + " arch: %3\n" + " cc: %4").arg(pathToGcc, compilerTriplet, architecture, cc); if (!cxx.isEmpty()) - qstdout << " cxx: " << cxx << "\n"; + qbsInfo() << DontPrintLogLevel << Tr::tr(" cxx: %1").arg(cxx); if (!ld.isEmpty()) - qstdout << " ld: " << ld << "\n"; - - if (!sysroot.isEmpty()) - qstdout << " sysroot: " << sysroot << "\n"; - if (!cflags.isEmpty()) - qstdout << " CFLAGS: " << cflags << "\n"; - if (!cxxflags.isEmpty()) - qstdout << " CXXFLAGS: " << cxxflags << "\n"; - if (!ldflags.isEmpty()) - qstdout << " CXXFLAGS: " << ldflags << "\n"; + qbsInfo() << DontPrintLogLevel << Tr::tr(" ld: %1").arg(ld); - qstdout << flush; - - if (!s) { - if (name.isEmpty()) - name = toolchainType; - s = Platform::Ptr(new Platform(name, settingsPath + "/" + name)); - } + Profile profile(toolchainType, settings); + profile.removeProfile(); // fixme should be cpp.toolchain // also there is no toolchain:clang - s->settings.setValue("toolchain", "gcc"); - s->settings.setValue(Platform::internalKey() + "/completeccpath", pathToGcc); - s->settings.setValue(Platform::internalKey() + "/target-triplet", compilerTriplet); - s->settings.setValue("architecture", architecture); - s->settings.setValue("endianness", endianness); + profile.setValue("qbs.toolchain", "gcc"); + profile.setValue("qbs.architecture", architecture); + profile.setValue("qbs.endianness", endianness); if (HostOsInfo::isMacHost()) - s->settings.setValue("targetOS", "mac"); + profile.setValue("qbs.targetOS", "mac"); else if (HostOsInfo::isLinuxHost()) - s->settings.setValue("targetOS", "linux"); + profile.setValue("qbs.targetOS", "linux"); else - s->settings.setValue("targetOS", "unknown"); //fixme + profile.setValue("qbs.targetOS", "unknown"); //fixme if (compilerName.contains('-')) { QStringList nl = compilerName.split('-'); - s->settings.setValue("cpp/compilerName", nl.takeLast()); - s->settings.setValue("cpp/toolchainPrefix", nl.join("-") + '-'); + profile.setValue("cpp.compilerName", nl.takeLast()); + profile.setValue("cpp.toolchainPrefix", nl.join("-") + '-'); } else { - s->settings.setValue("cpp/compilerName", compilerName); + profile.setValue("cpp.compilerName", compilerName); } - s->settings.setValue("cpp/toolchainInstallPath", pathToGccL.join("/")); - - if (!cross.isEmpty()) - s->settings.setValue("environment/CROSS_COMPILE", cross); - if (!cflags.isEmpty()) - s->settings.setValue("environment/CFLAGS", cflags); - if (!cxxflags.isEmpty()) - s->settings.setValue("environment/CXXFLAGS", cxxflags); - if (!ldflags.isEmpty()) - s->settings.setValue("environment/LDFLAGS", ldflags); - - platforms.insert(s->name, s); + profile.setValue("cpp.toolchainInstallPath", pathToGccL.join("/")); + profiles << profile; } -static void mingwProbe(const QString &settingsPath, QHash<QString, Platform::Ptr> &platforms) +static void mingwProbe(Settings *settings, QList<Profile> &profiles) { QString mingwPath; QString mingwBinPath; @@ -272,27 +210,33 @@ static void mingwProbe(const QString &settingsPath, QHash<QString, Platform::Ptr return; } - Platform::Ptr platform = platforms.value(gccMachineName); - printf("Platform '%s' detected in '%s'.", gccMachineName.data(), qPrintable(QDir::toNativeSeparators(mingwPath))); - if (!platform) { - platform = Platform::Ptr(new Platform(gccMachineName, settingsPath + "/" + gccMachineName)); - platforms.insert(platform->name, platform); - } - platform->settings.setValue("targetOS", "windows"); - platform->settings.setValue("cpp/toolchainInstallPath", QDir::toNativeSeparators(mingwBinPath)); - platform->settings.setValue("toolchain", "mingw"); + + Profile profile(QString::fromLocal8Bit(gccMachineName), settings); + qbsInfo() << DontPrintLogLevel + << Tr::tr("Platform '%1' detected in '%2'.").arg(profile.name(), mingwPath); + profile.setValue("qbs.targetOS", "windows"); + profile.setValue("cpp.toolchainInstallPath", mingwBinPath); + profile.setValue("qbs.toolchain", "mingw"); + profiles << profile; } -int probe(const QString &settingsPath, QHash<QString, Platform::Ptr> &platforms) +int probe() { + QList<Profile> profiles; + Settings settings; if (HostOsInfo::isWindowsHost()) { - msvcProbe(settingsPath, platforms); - mingwProbe(settingsPath, platforms); + msvcProbe(&settings, profiles); + mingwProbe(&settings, profiles); } else { - specific_probe(settingsPath, platforms, "gcc"); - specific_probe(settingsPath, platforms, "clang"); + specific_probe(&settings, profiles, QLatin1String("gcc")); + specific_probe(&settings, profiles, QLatin1String("clang")); + } + + if (profiles.isEmpty()) { + qbsWarning() << Tr::tr("Could not detect any toolchains. No profile created."); + } else if (profiles.count() == 1 && settings.defaultProfile().isEmpty()) { + qbsInfo() << DontPrintLogLevel << Tr::tr("Making profile '%1' the default."); + settings.setValue(QLatin1String("defaultProfile"), profiles.first().name()); } - if (platforms.isEmpty()) - qbsWarning("Could not detect any platforms."); return 0; } diff --git a/src/lib/tools/platform.h b/src/app/detect-toolchains/probe.h index af4d1b87c..ab2f42534 100644 --- a/src/lib/tools/platform.h +++ b/src/app/detect-toolchains/probe.h @@ -26,28 +26,9 @@ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ +#ifndef QBS_PROBE_H +#define QBS_PROBE_H -#ifndef QBS_PLATFORM_H -#define QBS_PLATFORM_H +int probe(); -#include <QSettings> -#include <QSharedPointer> -#include <QTextStream> - -namespace qbs { - -class Platform -{ -public: - typedef QSharedPointer<Platform> Ptr; - Platform(const QString &name, const QString& configpath); - QString name; - QSettings settings; - static QHash<QString, Platform::Ptr> platforms(); - static QString configBaseDir(); - static QString internalKey(); -}; - -} // namespace qbs - -#endif +#endif // Header guard diff --git a/src/app/platforms/main.cpp b/src/app/platforms/main.cpp deleted file mode 100644 index 2a79a1637..000000000 --- a/src/app/platforms/main.cpp +++ /dev/null @@ -1,237 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 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. -** -****************************************************************************/ - -#include <logging/consolelogger.h> -#include <tools/platform.h> -#include <tools/settings.h> - -#include <QCoreApplication> -#include <QDir> -#include <QDirIterator> -#include <QProcess> -#include <QSettings> -#include <QStringList> -#include <QTextStream> - -#ifdef Q_OS_UNIX -#include <iostream> -#include <termios.h> -#endif - -#ifdef Q_OS_WIN -#include <qt_windows.h> -#include <shlobj.h> -#endif - -#include <cstdio> - -using namespace qbs; - -static void showUsage() -{ - QTextStream s(stderr); - s << "platform [action]\n" - << "actions:\n" - << " ls|list -- list available platforms\n" - << " mv|rename <from> <to> -- rename a platform\n" - << " rm|remove <name> -- irrevocably remove the given target\n" - << " config <name> [<key>] [<value>] -- show or change configuration\n" - << " probe -- probe the current environment\n" - << " and construct qbs platforms for each compiler found\n" - << " print-config-base-dir -- prints the base dir of the platform configurations\n" - ; -} - -static QString toInternalSeparators(const QString &variable) -{ - QString transformedVar = variable; - return transformedVar.replace(QLatin1Char('.'), QLatin1Char('/')); -} - -static QString toExternalSeparators(const QString &variable) -{ - QString transformedVar = variable; - return transformedVar.replace(QLatin1Char('/'), QLatin1Char('.')); -} - -int probe(const QString &settingsPath, QHash<QString, Platform::Ptr> &platforms); - -int main(int argc, char **argv) -{ - QCoreApplication app(argc, argv); - QTextStream qstdout(stdout); - - ConsoleLogger cl; - - Settings settings; - QString defaultPlatform = settings.value("modules.qbs.platform").toString(); - - QString localSettingsPath = Platform::configBaseDir(); - if (!localSettingsPath.endsWith(QLatin1Char('/'))) - localSettingsPath.append(QLatin1Char('/')); - QDir().mkpath(localSettingsPath); - - enum Action { - ListPlatform, - ProbePlatform, - RenamePlatform, - RemovePlatform, - ConfigPlatform - }; - - Action action = ListPlatform; - - QStringList arguments = app.arguments(); - arguments.takeFirst(); - if (arguments.count()) { - QString cmd = arguments.takeFirst(); - if (cmd == "probe") { - action = ProbePlatform; - } else if (cmd == "rename" || cmd == "mv") { - action = RenamePlatform; - } else if (cmd == "rm" || cmd == "remove") { - action = RemovePlatform; - } else if (cmd == "config") { - action = ConfigPlatform; - } else if (cmd == "list" || cmd == "ls") { - action = ListPlatform; - } else if (cmd == "print-config-base-dir") { - puts(qPrintable(QDir::toNativeSeparators(Platform::configBaseDir()))); - return 0; - } else { - showUsage(); - return 3; - } - } - - QHash<QString, Platform::Ptr> platforms; - QDirIterator i(localSettingsPath, QDir::Dirs | QDir::NoDotAndDotDot); - while (i.hasNext()) { - i.next(); - Platform::Ptr platform(new Platform(i.fileName(), i.filePath())); - platforms.insert(platform->name, platform); - } - - if (action == ListPlatform) { - qstdout << "Platforms:\n"; - foreach (Platform::Ptr platform, platforms.values()) { - qstdout << "\t- " << platform->name; - if (platform->name == defaultPlatform) - qstdout << " (default)"; - qstdout << " "<< platform->settings.value("target-triplet").toString() << "\n"; - } - } else if (action == RenamePlatform) { - if (arguments.count() < 2) { - showUsage(); - return 3; - } - QString from = arguments.takeFirst(); - if (!platforms.contains(from)) { - qbsError("Cannot rename: No such target '%s'.", qPrintable(from)); - return 5; - } - QString to = arguments.takeFirst(); - if (platforms.contains(to)) { - qbsError("Cannot rename: Target '%s' already exists.", qPrintable(to)); - return 5; - } - if (!QFile(localSettingsPath + from).rename(localSettingsPath + to)) { - qbsError("File error moving '%s'' to '%s'.", - qPrintable(localSettingsPath + from), - qPrintable(localSettingsPath + to) - ); - return 5; - } - platforms.insert(to, platforms.take(from)); - } else if (action == RemovePlatform) { - if (arguments.count() < 1) { - showUsage(); - return 3; - } - QString targetName = arguments.takeFirst(); - if (!platforms.contains(targetName)) { - qbsError("Cannot remove: No such target '%s'.", qPrintable(targetName)); - return 5; - } - QDirIterator i1(localSettingsPath + targetName, - QDir::Files | QDir::NoDotAndDotDot | QDir::System | QDir::Hidden, - QDirIterator::Subdirectories); - while (i1.hasNext()) { - i1.next(); - QFile(i1.filePath()).remove(); - } - QDirIterator i2(localSettingsPath + targetName, - QDir::Dirs| QDir::NoDotAndDotDot | QDir::System | QDir::Hidden, - QDirIterator::Subdirectories); - while (i2.hasNext()) { - i2.next(); - QDir().rmdir(i2.filePath()); - } - QDir().rmdir(localSettingsPath + targetName); - platforms.remove(targetName); - } else if (action == ConfigPlatform) { - if (arguments.count() < 1) { - showUsage(); - return 3; - } - QString platformName = arguments.takeFirst(); - if (!platforms.contains(platformName)) { - qbsError("Unknown platform '%s'.", qPrintable(platformName)); - return 5; - } - Platform::Ptr p = platforms.value(platformName); - if (arguments.count()) { - const QString key = toInternalSeparators(arguments.takeFirst()); - if (arguments.count()) { - QString value = arguments.takeFirst(); - p->settings.setValue(key, value); - } - if (!p->settings.contains(key)) { - qbsError("No such configuration key '%s'.", - qPrintable(toExternalSeparators(key))); - return 7; - } - qstdout << p->settings.value(key).toString() << "\n"; - } else { - foreach (const QString &key, p->settings.allKeys()) { - qstdout << toExternalSeparators(key) - << "=" << p->settings.value(key).toString() << "\n"; - } - } - - } else if (action == ProbePlatform) { - bool firstRun = platforms.isEmpty(); - probe(localSettingsPath, platforms); - if (firstRun && !platforms.isEmpty()) { - settings.setValue(QLatin1String("modules.qbs.platform"), - platforms.values().at(0)->name); - } - } - return 0; -} diff --git a/src/app/qbs/parser/commandlineparser.cpp b/src/app/qbs/parser/commandlineparser.cpp index 6af745173..ebd95fe57 100644 --- a/src/app/qbs/parser/commandlineparser.cpp +++ b/src/app/qbs/parser/commandlineparser.cpp @@ -40,7 +40,6 @@ #include <tools/error.h> #include <tools/fileinfo.h> #include <tools/hostosinfo.h> -#include <tools/platform.h> #include <tools/settings.h> #include <QCoreApplication> diff --git a/src/app/shared/specialplatformssetup.cpp b/src/app/shared/specialplatformssetup.cpp index 8ffcb9a04..0f3f5d80f 100644 --- a/src/app/shared/specialplatformssetup.cpp +++ b/src/app/shared/specialplatformssetup.cpp @@ -28,6 +28,8 @@ ****************************************************************************/ #include "specialplatformssetup.h" +#include <tools/profile.h> + #include <QBuffer> #include <QCoreApplication> #include <QDir> @@ -35,7 +37,6 @@ #include <QFileInfo> #include <QProcess> #include <QProcessEnvironment> -#include <QSettings> #include <cstdio> @@ -51,17 +52,8 @@ void SpecialPlatformsSetup::setup() return; setupBaseDir(); - const QString qbsPath = QCoreApplication::applicationDirPath() + QLatin1String("/qbs"); - const QString commandLine = qbsPath + QLatin1String(" platforms print-config-base-dir"); - const QString configBaseDir = QString::fromLocal8Bit(runProcess(commandLine, - QProcessEnvironment::systemEnvironment())).trimmed(); - - foreach (const PlatformInfo &pi, gatherPlatformInfo()) { - writeConfigFile(pi, configBaseDir); - const QString registerCommandLine = QString::fromLocal8Bit("%1 config " - "profiles.%2.qbs.platform %2").arg(qbsPath, pi.name); - runProcess(registerCommandLine, QProcessEnvironment::systemEnvironment()); - } + foreach (const PlatformInfo &pi, gatherPlatformInfo()) + registerProfile(pi); } QString SpecialPlatformsSetup::helpString() const @@ -147,68 +139,31 @@ void SpecialPlatformsSetup::handleProcessError(const QString &commandLine, const throw Exception(completeMsg); } -void SpecialPlatformsSetup::writeConfigFile(const PlatformInfo &platformInfo, - const QString &configBaseDir) +void SpecialPlatformsSetup::registerProfile(const PlatformInfo &platformInfo) { - m_stdout << tr("Setting up platform '%1'...").arg(platformInfo.name) << endl; - - const QString configDir = configBaseDir + QLatin1Char('/') + platformInfo.name; - - /* - * A more correct solution would be to recursively remove and then recreate the directory. - * However, since it only contains one file, that currently seems like overkill. - */ - if (!QDir::root().mkpath(configDir)) { - throw Exception(tr("Directory '%1' could not be created.") - .arg(QDir::toNativeSeparators(configDir))); - } - const QString configFilePath = configDir + QLatin1String("/setup.ini"); - if (QFileInfo(configFilePath).exists()) { - QFile configFile(configFilePath); - if (!configFile.remove()) { - throw Exception(tr("Failed to remove old config file '%1': %2.") - .arg(QDir::toNativeSeparators(configFilePath), configFile.errorString())); - } - } - - QSettings settings(configFilePath, QSettings::IniFormat); - - settings.setValue(QLatin1String("toolchain"), QLatin1String("gcc")); - settings.setValue(QLatin1String("endianness"), QLatin1String("little-endian")); - settings.setValue(QLatin1String("targetOS"), platformInfo.targetOS); - settings.setValue(QLatin1String("targetPlatform"), platformInfo.targetPlatform); - settings.setValue(QLatin1String("sysroot"), platformInfo.sysrootDir); - - settings.beginGroup(QLatin1String("cpp")); - settings.setValue(QLatin1String("toolchainInstallPath"), platformInfo.toolchainDir); - settings.setValue(QLatin1String("compilerName"), platformInfo.compilerName); - settings.setValue(QLatin1String("cFlags"), platformInfo.cFlags); - settings.setValue(QLatin1String("cxxFlags"), platformInfo.cxxFlags); - settings.setValue(QLatin1String("linkerFlags"), platformInfo.ldFlags); - settings.endGroup(); - - settings.beginGroup(QLatin1String("qt/core")); - settings.setValue(QLatin1String("binPath"), platformInfo.qtBinDir); - settings.setValue(QLatin1String("libPath"), - platformInfo.sysrootDir + QLatin1String("/usr/lib")); - settings.setValue(QLatin1String("incPath"), platformInfo.qtIncDir); - settings.setValue(QLatin1String("mkspecPath"), platformInfo.qtMkspecPath); - settings.setValue(QLatin1String("namespace"), QString()); - settings.setValue(QLatin1String("libInfix"), QString()); - settings.endGroup(); - - settings.beginGroup(QLatin1String("environment")); - for (QHash<QString, QString>::ConstIterator it = platformInfo.environment.constBegin(); - it != platformInfo.environment.constEnd(); ++it) { - settings.setValue(it.key(), it.value()); - } - settings.endGroup(); - - settings.sync(); - if (settings.status() != QSettings::NoError) { - throw Exception(tr("Failed to write platform config file '%1'.") - .arg(QDir::toNativeSeparators(configFilePath))); - } + m_stdout << tr("Setting up profile '%1'...").arg(platformInfo.name) << endl; + + Profile profile(platformInfo.name); + profile.removeProfile(); + profile.setValue(QLatin1String("qbs.toolchain"), QLatin1String("gcc")); + profile.setValue(QLatin1String("qbs.endianness"), QLatin1String("little-endian")); + profile.setValue(QLatin1String("qbs.targetOS"), platformInfo.targetOS); + profile.setValue(QLatin1String("qbs.targetPlatform"), platformInfo.targetPlatform); + profile.setValue(QLatin1String("qbs.sysroot"), platformInfo.sysrootDir); + + profile.setValue(QLatin1String("cpp.toolchainInstallPath"), platformInfo.toolchainDir); + profile.setValue(QLatin1String("cpp.compilerName"), platformInfo.compilerName); + profile.setValue(QLatin1String("cpp.cFlags"), platformInfo.cFlags); + profile.setValue(QLatin1String("cpp.cxxFlags"), platformInfo.cxxFlags); + profile.setValue(QLatin1String("cpp.linkerFlags"), platformInfo.ldFlags); + + profile.setValue(QLatin1String("qt.core.binPath"), platformInfo.qtBinDir); + profile.setValue(QLatin1String("qt.core.libPath"), + platformInfo.sysrootDir + QLatin1String("/usr/lib")); + profile.setValue(QLatin1String("qt.core.incPath"), platformInfo.qtIncDir); + profile.setValue(QLatin1String("qt.core.mkspecPath"), platformInfo.qtMkspecPath); + profile.setValue(QLatin1String("qt.core.namespace"), QString()); + profile.setValue(QLatin1String("qt.core.libInfix"), QString()); } } // namespace qbs diff --git a/src/app/shared/specialplatformssetup.h b/src/app/shared/specialplatformssetup.h index f6f0e3a7d..64e18199f 100644 --- a/src/app/shared/specialplatformssetup.h +++ b/src/app/shared/specialplatformssetup.h @@ -87,7 +87,7 @@ private: void setupBaseDir(); void handleProcessError(const QString &commandLine, const QString &message, const QByteArray &output); - void writeConfigFile(const PlatformInfo &platformInfo, const QString &configBaseDir); + void registerProfile(const PlatformInfo &platformInfo); QString m_baseDir; QTextStream m_stdout; diff --git a/src/lib/api/project.cpp b/src/lib/api/project.cpp index 3d6c21275..507a5540c 100644 --- a/src/lib/api/project.cpp +++ b/src/lib/api/project.cpp @@ -41,7 +41,6 @@ #include <logging/translator.h> #include <tools/error.h> #include <tools/fileinfo.h> -#include <tools/platform.h> #include <tools/preferences.h> #include <tools/profile.h> #include <tools/scannerpluginmanager.h> @@ -259,17 +258,12 @@ SetupProjectJob *Project::setupProject(const QString &projectFilePath, */ QVariantMap Project::expandBuildConfiguration(const QVariantMap &buildConfig) { - QHash<QString, Platform::Ptr > platforms = Platform::platforms(); - if (platforms.isEmpty()) - throw Error(Tr::tr("No platforms configured. You must run 'qbs platforms probe' first.")); - Settings settings; QVariantMap expandedConfig = buildConfig; // Fill in buildCfg in this order (making sure not to overwrite a key already set by a previous stage) // 1) Things specified on command line (already in buildCfg at this point) // 2) Everything from the profile key - // 3) Everything from the platform QString profileName = expandedConfig.value("qbs.profile").toString(); if (profileName.isNull()) { profileName = settings.defaultProfile(); @@ -291,35 +285,11 @@ QVariantMap Project::expandBuildConfiguration(const QVariantMap &buildConfig) expandedConfig.insert(profileKey, profile.value(profileKey)); } - // (3) Need to make sure we have a value for qbs.platform before going any further - QVariant platformName = expandedConfig.value("qbs.platform"); - if (!platformName.isValid()) { - const QString platformKey = QLatin1String("qbs.platform"); - platformName = profile.value(platformKey); - if (platformName.isValid()) - expandedConfig.insert(platformKey, platformName); - } - Platform::Ptr platform = platforms.value(platformName.toString()); - if (!platform.isNull()) { - foreach (const QString &key, platform->settings.allKeys()) { - if (key.startsWith(Platform::internalKey())) - continue; - QString fixedKey = key; - int idx = fixedKey.lastIndexOf(QChar('/')); - if (idx > 0) - fixedKey[idx] = QChar('.'); - if (!expandedConfig.contains(fixedKey)) - expandedConfig.insert(fixedKey, platform->settings.value(key)); - } - } - if (!expandedConfig.value("qbs.buildVariant").isValid()) throw Error(Tr::tr("Property 'qbs.buildVariant' missing in build configuration.")); foreach (const QString &property, expandedConfig.keys()) { QStringList nameElements = property.split('.'); - if (nameElements.count() == 1 && nameElements.first() != "project") // ### Still need this because platform doesn't supply fully-qualified properties (yet), need to fix this - nameElements.prepend("qbs"); if (nameElements.count() > 2) { // ### workaround for submodules being represented internally as a single module of name "module/submodule" rather than two nested modules "module" and "submodule" QStringList allButLast = nameElements; allButLast.removeLast(); diff --git a/src/lib/tools/platform.cpp b/src/lib/tools/platform.cpp deleted file mode 100644 index 29abc3a85..000000000 --- a/src/lib/tools/platform.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 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. -** -****************************************************************************/ - -#include "platform.h" - -#include <tools/fileinfo.h> - -#include <QCoreApplication> -#include <QDir> -#include <QDirIterator> -#include <QSettings> -#include <QStringList> -#include <QTextStream> - -#ifdef Q_OS_WIN -# include <qt_windows.h> -# ifndef _WIN32_IE -# define _WIN32_IE 0x0400 // for MinGW -# endif -# include <shlobj.h> -#endif - -namespace qbs { -using namespace Internal; - -Platform::Platform(const QString &_name, const QString& configpath) - : name(_name) - , settings(configpath + "/setup.ini", QSettings::IniFormat) -{ -} - -QHash<QString, Platform::Ptr> Platform::platforms() -{ - QString localSettingsPath = configBaseDir(); - QHash<QString, Platform::Ptr> targets; - QDirIterator i(localSettingsPath, QDir::Dirs | QDir::NoDotAndDotDot); - while (i.hasNext()) { - i.next(); - Platform *t = new Platform(i.fileName(), i.filePath()); - targets.insert(t->name, Platform::Ptr(t)); - } - return targets; -} - -QString Platform::configBaseDir() -{ - QString localSettingsPath; -#if defined(Q_OS_UNIX) - localSettingsPath = QDir::homePath() + QLatin1String("/.config/QtProject/qbs/platforms"); - - // TODO: Remove in 0.4. - if (!FileInfo(localSettingsPath).exists()) { - const QString oldSettingsPath = QDir::homePath() - + QLatin1String("/.config/Nokia/qbs/platforms"); - if (FileInfo(oldSettingsPath).exists()) { - QString error; - if (!copyFileRecursion(oldSettingsPath, localSettingsPath, &error)) - qWarning("Failed to transfer settings: %s", qPrintable(error)); - } - } - -#elif defined(Q_OS_WIN) - wchar_t wszPath[MAX_PATH]; - if (SHGetSpecialFolderPath(NULL, wszPath, CSIDL_APPDATA, TRUE)) - localSettingsPath = QString::fromUtf16(reinterpret_cast<ushort*>(wszPath)) + "/qbs/platforms"; -#else -#error port me! -#endif - return localSettingsPath; -} - -QString Platform::internalKey() -{ - return QLatin1String("qbs-internal"); -} - -} // namespace qbs diff --git a/src/lib/tools/profile.cpp b/src/lib/tools/profile.cpp index 49c1f5401..e23b38e43 100644 --- a/src/lib/tools/profile.cpp +++ b/src/lib/tools/profile.cpp @@ -44,7 +44,7 @@ namespace qbs { * \enum Profile::KeySelection * This enum type specifies whether to enumerate keys recursively. * \value KeySelectionRecursive Indicates that key enumeration should happen recursively, i.e. - * it should go up the profile prototype chain. + * it should go up the base profile chain. * \value KeySelectionNonRecursive Indicates that only keys directly attached to a profile * should be listed. */ @@ -94,9 +94,17 @@ void Profile::remove(const QString &key) } /*! + * \brief Returns the name of this profile. + */ +QString Profile::name() const +{ + return m_name; +} + +/*! * \brief Returns all property keys in this profile. * If and only if selection is Profile::KeySelectionRecursive, this will also list keys defined - * in prototype profiles. + * in base profiles. */ QStringList Profile::allKeys(KeySelection selection) const { @@ -104,28 +112,36 @@ QStringList Profile::allKeys(KeySelection selection) const } /*! - * \brief Returns the name of this profile's prototype. - * The returned value is empty if the profile does not have a prototype. + * \brief Returns the name of this profile's base profile. + * The returned value is empty if the profile does not have a base profile. + */ +QString Profile::baseProfile() const +{ + return localValue(baseProfileKey()).toString(); +} + +/*! + * \brief Sets a new base profile for this profile. */ -QString Profile::prototype() const +void Profile::setBaseProfile(const QString &baseProfile) { - return localValue(prototypeKey()).toString(); + setValue(baseProfileKey(), baseProfile); } /*! - * Sets a new prototype for this profile. + * \brief Removes this profile's base profile setting. */ -void Profile::setPrototype(const QString &prototype) +void Profile::removeBaseProfile() { - setValue(prototypeKey(), prototype); + remove(baseProfileKey()); } /*! - * Removes this profile's prototype. + * \brief Removes this profile from the settings. */ -void Profile::removePrototype() +void Profile::removeProfile() { - remove(prototypeKey()); + remove(profileKey()); } QString Profile::profileKey() const @@ -133,9 +149,9 @@ QString Profile::profileKey() const return QLatin1String("profiles.") + m_name; } -QString Profile::prototypeKey() const +QString Profile::baseProfileKey() { - return QLatin1String("prototype"); + return QLatin1String("baseProfile"); } QVariant Profile::localValue(const QString &key) const @@ -155,10 +171,10 @@ QVariant Profile::possiblyInheritedValue(const QString &key, const QVariant &def const QVariant v = localValue(key); if (v.isValid()) return v; - const QString prototypeName = prototype(); - if (prototypeName.isEmpty()) + const QString baseProfileName = baseProfile(); + if (baseProfileName.isEmpty()) return defaultValue; - Profile parentProfile(prototypeName, m_settings); + Profile parentProfile(baseProfileName, m_settings); return parentProfile.possiblyInheritedValue(key, defaultValue, profileChain); } @@ -169,12 +185,13 @@ QStringList Profile::allKeysInternal(Profile::KeySelection selection, QStringList keys = m_settings->allKeysWithPrefix(profileKey()); if (selection == KeySelectionNonRecursive) return keys; - const QString prototypeName = prototype(); - if (prototypeName.isEmpty()) + const QString baseProfileName = baseProfile(); + if (baseProfileName.isEmpty()) return keys; - Profile parentProfile(prototypeName, m_settings); + Profile parentProfile(baseProfileName, m_settings); keys += parentProfile.allKeysInternal(KeySelectionRecursive, profileChain); keys.removeDuplicates(); + keys.removeOne(baseProfileKey()); keys.sort(); return keys; } diff --git a/src/lib/tools/profile.h b/src/lib/tools/profile.h index 8d62569f4..d667a219d 100644 --- a/src/lib/tools/profile.h +++ b/src/lib/tools/profile.h @@ -46,16 +46,20 @@ public: void setValue(const QString &key, const QVariant &value); void remove(const QString &key); - QString prototype() const; - void setPrototype(const QString &prototype); - void removePrototype(); + QString name() const; + + QString baseProfile() const; + void setBaseProfile(const QString &baseProfile); + void removeBaseProfile(); + + void removeProfile(); enum KeySelection { KeySelectionRecursive, KeySelectionNonRecursive }; QStringList allKeys(KeySelection selection) const; private: + static QString baseProfileKey(); QString profileKey() const; - QString prototypeKey() const; QVariant localValue(const QString &key) const; QString fullyQualifiedKey(const QString &key) const; QVariant possiblyInheritedValue(const QString &key, const QVariant &defaultValue, diff --git a/src/lib/tools/settings.cpp b/src/lib/tools/settings.cpp index 332625ebb..1c8219924 100644 --- a/src/lib/tools/settings.cpp +++ b/src/lib/tools/settings.cpp @@ -94,7 +94,7 @@ void Settings::remove(const QString &key) QString Settings::defaultProfile() const { - return value(QLatin1String("profile")).toString(); + return value(QLatin1String("defaultProfile")).toString(); } QString Settings::internalRepresentation(const QString &externalKey) const diff --git a/src/lib/tools/tools.pri b/src/lib/tools/tools.pri index f36b4d4c3..89c64db14 100644 --- a/src/lib/tools/tools.pri +++ b/src/lib/tools/tools.pri @@ -6,7 +6,6 @@ HEADERS += \ $$PWD/fileinfo.h \ $$PWD/filetime.h \ $$PWD/persistence.h \ - $$PWD/platform.h \ $$PWD/scannerpluginmanager.h \ $$PWD/scripttools.h \ $$PWD/settings.h \ @@ -23,7 +22,6 @@ SOURCES += \ $$PWD/error.cpp \ $$PWD/fileinfo.cpp \ $$PWD/persistence.cpp \ - $$PWD/platform.cpp \ $$PWD/scannerpluginmanager.cpp \ $$PWD/scripttools.cpp \ $$PWD/settings.cpp \ diff --git a/tests/auto/tools/tst_tools.cpp b/tests/auto/tools/tst_tools.cpp index d7813eaa1..12cdd30c7 100644 --- a/tests/auto/tools/tst_tools.cpp +++ b/tests/auto/tools/tst_tools.cpp @@ -133,20 +133,20 @@ private slots: Profile parentProfile("parent", &settings); Profile childProfile("child", &settings); try { - parentProfile.removePrototype(); + parentProfile.removeBaseProfile(); parentProfile.remove("testKey"); QCOMPARE(parentProfile.value("testKey", "none").toString(), QLatin1String("none")); parentProfile.setValue("testKey", "testValue"); QCOMPARE(parentProfile.value("testKey").toString(), QLatin1String("testValue")); childProfile.remove("testKey"); - childProfile.removePrototype(); + childProfile.removeBaseProfile(); QCOMPARE(childProfile.value("testKey", "none").toString(), QLatin1String("none")); - childProfile.setPrototype("blubb"); + childProfile.setBaseProfile("blubb"); QCOMPARE(childProfile.value("testKey", "none").toString(), QLatin1String("none")); - childProfile.setPrototype("parent"); + childProfile.setBaseProfile("parent"); QCOMPARE(childProfile.value("testKey").toString(), QLatin1String("testValue")); - childProfile.setPrototype("foo"); + childProfile.setBaseProfile("foo"); QCOMPARE(childProfile.value("testKey", "none").toString(), QLatin1String("none")); exceptionCaught = false; } catch (Error &) { @@ -155,8 +155,8 @@ private slots: QVERIFY(!exceptionCaught); try { - childProfile.setPrototype("parent"); - parentProfile.setPrototype("child"); + childProfile.setBaseProfile("parent"); + parentProfile.setBaseProfile("child"); QVERIFY(!childProfile.value("blubb").isValid()); exceptionCaught = false; } catch (Error &) { |