CppTools: Adapt CompilerOptionsBuilder to HeaderPathFilter

After we moved some of the code to HeaderPathFilter we now use it in
CompilerOptionsBuilder.

Task-number: QTCREATORBUG-21693
Change-Id: Iea3569465bbc135d72bd88f9c23026f2ace33aba
Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
This commit is contained in:
Marco Bubke
2018-12-19 18:37:02 +01:00
parent 5d1114fe52
commit 97828a96af
3 changed files with 42 additions and 116 deletions

View File

@@ -26,6 +26,7 @@
#include "compileroptionsbuilder.h"
#include "cppmodelmanager.h"
#include "headerpathfilter.h"
#include <coreplugin/icore.h>
@@ -230,57 +231,6 @@ static QString creatorResourcePath()
#endif
}
static QString clangIncludeDirectory(const QString &clangVersion,
const QString &clangResourceDirectory)
{
#ifndef UNIT_TESTS
return Core::ICore::clangIncludeDirectory(clangVersion, clangResourceDirectory);
#else
Q_UNUSED(clangVersion);
Q_UNUSED(clangResourceDirectory);
return QDir::toNativeSeparators(QString::fromUtf8(CLANG_RESOURCE_DIR ""));
#endif
}
static QStringList insertResourceDirectory(const QStringList &options,
const QString &resourceDir,
bool isMacOs = false)
{
// include/c++, include/g++, libc++\include and libc++abi\include
static const QString cppIncludes = R"((.*[\/\\]include[\/\\].*(g\+\+|c\+\+).*))"
R"(|(.*libc\+\+[\/\\]include))"
R"(|(.*libc\+\+abi[\/\\]include))";
QStringList optionsBeforeResourceDirectory;
QStringList optionsAfterResourceDirectory;
QRegularExpression includeRegExp;
if (!isMacOs) {
includeRegExp = QRegularExpression("\\A(" + cppIncludes + ")\\z");
} else {
// The same as includeRegExp but also matches /usr/local/include
includeRegExp = QRegularExpression(
"\\A(" + cppIncludes + R"(|([\/\\]usr[\/\\]local[\/\\]include))" + ")\\z");
}
for (const QString &option : options) {
if (option == includeSystemPathOption)
continue;
if (includeRegExp.match(option).hasMatch()) {
optionsBeforeResourceDirectory.push_back(includeSystemPathOption);
optionsBeforeResourceDirectory.push_back(option);
} else {
optionsAfterResourceDirectory.push_back(includeSystemPathOption);
optionsAfterResourceDirectory.push_back(option);
}
}
optionsBeforeResourceDirectory.push_back(includeSystemPathOption);
optionsBeforeResourceDirectory.push_back(resourceDir);
return optionsBeforeResourceDirectory + optionsAfterResourceDirectory;
}
void CompilerOptionsBuilder::insertWrappedQtHeaders()
{
if (m_useTweakedHeaderPaths == UseTweakedHeaderPaths::No)
@@ -296,77 +246,42 @@ void CompilerOptionsBuilder::insertWrappedQtHeaders()
m_options = m_options.mid(0, index) + wrappedQtHeaders + m_options.mid(index);
}
static bool excludeHeaderPath(const QString &headerPath)
{
// Always exclude clang system includes (including intrinsics) which do not come with libclang
// that Qt Creator uses for code model.
// For example GCC on macOS uses system clang include path which makes clang code model
// include incorrect system headers.
static const QRegularExpression clangIncludeDir(
R"(\A.*[\/\\]lib\d*[\/\\]clang[\/\\]\d+\.\d+(\.\d+)?[\/\\]include\z)");
return clangIncludeDir.match(headerPath).hasMatch();
}
void CompilerOptionsBuilder::addHeaderPathOptions()
{
HeaderPathFilter filter{m_projectPart,
m_useTweakedHeaderPaths,
m_clangVersion,
m_clangResourceDirectory};
filter.process();
using ProjectExplorer::HeaderPath;
using ProjectExplorer::HeaderPathType;
QStringList includes;
QStringList systemIncludes;
QStringList builtInIncludes;
for (const ProjectExplorer::HeaderPath &headerPath : qAsConst(m_projectPart.headerPaths)) {
if (headerPath.path.isEmpty())
continue;
if (excludeHeaderPath(headerPath.path))
continue;
switch (headerPath.type) {
case HeaderPathType::Framework:
includes.append("-F");
includes.append(QDir::toNativeSeparators(headerPath.path));
break;
case HeaderPathType::User:
includes.append(includeDirOptionForPath(headerPath.path));
includes.append(QDir::toNativeSeparators(headerPath.path));
break;
case HeaderPathType::BuiltIn:
builtInIncludes.append(includeSystemPathOption);
builtInIncludes.append(QDir::toNativeSeparators(headerPath.path));
break;
case HeaderPathType::System:
systemIncludes.append(m_useSystemHeader == UseSystemHeader::Yes
? QLatin1String(includeSystemPathOption)
: QLatin1String(includeUserPathOption));
systemIncludes.append(QDir::toNativeSeparators(headerPath.path));
break;
if (m_useTweakedHeaderPaths == UseTweakedHeaderPaths::Yes) {
// Exclude all built-in includes except Clang resource directory.
m_options.prepend("-nostdlibinc");
if (!m_clangVersion.isEmpty()) {
// Exclude all built-in includes and Clang resource directory.
m_options.prepend("-nostdinc");
}
}
m_options.append(includes);
m_options.append(systemIncludes);
if (m_useTweakedHeaderPaths == UseTweakedHeaderPaths::No)
return;
// Exclude all built-in includes except Clang resource directory.
m_options.prepend("-nostdlibinc");
if (!m_clangVersion.isEmpty()) {
// Exclude all built-in includes and Clang resource directory.
m_options.prepend("-nostdinc");
const QString clangIncludePath
= clangIncludeDirectory(m_clangVersion, m_clangResourceDirectory);
builtInIncludes = insertResourceDirectory(builtInIncludes,
clangIncludePath,
m_projectPart.toolChainTargetTriple.contains(
"darwin"));
for (const HeaderPath &headerPath : filter.userHeaderPaths) {
m_options.push_back(includeDirOptionForPath(headerPath.path));
m_options.push_back(QDir::toNativeSeparators(headerPath.path));
}
m_options.append(builtInIncludes);
for (const HeaderPath &headerPath : filter.systemHeaderPaths) {
m_options.push_back(includeDirOptionForSystemPath(headerPath.type));
m_options.push_back(QDir::toNativeSeparators(headerPath.path));
}
for (const HeaderPath &headerPath : filter.builtInHeaderPaths) {
m_options.push_back(includeSystemPathOption);
m_options.push_back(QDir::toNativeSeparators(headerPath.path));
}
}
void CompilerOptionsBuilder::addPrecompiledHeaderOptions(UsePrecompiledHeaders usePrecompiledHeaders)
@@ -658,6 +573,17 @@ void CompilerOptionsBuilder::addWrappedQtHeadersIncludePath(QStringList &list) c
}
}
QString CompilerOptionsBuilder::includeDirOptionForSystemPath(ProjectExplorer::HeaderPathType type) const
{
if (type == ProjectExplorer::HeaderPathType::Framework)
return "-F";
if (m_useSystemHeader == UseSystemHeader::Yes)
return includeSystemPathOption;
return includeUserPathOption;
}
void CompilerOptionsBuilder::addToolchainFlags()
{
// In case of MSVC we need builtin clang defines to correctly handle clang includes

View File

@@ -83,6 +83,7 @@ private:
bool excludeDefineDirective(const ProjectExplorer::Macro &macro) const;
QString includeDirOptionForPath(const QString &path) const;
void addWrappedQtHeadersIncludePath(QStringList &list) const;
QString includeDirOptionForSystemPath(ProjectExplorer::HeaderPathType type) const;
private:
const ProjectPart &m_projectPart;

View File

@@ -25,13 +25,11 @@
#pragma once
#include "compileroptionsbuilder.h"
#include "projectpart.h"
namespace CppTools {
enum class UseTweakedHeaderPaths : char { Yes, No };
class HeaderPathFilter
class CPPTOOLS_EXPORT HeaderPathFilter
{
public:
HeaderPathFilter(const ProjectPart &projectPart,
@@ -46,6 +44,7 @@ public:
void process();
private:
void filterHeaderPath(const ProjectExplorer::HeaderPath &headerPath);
void tweakHeaderPaths();