diff options
Diffstat (limited to 'src/plugins/cpptools/cppbaseprojectpartbuilder.cpp')
| -rw-r--r-- | src/plugins/cpptools/cppbaseprojectpartbuilder.cpp | 307 |
1 files changed, 307 insertions, 0 deletions
diff --git a/src/plugins/cpptools/cppbaseprojectpartbuilder.cpp b/src/plugins/cpptools/cppbaseprojectpartbuilder.cpp new file mode 100644 index 0000000000..021b12b4c2 --- /dev/null +++ b/src/plugins/cpptools/cppbaseprojectpartbuilder.cpp @@ -0,0 +1,307 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "cppbaseprojectpartbuilder.h" + +#include "cppprojectfile.h" +#include "cppprojectfilecategorizer.h" +#include "projectinfo.h" + +#include <projectexplorer/headerpath.h> +#include <projectexplorer/project.h> +#include <projectexplorer/projectexplorerconstants.h> + +#include <utils/qtcassert.h> + +namespace CppTools { + +BaseProjectPartBuilder::BaseProjectPartBuilder(ProjectInterface *project, + ProjectInfo &projectInfo) + : m_project(project) + , m_projectInfo(projectInfo) + , m_templatePart(new ProjectPart) +{ + QTC_CHECK(m_project); + m_templatePart->project = projectInfo.project(); + m_templatePart->displayName = m_project->displayName(); + m_templatePart->projectFile = m_project->projectFilePath(); +} + +void BaseProjectPartBuilder::setQtVersion(ProjectPart::QtVersion qtVersion) +{ + m_templatePart->qtVersion = qtVersion; +} + +void BaseProjectPartBuilder::setCFlags(const QStringList &flags) +{ + m_cFlags = flags; +} + +void BaseProjectPartBuilder::setCxxFlags(const QStringList &flags) +{ + m_cxxFlags = flags; +} + +void BaseProjectPartBuilder::setDefines(const QByteArray &defines) +{ + m_templatePart->projectDefines = defines; +} + +void BaseProjectPartBuilder::setHeaderPaths(const ProjectPartHeaderPaths &headerPaths) +{ + m_templatePart->headerPaths = headerPaths; +} + +void BaseProjectPartBuilder::setIncludePaths(const QStringList &includePaths) +{ + m_templatePart->headerPaths.clear(); + + foreach (const QString &includeFile, includePaths) { + ProjectPartHeaderPath hp(includeFile, ProjectPartHeaderPath::IncludePath); + + // The simple project managers are utterly ignorant of frameworks on OSX, and won't report + // framework paths. The work-around is to check if the include path ends in ".framework", + // and if so, add the parent directory as framework path. + if (includeFile.endsWith(QLatin1String(".framework"))) { + const int slashIdx = includeFile.lastIndexOf(QLatin1Char('/')); + if (slashIdx != -1) { + hp = ProjectPartHeaderPath(includeFile.left(slashIdx), + ProjectPartHeaderPath::FrameworkPath); + } + } + + m_templatePart->headerPaths += hp; + } +} + +void BaseProjectPartBuilder::setPreCompiledHeaders(const QStringList &preCompiledHeaders) +{ + m_templatePart->precompiledHeaders = preCompiledHeaders; +} + +void BaseProjectPartBuilder::setProjectFile(const QString &projectFile) +{ + m_templatePart->projectFile = projectFile; +} + +void BaseProjectPartBuilder::setDisplayName(const QString &displayName) +{ + m_templatePart->displayName = displayName; +} + +void BaseProjectPartBuilder::setConfigFileName(const QString &configFileName) +{ + m_templatePart->projectConfigFile = configFileName; +} + +QList<Core::Id> BaseProjectPartBuilder::createProjectPartsForFiles(const QStringList &filePaths, + FileClassifier fileClassifier) +{ + QList<Core::Id> languages; + + ProjectFileCategorizer cat(m_templatePart->displayName, filePaths, fileClassifier); + + if (cat.hasParts()) { + // The ProjextExplorer does not distinguish between other versions than C++ and QML. + languages += ProjectExplorer::Constants::LANG_CXX; + + if (cat.hasCSources()) { + createProjectPart(cat.cSources(), + cat.partName("C"), + ProjectPart::C11, + ProjectPart::NoExtensions); + } + + if (cat.hasObjcSources()) { + createProjectPart(cat.objcSources(), + cat.partName("Obj-C"), + ProjectPart::C11, + ProjectPart::ObjectiveCExtensions); + } + + if (cat.hasCxxSources()) { + createProjectPart(cat.cxxSources(), + cat.partName("C++"), + ProjectPart::CXX11, + ProjectPart::NoExtensions); + } + + if (cat.hasObjcxxSources()) { + createProjectPart(cat.objcxxSources(), + cat.partName("Obj-C++"), + ProjectPart::CXX11, + ProjectPart::ObjectiveCExtensions); + } + } + + return languages; +} + +namespace { + +class ToolChainEvaluator +{ +public: + ToolChainEvaluator(ProjectPart &projectPart, + const ToolChainInterface &toolChain) + : m_projectPart(projectPart) + , m_toolChain(toolChain) + , m_compilerFlags(toolChain.compilerFlags()) + { + } + + void evaluate() + { + mapLanguageVersion(); + mapLanguageExtensions(); + + addHeaderPaths(); + m_projectPart.toolchainDefines = m_toolChain.predefinedMacros(); + + m_projectPart.warningFlags = m_toolChain.warningFlags(); + m_projectPart.toolchainType = m_toolChain.type(); + m_projectPart.isMsvc2015Toolchain = m_toolChain.isMsvc2015Toolchain(); + m_projectPart.toolChainWordWidth = mapWordWith(m_toolChain.wordWidth()); + m_projectPart.targetTriple = m_toolChain.targetTriple(); + } + +private: + static ProjectPart::ToolChainWordWidth mapWordWith(unsigned wordWidth) + { + return wordWidth == 64 + ? ProjectPart::WordWidth64Bit + : ProjectPart::WordWidth32Bit; + } + + void mapLanguageVersion() + { + using namespace ProjectExplorer; + ProjectPart::LanguageVersion &languageVersion = m_projectPart.languageVersion; + + if (m_compilerFlags & ToolChain::StandardC11) + languageVersion = ProjectPart::C11; + else if (m_compilerFlags & ToolChain::StandardC99) + languageVersion = ProjectPart::C99; + else if (m_compilerFlags & ToolChain::StandardCxx17) + languageVersion = ProjectPart::CXX17; + else if (m_compilerFlags & ToolChain::StandardCxx14) + languageVersion = ProjectPart::CXX14; + else if (m_compilerFlags & ToolChain::StandardCxx11) + languageVersion = ProjectPart::CXX11; + else if (m_compilerFlags & ToolChain::StandardCxx98) + languageVersion = ProjectPart::CXX98; + } + + void mapLanguageExtensions() + { + using namespace ProjectExplorer; + ProjectPart::LanguageExtensions &languageExtensions = m_projectPart.languageExtensions; + + if (m_compilerFlags & ToolChain::BorlandExtensions) + languageExtensions |= ProjectPart::BorlandExtensions; + if (m_compilerFlags & ToolChain::GnuExtensions) + languageExtensions |= ProjectPart::GnuExtensions; + if (m_compilerFlags & ToolChain::MicrosoftExtensions) + languageExtensions |= ProjectPart::MicrosoftExtensions; + if (m_compilerFlags & ToolChain::OpenMP) + languageExtensions |= ProjectPart::OpenMPExtensions; + if (m_compilerFlags & ToolChain::ObjectiveC) + languageExtensions |= ProjectPart::ObjectiveCExtensions; + } + + static ProjectPartHeaderPath toProjectPartHeaderPath( + const ProjectExplorer::HeaderPath &headerPath) + { + const ProjectPartHeaderPath::Type headerPathType = + headerPath.kind() == ProjectExplorer::HeaderPath::FrameworkHeaderPath + ? ProjectPartHeaderPath::FrameworkPath + : ProjectPartHeaderPath::IncludePath; + + return ProjectPartHeaderPath(headerPath.path(), headerPathType); + } + + void addHeaderPaths() + { + ProjectPartHeaderPaths &headerPaths = m_projectPart.headerPaths; + + foreach (const ProjectExplorer::HeaderPath &header, m_toolChain.systemHeaderPaths()) { + const ProjectPartHeaderPath headerPath = toProjectPartHeaderPath(header); + if (!headerPaths.contains(headerPath)) + headerPaths.push_back(headerPath); + } + } + +private: + ProjectPart &m_projectPart; + + const ToolChainInterface &m_toolChain; + const ProjectExplorer::ToolChain::CompilerFlags m_compilerFlags; +}; + +} // anynomous + +void BaseProjectPartBuilder::evaluateToolChain(ProjectPart &projectPart, + const ToolChainInterface &toolChain) +{ + ToolChainEvaluator evaluator(projectPart, toolChain); + evaluator.evaluate(); +} + +void BaseProjectPartBuilder::createProjectPart(const ProjectFiles &projectFiles, + const QString &partName, + ProjectPart::LanguageVersion languageVersion, + ProjectPart::LanguageExtensions languageExtensions) +{ + ProjectPart::Ptr part(m_templatePart->copy()); + part->displayName = partName; + part->files = projectFiles; + part->languageVersion = languageVersion; + QTC_ASSERT(part->project, return); + + // TODO: If not toolchain is set, show a warning + if (const ToolChainInterfacePtr toolChain = selectToolChain(languageVersion)) + evaluateToolChain(*part.data(), *toolChain.get()); + + part->languageExtensions |= languageExtensions; + part->updateLanguageFeatures(); + + m_projectInfo.appendProjectPart(part); +} + +ToolChainInterfacePtr BaseProjectPartBuilder::selectToolChain( + ProjectPart::LanguageVersion languageVersion) +{ + ToolChainInterfacePtr toolChain = nullptr; + + if (languageVersion < ProjectPart::CXX98) + toolChain = m_project->toolChain(ProjectExplorer::ToolChain::Language::C, m_cFlags); + + if (!toolChain) // Use Cxx toolchain for C projects without C compiler in kit and for C++ code + toolChain = m_project->toolChain(ProjectExplorer::ToolChain::Language::Cxx, m_cxxFlags); + + return toolChain; +} + +} // namespace CppTools |
