aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/app/app.pri11
-rw-r--r--src/app/apps.qbs1
-rw-r--r--src/app/apptemplate.qbs2
-rw-r--r--src/app/qbs-setup-qt/setupqt.cpp1
-rw-r--r--src/app/qbs-setup-toolchains/probe.cpp13
-rw-r--r--src/lib/corelib/api/project.cpp9
-rw-r--r--src/lib/corelib/api/projectdata.cpp6
-rw-r--r--src/lib/corelib/api/projectdata.h1
-rw-r--r--src/lib/corelib/api/projectdata_p.h1
-rw-r--r--src/lib/corelib/api/runenvironment.cpp25
-rw-r--r--src/lib/corelib/buildgraph/executor.cpp6
-rw-r--r--src/lib/corelib/buildgraph/rulesapplicator.cpp5
-rw-r--r--src/lib/corelib/buildgraph/transformer.cpp7
-rw-r--r--src/lib/corelib/language/builtindeclarations.cpp13
-rw-r--r--src/lib/corelib/language/item.cpp8
-rw-r--r--src/lib/corelib/language/item.h1
-rw-r--r--src/lib/corelib/language/language.cpp13
-rw-r--r--src/lib/corelib/language/language.h1
-rw-r--r--src/lib/corelib/language/loader.cpp6
-rw-r--r--src/lib/corelib/language/moduleloader.cpp60
-rw-r--r--src/lib/corelib/language/moduleloader.h12
-rw-r--r--src/lib/corelib/language/projectresolver.cpp71
-rw-r--r--src/lib/corelib/language/projectresolver.h3
-rw-r--r--src/lib/corelib/language/testdata/erroneous/conflicting_fileTagsFilter.qbs13
-rw-r--r--src/lib/corelib/language/testdata/profilevaluesandoverriddenvalues.qbs5
-rw-r--r--src/lib/corelib/language/tst_language.cpp4
-rw-r--r--src/lib/corelib/tools/settings.cpp27
-rw-r--r--src/lib/qtprofilesetup/qtprofilesetup.cpp25
-rw-r--r--src/lib/qtprofilesetup/qtprofilesetup.h1
-rw-r--r--src/lib/qtprofilesetup/templates/core.qbs75
-rw-r--r--src/lib/qtprofilesetup/templates/gui.qbs2
31 files changed, 253 insertions, 175 deletions
diff --git a/src/app/app.pri b/src/app/app.pri
index 8dc6dc95b..3a86e5a0f 100644
--- a/src/app/app.pri
+++ b/src/app/app.pri
@@ -1,6 +1,12 @@
QT = core
TEMPLATE = app
-DESTDIR = ../../../bin
+!isEmpty(QBS_APPS_DESTDIR):DESTDIR = $${QBS_APPS_DESTDIR}
+else:DESTDIR = ../../../bin
+
+!isEmpty(QBS_APPS_RPATH_DIR) {
+ linux-*:QMAKE_LFLAGS += -Wl,-z,origin \'-Wl,-rpath,$${QBS_APPS_RPATH_DIR}\'
+ macx:QMAKE_LFLAGS += -Wl,-rpath,$${QBS_APPS_RPATH_DIR}
+}
CONFIG += console
CONFIG -= app_bundle
@@ -8,5 +14,6 @@ CONFIG -= app_bundle
include($${PWD}/../lib/corelib/use_corelib.pri)
include($${PWD}/shared/logging/logging.pri)
-target.path = $${QBS_INSTALL_PREFIX}/bin
+!isEmpty(QBS_APPS_INSTALL_DIR):target.path = $${QBS_APPS_INSTALL_DIR}
+else:target.path = $${QBS_INSTALL_PREFIX}/bin
INSTALLS += target
diff --git a/src/app/apps.qbs b/src/app/apps.qbs
index 56d8d3289..f3a87f81e 100644
--- a/src/app/apps.qbs
+++ b/src/app/apps.qbs
@@ -1,6 +1,7 @@
import qbs
Project {
+ property string appInstallDir: "bin"
references: [
"config/config.qbs",
"config-ui/config-ui.qbs",
diff --git a/src/app/apptemplate.qbs b/src/app/apptemplate.qbs
index 2d87a0233..7ebe33b2d 100644
--- a/src/app/apptemplate.qbs
+++ b/src/app/apptemplate.qbs
@@ -13,7 +13,7 @@ Product {
Group {
fileTagsFilter: product.type
qbs.install: true
- qbs.installDir: "bin"
+ qbs.installDir: project.appInstallDir
}
Group {
name: "logging"
diff --git a/src/app/qbs-setup-qt/setupqt.cpp b/src/app/qbs-setup-qt/setupqt.cpp
index b36272713..c7b1ea16d 100644
--- a/src/app/qbs-setup-qt/setupqt.cpp
+++ b/src/app/qbs-setup-qt/setupqt.cpp
@@ -180,6 +180,7 @@ QtEnvironment SetupQt::fetchEnvironment(const QString &qmakePath)
qtEnvironment.binaryPath = pathQueryValue(queryOutput, "QT_INSTALL_BINS");
qtEnvironment.documentationPath = pathQueryValue(queryOutput, "QT_INSTALL_DOCS");
qtEnvironment.pluginPath = pathQueryValue(queryOutput, "QT_INSTALL_PLUGINS");
+ qtEnvironment.qmlPath = pathQueryValue(queryOutput, "QT_INSTALL_QML");
qtEnvironment.qmlImportPath = pathQueryValue(queryOutput, "QT_INSTALL_IMPORTS");
qtEnvironment.qtVersion = QString::fromLocal8Bit(queryOutput.value("QT_VERSION"));
diff --git a/src/app/qbs-setup-toolchains/probe.cpp b/src/app/qbs-setup-toolchains/probe.cpp
index 63793dc63..4c35c4b65 100644
--- a/src/app/qbs-setup-toolchains/probe.cpp
+++ b/src/app/qbs-setup-toolchains/probe.cpp
@@ -250,9 +250,18 @@ void probe(Settings *settings)
void createProfile(const QString &profileName, const QString &toolchainType,
const QString &compilerFilePath, Settings *settings)
{
+ QFileInfo compiler(compilerFilePath);
+ if (compilerFilePath == compiler.fileName() && !compiler.exists())
+ compiler = QFileInfo(findExecutable(compilerFilePath));
+
+ if (!compiler.exists()) {
+ throw qbs::ErrorInfo(Tr::tr("Compiler '%1' not found")
+ .arg(compilerFilePath));
+ }
+
QStringList toolchainTypes;
if (toolchainType.isEmpty())
- toolchainTypes = toolchainTypeFromCompilerName(QFileInfo(compilerFilePath).fileName());
+ toolchainTypes = toolchainTypeFromCompilerName(compiler.fileName());
else
toolchainTypes = completeToolchainList(toolchainType);
@@ -262,7 +271,7 @@ void createProfile(const QString &profileName, const QString &toolchainType,
}
if (toolchainTypes.contains(QLatin1String("gcc")))
- createGccProfile(compilerFilePath, settings, toolchainTypes, profileName);
+ createGccProfile(compiler.absoluteFilePath(), settings, toolchainTypes, profileName);
else
throw qbs::ErrorInfo(Tr::tr("Cannot create profile: Unknown toolchain type."));
}
diff --git a/src/lib/corelib/api/project.cpp b/src/lib/corelib/api/project.cpp
index bea570aa3..dce270ef1 100644
--- a/src/lib/corelib/api/project.cpp
+++ b/src/lib/corelib/api/project.cpp
@@ -585,6 +585,14 @@ void ProjectPrivate::prepareChangeToProject()
retrieveProjectData(m_projectData, internalProject);
}
+static bool productIsRunnable(const ResolvedProductConstPtr &product)
+{
+ return product->fileTags.contains("application")
+ || (product->fileTags.contains("applicationbundle")
+ && product->moduleProperties->qbsPropertyValue(QLatin1String("targetOS"))
+ .toStringList().contains(QLatin1String("darwin")));
+}
+
void ProjectPrivate::retrieveProjectData(ProjectData &projectData,
const ResolvedProjectConstPtr &internalProject)
{
@@ -596,6 +604,7 @@ void ProjectPrivate::retrieveProjectData(ProjectData &projectData,
product.d->name = resolvedProduct->name;
product.d->location = resolvedProduct->location;
product.d->isEnabled = resolvedProduct->enabled;
+ product.d->isRunnable = productIsRunnable(resolvedProduct);
foreach (const GroupPtr &resolvedGroup, resolvedProduct->groups)
product.d->groups << createGroupDataFromGroup(resolvedGroup);
if (resolvedProduct->enabled) {
diff --git a/src/lib/corelib/api/projectdata.cpp b/src/lib/corelib/api/projectdata.cpp
index a5cc6093e..31ba1ef33 100644
--- a/src/lib/corelib/api/projectdata.cpp
+++ b/src/lib/corelib/api/projectdata.cpp
@@ -414,6 +414,12 @@ bool ProductData::isEnabled() const
return d->isEnabled;
}
+bool ProductData::isRunnable() const
+{
+ QBS_ASSERT(isValid(), return false);
+ return d->isRunnable;
+}
+
bool operator==(const ProductData &lhs, const ProductData &rhs)
{
return lhs.name() == rhs.name()
diff --git a/src/lib/corelib/api/projectdata.h b/src/lib/corelib/api/projectdata.h
index ba0016d0c..1d7625b82 100644
--- a/src/lib/corelib/api/projectdata.h
+++ b/src/lib/corelib/api/projectdata.h
@@ -176,6 +176,7 @@ public:
QList<TargetArtifact> targetArtifacts() const;
QList<GroupData> groups() const;
bool isEnabled() const;
+ bool isRunnable() const;
private:
QExplicitlySharedDataPointer<Internal::ProductDataPrivate> d;
diff --git a/src/lib/corelib/api/projectdata_p.h b/src/lib/corelib/api/projectdata_p.h
index 2eda4d932..b0006e89a 100644
--- a/src/lib/corelib/api/projectdata_p.h
+++ b/src/lib/corelib/api/projectdata_p.h
@@ -84,6 +84,7 @@ public:
QList<GroupData> groups;
QList<TargetArtifact> targetArtifacts;
bool isEnabled;
+ bool isRunnable;
bool isValid;
};
diff --git a/src/lib/corelib/api/runenvironment.cpp b/src/lib/corelib/api/runenvironment.cpp
index b0be216f8..386a1769d 100644
--- a/src/lib/corelib/api/runenvironment.cpp
+++ b/src/lib/corelib/api/runenvironment.cpp
@@ -129,6 +129,21 @@ int RunEnvironment::runShell()
return system(command.toLocal8Bit().constData());
}
+static QString findExecutable(const QStringList &fileNames)
+{
+ const QStringList path = QString::fromLocal8Bit(qgetenv("PATH"))
+ .split(HostOsInfo::pathListSeparator(), QString::SkipEmptyParts);
+
+ foreach (const QString &fileName, fileNames) {
+ foreach (const QString &ppath, path) {
+ const QString fullPath = ppath + QLatin1Char('/') + fileName;
+ if (QFileInfo(fullPath).exists())
+ return QDir::cleanPath(fullPath);
+ }
+ }
+ return QString();
+}
+
int RunEnvironment::runTarget(const QString &targetBin, const QStringList &arguments)
{
const QStringList targetOS = PropertyFinder().propertyValue(
@@ -154,6 +169,15 @@ int RunEnvironment::runTarget(const QString &targetBin, const QStringList &argum
}
}
+ if (completeSuffix == QLatin1String("js")) {
+ // The Node.js binary is called nodejs on Debian/Ubuntu-family operating systems due to a
+ // conflict with another package containing a binary named node
+ targetExecutable = findExecutable(QStringList()
+ << QLatin1String("nodejs")
+ << QLatin1String("node"));
+ targetArguments.prepend(targetBin);
+ }
+
// Only check if the target is executable if we're not running it through another
// known application such as msiexec or wine, as we can't check in this case anyways
if (targetBin == targetExecutable && !QFileInfo(targetExecutable).isExecutable()) {
@@ -166,6 +190,7 @@ int RunEnvironment::runTarget(const QString &targetBin, const QStringList &argum
d->logger.qbsInfo() << Tr::tr("Starting target '%1'.").arg(QDir::toNativeSeparators(targetBin));
QProcess process;
+ process.setWorkingDirectory(QFileInfo(targetBin).absolutePath());
process.setProcessEnvironment(d->resolvedProduct->runEnvironment);
process.setProcessChannelMode(QProcess::ForwardedChannels);
process.start(targetExecutable, targetArguments);
diff --git a/src/lib/corelib/buildgraph/executor.cpp b/src/lib/corelib/buildgraph/executor.cpp
index 024decbc7..283958220 100644
--- a/src/lib/corelib/buildgraph/executor.cpp
+++ b/src/lib/corelib/buildgraph/executor.cpp
@@ -791,8 +791,10 @@ void Executor::runTransformer(const TransformerPtr &transformer)
for (; it != transformer->outputs.end(); ++it) {
Artifact *output = *it;
QDir outDir = QFileInfo(output->filePath()).absoluteDir();
- if (!outDir.exists())
- outDir.mkpath(QLatin1String("."));
+ if (!outDir.exists() && !outDir.mkpath(QLatin1String("."))) {
+ throw ErrorInfo(tr("Failed to create directory '%1'.")
+ .arg(QDir::toNativeSeparators(outDir.absolutePath())));
+ }
}
}
diff --git a/src/lib/corelib/buildgraph/rulesapplicator.cpp b/src/lib/corelib/buildgraph/rulesapplicator.cpp
index 7cbcbf997..d80c10432 100644
--- a/src/lib/corelib/buildgraph/rulesapplicator.cpp
+++ b/src/lib/corelib/buildgraph/rulesapplicator.cpp
@@ -307,7 +307,7 @@ Artifact *RulesApplicator::createOutputArtifactFromRuleArtifact(
QScriptValue scriptValue = engine()->evaluate(ruleArtifact->fileName);
if (Q_UNLIKELY(engine()->hasErrorOrException(scriptValue)))
throw ErrorInfo(Tr::tr("Error in Rule.Artifact fileName: ") + scriptValue.toString());
- QString outputPath = scriptValue.toString();
+ QString outputPath = FileInfo::resolvePath(m_product->buildDirectory(), scriptValue.toString());
return createOutputArtifact(outputPath, ruleArtifact->fileTags, ruleArtifact->alwaysUpdated,
inputArtifacts);
}
@@ -428,7 +428,8 @@ Artifact *RulesApplicator::createOutputArtifactFromScriptValue(const QScriptValu
const ArtifactSet &inputArtifacts)
{
QBS_CHECK(obj.isObject());
- const QString filePath = obj.property(QLatin1String("filePath")).toVariant().toString();
+ const QString filePath = FileInfo::resolvePath(m_product->buildDirectory(),
+ obj.property(QLatin1String("filePath")).toVariant().toString());
const FileTags fileTags = FileTags::fromStringList(
obj.property(QLatin1String("fileTags")).toVariant().toStringList());
const QVariant alwaysUpdatedVar = obj.property(QLatin1String("alwaysUpdated")).toVariant();
diff --git a/src/lib/corelib/buildgraph/transformer.cpp b/src/lib/corelib/buildgraph/transformer.cpp
index 492feeb0c..c82962ed7 100644
--- a/src/lib/corelib/buildgraph/transformer.cpp
+++ b/src/lib/corelib/buildgraph/transformer.cpp
@@ -54,12 +54,7 @@ QScriptValue Transformer::translateFileConfig(QScriptEngine *scriptEngine, Artif
{
QScriptValue obj = scriptEngine->newObject();
ModuleProperties::init(obj, artifact);
-
- // ### undeprecate "fileName" and turn into a real file name in qbs 1.3
- ScriptEngine *qbsScriptEngine = static_cast<ScriptEngine *>(scriptEngine);
- qbsScriptEngine->setDeprecatedProperty(obj, QLatin1String("fileName"),
- QLatin1String("filePath"), artifact->filePath());
-
+ obj.setProperty(QLatin1String("fileName"), artifact->fileName());
obj.setProperty(QLatin1String("filePath"), artifact->filePath());
const QStringList fileTags = artifact->fileTags.toStringList();
obj.setProperty(QLatin1String("fileTags"), scriptEngine->toScriptValue(fileTags));
diff --git a/src/lib/corelib/language/builtindeclarations.cpp b/src/lib/corelib/language/builtindeclarations.cpp
index 02046e358..3ff60944b 100644
--- a/src/lib/corelib/language/builtindeclarations.cpp
+++ b/src/lib/corelib/language/builtindeclarations.cpp
@@ -109,6 +109,11 @@ static PropertyDeclaration nameProperty()
return PropertyDeclaration(QLatin1String("name"), PropertyDeclaration::String);
}
+static PropertyDeclaration buildDirProperty()
+{
+ return PropertyDeclaration(QLatin1String("buildDirectory"), PropertyDeclaration::Path);
+}
+
static PropertyDeclaration prepareScriptProperty()
{
PropertyDeclaration decl(QLatin1String("prepare"), PropertyDeclaration::Verbatim);
@@ -155,10 +160,6 @@ void BuiltinDeclarations::addExportItem()
void BuiltinDeclarations::addFileTaggerItem()
{
ItemDeclaration item(QLatin1String("FileTagger"));
-
- // TODO: Remove in 1.3
- item << PropertyDeclaration(QLatin1String("pattern"), PropertyDeclaration::StringList);
-
item << PropertyDeclaration(QLatin1String("patterns"), PropertyDeclaration::StringList);
item << PropertyDeclaration(QLatin1String("fileTags"), PropertyDeclaration::Variant);
insert(item);
@@ -245,9 +246,9 @@ void BuiltinDeclarations::addProductItem()
item << nameProperty();
decl = PropertyDeclaration(QLatin1String("targetName"), PropertyDeclaration::String);
decl.setInitialValueSource(QLatin1String("name"));
+ item << buildDirProperty();
item << decl;
decl = PropertyDeclaration(QLatin1String("destinationDirectory"), PropertyDeclaration::String);
- decl.setInitialValueSource(QLatin1String("'.'"));
item << decl;
item << PropertyDeclaration(QLatin1String("consoleApplication"),
PropertyDeclaration::Boolean);
@@ -272,6 +273,8 @@ void BuiltinDeclarations::addProjectItem()
<< QLatin1String("Rule"));
item << nameProperty();
item << conditionProperty();
+ item << buildDirProperty();
+ item << PropertyDeclaration(QLatin1String("sourceDirectory"), PropertyDeclaration::Path);
item << PropertyDeclaration(QLatin1String("references"), PropertyDeclaration::Variant,
PropertyDeclaration::PropertyNotAvailableInConfig);
item << PropertyDeclaration(QLatin1String("qbsSearchPaths"),
diff --git a/src/lib/corelib/language/item.cpp b/src/lib/corelib/language/item.cpp
index 7b42df5e6..8b1dcb72a 100644
--- a/src/lib/corelib/language/item.cpp
+++ b/src/lib/corelib/language/item.cpp
@@ -122,6 +122,14 @@ JSSourceValuePtr Item::sourceProperty(const QString &name) const
return v.staticCast<JSSourceValue>();
}
+VariantValuePtr Item::variantProperty(const QString &name) const
+{
+ ValuePtr v = property(name);
+ if (!v || v->type() != Value::VariantValueType)
+ return VariantValuePtr();
+ return v.staticCast<VariantValue>();
+}
+
const PropertyDeclaration Item::propertyDeclaration(const QString &name) const
{
const PropertyDeclaration decl = m_propertyDeclarations.value(name);
diff --git a/src/lib/corelib/language/item.h b/src/lib/corelib/language/item.h
index 866927a0e..8859957b0 100644
--- a/src/lib/corelib/language/item.h
+++ b/src/lib/corelib/language/item.h
@@ -102,6 +102,7 @@ public:
ValuePtr property(const QString &name) const;
ItemValuePtr itemProperty(const QString &name, bool create = false);
JSSourceValuePtr sourceProperty(const QString &name) const;
+ VariantValuePtr variantProperty(const QString &name) const;
void setPropertyObserver(ItemObserver *observer) const;
void setProperty(const QString &name, const ValuePtr &value);
void setPropertyDeclaration(const QString &name, const PropertyDeclaration &declaration);
diff --git a/src/lib/corelib/language/language.cpp b/src/lib/corelib/language/language.cpp
index eb5ad9652..4974a3e68 100644
--- a/src/lib/corelib/language/language.cpp
+++ b/src/lib/corelib/language/language.cpp
@@ -585,11 +585,6 @@ static QProcessEnvironment getProcessEnvironment(ScriptEngine *engine, EnvType e
const QScriptValue getEnvValue = engine->newFunction(js_getEnv, 1);
const QScriptValue putEnvValue = engine->newFunction(js_putEnv, 1);
-
- // TODO: Remove in 1.3
- scope.setProperty(QLatin1String("getenv"), getEnvValue);
- scope.setProperty(QLatin1String("putenv"), putEnvValue);
-
scope.setProperty(QLatin1String("getEnv"), getEnvValue);
scope.setProperty(QLatin1String("putEnv"), putEnvValue);
@@ -817,6 +812,14 @@ QStringList ResolvedProduct::generatedFiles(const QString &baseFile, const FileT
return QStringList();
}
+QString ResolvedProduct::buildDirectory() const
+{
+ const QString result = productProperties.value(QLatin1String("buildDirectory")).toString();
+ QBS_CHECK(!result.isEmpty());
+ return result;
+}
+
+
ResolvedProject::ResolvedProject() : enabled(true), m_topLevelProject(0)
{
}
diff --git a/src/lib/corelib/language/language.h b/src/lib/corelib/language/language.h
index 780af8f47..a76c8ad26 100644
--- a/src/lib/corelib/language/language.h
+++ b/src/lib/corelib/language/language.h
@@ -397,6 +397,7 @@ public:
TopLevelProject *topLevelProject() const;
QStringList generatedFiles(const QString &baseFile, const FileTags &tags) const;
+ QString buildDirectory() const;
private:
ResolvedProduct();
diff --git a/src/lib/corelib/language/loader.cpp b/src/lib/corelib/language/loader.cpp
index 62c1aadde..622cfa073 100644
--- a/src/lib/corelib/language/loader.cpp
+++ b/src/lib/corelib/language/loader.cpp
@@ -120,11 +120,7 @@ TopLevelProjectPtr Loader::loadProject(const SetupProjectParameters &parameters)
cancelationTimer.start(1000);
}
- ModuleLoaderResult loadResult
- = m_moduleLoader->load(parameters.projectFilePath(),
- parameters.overriddenValuesTree(),
- parameters.buildConfigurationTree(),
- true);
+ ModuleLoaderResult loadResult = m_moduleLoader->load(parameters);
const TopLevelProjectPtr project = m_projectResolver->resolve(loadResult, parameters);
// E.g. if the top-level project is disabled.
diff --git a/src/lib/corelib/language/moduleloader.cpp b/src/lib/corelib/language/moduleloader.cpp
index abe09814c..3dc7df283 100644
--- a/src/lib/corelib/language/moduleloader.cpp
+++ b/src/lib/corelib/language/moduleloader.cpp
@@ -36,6 +36,7 @@
#include "item.h"
#include "itemreader.h"
#include "scriptengine.h"
+#include "value.h"
#include <language/language.h>
#include <language/scriptengine.h>
#include <logging/logger.h>
@@ -101,15 +102,12 @@ void ModuleLoader::setSearchPaths(const QStringList &searchPaths)
}
}
-ModuleLoaderResult ModuleLoader::load(const QString &filePath,
- const QVariantMap &overriddenProperties, const QVariantMap &buildConfigProperties,
- bool wrapWithProjectItem)
+ModuleLoaderResult ModuleLoader::load(const SetupProjectParameters &parameters)
{
if (m_logger.traceEnabled())
- m_logger.qbsTrace() << "[MODLDR] load" << filePath;
+ m_logger.qbsTrace() << "[MODLDR] load" << parameters.projectFilePath();
+ m_parameters = parameters;
m_reader->clearItemCache();
- m_overriddenProperties = overriddenProperties;
- m_buildConfigProperties = buildConfigProperties;
m_validItemPropertyNamesPerItem.clear();
m_disabledItems.clear();
@@ -117,14 +115,21 @@ ModuleLoaderResult ModuleLoader::load(const QString &filePath,
m_pool = result.itemPool.data();
m_reader->setPool(m_pool);
- Item *root = m_reader->readFile(filePath);
+ Item *root = m_reader->readFile(parameters.projectFilePath());
if (!root)
return ModuleLoaderResult();
- if (wrapWithProjectItem && root->typeName() != QLatin1String("Project"))
+ if (root->typeName() != QLatin1String("Project"))
root = wrapWithProject(root);
- handleProject(&result, root, QSet<QString>() << QDir::cleanPath(filePath));
+ const QString buildDirectory
+ = TopLevelProject::deriveBuildDirectory(parameters.buildRoot(),
+ TopLevelProject::deriveId(parameters.finalBuildConfigurationTree()));
+ root->setProperty(QLatin1String("sourceDirectory"),
+ VariantValue::create(QFileInfo(root->file()->filePath()).absolutePath()));
+ root->setProperty(QLatin1String("buildDirectory"), VariantValue::create(buildDirectory));
+ handleProject(&result, root, buildDirectory,
+ QSet<QString>() << QDir::cleanPath(parameters.projectFilePath()));
result.root = root;
result.qbsFiles = m_reader->filesRead();
return result;
@@ -198,19 +203,20 @@ private:
};
void ModuleLoader::handleProject(ModuleLoaderResult *loadResult, Item *item,
- const QSet<QString> &referencedFilePaths)
+ const QString &buildDirectory, const QSet<QString> &referencedFilePaths)
{
if (!checkItemCondition(item))
return;
ProjectContext projectContext;
projectContext.result = loadResult;
+ projectContext.buildDirectory = buildDirectory;
projectContext.localModuleSearchPath = FileInfo::resolvePath(item->file()->dirPath(),
moduleSearchSubDir);
ProductContext dummyProductContext;
dummyProductContext.project = &projectContext;
loadBaseModule(&dummyProductContext, item);
- overrideItemProperties(item, QLatin1String("project"), m_overriddenProperties);
+ overrideItemProperties(item, QLatin1String("project"), m_parameters.overriddenValuesTree());
projectContext.extraSearchPaths = readExtraSearchPaths(item);
m_reader->pushExtraSearchPaths(projectContext.extraSearchPaths);
@@ -228,7 +234,7 @@ void ModuleLoader::handleProject(ModuleLoaderResult *loadResult, Item *item,
handleSubProject(&projectContext, child, referencedFilePaths);
} else if (child->typeName() == QLatin1String("Project")) {
copyProperties(item, child);
- handleProject(loadResult, child, referencedFilePaths);
+ handleProject(loadResult, child, buildDirectory, referencedFilePaths);
}
}
@@ -267,7 +273,7 @@ void ModuleLoader::handleProject(ModuleLoaderResult *loadResult, Item *item,
handleProduct(&projectContext, subItem);
} else if (subItem->typeName() == QLatin1String("Project")) {
copyProperties(item, subItem);
- handleProject(loadResult, subItem,
+ handleProject(loadResult, subItem, buildDirectory,
QSet<QString>(referencedFilePaths) << absReferencePath);
} else {
throw ErrorInfo(Tr::tr("The top-level item of a file in a \"references\" list must be "
@@ -290,6 +296,7 @@ void ModuleLoader::handleProduct(ProjectContext *projectContext, Item *item)
if (m_logger.traceEnabled())
m_logger.qbsTrace() << "[MODLDR] handleProduct " << item->file()->filePath();
+ initProductProperties(projectContext, item);
ProductContext productContext;
productContext.project = projectContext;
bool extraSearchPathsSet = false;
@@ -332,6 +339,23 @@ void ModuleLoader::handleProduct(ProjectContext *projectContext, Item *item)
m_reader->popExtraSearchPaths();
}
+void ModuleLoader::initProductProperties(const ProjectContext *project, Item *item)
+{
+ QString productName = m_evaluator->stringValue(item, QLatin1String("name"));
+ if (productName.isEmpty()) {
+ productName = FileInfo::completeBaseName(item->file()->filePath());
+ item->setProperty(QLatin1String("name"), VariantValue::create(productName));
+ }
+
+ item->setProperty(QLatin1String("buildDirectory"),
+ VariantValue::create(
+ FileInfo::resolvePath(project->buildDirectory, productName)));
+
+ item->setProperty(QLatin1String("sourceDirectory"),
+ VariantValue::create(
+ QFileInfo(item->file()->filePath()).absolutePath()));
+}
+
void ModuleLoader::handleSubProject(ModuleLoader::ProjectContext *projectContext, Item *item,
const QSet<QString> &referencedFilePaths)
{
@@ -380,7 +404,7 @@ void ModuleLoader::handleSubProject(ModuleLoader::ProjectContext *projectContext
Item::addChild(item, loadedItem);
item->setScope(projectContext->scope);
- handleProject(projectContext->result, loadedItem,
+ handleProject(projectContext->result, loadedItem, projectContext->buildDirectory,
QSet<QString>(referencedFilePaths) << subProjectFilePath);
}
@@ -792,7 +816,7 @@ Item *ModuleLoader::loadModuleFile(ProductContext *productContext, const QString
// Module properties that are defined in the profile are used as default values.
const QVariantMap profileModuleProperties
- = m_buildConfigProperties.value(fullModuleName).toMap();
+ = m_parameters.buildConfigurationTree().value(fullModuleName).toMap();
for (QVariantMap::const_iterator vmit = profileModuleProperties.begin();
vmit != profileModuleProperties.end(); ++vmit)
{
@@ -827,7 +851,6 @@ void ModuleLoader::setupBaseModulePrototype(Item *prototype)
BuiltinValue::create(BuiltinValue::GetNativeSettingFunction));
const BuiltinValuePtr getEnvValue = BuiltinValue::create(BuiltinValue::GetEnvFunction);
prototype->setProperty(QLatin1String("getEnv"), getEnvValue);
- prototype->setProperty(QLatin1String("getenv"), getEnvValue); // TODO: Remove in 1.3.
prototype->setProperty(QLatin1String("getHostOS"),
BuiltinValue::create(BuiltinValue::GetHostOSFunction));
prototype->setProperty(QLatin1String("canonicalArchitecture"),
@@ -913,7 +936,8 @@ void ModuleLoader::instantiateModule(ProductContext *productContext, Item *insta
}
// override module properties given on the command line
- const QVariantMap userModuleProperties = m_overriddenProperties.value(fullName).toMap();
+ const QVariantMap userModuleProperties
+ = m_parameters.overriddenValuesTree().value(fullName).toMap();
for (QVariantMap::const_iterator vmit = userModuleProperties.begin();
vmit != userModuleProperties.end(); ++vmit) {
if (Q_UNLIKELY(!moduleInstance->hasProperty(vmit.key()))) {
@@ -993,7 +1017,7 @@ void ModuleLoader::checkCancelation() const
{
if (m_progressObserver && m_progressObserver->canceled()) {
throw ErrorInfo(Tr::tr("Project resolving canceled for configuration %1.")
- .arg(TopLevelProject::deriveId(m_buildConfigProperties)));
+ .arg(TopLevelProject::deriveId(m_parameters.buildConfigurationTree())));
}
}
diff --git a/src/lib/corelib/language/moduleloader.h b/src/lib/corelib/language/moduleloader.h
index f6f62a2c3..5df1747fc 100644
--- a/src/lib/corelib/language/moduleloader.h
+++ b/src/lib/corelib/language/moduleloader.h
@@ -33,6 +33,7 @@
#include "forward_decls.h"
#include "itempool.h"
#include <logging/logger.h>
+#include <tools/setupprojectparameters.h>
#include <QMap>
#include <QSet>
@@ -98,9 +99,7 @@ public:
void setSearchPaths(const QStringList &searchPaths);
Evaluator *evaluator() const { return m_evaluator; }
- ModuleLoaderResult load(const QString &filePath,
- const QVariantMap &overriddenProperties, const QVariantMap &buildConfigProperties,
- bool wrapWithProjectItem = false);
+ ModuleLoaderResult load(const SetupProjectParameters &parameters);
static QString fullModuleName(const QStringList &moduleName);
static void overrideItemProperties(Item *item, const QString &buildConfigKey,
@@ -124,6 +123,7 @@ private:
{
public:
ModuleLoaderResult *result;
+ QString buildDirectory;
QString localModuleSearchPath;
};
@@ -146,9 +146,10 @@ private:
typedef QPair<Item *, ModuleLoaderResult::ProductInfo::Dependency> ProductDependencyResult;
typedef QList<ProductDependencyResult> ProductDependencyResults;
- void handleProject(ModuleLoaderResult *loadResult, Item *item,
+ void handleProject(ModuleLoaderResult *loadResult, Item *item, const QString &buildDirectory,
const QSet<QString> &referencedFilePaths);
void handleProduct(ProjectContext *projectContext, Item *item);
+ void initProductProperties(const ProjectContext *project, Item *item);
void handleSubProject(ProjectContext *projectContext, Item *item,
const QSet<QString> &referencedFilePaths);
void createAdditionalModuleInstancesInProduct(ProductContext *productContext);
@@ -198,8 +199,7 @@ private:
QMap<QString, QStringList> m_moduleDirListCache;
QHash<Item *, QSet<QString> > m_validItemPropertyNamesPerItem;
QSet<Item *> m_disabledItems;
- QVariantMap m_overriddenProperties;
- QVariantMap m_buildConfigProperties;
+ SetupProjectParameters m_parameters;
};
} // namespace Internal
diff --git a/src/lib/corelib/language/projectresolver.cpp b/src/lib/corelib/language/projectresolver.cpp
index fec042e1e..8b58912ed 100644
--- a/src/lib/corelib/language/projectresolver.cpp
+++ b/src/lib/corelib/language/projectresolver.cpp
@@ -274,23 +274,17 @@ void ProjectResolver::resolveProduct(Item *item, ProjectContext *projectContext)
ProductContext productContext;
m_productContext = &productContext;
productContext.item = item;
- const QString productSourceDirectory = QFileInfo(item->file()->filePath()).absolutePath();
- item->setProperty(QLatin1String("sourceDirectory"),
- VariantValue::create(productSourceDirectory));
- item->setProperty(QLatin1String("buildDirectory"), VariantValue::create(projectContext
- ->project->topLevelProject()->buildDirectory));
ResolvedProductPtr product = ResolvedProduct::create();
product->project = projectContext->project;
m_productItemMap.insert(product, item);
projectContext->project->products += product;
productContext.product = product;
product->name = m_evaluator->stringValue(item, QLatin1String("name"));
- if (product->name.isEmpty()) {
- product->name = FileInfo::completeBaseName(item->file()->filePath());
- item->setProperty(QLatin1String("name"), VariantValue::create(product->name));
- }
m_logger.qbsTrace() << "[PR] resolveProduct " << product->name;
+ // product->buildDirectory() isn't valid yet, because the productProperties map is not ready.
+ productContext.buildDirectory = m_evaluator->stringValue(item, QLatin1String("buildDirectory"));
+
if (std::find_if(item->modules().begin(), item->modules().end(),
ModuleNameEquals(product->name)) != item->modules().end()) {
throw ErrorInfo(
@@ -314,11 +308,20 @@ void ProjectResolver::resolveProduct(Item *item, ProjectContext *projectContext)
product->fileTags = m_evaluator->fileTagsValue(item, QLatin1String("type"));
product->targetName = m_evaluator->stringValue(item, QLatin1String("targetName"));
- product->sourceDirectory = productSourceDirectory;
- product->destinationDirectory
- = m_evaluator->stringValue(item, QLatin1String("destinationDirectory"));
+ product->sourceDirectory = m_evaluator->stringValue(item, QLatin1String("sourceDirectory"));
+ const QString destDirKey = QLatin1String("destinationDirectory");
+ product->destinationDirectory = m_evaluator->stringValue(item, destDirKey);
+
+ if (product->destinationDirectory.isEmpty()) {
+ product->destinationDirectory = productContext.buildDirectory;
+ } else {
+ product->destinationDirectory = FileInfo::resolvePath(
+ product->topLevelProject()->buildDirectory,
+ product->destinationDirectory);
+ }
product->location = item->location();
product->productProperties = createProductConfig();
+ product->productProperties.insert(destDirKey, product->destinationDirectory);
QVariantMap moduleProperties;
moduleProperties.insert(QLatin1String("modules"),
product->productProperties.take(QLatin1String("modules")));
@@ -384,15 +387,6 @@ void ProjectResolver::resolveModule(const QStringList &moduleName, Item *item,
m_productContext->additionalFileTags +=
m_evaluator->fileTagsValue(item, QLatin1String("additionalProductTypes"));
- // TODO: Remove in 1.3.
- bool additionalProductFileTagsWasSet;
- const QStringList additionalProductFileTags = m_evaluator->stringListValue(item, QLatin1String("additionalProductFileTags"),
- &additionalProductFileTagsWasSet);
- if (additionalProductFileTagsWasSet) {
- m_logger.printWarning(ErrorInfo(Tr::tr("The 'additionalProductFileTags' property is deprecated. Please "
- "use 'additionalProductTypes' instead."), item->location()));
- m_productContext->additionalFileTags += FileTags::fromStringList(additionalProductFileTags);
- }
foreach (const Item::Module &m, item->modules())
module->moduleDependencies += ModuleLoader::fullModuleName(m.name);
@@ -463,6 +457,17 @@ void ProjectResolver::resolveGroup(Item *item, ProjectContext *projectContext)
if (Q_UNLIKELY(!files.isEmpty()))
throw ErrorInfo(Tr::tr("Group.files and Group.fileTagsFilters are exclusive."),
item->location());
+
+ ProductContext::ArtifactPropertiesInfo apinfo
+ = m_productContext->artifactPropertiesPerFilter.value(fileTagsFilter);
+ if (apinfo.first) {
+ if (apinfo.second.fileName() == item->location().fileName()) {
+ ErrorInfo error(Tr::tr("Conflicting fileTagsFilter in Group items."));
+ error.append(Tr::tr("First item"), apinfo.second);
+ error.append(Tr::tr("Second item"), item->location());
+ throw error;
+ }
+ }
if (!isEnabled)
return;
ArtifactPropertiesPtr aprops = ArtifactProperties::create();
@@ -471,6 +476,8 @@ void ProjectResolver::resolveGroup(Item *item, ProjectContext *projectContext)
cfg->setValue(evaluateModuleValues(item));
aprops->setPropertyMapInternal(cfg);
m_productContext->product->artifactProperties += aprops;
+ m_productContext->artifactPropertiesPerFilter.insert(fileTagsFilter,
+ ProductContext::ArtifactPropertiesInfo(aprops, item->location()));
return;
}
if (Q_UNLIKELY(files.isEmpty() && !item->hasProperty(QLatin1String("files")))) {
@@ -710,24 +717,14 @@ void ProjectResolver::resolveFileTagger(Item *item, ProjectContext *projectConte
checkCancelation();
QList<FileTaggerConstPtr> &fileTaggers = m_productContext
? m_productContext->product->fileTaggers : projectContext->fileTaggers;
- QStringList patterns = m_evaluator->stringListValue(item, QLatin1String("patterns"));
+ const QStringList patterns = m_evaluator->stringListValue(item, QLatin1String("patterns"));
+ if (patterns.isEmpty())
+ throw ErrorInfo(Tr::tr("FileTagger.patterns must be a non-empty list."), item->location());
+
const FileTags fileTags = m_evaluator->fileTagsValue(item, QLatin1String("fileTags"));
if (fileTags.isEmpty())
throw ErrorInfo(Tr::tr("FileTagger.fileTags must not be empty."), item->location());
- // TODO: Remove in 1.3.
- bool patternWasSet;
- const QStringList oldPatterns = m_evaluator->stringListValue(item, QLatin1String("pattern"),
- &patternWasSet);
- if (patternWasSet) {
- m_logger.printWarning(ErrorInfo(Tr::tr("The 'pattern' property is deprecated. Please "
- "use 'patterns' instead."), item->location()));
- patterns << oldPatterns;
- }
-
- if (patterns.isEmpty())
- throw ErrorInfo(Tr::tr("FileTagger.patterns must be a non-empty list."), item->location());
-
foreach (const QString &pattern, patterns) {
if (pattern.isEmpty())
throw ErrorInfo(Tr::tr("A FileTagger pattern must not be empty."), item->location());
@@ -760,8 +757,8 @@ void ProjectResolver::resolveTransformer(Item *item, ProjectContext *projectCont
QString fileName = m_evaluator->stringValue(child, QLatin1String("fileName"));
if (Q_UNLIKELY(fileName.isEmpty()))
throw ErrorInfo(Tr::tr("Artifact fileName must not be empty."));
- artifact->absoluteFilePath = FileInfo::resolvePath(m_productContext->product->topLevelProject()->buildDirectory,
- fileName);
+ artifact->absoluteFilePath
+ = FileInfo::resolvePath(m_productContext->buildDirectory, fileName);
artifact->fileTags = m_evaluator->fileTagsValue(child, QLatin1String("fileTags"));
if (artifact->fileTags.isEmpty())
artifact->fileTags.insert(unknownFileTag());
diff --git a/src/lib/corelib/language/projectresolver.h b/src/lib/corelib/language/projectresolver.h
index 636fd7299..630786db7 100644
--- a/src/lib/corelib/language/projectresolver.h
+++ b/src/lib/corelib/language/projectresolver.h
@@ -77,8 +77,11 @@ private:
struct ProductContext
{
ResolvedProductPtr product;
+ QString buildDirectory;
FileTags additionalFileTags;
Item *item;
+ typedef QPair<ArtifactPropertiesPtr, CodeLocation> ArtifactPropertiesInfo;
+ QHash<QStringList, ArtifactPropertiesInfo> artifactPropertiesPerFilter;
};
struct ModuleContext
diff --git a/src/lib/corelib/language/testdata/erroneous/conflicting_fileTagsFilter.qbs b/src/lib/corelib/language/testdata/erroneous/conflicting_fileTagsFilter.qbs
new file mode 100644
index 000000000..54b3343e4
--- /dev/null
+++ b/src/lib/corelib/language/testdata/erroneous/conflicting_fileTagsFilter.qbs
@@ -0,0 +1,13 @@
+import qbs 1.0
+
+Application {
+ Group {
+ fileTagsFilter: "application"
+ qbs.install: true
+ }
+ Group {
+ fileTagsFilter: "application"
+ qbs.install: false
+ }
+}
+
diff --git a/src/lib/corelib/language/testdata/profilevaluesandoverriddenvalues.qbs b/src/lib/corelib/language/testdata/profilevaluesandoverriddenvalues.qbs
index cc1b7b2a2..0ba76c6f6 100644
--- a/src/lib/corelib/language/testdata/profilevaluesandoverriddenvalues.qbs
+++ b/src/lib/corelib/language/testdata/profilevaluesandoverriddenvalues.qbs
@@ -2,14 +2,15 @@ import qbs 1.0
Project {
Application {
- name: {
+ name: "product1"
+ type: {
if (!(dummy.cFlags instanceof Array))
throw new Error("dummy.cFlags: Array type expected.");
if (!(dummy.cxxFlags instanceof Array))
throw new Error("dummy.cxxFlags: Array type expected.");
if (!(dummy.defines instanceof Array))
throw new Error("dummy.defines: Array type expected.");
- return "product1";
+ return "application";
}
Depends { name: "dummy" }
// dummy.cxxFlags is set via profile and is not overridden
diff --git a/src/lib/corelib/language/tst_language.cpp b/src/lib/corelib/language/tst_language.cpp
index ff19b8afe..6873391e9 100644
--- a/src/lib/corelib/language/tst_language.cpp
+++ b/src/lib/corelib/language/tst_language.cpp
@@ -370,6 +370,8 @@ void TestLanguage::erroneousFiles_data()
<< "Unexpected item type 'Narf'";
QTest::newRow("invalid_child_item_type")
<< "Items of type 'Project' cannot contain items of type 'Depends'.";
+ QTest::newRow("conflicting_fileTagsFilter")
+ << "Conflicting fileTagsFilter in Group items";
}
void TestLanguage::erroneousFiles()
@@ -1113,7 +1115,7 @@ void TestLanguage::productDirectories()
QVERIFY(product);
const QVariantMap config = product->productProperties;
QCOMPARE(config.value(QLatin1String("buildDirectory")).toString(),
- buildDir(defaultParameters));
+ buildDir(defaultParameters) + QLatin1Char('/') + product->name);
QCOMPARE(config.value(QLatin1String("sourceDirectory")).toString(), testDataDir());
}
catch (const ErrorInfo &e) {
diff --git a/src/lib/corelib/tools/settings.cpp b/src/lib/corelib/tools/settings.cpp
index f59e83e2c..617fa2137 100644
--- a/src/lib/corelib/tools/settings.cpp
+++ b/src/lib/corelib/tools/settings.cpp
@@ -45,26 +45,6 @@ static QSettings::Format format()
return HostOsInfo::isWindowsHost() ? QSettings::IniFormat : QSettings::NativeFormat;
}
-static void migrateValue(QSettings *settings, const QString &key)
-{
- const QVariant v = settings->value(key);
- if (!v.isValid())
- return;
- settings->setValue(QLatin1String("org/qt-project/qbs/") + key, v);
- settings->remove(key);
-}
-
-static void migrateGroup(QSettings *settings, const QString &group)
-{
- QStringList fullKeys;
- settings->beginGroup(group);
- foreach (const QString &key, settings->allKeys())
- fullKeys += group + QLatin1Char('/') + key;
- settings->endGroup();
- foreach (const QString &key, fullKeys)
- migrateValue(settings, key);
-}
-
static QSettings *createQSettings(const QString &baseDir)
{
return baseDir.isEmpty()
@@ -75,13 +55,6 @@ static QSettings *createQSettings(const QString &baseDir)
Settings::Settings(const QString &baseDir) : m_settings(createQSettings(baseDir))
{
- // Migrate settings to internal group.
- // ### remove in qbs 1.3
- if (!m_settings->childGroups().contains(QLatin1String("org/qt-project/qbs"))) {
- migrateValue(m_settings, QLatin1String("defaultProfile"));
- migrateGroup(m_settings, QLatin1String("profiles"));
- migrateGroup(m_settings, QLatin1String("preferences"));
- }
// Actual qbs settings are stored transparently within a group, because QSettings
// can see non-qbs fallback settings e.g. from QtProject that we're not interested in.
m_settings->beginGroup(QLatin1String("org/qt-project/qbs"));
diff --git a/src/lib/qtprofilesetup/qtprofilesetup.cpp b/src/lib/qtprofilesetup/qtprofilesetup.cpp
index 31b6950a1..ddaec6c8e 100644
--- a/src/lib/qtprofilesetup/qtprofilesetup.cpp
+++ b/src/lib/qtprofilesetup/qtprofilesetup.cpp
@@ -119,6 +119,13 @@ static void addDesignerComponentsModule(QList<QtModuleInfo> &modules)
modules << module;
}
+static QString quotedPath(const QString &str)
+{
+ return QLatin1Char('"')
+ + QDir::fromNativeSeparators(str).replace(QLatin1Char('"'), QLatin1String("\\\""))
+ + QLatin1Char('"');
+}
+
static void createModules(Profile &profile, Settings *settings,
const QtEnvironment &qtEnvironment)
{
@@ -314,9 +321,21 @@ static void createModules(Profile &profile, Settings *settings,
const QByteArray debugMacro = module.qbsName == QLatin1String("declarative")
|| qtEnvironment.qtMajorVersion < 5
? "QT_DECLARATIVE_DEBUG" : "QT_QML_DEBUG";
- propertiesString = "property bool qmlDebugging: false\n"
- " cpp.defines: "
- "qmlDebugging ? base.concat('" + debugMacro + "') : base";
+
+ const QString indent = QLatin1String(" ");
+ QTextStream s(&propertiesString);
+ s << "property bool qmlDebugging: false" << endl
+ << indent << "cpp.defines: "
+ << "qmlDebugging ? base.concat('" + debugMacro + "') : base" << endl;
+
+ s << indent << "property string qmlPath";
+ if (qtEnvironment.qmlPath.isEmpty())
+ s << endl;
+ else
+ s << ": " << quotedPath(qtEnvironment.qmlPath) << endl;
+
+ s << indent << "property string qmlImportsPath: "
+ << quotedPath(qtEnvironment.qmlImportPath);
}
content.replace("### special properties", propertiesString);
moduleFile.resize(0);
diff --git a/src/lib/qtprofilesetup/qtprofilesetup.h b/src/lib/qtprofilesetup/qtprofilesetup.h
index a2283202a..88e56d2c9 100644
--- a/src/lib/qtprofilesetup/qtprofilesetup.h
+++ b/src/lib/qtprofilesetup/qtprofilesetup.h
@@ -43,6 +43,7 @@ public:
QString libraryPath;
QString includePath;
QString binaryPath;
+ QString qmlPath;
QString qmlImportPath;
QString documentationPath;
QString dataPath;
diff --git a/src/lib/qtprofilesetup/templates/core.qbs b/src/lib/qtprofilesetup/templates/core.qbs
index 0d706b255..deb7695d4 100644
--- a/src/lib/qtprofilesetup/templates/core.qbs
+++ b/src/lib/qtprofilesetup/templates/core.qbs
@@ -37,7 +37,7 @@ Module {
// These are deliberately not path types
// We don't want to resolve them against the source directory
- property string generatedFilesDir: "GeneratedFiles/" + product.name
+ property string generatedFilesDir: product.buildDirectory + "/GeneratedFiles"
property string qmFilesDir: product.destinationDirectory
// private properties
@@ -62,7 +62,7 @@ Module {
paths.push(libPath + '/QtCore' + libInfix + '.framework/Versions/' + versionMajor + '/Headers');
paths.push(incPath + '/QtCore');
paths.push(incPath);
- paths.push(product.buildDirectory + '/' + generatedFilesDir);
+ paths.push(generatedFilesDir);
return paths;
}
cpp.libraryPaths: {
@@ -117,54 +117,29 @@ Module {
additionalProductTypes: ["qm"]
validate: {
- var requiredProperties = {
- "binPath": binPath,
- "incPath": incPath,
- "libPath": libPath,
- "mkspecPath": mkspecPath,
- "version": version,
- "config": config,
- "qtConfig": qtConfig,
- // Validate these in case 'version' is in some non-standard format
- "versionMajor": versionMajor,
- "versionMinor": versionMinor,
- "versionPatch": versionPatch
- };
-
- if (!staticBuild) {
- requiredProperties["pluginPath"] = pluginPath;
- }
-
- var missingProperties = [];
- for (var i in requiredProperties) {
- if (requiredProperties[i] === undefined) {
- missingProperties.push("Qt.core." + i);
- }
- }
-
- var invalidProperties = {};
- if (versionMajor <= 0)
- invalidProperties["versionMajor"] = "must be > 0";
- if (versionMinor < 0)
- invalidProperties["versionMinor"] = "must be >= 0";
- if (versionPatch < 0)
- invalidProperties["versionPatch"] = "must be >= 0";
-
- var errorMessage = "";
- if (missingProperties.length > 0) {
- errorMessage += "The following Qt module properties are not set. " +
- "Set them in your profile:\n" +
- missingProperties.sort().join("\n");
- }
-
- if (Object.keys(invalidProperties).length > 0) {
- errorMessage += "The following Qt module properties have invalid values:\n" +
- Object.map(invalidProperties,
- function(msg, prop) { return prop + ": " + msg; }).join("\n");
- }
-
- if (errorMessage.length > 0)
- throw errorMessage;
+ var validator = new ModUtils.PropertyValidator("Qt.core");
+ validator.setRequiredProperty("binPath", binPath);
+ validator.setRequiredProperty("incPath", incPath);
+ validator.setRequiredProperty("libPath", libPath);
+ validator.setRequiredProperty("mkspecPath", mkspecPath);
+ validator.setRequiredProperty("version", version);
+ validator.setRequiredProperty("config", config);
+ validator.setRequiredProperty("qtConfig", qtConfig);
+ validator.setRequiredProperty("versionMajor", versionMajor);
+ validator.setRequiredProperty("versionMinor", versionMinor);
+ validator.setRequiredProperty("versionPatch", versionPatch);
+
+ if (!staticBuild)
+ validator.setRequiredProperty("pluginPath", pluginPath);
+
+ // Allow custom version suffix since some distributions might want to do this,
+ // but otherwise the version must start with a valid 3-component string
+ validator.addVersionValidator("version", version, 3, 3, true);
+ validator.addRangeValidator("versionMajor", versionMajor, 1);
+ validator.addRangeValidator("versionMinor", versionMinor, 0);
+ validator.addRangeValidator("versionPatch", versionPatch, 0);
+
+ validator.validate();
}
setupRunEnvironment: {
diff --git a/src/lib/qtprofilesetup/templates/gui.qbs b/src/lib/qtprofilesetup/templates/gui.qbs
index 02b90f40c..b0a17aa6c 100644
--- a/src/lib/qtprofilesetup/templates/gui.qbs
+++ b/src/lib/qtprofilesetup/templates/gui.qbs
@@ -18,7 +18,7 @@ QtModule {
Artifact {
// ### TODO we want to access the module's property "Qt.core.generatedFilesDir" here. But without evaluating all available properties a priori.
- fileName: 'GeneratedFiles/' + product.name + '/ui_' + input.completeBaseName + '.h'
+ fileName: 'GeneratedFiles/ui_' + input.completeBaseName + '.h'
fileTags: ["hpp"]
}