From 38faf098c8fd085833e194bb99524313b3ea43ba Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Mon, 23 Jan 2023 12:52:52 +0100 Subject: [PATCH] QbsProjectManager: Refactor raw project part creation No functional changes. Preparation for bugfix. Change-Id: Ib391a597b2ba615250b1219451f7dc537476f8af Reviewed-by: Reviewed-by: Qt CI Bot Reviewed-by: Christian Stenger --- src/plugins/qbsprojectmanager/qbsproject.cpp | 234 ++++++++++--------- 1 file changed, 123 insertions(+), 111 deletions(-) diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp index dc9caef34c0..8a8676fefdc 100644 --- a/src/plugins/qbsprojectmanager/qbsproject.cpp +++ b/src/plugins/qbsprojectmanager/qbsproject.cpp @@ -847,6 +847,127 @@ static void getExpandedCompilerFlags(QStringList &cFlags, QStringList &cxxFlags, } } +static RawProjectPart generateProjectPart( + const QJsonObject &product, + const QJsonObject &group, + const std::shared_ptr &cToolChain, + const std::shared_ptr &cxxToolChain, + QtMajorVersion qtVersion, + QString cPch, + QString cxxPch, + QString objcPch, + QString objcxxPch + ) +{ + const QString productName = product.value("full-display-name").toString(); + const QString groupName = group.value("name").toString(); + RawProjectPart rpp; + rpp.setQtVersion(qtVersion); + QJsonObject props = group.value("module-properties").toObject(); + if (props.isEmpty()) + props = product.value("module-properties").toObject(); + rpp.setCallGroupId(groupLocationToCallGroupId(group.value("location").toObject())); + + QStringList cFlags; + QStringList cxxFlags; + getExpandedCompilerFlags(cFlags, cxxFlags, props); + rpp.setFlagsForC({cToolChain.get(), cFlags, {}}); + rpp.setFlagsForCxx({cxxToolChain.get(), cxxFlags, {}}); + + const QStringList defines = arrayToStringList(props.value("cpp.defines")) + + arrayToStringList(props.value("cpp.platformDefines")); + rpp.setMacros(transform(defines, + [](const QString &s) { return Macro::fromKeyValue(s); })); + + ProjectExplorer::HeaderPaths grpHeaderPaths; + QStringList list = arrayToStringList(props.value("cpp.includePaths")); + list.removeDuplicates(); + for (const QString &p : std::as_const(list)) + grpHeaderPaths += HeaderPath::makeUser(FilePath::fromUserInput(p)); + list = arrayToStringList(props.value("cpp.distributionIncludePaths")) + + arrayToStringList(props.value("cpp.systemIncludePaths")); + list.removeDuplicates(); + for (const QString &p : std::as_const(list)) + grpHeaderPaths += HeaderPath::makeSystem(FilePath::fromUserInput(p)); + list = arrayToStringList(props.value("cpp.frameworkPaths")); + list.append(arrayToStringList(props.value("cpp.systemFrameworkPaths"))); + list.removeDuplicates(); + for (const QString &p : std::as_const(list)) + grpHeaderPaths += HeaderPath::makeFramework(FilePath::fromUserInput(p)); + rpp.setHeaderPaths(grpHeaderPaths); + rpp.setDisplayName(groupName); + const QJsonObject location = group.value("location").toObject(); + rpp.setProjectFileLocation(location.value("file-path").toString(), + location.value("line").toInt(), + location.value("column").toInt()); + rpp.setBuildSystemTarget(QbsProductNode::getBuildKey(product)); + if (product.value("is-runnable").toBool()) { + rpp.setBuildTargetType(BuildTargetType::Executable); + } else { + const QJsonArray pType = product.value("type").toArray(); + if (pType.contains("staticlibrary") || pType.contains("dynamiclibrary") + || pType.contains("loadablemodule")) { + rpp.setBuildTargetType(BuildTargetType::Library); + } else { + rpp.setBuildTargetType(BuildTargetType::Unknown); + } + } + rpp.setSelectedForBuilding(group.value("is-enabled").toBool()); + + QHash filePathToSourceArtifact; + bool hasCFiles = false; + bool hasCxxFiles = false; + bool hasObjcFiles = false; + bool hasObjcxxFiles = false; + const auto artifactWorker = [&](const QJsonObject &source) { + const QString filePath = source.value("file-path").toString(); + filePathToSourceArtifact.insert(filePath, source); + for (const QJsonValue &tag : source.value("file-tags").toArray()) { + if (tag == "c") + hasCFiles = true; + else if (tag == "cpp") + hasCxxFiles = true; + else if (tag == "objc") + hasObjcFiles = true; + else if (tag == "objcpp") + hasObjcxxFiles = true; + } + }; + forAllArtifacts(group, artifactWorker); + + QSet pchFiles; + if (hasCFiles && props.value("cpp.useCPrecompiledHeader").toBool() + && !cPch.isEmpty()) { + pchFiles << cPch; + } + if (hasCxxFiles && props.value("cpp.useCxxPrecompiledHeader").toBool() + && !cxxPch.isEmpty()) { + pchFiles << cxxPch; + } + if (hasObjcFiles && props.value("cpp.useObjcPrecompiledHeader").toBool() + && !objcPch.isEmpty()) { + pchFiles << objcPch; + } + if (hasObjcxxFiles + && props.value("cpp.useObjcxxPrecompiledHeader").toBool() + && !objcxxPch.isEmpty()) { + pchFiles << objcxxPch; + } + if (pchFiles.count() > 1) { + qCWarning(qbsPmLog) << "More than one pch file enabled for source files in group" + << groupName << "in product" << productName; + qCWarning(qbsPmLog) << "Expect problems with code model"; + } + rpp.setPreCompiledHeaders(Utils::toList(pchFiles)); + rpp.setIncludedFiles(arrayToStringList(props.value("cpp.prefixHeaders"))); + rpp.setFiles(filePathToSourceArtifact.keys(), {}, + [filePathToSourceArtifact](const QString &filePath) { + // Keep this lambda thread-safe! + return getMimeType(filePathToSourceArtifact.value(filePath)); + }); + return rpp; +} + static RawProjectParts generateProjectParts( const QJsonObject &projectData, const std::shared_ptr &cToolChain, @@ -856,7 +977,6 @@ static RawProjectParts generateProjectParts( { RawProjectParts rpps; forAllProducts(projectData, [&](const QJsonObject &prd) { - const QString productName = prd.value("full-display-name").toString(); QString cPch; QString cxxPch; QString objcPch; @@ -873,122 +993,14 @@ static RawProjectParts generateProjectParts( objcxxPch = artifact.value("file-path").toString(); }; forAllArtifacts(prd, ArtifactType::All, pchFinder); - const Utils::QtMajorVersion qtVersionForPart = prd.value("module-properties").toObject().value("Qt.core.version").isUndefined() ? Utils::QtMajorVersion::None : qtVersion; - const QJsonArray groups = prd.value("groups").toArray(); for (const QJsonValue &g : groups) { - const QJsonObject grp = g.toObject(); - const QString groupName = grp.value("name").toString(); - - RawProjectPart rpp; - rpp.setQtVersion(qtVersionForPart); - QJsonObject props = grp.value("module-properties").toObject(); - if (props.isEmpty()) - props = prd.value("module-properties").toObject(); - rpp.setCallGroupId(groupLocationToCallGroupId(grp.value("location").toObject())); - - QStringList cFlags; - QStringList cxxFlags; - getExpandedCompilerFlags(cFlags, cxxFlags, props); - rpp.setFlagsForC({cToolChain.get(), cFlags, {}}); - rpp.setFlagsForCxx({cxxToolChain.get(), cxxFlags, {}}); - - const QStringList defines = arrayToStringList(props.value("cpp.defines")) - + arrayToStringList(props.value("cpp.platformDefines")); - rpp.setMacros(transform(defines, - [](const QString &s) { return Macro::fromKeyValue(s); })); - - ProjectExplorer::HeaderPaths grpHeaderPaths; - QStringList list = arrayToStringList(props.value("cpp.includePaths")); - list.removeDuplicates(); - for (const QString &p : std::as_const(list)) - grpHeaderPaths += HeaderPath::makeUser(FilePath::fromUserInput(p)); - list = arrayToStringList(props.value("cpp.distributionIncludePaths")) - + arrayToStringList(props.value("cpp.systemIncludePaths")); - list.removeDuplicates(); - for (const QString &p : std::as_const(list)) - grpHeaderPaths += HeaderPath::makeSystem(FilePath::fromUserInput(p)); - list = arrayToStringList(props.value("cpp.frameworkPaths")); - list.append(arrayToStringList(props.value("cpp.systemFrameworkPaths"))); - list.removeDuplicates(); - for (const QString &p : std::as_const(list)) - grpHeaderPaths += HeaderPath::makeFramework(FilePath::fromUserInput(p)); - rpp.setHeaderPaths(grpHeaderPaths); - rpp.setDisplayName(groupName); - const QJsonObject location = grp.value("location").toObject(); - rpp.setProjectFileLocation(location.value("file-path").toString(), - location.value("line").toInt(), - location.value("column").toInt()); - rpp.setBuildSystemTarget(QbsProductNode::getBuildKey(prd)); - if (prd.value("is-runnable").toBool()) { - rpp.setBuildTargetType(BuildTargetType::Executable); - } else { - const QJsonArray pType = prd.value("type").toArray(); - if (pType.contains("staticlibrary") || pType.contains("dynamiclibrary") - || pType.contains("loadablemodule")) { - rpp.setBuildTargetType(BuildTargetType::Library); - } else { - rpp.setBuildTargetType(BuildTargetType::Unknown); - } - } - rpp.setSelectedForBuilding(grp.value("is-enabled").toBool()); - - QHash filePathToSourceArtifact; - bool hasCFiles = false; - bool hasCxxFiles = false; - bool hasObjcFiles = false; - bool hasObjcxxFiles = false; - const auto artifactWorker = [&](const QJsonObject &source) { - const QString filePath = source.value("file-path").toString(); - filePathToSourceArtifact.insert(filePath, source); - for (const QJsonValue &tag : source.value("file-tags").toArray()) { - if (tag == "c") - hasCFiles = true; - else if (tag == "cpp") - hasCxxFiles = true; - else if (tag == "objc") - hasObjcFiles = true; - else if (tag == "objcpp") - hasObjcxxFiles = true; - } - }; - forAllArtifacts(grp, artifactWorker); - - QSet pchFiles; - if (hasCFiles && props.value("cpp.useCPrecompiledHeader").toBool() - && !cPch.isEmpty()) { - pchFiles << cPch; - } - if (hasCxxFiles && props.value("cpp.useCxxPrecompiledHeader").toBool() - && !cxxPch.isEmpty()) { - pchFiles << cxxPch; - } - if (hasObjcFiles && props.value("cpp.useObjcPrecompiledHeader").toBool() - && !objcPch.isEmpty()) { - pchFiles << objcPch; - } - if (hasObjcxxFiles - && props.value("cpp.useObjcxxPrecompiledHeader").toBool() - && !objcxxPch.isEmpty()) { - pchFiles << objcxxPch; - } - if (pchFiles.count() > 1) { - qCWarning(qbsPmLog) << "More than one pch file enabled for source files in group" - << groupName << "in product" << productName; - qCWarning(qbsPmLog) << "Expect problems with code model"; - } - rpp.setPreCompiledHeaders(Utils::toList(pchFiles)); - rpp.setIncludedFiles(arrayToStringList(props.value("cpp.prefixHeaders"))); - rpp.setFiles(filePathToSourceArtifact.keys(), {}, - [filePathToSourceArtifact](const QString &filePath) { - // Keep this lambda thread-safe! - return getMimeType(filePathToSourceArtifact.value(filePath)); - }); - rpps.append(rpp); + rpps.append(generateProjectPart(prd, g.toObject(), cToolChain, cxxToolChain, + qtVersionForPart, cPch, cxxPch, objcPch, objcxxPch)); } }); return rpps;