diff options
Diffstat (limited to 'src/lib/corelib/language/language.cpp')
-rw-r--r-- | src/lib/corelib/language/language.cpp | 190 |
1 files changed, 104 insertions, 86 deletions
diff --git a/src/lib/corelib/language/language.cpp b/src/lib/corelib/language/language.cpp index 3db41b8c8..b3f4b2a64 100644 --- a/src/lib/corelib/language/language.cpp +++ b/src/lib/corelib/language/language.cpp @@ -51,6 +51,8 @@ #include <buildgraph/rulegraph.h> // TODO: Move to language? #include <buildgraph/transformer.h> #include <jsextensions/jsextensions.h> +#include <language/value.h> +#include <loader/loaderutils.h> #include <logging/categories.h> #include <logging/translator.h> #include <tools/buildgraphlocker.h> @@ -60,6 +62,7 @@ #include <tools/qbsassert.h> #include <tools/qttools.h> #include <tools/scripttools.h> +#include <tools/setupprojectparameters.h> #include <tools/stlutils.h> #include <tools/stringconstants.h> @@ -68,8 +71,6 @@ #include <QtCore/qdiriterator.h> #include <QtCore/qmap.h> -#include <QtScript/qscriptvalue.h> - #include <algorithm> #include <memory> #include <mutex> @@ -117,6 +118,12 @@ bool Probe::needsReconfigure(const FileTime &referenceTime) const return Internal::any_of(m_importedFilesUsed, criterion); } +void Probe::restoreValues() +{ + for (auto it = m_properties.begin(), end = m_properties.end(); it != end; ++it) { + m_values[it.key()] = VariantValue::createStored(it.value()); + } +} /*! * \class SourceArtifact @@ -137,41 +144,16 @@ bool Probe::needsReconfigure(const FileTime &referenceTime) const /*! * \variable ResolvedGroup::files * \brief The files listed in the group item's "files" binding. - * Note that these do not include expanded wildcards. */ /*! * \variable ResolvedGroup::wildcards - * \brief Represents the wildcard elements in this group's "files" binding. + * \brief Represents the wildcard patterns in this group's "files" binding. * If no wildcards are specified there, this variable is null. * \sa SourceWildCards */ /*! - * \brief Returns all files specified in the group item as source artifacts. - * This includes the expanded list of wildcards. - */ -std::vector<SourceArtifactPtr> ResolvedGroup::allFiles() const -{ - std::vector<SourceArtifactPtr> lst = files; - if (wildcards) - lst << wildcards->files; - return lst; -} - -void ResolvedGroup::load(PersistentPool &pool) -{ - serializationOp<PersistentPool::Load>(pool); - if (wildcards) - wildcards->group = this; -} - -void ResolvedGroup::store(PersistentPool &pool) -{ - serializationOp<PersistentPool::Store>(pool); -} - -/*! * \class RuleArtifact * \brief The \c RuleArtifact class represents an Artifact item encountered in the context * of a Rule item. @@ -313,7 +295,7 @@ void ResolvedProduct::accept(BuildGraphVisitor *visitor) const { if (!buildData) return; - for (BuildGraphNode * const node : qAsConst(buildData->rootNodes())) + for (BuildGraphNode * const node : std::as_const(buildData->rootNodes())) node->accept(visitor); } @@ -325,7 +307,7 @@ std::vector<SourceArtifactPtr> ResolvedProduct::allFiles() const { std::vector<SourceArtifactPtr> lst; for (const auto &group : groups) - lst << group->allFiles(); + lst << group->files; return lst; } @@ -338,7 +320,7 @@ std::vector<SourceArtifactPtr> ResolvedProduct::allEnabledFiles() const std::vector<SourceArtifactPtr> lst; for (const auto &group : groups) { if (group->enabled) - lst << group->allFiles(); + lst << group->files; } return lst; } @@ -347,7 +329,7 @@ FileTags ResolvedProduct::fileTagsForFileName(const QString &fileName) const { FileTags result; std::unique_ptr<int> priority; - for (const FileTaggerConstPtr &tagger : qAsConst(fileTaggers)) { + for (const FileTaggerConstPtr &tagger : std::as_const(fileTaggers)) { for (const QRegularExpression &pattern : tagger->patterns()) { if (pattern.match(fileName).hasMatch()) { if (priority) { @@ -374,6 +356,8 @@ void ResolvedProduct::load(PersistentPool &pool) rule->product = this; for (const ResolvedModulePtr &module : modules) module->product = this; + for (const auto &group: groups) + group->restoreWildcards(buildDirectory()); } void ResolvedProduct::store(PersistentPool &pool) @@ -425,18 +409,9 @@ QString ResolvedProduct::uniqueName() const return uniqueName(name, multiplexConfigurationId); } -QString ResolvedProduct::fullDisplayName(const QString &name, - const QString &multiplexConfigurationId) -{ - QString result = name; - if (!multiplexConfigurationId.isEmpty()) - result.append(QLatin1Char(' ')).append(multiplexIdToString(multiplexConfigurationId)); - return result; -} - QString ResolvedProduct::fullDisplayName() const { - return fullDisplayName(name, multiplexConfigurationId); + return fullProductDisplayName(name, multiplexConfigurationId); } QString ResolvedProduct::profile() const @@ -512,6 +487,19 @@ QString ResolvedProduct::cachedExecutablePath(const QString &origFilePath) const return m_executablePathCache.value(origFilePath); } +void ResolvedGroup::restoreWildcards(const QString &buildDir) +{ + if (wildcards) { + wildcards->buildDir = buildDir; + wildcards->prefix = prefix; + wildcards->baseDir = FileInfo::path(location.filePath()); + for (const auto &sourceArtifact : files) { + if (sourceArtifact->fromWildcard) + wildcards->expandedFiles += sourceArtifact->absoluteFilePath; + } + } +} + ResolvedProject::ResolvedProject() : enabled(true), m_topLevelProject(nullptr) { @@ -523,7 +511,7 @@ void ResolvedProject::accept(BuildGraphVisitor *visitor) const { for (const ResolvedProductPtr &product : products) product->accept(visitor); - for (const ResolvedProjectPtr &subProject : qAsConst(subProjects)) + for (const ResolvedProjectPtr &subProject : std::as_const(subProjects)) subProject->accept(visitor); } @@ -550,7 +538,7 @@ std::vector<ResolvedProjectPtr> ResolvedProject::allSubProjects() const std::vector<ResolvedProductPtr> ResolvedProject::allProducts() const { std::vector<ResolvedProductPtr> productList = products; - for (const auto &subProject : qAsConst(subProjects)) + for (const auto &subProject : std::as_const(subProjects)) productList << subProject->allProducts(); return productList; } @@ -562,11 +550,11 @@ void ResolvedProject::load(PersistentPool &pool) [](const ResolvedProductPtr &p) { if (!p->buildData) return; - for (BuildGraphNode * const node : qAsConst(p->buildData->allNodes())) { + for (BuildGraphNode * const node : std::as_const(p->buildData->allNodes())) { node->product = p; // restore parent links - for (BuildGraphNode * const child : qAsConst(node->children)) + for (BuildGraphNode * const child : std::as_const(node->children)) child->parents.insert(node); } }); @@ -592,7 +580,7 @@ TopLevelProject::~TopLevelProject() QString TopLevelProject::deriveId(const QVariantMap &config) { const QVariantMap qbsProperties = config.value(StringConstants::qbsModule()).toMap(); - const QString configurationName = qbsProperties.value( + QString configurationName = qbsProperties.value( StringConstants::configurationNameProperty()).toString(); return configurationName; } @@ -619,6 +607,16 @@ void TopLevelProject::makeModuleProvidersNonTransient() m.transientOutput = false; } +QVariantMap TopLevelProject::fullProfileConfigsTree() const +{ + QVariantMap tree; + for (auto it = profileConfigs.cbegin(); it != profileConfigs.cend(); ++it) { + tree.insert(it.key(), SetupProjectParameters::finalBuildConfigurationTree( + it.value().toMap(), overriddenValues)); + } + return tree; +} + QString TopLevelProject::buildGraphFilePath() const { return ProjectBuildData::deriveBuildGraphFilePath(buildDirectory, id()); @@ -665,7 +663,7 @@ void TopLevelProject::store(PersistentPool &pool) void TopLevelProject::cleanupModuleProviderOutput() { QString error; - for (const ModuleProviderInfo &m : qAsConst(moduleProviderInfo.providers)) { + for (const ModuleProviderInfo &m : std::as_const(moduleProviderInfo.providers)) { if (m.transientOutput) { if (!removeDirectoryWithContents(m.outputDirPath(buildDirectory), &error)) qCWarning(lcBuildGraph) << "Error removing module provider output:" << error; @@ -709,25 +707,22 @@ void TopLevelProject::cleanupModuleProviderOutput() * \brief The \c SourceArtifacts resulting from the expanded list of matching files. */ -Set<QString> SourceWildCards::expandPatterns(const GroupConstPtr &group, - const QString &baseDir, const QString &buildDir) +void SourceWildCards::expandPatterns() { - Set<QString> files = expandPatterns(group, patterns, baseDir, buildDir); - files -= expandPatterns(group, excludePatterns, baseDir, buildDir); - return files; + dirTimeStamps.clear(); + expandedFiles = expandPatterns(patterns) - expandPatterns(excludePatterns); } -Set<QString> SourceWildCards::expandPatterns(const GroupConstPtr &group, - const QStringList &patterns, const QString &baseDir, const QString &buildDir) +Set<QString> SourceWildCards::expandPatterns(const QStringList &patterns) { Set<QString> files; - QString expandedPrefix = group->prefix; + QString expandedPrefix = prefix; if (expandedPrefix.startsWith(StringConstants::tildeSlash())) expandedPrefix.replace(0, 1, QDir::homePath()); for (QString pattern : patterns) { pattern.prepend(expandedPrefix); pattern.replace(QLatin1Char('\\'), QLatin1Char('/')); - QStringList parts = pattern.split(QLatin1Char('/'), QBS_SKIP_EMPTY_PARTS); + QStringList parts = pattern.split(QLatin1Char('/'), Qt::SkipEmptyParts); if (FileInfo::isAbsolute(pattern)) { QString rootDir; if (HostOsInfo::isWindowsHost() && pattern.at(0) != QLatin1Char('/')) { @@ -737,18 +732,17 @@ Set<QString> SourceWildCards::expandPatterns(const GroupConstPtr &group, } else { rootDir = QLatin1Char('/'); } - expandPatterns(files, group, parts, rootDir, buildDir); + expandPatterns(files, parts, rootDir); } else { - expandPatterns(files, group, parts, baseDir, buildDir); + expandPatterns(files, parts, baseDir); } } return files; } -void SourceWildCards::expandPatterns(Set<QString> &result, const GroupConstPtr &group, - const QStringList &parts, - const QString &baseDir, const QString &buildDir) +void SourceWildCards::expandPatterns(Set<QString> &result, const QStringList &parts, + const QString &baseDir) { // People might build directly in the project source directory. This is okay, since // we keep the build data in a "container" directory. However, we must make sure we don't @@ -756,8 +750,6 @@ void SourceWildCards::expandPatterns(Set<QString> &result, const GroupConstPtr & if (baseDir.startsWith(buildDir)) return; - dirTimeStamps.emplace_back(baseDir, FileInfo(baseDir).lastModified()); - QStringList changed_parts = parts; bool recursive = false; QString part = changed_parts.takeFirst(); @@ -784,8 +776,12 @@ void SourceWildCards::expandPatterns(Set<QString> &result, const GroupConstPtr & : QDir::Files | QDir::System | QDir::Dirs; // This one is needed to get symbolic links to directories - if (isDir && !FileInfo::isPattern(filePattern)) + if (FileInfo::isPattern(filePattern)) { + if (!recursive) + dirTimeStamps.emplace_back(baseDir, FileInfo(baseDir).lastModified()); + } else if (isDir) { itFilters |= QDir::Hidden; + } if (filePattern != StringConstants::dotDot() && filePattern != StringConstants::dot()) itFilters |= QDir::NoDotAndDotDot; @@ -797,16 +793,28 @@ void SourceWildCards::expandPatterns(Set<QString> &result, const GroupConstPtr & continue; // See above. if (!isDir && it.fileInfo().isDir() && !it.fileInfo().isSymLink()) continue; - if (isDir) { - expandPatterns(result, group, changed_parts, filePath, buildDir); - } else { - if (parentDir != baseDir) - dirTimeStamps.emplace_back(parentDir, FileInfo(baseDir).lastModified()); + if (isDir) + expandPatterns(result, changed_parts, filePath); + else result += QDir::cleanPath(filePath); - } } } +bool SourceWildCards::hasChangedSinceExpansion() const +{ + const bool reExpansionRequired = + Internal::any_of(dirTimeStamps, + [](const std::pair<QString, FileTime> &pair) { + return FileInfo(pair.first).lastModified() > pair.second; + }); + if (reExpansionRequired) + return true; + + auto wc = *this; + wc.expandPatterns(); + return this->expandedFiles != wc.expandedFiles; +} + template<typename L> QMap<QString, typename L::value_type> listToMap(const L &list) { @@ -915,11 +923,6 @@ bool artifactPropertyListsAreEqual(const std::vector<ArtifactPropertiesPtr> &l1, return listsAreEqual(l1, l2); } -QString multiplexIdToString(const QString &id) -{ - return QString::fromUtf8(QByteArray::fromBase64(id.toUtf8())); -} - bool operator==(const PrivateScriptFunction &a, const PrivateScriptFunction &b) { return equals(a.m_sharedData.get(), b.m_sharedData.get()); @@ -935,7 +938,7 @@ bool operator==(const ExportedProperty &p1, const ExportedProperty &p2) bool operator==(const ExportedModuleDependency &d1, const ExportedModuleDependency &d2) { - return d1.name == d2.name && d1.moduleProperties == d2.moduleProperties; + return d1.name == d2.name && qVariantMapsEqual(d1.moduleProperties, d2.moduleProperties); } bool equals(const std::vector<ExportedItemPtr> &l1, const std::vector<ExportedItemPtr> &l2) @@ -962,20 +965,35 @@ bool operator==(const ExportedModule &m1, const ExportedModule &m2) for (auto it1 = m1.cbegin(), it2 = m2.cbegin(); it1 != m1.cend(); ++it1, ++it2) { if (it1.key()->name != it2.key()->name) return false; - if (it1.value() != it2.value()) + if (!qVariantMapsEqual(it1.value(), it2.value())) return false; } return true; }; - return m1.propertyValues == m2.propertyValues - && m1.modulePropertyValues == m2.modulePropertyValues - && equals(m1.children, m2.children) - && m1.m_properties == m2.m_properties - && m1.importStatements == m2.importStatements - && m1.productDependencies.size() == m2.productDependencies.size() - && m1.productDependencies == m2.productDependencies - && depMapsEqual(m1.dependencyParameters, m2.dependencyParameters); + return qVariantMapsEqual(m1.propertyValues, m2.propertyValues) + && qVariantMapsEqual(m1.modulePropertyValues, m2.modulePropertyValues) + && equals(m1.children, m2.children) && m1.m_properties == m2.m_properties + && m1.importStatements == m2.importStatements + && m1.productDependencies.size() == m2.productDependencies.size() + && m1.productDependencies == m2.productDependencies + && depMapsEqual(m1.dependencyParameters, m2.dependencyParameters); +} + +JSValue PrivateScriptFunction::getFunction(ScriptEngine *engine, const QString &errorMessage) const +{ + if (JS_IsUndefined(scriptFunction)) { + ScopedJsValue val(engine->context(), + engine->evaluate(JsValueOwner::Caller, sourceCode(), + location().filePath(), location().line())); + if (Q_UNLIKELY(!JS_IsFunction(engine->context(), val))) + throw ErrorInfo(errorMessage, location()); + scriptFunction = val.release(); + engine->addExternallyCachedValue(&scriptFunction); + } else { + QBS_CHECK(JS_IsFunction(engine->context(), scriptFunction)); + } + return scriptFunction; } } // namespace Internal |