GenericProjectManager: Add support for pre-compiled headers

Users can now add the tag "pch" after a file path in the .files file, and
we will pass this information on to the code model.

[ChangeLog][plugins][genericprojectmanager]
Added support for precompiled headers in generic projects for
Clang Code Model.
In order to use it, inside <projectName>.files add the "pch" tag just
after the filename and the '|' separator, example:
... other files ...
src/pch.h|pch
... other files ...

Fixes: QTCREATORBUG-26532
Change-Id: Iffc9d49cfc0bf92eba56cfc08a3977b0be777131
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
XutaxKamay
2021-11-10 15:13:14 +01:00
committed by admin
parent 162c68cb79
commit e88d049402

View File

@@ -66,9 +66,12 @@
#include <QFileInfo> #include <QFileInfo>
#include <QHash> #include <QHash>
#include <QMetaObject> #include <QMetaObject>
#include <QPair>
#include <QSet> #include <QSet>
#include <QStringList> #include <QStringList>
#include <set>
using namespace Core; using namespace Core;
using namespace ProjectExplorer; using namespace ProjectExplorer;
using namespace Utils; using namespace Utils;
@@ -148,7 +151,9 @@ public:
bool saveRawList(const QStringList &rawList, const QString &fileName); bool saveRawList(const QStringList &rawList, const QString &fileName);
void parse(RefreshOptions options); void parse(RefreshOptions options);
QStringList processEntries(const QStringList &paths, using SourceFile = QPair<FilePath, QStringList>;
using SourceFiles = QList<SourceFile>;
SourceFiles processEntries(const QStringList &paths,
QHash<QString, QString> *map = nullptr) const; QHash<QString, QString> *map = nullptr) const;
Utils::FilePath findCommonSourceRoot(); Utils::FilePath findCommonSourceRoot();
@@ -165,7 +170,7 @@ private:
QString m_cxxflagsFileName; QString m_cxxflagsFileName;
QString m_cflagsFileName; QString m_cflagsFileName;
QStringList m_rawFileList; QStringList m_rawFileList;
QStringList m_files; SourceFiles m_files;
QHash<QString, QString> m_rawListEntries; QHash<QString, QString> m_rawListEntries;
QStringList m_rawProjectIncludePaths; QStringList m_rawProjectIncludePaths;
ProjectExplorer::HeaderPaths m_projectIncludePaths; ProjectExplorer::HeaderPaths m_projectIncludePaths;
@@ -177,7 +182,6 @@ private:
Utils::FileSystemWatcher m_deployFileWatcher; Utils::FileSystemWatcher m_deployFileWatcher;
}; };
//////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////
// //
// GenericProject // GenericProject
@@ -452,8 +456,9 @@ FilePath GenericBuildSystem::findCommonSourceRoot()
if (m_files.isEmpty()) if (m_files.isEmpty())
return FilePath::fromFileInfo(QFileInfo(m_filesFileName)); return FilePath::fromFileInfo(QFileInfo(m_filesFileName));
QString root = m_files.front(); QString root = m_files.front().first.toString();
for (const QString &item : qAsConst(m_files)) { for (const SourceFile &sourceFile : qAsConst(m_files)) {
const QString item = sourceFile.first.toString();
if (root.length() > item.length()) if (root.length() > item.length())
root.truncate(item.length()); root.truncate(item.length());
@@ -480,11 +485,11 @@ void GenericBuildSystem::refresh(RefreshOptions options)
FilePath baseDir = findCommonSourceRoot(); FilePath baseDir = findCommonSourceRoot();
std::vector<std::unique_ptr<FileNode>> fileNodes; std::vector<std::unique_ptr<FileNode>> fileNodes;
for (const QString &f : qAsConst(m_files)) { for (const SourceFile &f : qAsConst(m_files)) {
FileType fileType = FileType::Source; // ### FIXME FileType fileType = FileType::Source; // ### FIXME
if (f.endsWith(".qrc")) if (f.first.endsWith(".qrc"))
fileType = FileType::Resource; fileType = FileType::Resource;
fileNodes.emplace_back(std::make_unique<FileNode>(FilePath::fromString(f), fileType)); fileNodes.emplace_back(std::make_unique<FileNode>(f.first, fileType));
} }
newRoot->addNestedNodes(std::move(fileNodes), baseDir); newRoot->addNestedNodes(std::move(fileNodes), baseDir);
@@ -517,8 +522,8 @@ void GenericBuildSystem::refresh(RefreshOptions options)
* The \a map variable is an optional argument that will map the returned * The \a map variable is an optional argument that will map the returned
* absolute paths back to their original \a entries. * absolute paths back to their original \a entries.
*/ */
QStringList GenericBuildSystem::processEntries(const QStringList &paths, GenericBuildSystem::SourceFiles GenericBuildSystem::processEntries(
QHash<QString, QString> *map) const const QStringList &paths, QHash<QString, QString> *map) const
{ {
const BuildConfiguration *const buildConfig = target()->activeBuildConfiguration(); const BuildConfiguration *const buildConfig = target()->activeBuildConfiguration();
@@ -534,7 +539,8 @@ QStringList GenericBuildSystem::processEntries(const QStringList &paths,
const QDir projectDir(projectDirectory().toString()); const QDir projectDir(projectDirectory().toString());
QFileInfo fileInfo; QFileInfo fileInfo;
QStringList absolutePaths; SourceFiles sourceFiles;
std::set<QString> seenFiles;
for (const QString &path : paths) { for (const QString &path : paths) {
QString trimmedPath = path.trimmed(); QString trimmedPath = path.trimmed();
if (trimmedPath.isEmpty()) if (trimmedPath.isEmpty())
@@ -545,16 +551,26 @@ QStringList GenericBuildSystem::processEntries(const QStringList &paths,
trimmedPath = Utils::FilePath::fromUserInput(trimmedPath).toString(); trimmedPath = Utils::FilePath::fromUserInput(trimmedPath).toString();
QStringList tagsForFile;
const int tagListPos = trimmedPath.indexOf('|');
if (tagListPos != -1) {
tagsForFile = trimmedPath.mid(tagListPos + 1).simplified()
.split(' ', Qt::SkipEmptyParts);
trimmedPath = trimmedPath.left(tagListPos).trimmed();
}
if (!seenFiles.insert(trimmedPath).second)
continue;
fileInfo.setFile(projectDir, trimmedPath); fileInfo.setFile(projectDir, trimmedPath);
if (fileInfo.exists()) { if (fileInfo.exists()) {
const QString absPath = fileInfo.absoluteFilePath(); const QString absPath = fileInfo.absoluteFilePath();
absolutePaths.append(absPath); sourceFiles.append({FilePath::fromString(absPath), tagsForFile});
if (map) if (map)
map->insert(absPath, trimmedPath); map->insert(absPath, trimmedPath);
} }
} }
absolutePaths.removeDuplicates(); return sourceFiles;
return absolutePaths;
} }
void GenericBuildSystem::refreshCppCodeModel() void GenericBuildSystem::refreshCppCodeModel()
@@ -574,7 +590,15 @@ void GenericBuildSystem::refreshCppCodeModel()
rpp.setConfigFileName(m_configFileName); rpp.setConfigFileName(m_configFileName);
rpp.setFlagsForCxx({nullptr, m_cxxflags, projectDirectory().toString()}); rpp.setFlagsForCxx({nullptr, m_cxxflags, projectDirectory().toString()});
rpp.setFlagsForC({nullptr, m_cflags, projectDirectory().toString()}); rpp.setFlagsForC({nullptr, m_cflags, projectDirectory().toString()});
rpp.setFiles(m_files);
static const auto sourceFilesToStringList = [](const SourceFiles &sourceFiles) {
return Utils::transform(sourceFiles, [](const SourceFile &f) {
return f.first.toString();
});
};
rpp.setFiles(sourceFilesToStringList(m_files));
rpp.setPreCompiledHeaders(sourceFilesToStringList(
Utils::filtered(m_files, [](const SourceFile &f) { return f.second.contains("pch"); })));
m_cppCodeModelUpdater->update({project(), kitInfo, activeParseEnvironment(), {rpp}}); m_cppCodeModelUpdater->update({project(), kitInfo, activeParseEnvironment(), {rpp}});
} }