forked from qt-creator/qt-creator
CppTools: Add toolchain type to project part and use it
Making CompilerOptionsBuilder to use the toolchain from the project part simplifies its public API, but following the code paths initiated by ClangCodeModel and ClangStaticAnalyzer gets harder, so better enable the separation of those by making CompilerOptionsBuilder a base class. Change-Id: I0a6bb3f8323ba09b88135a7f9d1ef967331a8ff0 Reviewed-by: Christian Kandeler <christian.kandeler@theqtcompany.com>
This commit is contained in:
@@ -113,6 +113,7 @@ void ProjectPart::evaluateToolchain(const ToolChain *tc,
|
||||
}
|
||||
|
||||
toolchainDefines = tc->predefinedMacros(commandLineFlags);
|
||||
toolchainType = tc->type();
|
||||
updateLanguageFeatures();
|
||||
}
|
||||
|
||||
@@ -516,12 +517,27 @@ void CompilerOptionsBuilder::add(const QString &option)
|
||||
m_options.append(option);
|
||||
}
|
||||
|
||||
void CompilerOptionsBuilder::addHeaderPathOptions(IsBlackListed isBlackListed,
|
||||
const QString &toolchainType)
|
||||
QString CompilerOptionsBuilder::defineLineToDefineOption(const QByteArray &defineLine)
|
||||
{
|
||||
QByteArray str = defineLine.mid(8);
|
||||
int spaceIdx = str.indexOf(' ');
|
||||
const QString option = defineOption();
|
||||
const bool hasValue = spaceIdx != -1;
|
||||
QString arg = option + QLatin1String(str.left(hasValue ? spaceIdx : str.size()) + '=');
|
||||
if (hasValue)
|
||||
arg += QLatin1String(str.mid(spaceIdx + 1));
|
||||
return arg;
|
||||
}
|
||||
|
||||
void CompilerOptionsBuilder::addDefine(const QByteArray &defineLine)
|
||||
{
|
||||
m_options.append(defineLineToDefineOption(defineLine));
|
||||
}
|
||||
|
||||
void CompilerOptionsBuilder::addHeaderPathOptions()
|
||||
{
|
||||
typedef ProjectPart::HeaderPath HeaderPath;
|
||||
const QString defaultPrefix
|
||||
= QLatin1String(toolchainType == QLatin1String("msvc") ? "/I" : "-I");
|
||||
const QString defaultPrefix = includeOption();
|
||||
|
||||
QStringList result;
|
||||
|
||||
@@ -529,7 +545,7 @@ void CompilerOptionsBuilder::addHeaderPathOptions(IsBlackListed isBlackListed,
|
||||
if (headerPath.path.isEmpty())
|
||||
continue;
|
||||
|
||||
if (isBlackListed && isBlackListed(headerPath.path))
|
||||
if (excludeHeaderPath(headerPath.path))
|
||||
continue;
|
||||
|
||||
QString prefix;
|
||||
@@ -550,45 +566,18 @@ void CompilerOptionsBuilder::addHeaderPathOptions(IsBlackListed isBlackListed,
|
||||
m_options.append(result);
|
||||
}
|
||||
|
||||
void CompilerOptionsBuilder::addToolchainAndProjectDefines(const QString &toolchainType)
|
||||
void CompilerOptionsBuilder::addToolchainAndProjectDefines()
|
||||
{
|
||||
QByteArray extendedDefines = m_projectPart->toolchainDefines + m_projectPart->projectDefines;
|
||||
QStringList result;
|
||||
|
||||
// In gcc headers, lots of built-ins are referenced that clang does not understand.
|
||||
// Therefore, prevent the inclusion of the header that references them. Of course, this
|
||||
// will break if code actually requires stuff from there, but that should be the less common
|
||||
// case.
|
||||
if (toolchainType == QLatin1String("mingw") || toolchainType == QLatin1String("gcc"))
|
||||
extendedDefines += "#define _X86INTRIN_H_INCLUDED\n";
|
||||
|
||||
foreach (QByteArray def, extendedDefines.split('\n')) {
|
||||
if (def.isEmpty())
|
||||
if (def.isEmpty() || excludeDefineLine(def))
|
||||
continue;
|
||||
|
||||
// This is a quick fix for QTCREATORBUG-11501.
|
||||
// TODO: do a proper fix, see QTCREATORBUG-11709.
|
||||
if (def.startsWith("#define __cplusplus"))
|
||||
continue;
|
||||
|
||||
// gcc 4.9 has:
|
||||
// #define __has_include(STR) __has_include__(STR)
|
||||
// #define __has_include_next(STR) __has_include_next__(STR)
|
||||
// The right-hand sides are gcc built-ins that clang does not understand, and they'd
|
||||
// override clang's own (non-macro, it seems) definitions of the symbols on the left-hand
|
||||
// side.
|
||||
if (toolchainType == QLatin1String("gcc") && def.contains("has_include"))
|
||||
continue;
|
||||
|
||||
QByteArray str = def.mid(8);
|
||||
int spaceIdx = str.indexOf(' ');
|
||||
const QString option = QLatin1String(toolchainType == QLatin1String("msvc") ? "/D" : "-D");
|
||||
const bool hasValue = spaceIdx != -1;
|
||||
QString arg = option + QLatin1String(str.left(hasValue ? spaceIdx : str.size()) + '=');
|
||||
if (hasValue)
|
||||
arg += QLatin1String(str.mid(spaceIdx + 1));
|
||||
if (!result.contains(arg))
|
||||
result.append(arg);
|
||||
const QString defineOption = defineLineToDefineOption(def);
|
||||
if (!result.contains(defineOption))
|
||||
result.append(defineOption);
|
||||
}
|
||||
|
||||
m_options.append(result);
|
||||
@@ -651,41 +640,16 @@ static QStringList createLanguageOptionGcc(ProjectFile::Kind fileKind, bool objc
|
||||
return opts;
|
||||
}
|
||||
|
||||
static QStringList createLanguageOptionMsvc(ProjectFile::Kind fileKind)
|
||||
{
|
||||
QStringList opts;
|
||||
switch (fileKind) {
|
||||
case ProjectFile::CHeader:
|
||||
case ProjectFile::CSource:
|
||||
opts << QLatin1String("/TC");
|
||||
break;
|
||||
case ProjectFile::CXXHeader:
|
||||
case ProjectFile::CXXSource:
|
||||
opts << QLatin1String("/TP");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return opts;
|
||||
}
|
||||
|
||||
void CompilerOptionsBuilder::addLanguageOption(ProjectFile::Kind fileKind,
|
||||
const QString &toolchainType)
|
||||
void CompilerOptionsBuilder::addLanguageOption(ProjectFile::Kind fileKind)
|
||||
{
|
||||
const bool objcExt = m_projectPart->languageExtensions & ProjectPart::ObjectiveCExtensions;
|
||||
const QStringList options = toolchainType == QLatin1String("msvc")
|
||||
? createLanguageOptionMsvc(fileKind)
|
||||
: createLanguageOptionGcc(fileKind, objcExt);
|
||||
const QStringList options = createLanguageOptionGcc(fileKind, objcExt);
|
||||
m_options.append(options);
|
||||
}
|
||||
|
||||
void CompilerOptionsBuilder::addOptionsForLanguage(bool checkForBorlandExtensions,
|
||||
const QString &toolchainType)
|
||||
void CompilerOptionsBuilder::addOptionsForLanguage(bool checkForBorlandExtensions)
|
||||
{
|
||||
QStringList opts;
|
||||
if (toolchainType == QLatin1String("msvc"))
|
||||
return;
|
||||
|
||||
const ProjectPart::LanguageExtensions languageExtensions = m_projectPart->languageExtensions;
|
||||
const bool gnuExtensions = languageExtensions & ProjectPart::GnuExtensions;
|
||||
switch (m_projectPart->languageVersion) {
|
||||
@@ -723,3 +687,29 @@ void CompilerOptionsBuilder::addOptionsForLanguage(bool checkForBorlandExtension
|
||||
|
||||
m_options.append(opts);
|
||||
}
|
||||
|
||||
QString CompilerOptionsBuilder::includeOption() const
|
||||
{
|
||||
return QLatin1String("-I");
|
||||
}
|
||||
|
||||
QString CompilerOptionsBuilder::defineOption() const
|
||||
{
|
||||
return QLatin1String("-D");
|
||||
}
|
||||
|
||||
bool CompilerOptionsBuilder::excludeDefineLine(const QByteArray &defineLine) const
|
||||
{
|
||||
// This is a quick fix for QTCREATORBUG-11501.
|
||||
// TODO: do a proper fix, see QTCREATORBUG-11709.
|
||||
if (defineLine.startsWith("#define __cplusplus"))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CompilerOptionsBuilder::excludeHeaderPath(const QString &headerPath) const
|
||||
{
|
||||
Q_UNUSED(headerPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -130,6 +130,7 @@ public: // fields
|
||||
QString projectConfigFile; // currently only used by the Generic Project Manager
|
||||
QByteArray projectDefines;
|
||||
QByteArray toolchainDefines;
|
||||
QString toolchainType;
|
||||
QList<HeaderPath> headerPaths;
|
||||
QStringList precompiledHeaders;
|
||||
LanguageVersion languageVersion;
|
||||
@@ -215,22 +216,32 @@ class CPPTOOLS_EXPORT CompilerOptionsBuilder
|
||||
{
|
||||
public:
|
||||
CompilerOptionsBuilder(const ProjectPart::Ptr &projectPart);
|
||||
virtual ~CompilerOptionsBuilder() {}
|
||||
|
||||
QStringList options() const;
|
||||
|
||||
// Add custom options
|
||||
void add(const QString &option);
|
||||
void addDefine(const QByteArray &defineLine);
|
||||
|
||||
typedef std::function<bool (const QString &)> IsBlackListed;
|
||||
void addHeaderPathOptions(IsBlackListed isBlackListed = IsBlackListed(),
|
||||
const QString &toolchainType = QLatin1String("clang"));
|
||||
void addToolchainAndProjectDefines(const QString &toolchainType = QLatin1String("clang"));
|
||||
void addLanguageOption(ProjectFile::Kind fileKind,
|
||||
const QString &toolchainType = QLatin1String("clang"));
|
||||
void addOptionsForLanguage(bool checkForBorlandExtensions = true,
|
||||
const QString &toolchainType = QLatin1String("clang"));
|
||||
// Add options based on project part
|
||||
void addHeaderPathOptions();
|
||||
void addToolchainAndProjectDefines();
|
||||
virtual void addLanguageOption(ProjectFile::Kind fileKind);
|
||||
virtual void addOptionsForLanguage(bool checkForBorlandExtensions = true);
|
||||
|
||||
protected:
|
||||
virtual bool excludeDefineLine(const QByteArray &defineLine) const;
|
||||
virtual bool excludeHeaderPath(const QString &headerPath) const;
|
||||
|
||||
virtual QString defineOption() const;
|
||||
virtual QString includeOption() const;
|
||||
|
||||
const ProjectPart::Ptr m_projectPart;
|
||||
|
||||
private:
|
||||
ProjectPart::Ptr m_projectPart;
|
||||
QString defineLineToDefineOption(const QByteArray &defineLine);
|
||||
|
||||
QStringList m_options;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user