diff --git a/src/plugins/cpptools/compileroptionsbuilder.cpp b/src/plugins/cpptools/compileroptionsbuilder.cpp new file mode 100644 index 00000000000..8ab04352e0f --- /dev/null +++ b/src/plugins/cpptools/compileroptionsbuilder.cpp @@ -0,0 +1,261 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "compileroptionsbuilder.h" + +#include + +namespace CppTools { + +CompilerOptionsBuilder::CompilerOptionsBuilder(const ProjectPart &projectPart) + : m_projectPart(projectPart) +{ +} + +QStringList CompilerOptionsBuilder::options() const +{ + return m_options; +} + +void CompilerOptionsBuilder::add(const QString &option) +{ + m_options.append(option); +} + +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 ProjectPartHeaderPath HeaderPath; + const QString defaultPrefix = includeOption(); + + QStringList result; + + foreach (const HeaderPath &headerPath , m_projectPart.headerPaths) { + if (headerPath.path.isEmpty()) + continue; + + if (excludeHeaderPath(headerPath.path)) + continue; + + QString prefix; + switch (headerPath.type) { + case HeaderPath::FrameworkPath: + prefix = QLatin1String("-F"); + break; + default: // This shouldn't happen, but let's be nice..: + // intentional fall-through: + case HeaderPath::IncludePath: + prefix = defaultPrefix; + break; + } + + result.append(prefix + headerPath.path); + } + + m_options.append(result); +} + +void CompilerOptionsBuilder::addToolchainAndProjectDefines() +{ + QByteArray extendedDefines = m_projectPart.toolchainDefines + m_projectPart.projectDefines; + QStringList result; + + foreach (QByteArray def, extendedDefines.split('\n')) { + if (def.isEmpty() || excludeDefineLine(def)) + continue; + + const QString defineOption = defineLineToDefineOption(def); + if (!result.contains(defineOption)) + result.append(defineOption); + } + + m_options.append(result); +} + +static QStringList createLanguageOptionGcc(ProjectFile::Kind fileKind, bool objcExt) +{ + QStringList opts; + + switch (fileKind) { + case ProjectFile::Unclassified: + break; + case ProjectFile::CHeader: + if (objcExt) + opts += QLatin1String("objective-c-header"); + else + opts += QLatin1String("c-header"); + break; + + case ProjectFile::CXXHeader: + default: + if (!objcExt) { + opts += QLatin1String("c++-header"); + break; + } // else: fall-through! + case ProjectFile::ObjCHeader: + case ProjectFile::ObjCXXHeader: + opts += QLatin1String("objective-c++-header"); + break; + + case ProjectFile::CSource: + if (!objcExt) { + opts += QLatin1String("c"); + break; + } // else: fall-through! + case ProjectFile::ObjCSource: + opts += QLatin1String("objective-c"); + break; + + case ProjectFile::CXXSource: + if (!objcExt) { + opts += QLatin1String("c++"); + break; + } // else: fall-through! + case ProjectFile::ObjCXXSource: + opts += QLatin1String("objective-c++"); + break; + + case ProjectFile::OpenCLSource: + opts += QLatin1String("cl"); + break; + case ProjectFile::CudaSource: + opts += QLatin1String("cuda"); + break; + } + + if (!opts.isEmpty()) + opts.prepend(QLatin1String("-x")); + + return opts; +} + +void CompilerOptionsBuilder::addLanguageOption(ProjectFile::Kind fileKind) +{ + const bool objcExt = m_projectPart.languageExtensions & ProjectPart::ObjectiveCExtensions; + const QStringList options = createLanguageOptionGcc(fileKind, objcExt); + m_options.append(options); +} + +void CompilerOptionsBuilder::addOptionsForLanguage(bool checkForBorlandExtensions) +{ + QStringList opts; + const ProjectPart::LanguageExtensions languageExtensions = m_projectPart.languageExtensions; + const bool gnuExtensions = languageExtensions & ProjectPart::GnuExtensions; + switch (m_projectPart.languageVersion) { + case ProjectPart::C89: + opts << (gnuExtensions ? QLatin1String("-std=gnu89") : QLatin1String("-std=c89")); + break; + case ProjectPart::C99: + opts << (gnuExtensions ? QLatin1String("-std=gnu99") : QLatin1String("-std=c99")); + break; + case ProjectPart::C11: + opts << (gnuExtensions ? QLatin1String("-std=gnu11") : QLatin1String("-std=c11")); + break; + case ProjectPart::CXX11: + opts << (gnuExtensions ? QLatin1String("-std=gnu++11") : QLatin1String("-std=c++11")); + break; + case ProjectPart::CXX98: + opts << (gnuExtensions ? QLatin1String("-std=gnu++98") : QLatin1String("-std=c++98")); + break; + case ProjectPart::CXX03: + // Clang 3.6 does not know -std=gnu++03. + opts << QLatin1String("-std=c++03"); + break; + case ProjectPart::CXX14: + opts << (gnuExtensions ? QLatin1String("-std=gnu++14") : QLatin1String("-std=c++14")); + break; + case ProjectPart::CXX17: + // TODO: Change to (probably) "gnu++17"/"c++17" at some point in the future. + opts << (gnuExtensions ? QLatin1String("-std=gnu++1z") : QLatin1String("-std=c++1z")); + break; + } + + if (languageExtensions & ProjectPart::MicrosoftExtensions) + opts << QLatin1String("-fms-extensions"); + + if (checkForBorlandExtensions && (languageExtensions & ProjectPart::BorlandExtensions)) + opts << QLatin1String("-fborland-extensions"); + + 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; + + // 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. + const bool isGccToolchain = m_projectPart.toolchainType == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID; + if (isGccToolchain && defineLine.contains("has_include")) + return true; + + return false; +} + +bool CompilerOptionsBuilder::excludeHeaderPath(const QString &headerPath) const +{ + Q_UNUSED(headerPath); + return false; +} + +} // namespace CppTools diff --git a/src/plugins/cpptools/compileroptionsbuilder.h b/src/plugins/cpptools/compileroptionsbuilder.h new file mode 100644 index 00000000000..7751d8d160b --- /dev/null +++ b/src/plugins/cpptools/compileroptionsbuilder.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef CPPTOOLS_COMPILEROPTIONSBUILDER_H +#define CPPTOOLS_COMPILEROPTIONSBUILDER_H + +#include "cpptools_global.h" + +#include "projectpart.h" + +namespace CppTools { + +class CPPTOOLS_EXPORT CompilerOptionsBuilder +{ +public: + CompilerOptionsBuilder(const ProjectPart &projectPart); + virtual ~CompilerOptionsBuilder() {} + + QStringList options() const; + + // Add custom options + void add(const QString &option); + void addDefine(const QByteArray &defineLine); + + // 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 m_projectPart; + +private: + QString defineLineToDefineOption(const QByteArray &defineLine); + + QStringList m_options; +}; + +} // namespace CppTools + +#endif // CPPTOOLS_COMPILEROPTIONSBUILDER_H diff --git a/src/plugins/cpptools/cppprojects.cpp b/src/plugins/cpptools/cppprojects.cpp index 29c13d08345..8a8c176537f 100644 --- a/src/plugins/cpptools/cppprojects.cpp +++ b/src/plugins/cpptools/cppprojects.cpp @@ -48,226 +48,3 @@ using namespace CppTools; using namespace ProjectExplorer; -CompilerOptionsBuilder::CompilerOptionsBuilder(const ProjectPart &projectPart) - : m_projectPart(projectPart) -{ -} - -QStringList CompilerOptionsBuilder::options() const -{ - return m_options; -} - -void CompilerOptionsBuilder::add(const QString &option) -{ - m_options.append(option); -} - -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 ProjectPartHeaderPath HeaderPath; - const QString defaultPrefix = includeOption(); - - QStringList result; - - foreach (const HeaderPath &headerPath , m_projectPart.headerPaths) { - if (headerPath.path.isEmpty()) - continue; - - if (excludeHeaderPath(headerPath.path)) - continue; - - QString prefix; - switch (headerPath.type) { - case HeaderPath::FrameworkPath: - prefix = QLatin1String("-F"); - break; - default: // This shouldn't happen, but let's be nice..: - // intentional fall-through: - case HeaderPath::IncludePath: - prefix = defaultPrefix; - break; - } - - result.append(prefix + headerPath.path); - } - - m_options.append(result); -} - -void CompilerOptionsBuilder::addToolchainAndProjectDefines() -{ - QByteArray extendedDefines = m_projectPart.toolchainDefines + m_projectPart.projectDefines; - QStringList result; - - foreach (QByteArray def, extendedDefines.split('\n')) { - if (def.isEmpty() || excludeDefineLine(def)) - continue; - - const QString defineOption = defineLineToDefineOption(def); - if (!result.contains(defineOption)) - result.append(defineOption); - } - - m_options.append(result); -} - -static QStringList createLanguageOptionGcc(ProjectFile::Kind fileKind, bool objcExt) -{ - QStringList opts; - - switch (fileKind) { - case ProjectFile::Unclassified: - break; - case ProjectFile::CHeader: - if (objcExt) - opts += QLatin1String("objective-c-header"); - else - opts += QLatin1String("c-header"); - break; - - case ProjectFile::CXXHeader: - default: - if (!objcExt) { - opts += QLatin1String("c++-header"); - break; - } // else: fall-through! - case ProjectFile::ObjCHeader: - case ProjectFile::ObjCXXHeader: - opts += QLatin1String("objective-c++-header"); - break; - - case ProjectFile::CSource: - if (!objcExt) { - opts += QLatin1String("c"); - break; - } // else: fall-through! - case ProjectFile::ObjCSource: - opts += QLatin1String("objective-c"); - break; - - case ProjectFile::CXXSource: - if (!objcExt) { - opts += QLatin1String("c++"); - break; - } // else: fall-through! - case ProjectFile::ObjCXXSource: - opts += QLatin1String("objective-c++"); - break; - - case ProjectFile::OpenCLSource: - opts += QLatin1String("cl"); - break; - case ProjectFile::CudaSource: - opts += QLatin1String("cuda"); - break; - } - - if (!opts.isEmpty()) - opts.prepend(QLatin1String("-x")); - - return opts; -} - -void CompilerOptionsBuilder::addLanguageOption(ProjectFile::Kind fileKind) -{ - const bool objcExt = m_projectPart.languageExtensions & ProjectPart::ObjectiveCExtensions; - const QStringList options = createLanguageOptionGcc(fileKind, objcExt); - m_options.append(options); -} - -void CompilerOptionsBuilder::addOptionsForLanguage(bool checkForBorlandExtensions) -{ - QStringList opts; - const ProjectPart::LanguageExtensions languageExtensions = m_projectPart.languageExtensions; - const bool gnuExtensions = languageExtensions & ProjectPart::GnuExtensions; - switch (m_projectPart.languageVersion) { - case ProjectPart::C89: - opts << (gnuExtensions ? QLatin1String("-std=gnu89") : QLatin1String("-std=c89")); - break; - case ProjectPart::C99: - opts << (gnuExtensions ? QLatin1String("-std=gnu99") : QLatin1String("-std=c99")); - break; - case ProjectPart::C11: - opts << (gnuExtensions ? QLatin1String("-std=gnu11") : QLatin1String("-std=c11")); - break; - case ProjectPart::CXX11: - opts << (gnuExtensions ? QLatin1String("-std=gnu++11") : QLatin1String("-std=c++11")); - break; - case ProjectPart::CXX98: - opts << (gnuExtensions ? QLatin1String("-std=gnu++98") : QLatin1String("-std=c++98")); - break; - case ProjectPart::CXX03: - // Clang 3.6 does not know -std=gnu++03. - opts << QLatin1String("-std=c++03"); - break; - case ProjectPart::CXX14: - opts << (gnuExtensions ? QLatin1String("-std=gnu++14") : QLatin1String("-std=c++14")); - break; - case ProjectPart::CXX17: - // TODO: Change to (probably) "gnu++17"/"c++17" at some point in the future. - opts << (gnuExtensions ? QLatin1String("-std=gnu++1z") : QLatin1String("-std=c++1z")); - break; - } - - if (languageExtensions & ProjectPart::MicrosoftExtensions) - opts << QLatin1String("-fms-extensions"); - - if (checkForBorlandExtensions && (languageExtensions & ProjectPart::BorlandExtensions)) - opts << QLatin1String("-fborland-extensions"); - - 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; - - // 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. - const bool isGccToolchain = m_projectPart.toolchainType == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID; - if (isGccToolchain && defineLine.contains("has_include")) - return true; - - return false; -} - -bool CompilerOptionsBuilder::excludeHeaderPath(const QString &headerPath) const -{ - Q_UNUSED(headerPath); - return false; -} diff --git a/src/plugins/cpptools/cppprojects.h b/src/plugins/cpptools/cppprojects.h index 29ad74c70c4..6801d3d378f 100644 --- a/src/plugins/cpptools/cppprojects.h +++ b/src/plugins/cpptools/cppprojects.h @@ -37,6 +37,7 @@ #include "projectpartbuilder.h" #include "projectinfo.h" #include "projectpart.h" +#include "compileroptionsbuilder.h" #include @@ -54,38 +55,6 @@ namespace Utils { class FileName; } namespace CppTools { -class CPPTOOLS_EXPORT CompilerOptionsBuilder -{ -public: - CompilerOptionsBuilder(const ProjectPart &projectPart); - virtual ~CompilerOptionsBuilder() {} - - QStringList options() const; - - // Add custom options - void add(const QString &option); - void addDefine(const QByteArray &defineLine); - - // 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 m_projectPart; - -private: - QString defineLineToDefineOption(const QByteArray &defineLine); - - QStringList m_options; -}; } // namespace CppTools diff --git a/src/plugins/cpptools/cpptools.pro b/src/plugins/cpptools/cpptools.pro index 947be7d06f7..5adfa2554f1 100644 --- a/src/plugins/cpptools/cpptools.pro +++ b/src/plugins/cpptools/cpptools.pro @@ -73,7 +73,8 @@ HEADERS += \ projectpart.h \ projectpartheaderpath.h \ projectinfo.h \ - projectpartbuilder.h + projectpartbuilder.h \ + compileroptionsbuilder.h SOURCES += \ abstracteditorsupport.cpp \ @@ -142,7 +143,8 @@ SOURCES += \ cpptoolsbridgeqtcreatorimplementation.cpp \ projectpart.cpp \ projectinfo.cpp \ - projectpartbuilder.cpp + projectpartbuilder.cpp \ + compileroptionsbuilder.cpp FORMS += \ completionsettingspage.ui \ diff --git a/src/plugins/cpptools/cpptools.qbs b/src/plugins/cpptools/cpptools.qbs index 78c1328e9f9..86d1ce66bbc 100644 --- a/src/plugins/cpptools/cpptools.qbs +++ b/src/plugins/cpptools/cpptools.qbs @@ -31,6 +31,7 @@ QtcPlugin { "builtineditordocumentparser.cpp", "builtineditordocumentparser.h", "builtineditordocumentprocessor.cpp", "builtineditordocumentprocessor.h", "builtinindexingsupport.cpp", "builtinindexingsupport.h", + "compileroptionsbuilder.cpp", "compileroptionsbuilder.h", "commentssettings.cpp", "commentssettings.h", "completionsettingspage.cpp", "completionsettingspage.h", "completionsettingspage.ui", "cppchecksymbols.cpp", "cppchecksymbols.h",