Files
qt-creator/src/plugins/projectexplorer/toolchain.h

439 lines
15 KiB
C
Raw Normal View History

// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
2009-03-20 14:57:12 +01:00
#pragma once
#include "projectexplorer_export.h"
#include "abi.h"
#include "devicesupport/idevicefwd.h"
#include "headerpath.h"
#include "projectmacro.h"
#include "task.h"
#include "toolchaincache.h"
#include <utils/aspects.h>
#include <utils/cpplanguage_details.h>
#include <utils/environment.h>
#include <utils/store.h>
#include <QDateTime>
ProjectExplorer: Stop pretending that C and C++ compilers are unrelated Motivation: a) It was ridiculous that when users wanted to manually add a new toolchain, they had to do the entire setup twice. b) It was equally weird that users had to take care to choose matching toolchains when setting up a kit, or indeed that it was even possible to mix random toolchains in the first place. User-visible changes: - The "C" and "C++" categories in the toolchain settings page have been merged into a single "C/C++" category. - When adding a new toolchain, the "C" and "C++" sub-menus are gone. Instead, the toolchain config widget offers two path choosers if the respective toolchain type supports C and C++ compilers. - By default, the C++ compiler file path is derived from the C compiler file path automatically, so the user usually has to enter only the former. - In the kit settings page, the "C" and "C++" toolchain combo boxes have been replaced by a single "C/C++" combo box, relieving the user of the responsibility to choose two matching toolchains. Implementation: The notion that a Toolchain object corresponds to a single compiler is so deeply engrained in the code that it cannot realistically be changed in the short term. We therefore introduce the concept of a "toolchain bundle" as an additional layer that groups matching C and C++ toolchains together. This way, most code dealing with toolchains stays unchanged, and only the presentation layer (i.e. the toolchain and kit settings pages) needed to be rewritten. Once set up in a bundle, toolchains stay implicitly linked together so the matching only needs to be done once. In follow-up patches, we will make use of toolchain bundles in all the places where kits are auto-created, eliminating the risk of mixing incompatible toolchains in a kit. Change-Id: Ie6c5add9963e7c1096268dd77acd624671b2674f Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: hjk <hjk@qt.io>
2024-07-11 13:03:12 +02:00
#include <QSet>
CppTools/ProjectManagers: Reduce ui blocking when loading projects ${AnyProject}::updateCppCodeModel() did two potentially not that cheap operations in the ui thread: (1) Querying the MimeDatabase for the mime type for the source files of the project. In 99.9% of the cases no files need to be read for this as the file extension will resolve the type. The expensiveness comes from the sheer number of files that can occur. (2) Calling compilers with the "(sub)project's compiler command line" to determine the macros. While the caches avoid redundant calls, the number of the unique compiler calls makes this still a ui-freezing experience. These two operations are moved into a worker thread. For this, the expensive compiler calls are encapsulated in thread safe lambdas ("runners") in order to keep the "mutexed" data minimal. The original API calls of the toolchains are implemented in terms of the runners. While adapting the project managers, remove also the calls to setProjectLanguage(). These are redundant because all of the project managers already set a proper value in the constructor. Also, currently there is no need (client) to report back detection of C sources in project parts. This also keeps CppProjectUpdater simple. There is still room for improvement: * Run the compiler calls in parallel instead of sequence. * Ensure that the mime type for a file is determined exactly once. Change-Id: I2efc4e132ee88e3c8f264012ec8fafe3d86c404f Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
2017-02-06 16:59:53 +01:00
#include <functional>
#include <memory>
ProjectExplorer: Stop pretending that C and C++ compilers are unrelated Motivation: a) It was ridiculous that when users wanted to manually add a new toolchain, they had to do the entire setup twice. b) It was equally weird that users had to take care to choose matching toolchains when setting up a kit, or indeed that it was even possible to mix random toolchains in the first place. User-visible changes: - The "C" and "C++" categories in the toolchain settings page have been merged into a single "C/C++" category. - When adding a new toolchain, the "C" and "C++" sub-menus are gone. Instead, the toolchain config widget offers two path choosers if the respective toolchain type supports C and C++ compilers. - By default, the C++ compiler file path is derived from the C compiler file path automatically, so the user usually has to enter only the former. - In the kit settings page, the "C" and "C++" toolchain combo boxes have been replaced by a single "C/C++" combo box, relieving the user of the responsibility to choose two matching toolchains. Implementation: The notion that a Toolchain object corresponds to a single compiler is so deeply engrained in the code that it cannot realistically be changed in the short term. We therefore introduce the concept of a "toolchain bundle" as an additional layer that groups matching C and C++ toolchains together. This way, most code dealing with toolchains stays unchanged, and only the presentation layer (i.e. the toolchain and kit settings pages) needed to be rewritten. Once set up in a bundle, toolchains stay implicitly linked together so the matching only needs to be done once. In follow-up patches, we will make use of toolchain bundles in all the places where kits are auto-created, eliminating the risk of mixing incompatible toolchains in a kit. Change-Id: Ie6c5add9963e7c1096268dd77acd624671b2674f Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: hjk <hjk@qt.io>
2024-07-11 13:03:12 +02:00
#include <optional>
CppTools/ProjectManagers: Reduce ui blocking when loading projects ${AnyProject}::updateCppCodeModel() did two potentially not that cheap operations in the ui thread: (1) Querying the MimeDatabase for the mime type for the source files of the project. In 99.9% of the cases no files need to be read for this as the file extension will resolve the type. The expensiveness comes from the sheer number of files that can occur. (2) Calling compilers with the "(sub)project's compiler command line" to determine the macros. While the caches avoid redundant calls, the number of the unique compiler calls makes this still a ui-freezing experience. These two operations are moved into a worker thread. For this, the expensive compiler calls are encapsulated in thread safe lambdas ("runners") in order to keep the "mutexed" data minimal. The original API calls of the toolchains are implemented in terms of the runners. While adapting the project managers, remove also the calls to setProjectLanguage(). These are redundant because all of the project managers already set a proper value in the constructor. Also, currently there is no need (client) to report back detection of C sources in project parts. This also keeps CppProjectUpdater simple. There is still room for improvement: * Run the compiler calls in parallel instead of sequence. * Ensure that the mime type for a file is determined exactly once. Change-Id: I2efc4e132ee88e3c8f264012ec8fafe3d86c404f Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
2017-02-06 16:59:53 +01:00
namespace Utils { class OutputLineParser; }
namespace ProjectExplorer {
namespace Internal { class ToolchainPrivate; }
namespace Deprecated {
// Deprecated in 4.3:
namespace Toolchain {
enum Language {
None = 0,
C,
Cxx
};
QString languageId(Language l);
} // namespace Toolchain
} // namespace Deprecated
class GccToolchain;
class ToolchainConfigWidget;
class ToolchainFactory;
class Kit;
namespace Internal { class ToolchainSettingsAccessor; }
class PROJECTEXPLORER_EXPORT ToolchainDescription
{
public:
Utils::FilePath compilerPath;
Utils::Id language;
};
ProjectExplorer: Stop pretending that C and C++ compilers are unrelated Motivation: a) It was ridiculous that when users wanted to manually add a new toolchain, they had to do the entire setup twice. b) It was equally weird that users had to take care to choose matching toolchains when setting up a kit, or indeed that it was even possible to mix random toolchains in the first place. User-visible changes: - The "C" and "C++" categories in the toolchain settings page have been merged into a single "C/C++" category. - When adding a new toolchain, the "C" and "C++" sub-menus are gone. Instead, the toolchain config widget offers two path choosers if the respective toolchain type supports C and C++ compilers. - By default, the C++ compiler file path is derived from the C compiler file path automatically, so the user usually has to enter only the former. - In the kit settings page, the "C" and "C++" toolchain combo boxes have been replaced by a single "C/C++" combo box, relieving the user of the responsibility to choose two matching toolchains. Implementation: The notion that a Toolchain object corresponds to a single compiler is so deeply engrained in the code that it cannot realistically be changed in the short term. We therefore introduce the concept of a "toolchain bundle" as an additional layer that groups matching C and C++ toolchains together. This way, most code dealing with toolchains stays unchanged, and only the presentation layer (i.e. the toolchain and kit settings pages) needed to be rewritten. Once set up in a bundle, toolchains stay implicitly linked together so the matching only needs to be done once. In follow-up patches, we will make use of toolchain bundles in all the places where kits are auto-created, eliminating the risk of mixing incompatible toolchains in a kit. Change-Id: Ie6c5add9963e7c1096268dd77acd624671b2674f Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: hjk <hjk@qt.io>
2024-07-11 13:03:12 +02:00
using LanguageCategory = QSet<Utils::Id>;
// --------------------------------------------------------------------------
// Toolchain (documentation inside)
// --------------------------------------------------------------------------
class PROJECTEXPLORER_EXPORT Toolchain : public Utils::AspectContainer
{
public:
enum Detection {
ManualDetection,
AutoDetection,
AutoDetectionFromSdk,
UninitializedDetection,
};
using Predicate = std::function<bool(const Toolchain *)>;
virtual ~Toolchain();
QString displayName() const;
void setDisplayName(const QString &name);
bool isAutoDetected() const;
bool isSdkProvided() const { return detection() == AutoDetectionFromSdk; }
Detection detection() const;
QString detectionSource() const;
ToolchainFactory *factory() const;
QByteArray id() const;
ProjectExplorer: Stop pretending that C and C++ compilers are unrelated Motivation: a) It was ridiculous that when users wanted to manually add a new toolchain, they had to do the entire setup twice. b) It was equally weird that users had to take care to choose matching toolchains when setting up a kit, or indeed that it was even possible to mix random toolchains in the first place. User-visible changes: - The "C" and "C++" categories in the toolchain settings page have been merged into a single "C/C++" category. - When adding a new toolchain, the "C" and "C++" sub-menus are gone. Instead, the toolchain config widget offers two path choosers if the respective toolchain type supports C and C++ compilers. - By default, the C++ compiler file path is derived from the C compiler file path automatically, so the user usually has to enter only the former. - In the kit settings page, the "C" and "C++" toolchain combo boxes have been replaced by a single "C/C++" combo box, relieving the user of the responsibility to choose two matching toolchains. Implementation: The notion that a Toolchain object corresponds to a single compiler is so deeply engrained in the code that it cannot realistically be changed in the short term. We therefore introduce the concept of a "toolchain bundle" as an additional layer that groups matching C and C++ toolchains together. This way, most code dealing with toolchains stays unchanged, and only the presentation layer (i.e. the toolchain and kit settings pages) needed to be rewritten. Once set up in a bundle, toolchains stay implicitly linked together so the matching only needs to be done once. In follow-up patches, we will make use of toolchain bundles in all the places where kits are auto-created, eliminating the risk of mixing incompatible toolchains in a kit. Change-Id: Ie6c5add9963e7c1096268dd77acd624671b2674f Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: hjk <hjk@qt.io>
2024-07-11 13:03:12 +02:00
Utils::Id bundleId() const;
void setBundleId(Utils::Id id);
bool canShareBundle(const Toolchain &other) const;
virtual QStringList suggestedMkspecList() const;
Utils::Id typeId() const;
QString typeDisplayName() const;
Abi targetAbi() const;
void setTargetAbi(const Abi &abi);
virtual ProjectExplorer::Abis supportedAbis() const;
virtual QString originalTargetTriple() const { return {}; }
virtual QStringList extraCodeModelFlags() const { return {}; }
virtual Utils::FilePath installDir() const { return {}; }
virtual bool hostPrefersToolchain() const { return true; }
virtual bool isValid() const;
virtual Utils::LanguageExtensions languageExtensions(const QStringList &cxxflags) const = 0;
virtual Utils::WarningFlags warningFlags(const QStringList &cflags) const = 0;
virtual Utils::FilePaths includedFiles(const QStringList &flags, const Utils::FilePath &directory) const;
virtual QString sysRoot() const;
CppTools/ProjectManagers: Reduce ui blocking when loading projects ${AnyProject}::updateCppCodeModel() did two potentially not that cheap operations in the ui thread: (1) Querying the MimeDatabase for the mime type for the source files of the project. In 99.9% of the cases no files need to be read for this as the file extension will resolve the type. The expensiveness comes from the sheer number of files that can occur. (2) Calling compilers with the "(sub)project's compiler command line" to determine the macros. While the caches avoid redundant calls, the number of the unique compiler calls makes this still a ui-freezing experience. These two operations are moved into a worker thread. For this, the expensive compiler calls are encapsulated in thread safe lambdas ("runners") in order to keep the "mutexed" data minimal. The original API calls of the toolchains are implemented in terms of the runners. While adapting the project managers, remove also the calls to setProjectLanguage(). These are redundant because all of the project managers already set a proper value in the constructor. Also, currently there is no need (client) to report back detection of C sources in project parts. This also keeps CppProjectUpdater simple. There is still room for improvement: * Run the compiler calls in parallel instead of sequence. * Ensure that the mime type for a file is determined exactly once. Change-Id: I2efc4e132ee88e3c8f264012ec8fafe3d86c404f Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
2017-02-06 16:59:53 +01:00
QString explicitCodeModelTargetTriple() const;
QString effectiveCodeModelTargetTriple() const;
void setExplicitCodeModelTargetTriple(const QString &triple);
class MacroInspectionReport
{
public:
Macros macros;
Utils::LanguageVersion languageVersion;
};
using MacrosCache = std::shared_ptr<Cache<QStringList, Toolchain::MacroInspectionReport, 64>>;
using HeaderPathsCache = std::shared_ptr<Cache<QPair<Utils::Environment, QStringList>, HeaderPaths>>;
// A MacroInspectionRunner is created in the ui thread and runs in another thread.
using MacroInspectionRunner = std::function<MacroInspectionReport(const QStringList &cxxflags)>;
virtual MacroInspectionRunner createMacroInspectionRunner() const = 0;
CppTools/ProjectManagers: Reduce ui blocking when loading projects ${AnyProject}::updateCppCodeModel() did two potentially not that cheap operations in the ui thread: (1) Querying the MimeDatabase for the mime type for the source files of the project. In 99.9% of the cases no files need to be read for this as the file extension will resolve the type. The expensiveness comes from the sheer number of files that can occur. (2) Calling compilers with the "(sub)project's compiler command line" to determine the macros. While the caches avoid redundant calls, the number of the unique compiler calls makes this still a ui-freezing experience. These two operations are moved into a worker thread. For this, the expensive compiler calls are encapsulated in thread safe lambdas ("runners") in order to keep the "mutexed" data minimal. The original API calls of the toolchains are implemented in terms of the runners. While adapting the project managers, remove also the calls to setProjectLanguage(). These are redundant because all of the project managers already set a proper value in the constructor. Also, currently there is no need (client) to report back detection of C sources in project parts. This also keeps CppProjectUpdater simple. There is still room for improvement: * Run the compiler calls in parallel instead of sequence. * Ensure that the mime type for a file is determined exactly once. Change-Id: I2efc4e132ee88e3c8f264012ec8fafe3d86c404f Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
2017-02-06 16:59:53 +01:00
// A BuiltInHeaderPathsRunner is created in the ui thread and runs in another thread.
using BuiltInHeaderPathsRunner = std::function<HeaderPaths(
const QStringList &cxxflags, const Utils::FilePath &sysRoot, const QString &originalTargetTriple)>;
virtual BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner(const Utils::Environment &env) const = 0;
virtual void addToEnvironment(Utils::Environment &env) const = 0;
virtual Utils::FilePath makeCommand(const Utils::Environment &env) const = 0;
Utils::Id language() const;
virtual Utils::FilePath compilerCommand() const; // FIXME: De-virtualize.
ProjectExplorer: Stop pretending that C and C++ compilers are unrelated Motivation: a) It was ridiculous that when users wanted to manually add a new toolchain, they had to do the entire setup twice. b) It was equally weird that users had to take care to choose matching toolchains when setting up a kit, or indeed that it was even possible to mix random toolchains in the first place. User-visible changes: - The "C" and "C++" categories in the toolchain settings page have been merged into a single "C/C++" category. - When adding a new toolchain, the "C" and "C++" sub-menus are gone. Instead, the toolchain config widget offers two path choosers if the respective toolchain type supports C and C++ compilers. - By default, the C++ compiler file path is derived from the C compiler file path automatically, so the user usually has to enter only the former. - In the kit settings page, the "C" and "C++" toolchain combo boxes have been replaced by a single "C/C++" combo box, relieving the user of the responsibility to choose two matching toolchains. Implementation: The notion that a Toolchain object corresponds to a single compiler is so deeply engrained in the code that it cannot realistically be changed in the short term. We therefore introduce the concept of a "toolchain bundle" as an additional layer that groups matching C and C++ toolchains together. This way, most code dealing with toolchains stays unchanged, and only the presentation layer (i.e. the toolchain and kit settings pages) needed to be rewritten. Once set up in a bundle, toolchains stay implicitly linked together so the matching only needs to be done once. In follow-up patches, we will make use of toolchain bundles in all the places where kits are auto-created, eliminating the risk of mixing incompatible toolchains in a kit. Change-Id: Ie6c5add9963e7c1096268dd77acd624671b2674f Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: hjk <hjk@qt.io>
2024-07-11 13:03:12 +02:00
virtual void setCompilerCommand(const Utils::FilePath &command);
virtual bool matchesCompilerCommand(const Utils::FilePath &command) const;
virtual QList<Utils::OutputLineParser *> createOutputParsers() const = 0;
virtual bool operator ==(const Toolchain &) const;
2010-04-09 18:43:05 +02:00
Toolchain *clone() const;
2010-04-09 18:43:05 +02:00
// Used by the toolchainmanager to save user-generated tool chains.
// Make sure to call this function when deriving!
void toMap(Utils::Store &map) const override;
virtual Tasks validateKit(const Kit *k) const;
virtual bool isJobCountSupported() const { return true; }
void setLanguage(Utils::Id language);
void setDetection(Detection d);
void setDetectionSource(const QString &source);
static Utils::LanguageVersion cxxLanguageVersion(const QByteArray &cplusplusMacroValue);
static Utils::LanguageVersion languageVersion(const Utils::Id &language, const Macros &macros);
enum Priority {
PriorityLow = 0,
PriorityNormal = 10,
PriorityHigh = 20,
};
virtual int priority() const { return PriorityNormal; }
virtual GccToolchain *asGccToolchain() { return nullptr; }
ProjectExplorer: Stop pretending that C and C++ compilers are unrelated Motivation: a) It was ridiculous that when users wanted to manually add a new toolchain, they had to do the entire setup twice. b) It was equally weird that users had to take care to choose matching toolchains when setting up a kit, or indeed that it was even possible to mix random toolchains in the first place. User-visible changes: - The "C" and "C++" categories in the toolchain settings page have been merged into a single "C/C++" category. - When adding a new toolchain, the "C" and "C++" sub-menus are gone. Instead, the toolchain config widget offers two path choosers if the respective toolchain type supports C and C++ compilers. - By default, the C++ compiler file path is derived from the C compiler file path automatically, so the user usually has to enter only the former. - In the kit settings page, the "C" and "C++" toolchain combo boxes have been replaced by a single "C/C++" combo box, relieving the user of the responsibility to choose two matching toolchains. Implementation: The notion that a Toolchain object corresponds to a single compiler is so deeply engrained in the code that it cannot realistically be changed in the short term. We therefore introduce the concept of a "toolchain bundle" as an additional layer that groups matching C and C++ toolchains together. This way, most code dealing with toolchains stays unchanged, and only the presentation layer (i.e. the toolchain and kit settings pages) needed to be rewritten. Once set up in a bundle, toolchains stay implicitly linked together so the matching only needs to be done once. In follow-up patches, we will make use of toolchain bundles in all the places where kits are auto-created, eliminating the risk of mixing incompatible toolchains in a kit. Change-Id: Ie6c5add9963e7c1096268dd77acd624671b2674f Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: hjk <hjk@qt.io>
2024-07-11 13:03:12 +02:00
Utils::FilePath correspondingCompilerCommand(Utils::Id otherLanguage) const;
protected:
explicit Toolchain(Utils::Id typeId);
void setTypeDisplayName(const QString &typeName);
void setTargetAbiNoSignal(const Abi &abi);
void setTargetAbiKey(const Utils::Key &abiKey);
void setCompilerCommandKey(const Utils::Key &commandKey);
const MacrosCache &predefinedMacrosCache() const;
const HeaderPathsCache &headerPathsCache() const;
void toolChainUpdated();
// Make sure to call this function when deriving!
void fromMap(const Utils::Store &data) override;
void reportError();
bool hasError() const;
enum class PossiblyConcatenatedFlag { No, Yes };
static Utils::FilePaths includedFiles(const QString &option,
const QStringList &flags,
const Utils::FilePath &directoryPath,
PossiblyConcatenatedFlag possiblyConcatenated);
private:
Toolchain(const Toolchain &) = delete;
Toolchain &operator=(const Toolchain &) = delete;
ProjectExplorer: Stop pretending that C and C++ compilers are unrelated Motivation: a) It was ridiculous that when users wanted to manually add a new toolchain, they had to do the entire setup twice. b) It was equally weird that users had to take care to choose matching toolchains when setting up a kit, or indeed that it was even possible to mix random toolchains in the first place. User-visible changes: - The "C" and "C++" categories in the toolchain settings page have been merged into a single "C/C++" category. - When adding a new toolchain, the "C" and "C++" sub-menus are gone. Instead, the toolchain config widget offers two path choosers if the respective toolchain type supports C and C++ compilers. - By default, the C++ compiler file path is derived from the C compiler file path automatically, so the user usually has to enter only the former. - In the kit settings page, the "C" and "C++" toolchain combo boxes have been replaced by a single "C/C++" combo box, relieving the user of the responsibility to choose two matching toolchains. Implementation: The notion that a Toolchain object corresponds to a single compiler is so deeply engrained in the code that it cannot realistically be changed in the short term. We therefore introduce the concept of a "toolchain bundle" as an additional layer that groups matching C and C++ toolchains together. This way, most code dealing with toolchains stays unchanged, and only the presentation layer (i.e. the toolchain and kit settings pages) needed to be rewritten. Once set up in a bundle, toolchains stay implicitly linked together so the matching only needs to be done once. In follow-up patches, we will make use of toolchain bundles in all the places where kits are auto-created, eliminating the risk of mixing incompatible toolchains in a kit. Change-Id: Ie6c5add9963e7c1096268dd77acd624671b2674f Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: hjk <hjk@qt.io>
2024-07-11 13:03:12 +02:00
virtual bool canShareBundleImpl(const Toolchain &other) const;
const std::unique_ptr<Internal::ToolchainPrivate> d;
friend class Internal::ToolchainSettingsAccessor;
friend class ToolchainFactory;
};
using Toolchains = QList<Toolchain *>;
ProjectExplorer: Stop pretending that C and C++ compilers are unrelated Motivation: a) It was ridiculous that when users wanted to manually add a new toolchain, they had to do the entire setup twice. b) It was equally weird that users had to take care to choose matching toolchains when setting up a kit, or indeed that it was even possible to mix random toolchains in the first place. User-visible changes: - The "C" and "C++" categories in the toolchain settings page have been merged into a single "C/C++" category. - When adding a new toolchain, the "C" and "C++" sub-menus are gone. Instead, the toolchain config widget offers two path choosers if the respective toolchain type supports C and C++ compilers. - By default, the C++ compiler file path is derived from the C compiler file path automatically, so the user usually has to enter only the former. - In the kit settings page, the "C" and "C++" toolchain combo boxes have been replaced by a single "C/C++" combo box, relieving the user of the responsibility to choose two matching toolchains. Implementation: The notion that a Toolchain object corresponds to a single compiler is so deeply engrained in the code that it cannot realistically be changed in the short term. We therefore introduce the concept of a "toolchain bundle" as an additional layer that groups matching C and C++ toolchains together. This way, most code dealing with toolchains stays unchanged, and only the presentation layer (i.e. the toolchain and kit settings pages) needed to be rewritten. Once set up in a bundle, toolchains stay implicitly linked together so the matching only needs to be done once. In follow-up patches, we will make use of toolchain bundles in all the places where kits are auto-created, eliminating the risk of mixing incompatible toolchains in a kit. Change-Id: Ie6c5add9963e7c1096268dd77acd624671b2674f Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: hjk <hjk@qt.io>
2024-07-11 13:03:12 +02:00
class PROJECTEXPLORER_EXPORT ToolchainBundle
{
public:
// Setting up a bundle may necessitate creating additional toolchains.
// Depending on the context, these should or should not be registered
// immediately with the ToolchainManager.
enum class AutoRegister { On, Off, NotApplicable };
ProjectExplorer: Stop pretending that C and C++ compilers are unrelated Motivation: a) It was ridiculous that when users wanted to manually add a new toolchain, they had to do the entire setup twice. b) It was equally weird that users had to take care to choose matching toolchains when setting up a kit, or indeed that it was even possible to mix random toolchains in the first place. User-visible changes: - The "C" and "C++" categories in the toolchain settings page have been merged into a single "C/C++" category. - When adding a new toolchain, the "C" and "C++" sub-menus are gone. Instead, the toolchain config widget offers two path choosers if the respective toolchain type supports C and C++ compilers. - By default, the C++ compiler file path is derived from the C compiler file path automatically, so the user usually has to enter only the former. - In the kit settings page, the "C" and "C++" toolchain combo boxes have been replaced by a single "C/C++" combo box, relieving the user of the responsibility to choose two matching toolchains. Implementation: The notion that a Toolchain object corresponds to a single compiler is so deeply engrained in the code that it cannot realistically be changed in the short term. We therefore introduce the concept of a "toolchain bundle" as an additional layer that groups matching C and C++ toolchains together. This way, most code dealing with toolchains stays unchanged, and only the presentation layer (i.e. the toolchain and kit settings pages) needed to be rewritten. Once set up in a bundle, toolchains stay implicitly linked together so the matching only needs to be done once. In follow-up patches, we will make use of toolchain bundles in all the places where kits are auto-created, eliminating the risk of mixing incompatible toolchains in a kit. Change-Id: Ie6c5add9963e7c1096268dd77acd624671b2674f Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: hjk <hjk@qt.io>
2024-07-11 13:03:12 +02:00
ToolchainBundle(const Toolchains &toolchains, AutoRegister autoRegister);
static QList<ToolchainBundle> collectBundles(AutoRegister autoRegister);
static QList<ToolchainBundle> collectBundles(
const Toolchains &toolchains, AutoRegister autoRegister);
ProjectExplorer: Stop pretending that C and C++ compilers are unrelated Motivation: a) It was ridiculous that when users wanted to manually add a new toolchain, they had to do the entire setup twice. b) It was equally weird that users had to take care to choose matching toolchains when setting up a kit, or indeed that it was even possible to mix random toolchains in the first place. User-visible changes: - The "C" and "C++" categories in the toolchain settings page have been merged into a single "C/C++" category. - When adding a new toolchain, the "C" and "C++" sub-menus are gone. Instead, the toolchain config widget offers two path choosers if the respective toolchain type supports C and C++ compilers. - By default, the C++ compiler file path is derived from the C compiler file path automatically, so the user usually has to enter only the former. - In the kit settings page, the "C" and "C++" toolchain combo boxes have been replaced by a single "C/C++" combo box, relieving the user of the responsibility to choose two matching toolchains. Implementation: The notion that a Toolchain object corresponds to a single compiler is so deeply engrained in the code that it cannot realistically be changed in the short term. We therefore introduce the concept of a "toolchain bundle" as an additional layer that groups matching C and C++ toolchains together. This way, most code dealing with toolchains stays unchanged, and only the presentation layer (i.e. the toolchain and kit settings pages) needed to be rewritten. Once set up in a bundle, toolchains stay implicitly linked together so the matching only needs to be done once. In follow-up patches, we will make use of toolchain bundles in all the places where kits are auto-created, eliminating the risk of mixing incompatible toolchains in a kit. Change-Id: Ie6c5add9963e7c1096268dd77acd624671b2674f Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: hjk <hjk@qt.io>
2024-07-11 13:03:12 +02:00
template<typename R, class T = Toolchain, typename... A>
R get(R (T:: *getter)(A...) const, A&&... args) const
{
return std::invoke(getter, static_cast<T &>(*m_toolchains.first()), std::forward<A>(args)...);
}
template<class T = Toolchain, typename R> R& get(R T::*member) const
{
return static_cast<T &>(*m_toolchains.first()).*member;
}
template<class T = Toolchain, typename ...A> void set(void (T::*setter)(const A&...), const A& ...args)
{
for (Toolchain * const tc : std::as_const(m_toolchains))
std::invoke(setter, static_cast<T &>(*tc), args...);
}
template<class T = Toolchain, typename ...A> void set(void (T::*setter)(A...), const A ...args)
{
for (Toolchain * const tc : std::as_const(m_toolchains))
std::invoke(setter, static_cast<T &>(*tc), args...);
}
template<typename T> void forEach(const std::function<void(T &toolchain)> &modifier) const
ProjectExplorer: Stop pretending that C and C++ compilers are unrelated Motivation: a) It was ridiculous that when users wanted to manually add a new toolchain, they had to do the entire setup twice. b) It was equally weird that users had to take care to choose matching toolchains when setting up a kit, or indeed that it was even possible to mix random toolchains in the first place. User-visible changes: - The "C" and "C++" categories in the toolchain settings page have been merged into a single "C/C++" category. - When adding a new toolchain, the "C" and "C++" sub-menus are gone. Instead, the toolchain config widget offers two path choosers if the respective toolchain type supports C and C++ compilers. - By default, the C++ compiler file path is derived from the C compiler file path automatically, so the user usually has to enter only the former. - In the kit settings page, the "C" and "C++" toolchain combo boxes have been replaced by a single "C/C++" combo box, relieving the user of the responsibility to choose two matching toolchains. Implementation: The notion that a Toolchain object corresponds to a single compiler is so deeply engrained in the code that it cannot realistically be changed in the short term. We therefore introduce the concept of a "toolchain bundle" as an additional layer that groups matching C and C++ toolchains together. This way, most code dealing with toolchains stays unchanged, and only the presentation layer (i.e. the toolchain and kit settings pages) needed to be rewritten. Once set up in a bundle, toolchains stay implicitly linked together so the matching only needs to be done once. In follow-up patches, we will make use of toolchain bundles in all the places where kits are auto-created, eliminating the risk of mixing incompatible toolchains in a kit. Change-Id: Ie6c5add9963e7c1096268dd77acd624671b2674f Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: hjk <hjk@qt.io>
2024-07-11 13:03:12 +02:00
{
for (Toolchain * const tc : std::as_const(m_toolchains))
modifier(static_cast<T &>(*tc));
}
template<typename T> void forEach(const std::function<void(const T &toolchain)> &func) const
{
for (const Toolchain * const tc : m_toolchains)
func(static_cast<const T &>(*tc));
}
int size() const { return m_toolchains.size(); }
const QList<Toolchain *> toolchains() const { return m_toolchains; }
ToolchainFactory *factory() const;
Utils::Id bundleId() const { return get(&Toolchain::bundleId); }
QString displayName() const;
Utils::Id type() const { return get(&Toolchain::typeId); }
QString typeDisplayName() const { return get(&Toolchain::typeDisplayName); }
QStringList extraCodeModelFlags() const { return get(&Toolchain::extraCodeModelFlags); }
bool isAutoDetected() const { return get(&Toolchain::isAutoDetected); }
bool isSdkProvided() const { return get(&Toolchain::isSdkProvided); }
Utils::FilePath compilerCommand(Utils::Id language) const;
Abi targetAbi() const { return get(&Toolchain::targetAbi); }
QList<Abi> supportedAbis() const { return get(&Toolchain::supportedAbis); }
Utils::FilePath makeCommand(const Utils::Environment &env) const
{
return get(&Toolchain::makeCommand, env);
}
enum class Valid { All, Some, None };
Valid validity() const;
bool isCompletelyValid() const { return validity() == Valid::All; }
ProjectExplorer: Stop pretending that C and C++ compilers are unrelated Motivation: a) It was ridiculous that when users wanted to manually add a new toolchain, they had to do the entire setup twice. b) It was equally weird that users had to take care to choose matching toolchains when setting up a kit, or indeed that it was even possible to mix random toolchains in the first place. User-visible changes: - The "C" and "C++" categories in the toolchain settings page have been merged into a single "C/C++" category. - When adding a new toolchain, the "C" and "C++" sub-menus are gone. Instead, the toolchain config widget offers two path choosers if the respective toolchain type supports C and C++ compilers. - By default, the C++ compiler file path is derived from the C compiler file path automatically, so the user usually has to enter only the former. - In the kit settings page, the "C" and "C++" toolchain combo boxes have been replaced by a single "C/C++" combo box, relieving the user of the responsibility to choose two matching toolchains. Implementation: The notion that a Toolchain object corresponds to a single compiler is so deeply engrained in the code that it cannot realistically be changed in the short term. We therefore introduce the concept of a "toolchain bundle" as an additional layer that groups matching C and C++ toolchains together. This way, most code dealing with toolchains stays unchanged, and only the presentation layer (i.e. the toolchain and kit settings pages) needed to be rewritten. Once set up in a bundle, toolchains stay implicitly linked together so the matching only needs to be done once. In follow-up patches, we will make use of toolchain bundles in all the places where kits are auto-created, eliminating the risk of mixing incompatible toolchains in a kit. Change-Id: Ie6c5add9963e7c1096268dd77acd624671b2674f Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: hjk <hjk@qt.io>
2024-07-11 13:03:12 +02:00
void setDetection(Toolchain::Detection d) { set(&Toolchain::setDetection, d); }
void setCompilerCommand(Utils::Id language, const Utils::FilePath &cmd);
void setDisplayName(const QString &name) { set(&Toolchain::setDisplayName, name); }
void setTargetAbi(const Abi &abi) { set(&Toolchain::setTargetAbi, abi); }
ToolchainBundle clone() const;
// Rampdown operations. No regular access to the bundle is allowed after calling these.
bool removeToolchain(Toolchain *tc) { return m_toolchains.removeOne(tc); }
void clearToolchains() { m_toolchains.clear(); }
void deleteToolchains();
friend bool operator==(const ToolchainBundle &b1, const ToolchainBundle &b2)
{
return b1.m_toolchains == b2.m_toolchains;
}
private:
void addMissingToolchains(AutoRegister autoRegister);
static QList<ToolchainBundle> bundleUnbundledToolchains(
const Toolchains &unbundled, AutoRegister autoRegister);
ProjectExplorer: Stop pretending that C and C++ compilers are unrelated Motivation: a) It was ridiculous that when users wanted to manually add a new toolchain, they had to do the entire setup twice. b) It was equally weird that users had to take care to choose matching toolchains when setting up a kit, or indeed that it was even possible to mix random toolchains in the first place. User-visible changes: - The "C" and "C++" categories in the toolchain settings page have been merged into a single "C/C++" category. - When adding a new toolchain, the "C" and "C++" sub-menus are gone. Instead, the toolchain config widget offers two path choosers if the respective toolchain type supports C and C++ compilers. - By default, the C++ compiler file path is derived from the C compiler file path automatically, so the user usually has to enter only the former. - In the kit settings page, the "C" and "C++" toolchain combo boxes have been replaced by a single "C/C++" combo box, relieving the user of the responsibility to choose two matching toolchains. Implementation: The notion that a Toolchain object corresponds to a single compiler is so deeply engrained in the code that it cannot realistically be changed in the short term. We therefore introduce the concept of a "toolchain bundle" as an additional layer that groups matching C and C++ toolchains together. This way, most code dealing with toolchains stays unchanged, and only the presentation layer (i.e. the toolchain and kit settings pages) needed to be rewritten. Once set up in a bundle, toolchains stay implicitly linked together so the matching only needs to be done once. In follow-up patches, we will make use of toolchain bundles in all the places where kits are auto-created, eliminating the risk of mixing incompatible toolchains in a kit. Change-Id: Ie6c5add9963e7c1096268dd77acd624671b2674f Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: hjk <hjk@qt.io>
2024-07-11 13:03:12 +02:00
Toolchains m_toolchains;
};
class PROJECTEXPLORER_EXPORT BadToolchain
{
public:
BadToolchain(const Utils::FilePath &filePath);
BadToolchain(const Utils::FilePath &filePath, const Utils::FilePath &symlinkTarget,
const QDateTime &timestamp);
Utils::Store toMap() const;
static BadToolchain fromMap(const Utils::Store &map);
Utils::FilePath filePath;
Utils::FilePath symlinkTarget;
QDateTime timestamp;
};
class PROJECTEXPLORER_EXPORT BadToolchains
{
public:
BadToolchains(const QList<BadToolchain> &toolchains = {});
bool isBadToolchain(const Utils::FilePath &toolchain) const;
QVariant toVariant() const;
static BadToolchains fromVariant(const QVariant &v);
QList<BadToolchain> toolchains;
};
class PROJECTEXPLORER_EXPORT ToolchainDetector
{
public:
ToolchainDetector(const Toolchains &alreadyKnown,
const IDeviceConstPtr &device,
const Utils::FilePaths &searchPaths);
const Toolchains alreadyKnown;
const IDeviceConstPtr device;
const Utils::FilePaths searchPaths; // If empty use device path and/or magic.
};
class PROJECTEXPLORER_EXPORT AsyncToolchainDetector
{
public:
AsyncToolchainDetector(
const ToolchainDetector &detector,
const std::function<Toolchains(const ToolchainDetector &)> &func,
const std::function<bool(const Toolchain *, const Toolchains &)> &alreadyRegistered);
void run();
private:
ToolchainDetector m_detector;
std::function<Toolchains(const ToolchainDetector &)> m_func;
std::function<bool(Toolchain *, const Toolchains &)> m_alreadyRegistered;
};
class PROJECTEXPLORER_EXPORT ToolchainFactory
{
ToolchainFactory(const ToolchainFactory &) = delete;
ToolchainFactory &operator=(const ToolchainFactory &) = delete;
public:
ToolchainFactory();
virtual ~ToolchainFactory();
static const QList<ToolchainFactory *> allToolchainFactories();
static ToolchainFactory *factoryForType(Utils::Id typeId);
QString displayName() const { return m_displayName; }
Utils::Id supportedToolchainType() const;
virtual std::optional<AsyncToolchainDetector> asyncAutoDetector(
const ToolchainDetector &detector) const;
virtual Toolchains autoDetect(const ToolchainDetector &detector) const;
virtual Toolchains detectForImport(const ToolchainDescription &tcd) const;
ProjectExplorer: Stop pretending that C and C++ compilers are unrelated Motivation: a) It was ridiculous that when users wanted to manually add a new toolchain, they had to do the entire setup twice. b) It was equally weird that users had to take care to choose matching toolchains when setting up a kit, or indeed that it was even possible to mix random toolchains in the first place. User-visible changes: - The "C" and "C++" categories in the toolchain settings page have been merged into a single "C/C++" category. - When adding a new toolchain, the "C" and "C++" sub-menus are gone. Instead, the toolchain config widget offers two path choosers if the respective toolchain type supports C and C++ compilers. - By default, the C++ compiler file path is derived from the C compiler file path automatically, so the user usually has to enter only the former. - In the kit settings page, the "C" and "C++" toolchain combo boxes have been replaced by a single "C/C++" combo box, relieving the user of the responsibility to choose two matching toolchains. Implementation: The notion that a Toolchain object corresponds to a single compiler is so deeply engrained in the code that it cannot realistically be changed in the short term. We therefore introduce the concept of a "toolchain bundle" as an additional layer that groups matching C and C++ toolchains together. This way, most code dealing with toolchains stays unchanged, and only the presentation layer (i.e. the toolchain and kit settings pages) needed to be rewritten. Once set up in a bundle, toolchains stay implicitly linked together so the matching only needs to be done once. In follow-up patches, we will make use of toolchain bundles in all the places where kits are auto-created, eliminating the risk of mixing incompatible toolchains in a kit. Change-Id: Ie6c5add9963e7c1096268dd77acd624671b2674f Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: hjk <hjk@qt.io>
2024-07-11 13:03:12 +02:00
virtual std::unique_ptr<ToolchainConfigWidget> createConfigurationWidget(
const ToolchainBundle &bundle) const = 0;
virtual Utils::FilePath correspondingCompilerCommand(
const Utils::FilePath &srcPath, Utils::Id targetLang) const;
virtual bool canCreate() const;
Toolchain *create() const;
Toolchain *restore(const Utils::Store &data);
static QByteArray idFromMap(const Utils::Store &data);
static Utils::Id typeIdFromMap(const Utils::Store &data);
static void autoDetectionToMap(Utils::Store &data, bool detected);
static Toolchain *createToolchain(Utils::Id toolchainType);
QList<Utils::Id> supportedLanguages() const;
ProjectExplorer: Stop pretending that C and C++ compilers are unrelated Motivation: a) It was ridiculous that when users wanted to manually add a new toolchain, they had to do the entire setup twice. b) It was equally weird that users had to take care to choose matching toolchains when setting up a kit, or indeed that it was even possible to mix random toolchains in the first place. User-visible changes: - The "C" and "C++" categories in the toolchain settings page have been merged into a single "C/C++" category. - When adding a new toolchain, the "C" and "C++" sub-menus are gone. Instead, the toolchain config widget offers two path choosers if the respective toolchain type supports C and C++ compilers. - By default, the C++ compiler file path is derived from the C compiler file path automatically, so the user usually has to enter only the former. - In the kit settings page, the "C" and "C++" toolchain combo boxes have been replaced by a single "C/C++" combo box, relieving the user of the responsibility to choose two matching toolchains. Implementation: The notion that a Toolchain object corresponds to a single compiler is so deeply engrained in the code that it cannot realistically be changed in the short term. We therefore introduce the concept of a "toolchain bundle" as an additional layer that groups matching C and C++ toolchains together. This way, most code dealing with toolchains stays unchanged, and only the presentation layer (i.e. the toolchain and kit settings pages) needed to be rewritten. Once set up in a bundle, toolchains stay implicitly linked together so the matching only needs to be done once. In follow-up patches, we will make use of toolchain bundles in all the places where kits are auto-created, eliminating the risk of mixing incompatible toolchains in a kit. Change-Id: Ie6c5add9963e7c1096268dd77acd624671b2674f Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: hjk <hjk@qt.io>
2024-07-11 13:03:12 +02:00
LanguageCategory languageCategory() const;
void setUserCreatable(bool userCreatable);
protected:
void setDisplayName(const QString &name) { m_displayName = name; }
void setSupportedToolchainType(const Utils::Id &supportedToolchainType);
void setSupportedLanguages(const QList<Utils::Id> &supportedLanguages);
using ToolchainConstructor = std::function<Toolchain *()>;
void setToolchainConstructor(const ToolchainConstructor &constructor);
ToolchainConstructor toolchainConstructor() const;
class Candidate {
public:
Utils::FilePath compilerPath;
QString compilerVersion;
bool operator==(const ToolchainFactory::Candidate &other) const {
return compilerPath == other.compilerPath
&& compilerVersion == other.compilerVersion;
}
};
using Candidates = QVector<Candidate>;
private:
QString m_displayName;
Utils::Id m_supportedToolchainType;
QList<Utils::Id> m_supportedLanguages;
bool m_userCreatable = false;
ToolchainConstructor m_toolchainConstructor;
};
} // namespace ProjectExplorer