2022-08-19 15:59:36 +02:00
|
|
|
// Copyright (C) 2016 The Qt Company Ltd.
|
2022-12-21 10:12:09 +01:00
|
|
|
// 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
|
|
|
|
2009-02-10 15:34:25 +01:00
|
|
|
#include "toolchain.h"
|
2011-03-24 13:27:26 +01:00
|
|
|
|
2012-04-24 15:49:09 +02:00
|
|
|
#include "abi.h"
|
2022-04-12 21:01:45 +02:00
|
|
|
#include "devicesupport/idevice.h"
|
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 "gcctoolchain.h"
|
2016-12-16 00:43:14 +01:00
|
|
|
#include "projectexplorerconstants.h"
|
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 "projectexplorertr.h"
|
2011-03-24 13:27:26 +01:00
|
|
|
#include "toolchainmanager.h"
|
2013-03-21 12:27:18 +01:00
|
|
|
#include "task.h"
|
2011-03-24 13:27:26 +01:00
|
|
|
|
2024-01-02 09:05:37 +01:00
|
|
|
#include <utils/async.h>
|
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 <utils/pathchooser.h>
|
2015-07-09 11:34:37 +02:00
|
|
|
#include <utils/qtcassert.h>
|
2009-03-16 18:13:45 +01:00
|
|
|
|
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 <QHash>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QUuid>
|
2009-02-10 15:34:25 +01:00
|
|
|
|
2022-01-18 15:42:02 +01:00
|
|
|
#include <utility>
|
|
|
|
|
|
2020-11-13 09:39:32 +01:00
|
|
|
using namespace Utils;
|
|
|
|
|
|
2011-02-01 18:36:00 +01:00
|
|
|
namespace ProjectExplorer {
|
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
|
|
|
|
2011-02-01 18:36:00 +01:00
|
|
|
namespace Internal {
|
2009-02-10 15:34:25 +01:00
|
|
|
|
2023-07-07 14:34:35 +02:00
|
|
|
const char ID_KEY[] = "ProjectExplorer.ToolChain.Id";
|
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
|
|
|
const char BUNDLE_ID_KEY[] = "ProjectExplorer.ToolChain.BundleId";
|
2023-07-07 14:34:35 +02:00
|
|
|
const char DISPLAY_NAME_KEY[] = "ProjectExplorer.ToolChain.DisplayName";
|
|
|
|
|
const char AUTODETECT_KEY[] = "ProjectExplorer.ToolChain.Autodetect";
|
|
|
|
|
const char DETECTION_SOURCE_KEY[] = "ProjectExplorer.ToolChain.DetectionSource";
|
|
|
|
|
const char LANGUAGE_KEY_V1[] = "ProjectExplorer.ToolChain.Language"; // For QtCreator <= 4.2
|
|
|
|
|
const char LANGUAGE_KEY_V2[] = "ProjectExplorer.ToolChain.LanguageV2"; // For QtCreator > 4.2
|
|
|
|
|
const char CODE_MODEL_TRIPLE_KEY[] = "ExplicitCodeModelTargetTriple";
|
|
|
|
|
|
2023-11-22 14:39:32 +01:00
|
|
|
QList<ToolchainFactory *> &toolchainFactories()
|
2023-07-07 14:34:35 +02:00
|
|
|
{
|
2023-11-27 17:09:08 +01:00
|
|
|
static QList<ToolchainFactory *> theToolchainFactories;
|
|
|
|
|
return theToolchainFactories;
|
2023-07-07 14:34:35 +02:00
|
|
|
}
|
2019-05-13 16:18:25 +02:00
|
|
|
|
2011-02-01 18:36:00 +01:00
|
|
|
// --------------------------------------------------------------------------
|
2023-11-27 17:09:08 +01:00
|
|
|
// ToolchainPrivate
|
2011-02-01 18:36:00 +01:00
|
|
|
// --------------------------------------------------------------------------
|
2009-02-10 15:34:25 +01:00
|
|
|
|
2023-11-27 17:09:08 +01:00
|
|
|
class ToolchainPrivate
|
2009-02-10 15:34:25 +01:00
|
|
|
{
|
2011-02-01 18:36:00 +01:00
|
|
|
public:
|
2023-11-24 15:53:31 +01:00
|
|
|
using Detection = Toolchain::Detection;
|
2013-09-03 10:58:59 +02:00
|
|
|
|
2023-11-27 17:09:08 +01:00
|
|
|
explicit ToolchainPrivate(Id typeId) :
|
2015-07-09 11:34:37 +02:00
|
|
|
m_id(QUuid::createUuid().toByteArray()),
|
|
|
|
|
m_typeId(typeId),
|
2023-11-24 15:53:31 +01:00
|
|
|
m_predefinedMacrosCache(new Toolchain::MacrosCache::element_type()),
|
|
|
|
|
m_headerPathsCache(new Toolchain::HeaderPathsCache::element_type())
|
2015-07-07 15:37:50 +02:00
|
|
|
{
|
|
|
|
|
QTC_ASSERT(m_typeId.isValid(), return);
|
2023-08-24 12:41:45 +02:00
|
|
|
QTC_ASSERT(!m_typeId.name().contains(':'), return);
|
2015-07-07 15:37:50 +02:00
|
|
|
}
|
2009-02-10 15:34:25 +01:00
|
|
|
|
2015-07-07 12:01:22 +02:00
|
|
|
QByteArray m_id;
|
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
|
|
|
Id m_bundleId;
|
2020-11-13 09:39:32 +01:00
|
|
|
FilePath m_compilerCommand;
|
2023-08-24 12:41:45 +02:00
|
|
|
Key m_compilerCommandKey;
|
2020-11-10 14:05:58 +01:00
|
|
|
Abi m_targetAbi;
|
2023-08-24 12:41:45 +02:00
|
|
|
Key m_targetAbiKey;
|
2023-07-07 14:34:35 +02:00
|
|
|
QSet<Id> m_supportedLanguages;
|
2016-04-13 15:52:14 +02:00
|
|
|
mutable QString m_displayName;
|
2019-06-19 17:28:20 +02:00
|
|
|
QString m_typeDisplayName;
|
2023-07-07 14:34:35 +02:00
|
|
|
Id m_typeId;
|
|
|
|
|
Id m_language;
|
2023-11-24 15:53:31 +01:00
|
|
|
Detection m_detection = Toolchain::UninitializedDetection;
|
2021-07-12 14:19:23 +02:00
|
|
|
QString m_detectionSource;
|
2022-01-20 16:53:55 +01:00
|
|
|
QString m_explicitCodeModelTargetTriple;
|
2019-05-09 11:24:54 +02:00
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
Toolchain::MacrosCache m_predefinedMacrosCache;
|
|
|
|
|
Toolchain::HeaderPathsCache m_headerPathsCache;
|
2022-09-29 13:07:41 +02:00
|
|
|
std::optional<bool> m_isValid;
|
2023-07-21 19:15:02 +02:00
|
|
|
bool m_hasError = false;
|
2011-02-01 18:36:00 +01:00
|
|
|
};
|
2009-02-10 15:34:25 +01:00
|
|
|
|
2016-12-16 00:43:14 +01:00
|
|
|
|
2021-04-30 10:11:16 +02:00
|
|
|
// Deprecated used from QtCreator <= 4.2
|
|
|
|
|
|
2023-07-07 14:34:35 +02:00
|
|
|
Id fromLanguageV1(int language)
|
2021-04-30 10:11:16 +02:00
|
|
|
{
|
|
|
|
|
switch (language)
|
|
|
|
|
{
|
|
|
|
|
case Deprecated::Toolchain::C :
|
2023-07-07 14:34:35 +02:00
|
|
|
return Id(Constants::C_LANGUAGE_ID);
|
2021-04-30 10:11:16 +02:00
|
|
|
case Deprecated::Toolchain::Cxx:
|
2023-07-07 14:34:35 +02:00
|
|
|
return Id(Constants::CXX_LANGUAGE_ID);
|
2021-04-30 10:11:16 +02:00
|
|
|
case Deprecated::Toolchain::None:
|
|
|
|
|
default:
|
2023-08-01 20:52:58 +02:00
|
|
|
return {};
|
2021-04-30 10:11:16 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace Internal
|
|
|
|
|
|
2023-07-07 14:34:35 +02:00
|
|
|
namespace Deprecated::Toolchain {
|
|
|
|
|
|
2021-04-30 10:11:16 +02:00
|
|
|
QString languageId(Language l)
|
|
|
|
|
{
|
|
|
|
|
switch (l) {
|
|
|
|
|
case Language::None:
|
|
|
|
|
return QStringLiteral("None");
|
|
|
|
|
case Language::C:
|
|
|
|
|
return QStringLiteral("C");
|
|
|
|
|
case Language::Cxx:
|
|
|
|
|
return QStringLiteral("Cxx");
|
|
|
|
|
};
|
2023-08-01 20:52:58 +02:00
|
|
|
return {};
|
2021-04-30 10:11:16 +02:00
|
|
|
}
|
2023-07-07 14:34:35 +02:00
|
|
|
|
2023-11-27 17:09:08 +01:00
|
|
|
} // namespace Deprecated::Toolchain
|
2023-07-07 14:34:35 +02:00
|
|
|
|
|
|
|
|
using namespace Internal;
|
2016-12-16 00:43:14 +01:00
|
|
|
|
2011-04-14 12:58:14 +02:00
|
|
|
/*!
|
2023-11-27 16:42:42 +01:00
|
|
|
\class ProjectExplorer::Toolchain
|
|
|
|
|
\brief The Toolchain class represents a tool chain.
|
|
|
|
|
\sa ProjectExplorer::ToolchainManager
|
2011-04-14 12:58:14 +02:00
|
|
|
*/
|
|
|
|
|
|
2011-02-01 18:36:00 +01:00
|
|
|
// --------------------------------------------------------------------------
|
2009-02-10 15:34:25 +01:00
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
Toolchain::Toolchain(Id typeId) :
|
2023-11-27 17:09:08 +01:00
|
|
|
d(std::make_unique<ToolchainPrivate>(typeId))
|
2016-07-12 10:22:09 +02:00
|
|
|
{
|
|
|
|
|
}
|
2010-04-09 18:43:05 +02:00
|
|
|
|
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
|
|
|
bool Toolchain::canShareBundleImpl(const Toolchain &other) const
|
|
|
|
|
{
|
|
|
|
|
Q_UNUSED(other)
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
void Toolchain::setLanguage(Id language)
|
2016-07-12 10:22:09 +02:00
|
|
|
{
|
2016-12-16 00:43:14 +01:00
|
|
|
QTC_ASSERT(language.isValid(), return);
|
2023-11-27 16:42:42 +01:00
|
|
|
QTC_ASSERT(ToolchainManager::isLanguageSupported(language), return);
|
2016-07-12 10:22:09 +02:00
|
|
|
|
2016-12-16 00:43:14 +01:00
|
|
|
d->m_language = language;
|
2016-07-12 10:22:09 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
Toolchain::~Toolchain() = default;
|
2010-04-09 18:43:05 +02:00
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
QString Toolchain::displayName() const
|
2009-02-10 15:34:25 +01:00
|
|
|
{
|
2011-09-07 14:26:11 +02:00
|
|
|
if (d->m_displayName.isEmpty())
|
2012-01-30 11:55:21 +01:00
|
|
|
return typeDisplayName();
|
2011-09-07 14:26:11 +02:00
|
|
|
return d->m_displayName;
|
2010-03-04 15:23:02 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
void Toolchain::setDisplayName(const QString &name)
|
2010-03-04 15:23:02 +01:00
|
|
|
{
|
2011-09-07 14:26:11 +02:00
|
|
|
if (d->m_displayName == name)
|
2011-03-24 13:27:26 +01:00
|
|
|
return;
|
|
|
|
|
|
2011-09-07 14:26:11 +02:00
|
|
|
d->m_displayName = name;
|
2011-03-24 13:27:26 +01:00
|
|
|
toolChainUpdated();
|
2010-03-04 15:23:02 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
bool Toolchain::isAutoDetected() const
|
2020-09-08 16:54:11 +02:00
|
|
|
{
|
|
|
|
|
return detection() == AutoDetection || detection() == AutoDetectionFromSdk;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
Toolchain::Detection Toolchain::detection() const
|
2010-03-04 15:23:02 +01:00
|
|
|
{
|
2013-09-03 10:58:59 +02:00
|
|
|
return d->m_detection;
|
2010-03-04 15:23:02 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
QString Toolchain::detectionSource() const
|
2021-07-12 14:19:23 +02:00
|
|
|
{
|
|
|
|
|
return d->m_detectionSource;
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-13 12:38:23 +02:00
|
|
|
ToolchainFactory *Toolchain::factory() const
|
|
|
|
|
{
|
|
|
|
|
return ToolchainFactory::factoryForType(typeId());
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
QByteArray Toolchain::id() const
|
2010-03-04 15:23:02 +01:00
|
|
|
{
|
2011-09-07 14:26:11 +02:00
|
|
|
return d->m_id;
|
2010-03-04 15:23:02 +01:00
|
|
|
}
|
|
|
|
|
|
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
|
|
|
Id Toolchain::bundleId() const
|
|
|
|
|
{
|
|
|
|
|
return d->m_bundleId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Toolchain::setBundleId(Utils::Id id)
|
|
|
|
|
{
|
|
|
|
|
d->m_bundleId = id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Toolchain::canShareBundle(const Toolchain &other) const
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(typeId() == other.typeId(), return false);
|
|
|
|
|
QTC_ASSERT(language() != other.language(), return false);
|
|
|
|
|
|
|
|
|
|
if (int(factory()->supportedLanguages().size()) == 1)
|
|
|
|
|
return false;
|
|
|
|
|
if (detection() != other.detection())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (typeId() != Constants::MSVC_TOOLCHAIN_TYPEID
|
|
|
|
|
&& typeId() != Constants::CLANG_CL_TOOLCHAIN_TYPEID
|
|
|
|
|
&& (targetAbi() != other.targetAbi() || supportedAbis() != other.supportedAbis()
|
|
|
|
|
|| extraCodeModelFlags() != other.extraCodeModelFlags()
|
|
|
|
|
|| suggestedMkspecList() != other.suggestedMkspecList() || sysRoot() != other.sysRoot()
|
|
|
|
|
|| correspondingCompilerCommand(other.language()) != other.compilerCommand())) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return canShareBundleImpl(other);
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
QStringList Toolchain::suggestedMkspecList() const
|
2013-03-25 17:13:18 +01:00
|
|
|
{
|
2019-05-27 14:22:15 +02:00
|
|
|
return {};
|
2013-03-25 17:13:18 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
Id Toolchain::typeId() const
|
2015-07-09 11:34:37 +02:00
|
|
|
{
|
|
|
|
|
return d->m_typeId;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
Abis Toolchain::supportedAbis() const
|
2016-09-20 15:59:56 +02:00
|
|
|
{
|
2017-02-22 15:09:35 +01:00
|
|
|
return {targetAbi()};
|
2016-09-20 15:59:56 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
bool Toolchain::isValid() const
|
2020-11-13 12:53:14 +01:00
|
|
|
{
|
2022-09-29 13:07:41 +02:00
|
|
|
if (!d->m_isValid.has_value())
|
|
|
|
|
d->m_isValid = !compilerCommand().isEmpty() && compilerCommand().isExecutableFile();
|
|
|
|
|
|
|
|
|
|
return d->m_isValid.value_or(false);
|
2020-11-13 12:53:14 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
FilePaths Toolchain::includedFiles(const QStringList &flags, const FilePath &directory) const
|
2018-06-11 12:52:04 +02:00
|
|
|
{
|
|
|
|
|
Q_UNUSED(flags)
|
|
|
|
|
Q_UNUSED(directory)
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
Id Toolchain::language() const
|
2016-07-12 10:22:09 +02:00
|
|
|
{
|
|
|
|
|
return d->m_language;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
bool Toolchain::operator == (const Toolchain &tc) const
|
2010-04-21 17:24:37 +02:00
|
|
|
{
|
2011-02-01 18:36:00 +01:00
|
|
|
if (this == &tc)
|
|
|
|
|
return true;
|
2010-09-08 15:22:58 +02:00
|
|
|
|
2011-12-19 12:06:44 +01:00
|
|
|
// We ignore displayname
|
2016-10-30 12:01:38 +02:00
|
|
|
return typeId() == tc.typeId()
|
|
|
|
|
&& isAutoDetected() == tc.isAutoDetected()
|
|
|
|
|
&& language() == tc.language();
|
2009-02-10 15:34:25 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
Toolchain *Toolchain::clone() const
|
2019-05-13 16:18:25 +02:00
|
|
|
{
|
2024-07-13 12:38:23 +02:00
|
|
|
if (ToolchainFactory * const f = factory()) {
|
2024-07-11 13:03:12 +02:00
|
|
|
Toolchain *tc = f->create();
|
|
|
|
|
QTC_ASSERT(tc, return nullptr);
|
|
|
|
|
Store data;
|
|
|
|
|
toMap(data);
|
|
|
|
|
tc->fromMap(data);
|
|
|
|
|
// New ID for the clone. It's different.
|
|
|
|
|
tc->d->m_id = QUuid::createUuid().toByteArray();
|
|
|
|
|
return tc;
|
2019-05-13 16:18:25 +02:00
|
|
|
}
|
|
|
|
|
QTC_CHECK(false);
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-14 12:58:14 +02:00
|
|
|
/*!
|
2013-09-10 17:16:10 +02:00
|
|
|
Used by the tool chain manager to save user-generated tool chains.
|
2011-04-14 12:58:14 +02:00
|
|
|
|
2013-10-07 13:34:40 +02:00
|
|
|
Make sure to call this function when deriving.
|
2011-04-14 12:58:14 +02:00
|
|
|
*/
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
void Toolchain::toMap(Store &result) const
|
2009-02-10 15:34:25 +01:00
|
|
|
{
|
2023-07-20 17:15:13 +02:00
|
|
|
AspectContainer::toMap(result);
|
|
|
|
|
|
2015-07-09 11:34:37 +02:00
|
|
|
QString idToSave = d->m_typeId.toString() + QLatin1Char(':') + QString::fromUtf8(id());
|
2023-08-24 12:41:45 +02:00
|
|
|
result.insert(ID_KEY, idToSave);
|
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
|
|
|
result.insert(BUNDLE_ID_KEY, d->m_bundleId.toSetting());
|
2023-08-24 12:41:45 +02:00
|
|
|
result.insert(DISPLAY_NAME_KEY, displayName());
|
|
|
|
|
result.insert(AUTODETECT_KEY, isAutoDetected());
|
|
|
|
|
result.insert(DETECTION_SOURCE_KEY, d->m_detectionSource);
|
2022-01-20 16:53:55 +01:00
|
|
|
result.insert(CODE_MODEL_TRIPLE_KEY, d->m_explicitCodeModelTargetTriple);
|
2021-04-30 10:11:16 +02:00
|
|
|
// <Compatibility with QtC 4.2>
|
|
|
|
|
int oldLanguageId = -1;
|
|
|
|
|
if (language() == ProjectExplorer::Constants::C_LANGUAGE_ID)
|
|
|
|
|
oldLanguageId = 1;
|
|
|
|
|
else if (language() == ProjectExplorer::Constants::CXX_LANGUAGE_ID)
|
|
|
|
|
oldLanguageId = 2;
|
|
|
|
|
if (oldLanguageId >= 0)
|
|
|
|
|
result.insert(LANGUAGE_KEY_V1, oldLanguageId);
|
|
|
|
|
// </Compatibility>
|
2023-08-24 12:41:45 +02:00
|
|
|
result.insert(LANGUAGE_KEY_V2, language().toSetting());
|
2020-11-10 14:05:58 +01:00
|
|
|
if (!d->m_targetAbiKey.isEmpty())
|
|
|
|
|
result.insert(d->m_targetAbiKey, d->m_targetAbi.toString());
|
2020-11-13 09:39:32 +01:00
|
|
|
if (!d->m_compilerCommandKey.isEmpty())
|
2023-01-03 12:31:52 +01:00
|
|
|
result.insert(d->m_compilerCommandKey, d->m_compilerCommand.toSettings());
|
2010-03-04 15:23:02 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
void Toolchain::toolChainUpdated()
|
2011-03-24 13:27:26 +01:00
|
|
|
{
|
2019-05-09 11:24:54 +02:00
|
|
|
d->m_predefinedMacrosCache->invalidate();
|
|
|
|
|
d->m_headerPathsCache->invalidate();
|
|
|
|
|
|
2023-11-27 16:42:42 +01:00
|
|
|
ToolchainManager::notifyAboutUpdate(this);
|
2010-03-04 15:23:02 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
void Toolchain::setDetection(Toolchain::Detection de)
|
2011-03-01 16:34:02 +01:00
|
|
|
{
|
2021-05-18 14:32:26 +02:00
|
|
|
d->m_detection = de;
|
2011-03-01 16:34:02 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
void Toolchain::setDetectionSource(const QString &source)
|
2021-07-12 14:19:23 +02:00
|
|
|
{
|
|
|
|
|
d->m_detectionSource = source;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
QString Toolchain::typeDisplayName() const
|
2019-06-19 17:28:20 +02:00
|
|
|
{
|
|
|
|
|
return d->m_typeDisplayName;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
Abi Toolchain::targetAbi() const
|
2020-11-10 14:05:58 +01:00
|
|
|
{
|
|
|
|
|
return d->m_targetAbi;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
void Toolchain::setTargetAbi(const Abi &abi)
|
2020-11-10 14:05:58 +01:00
|
|
|
{
|
|
|
|
|
if (abi == d->m_targetAbi)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
d->m_targetAbi = abi;
|
|
|
|
|
toolChainUpdated();
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
void Toolchain::setTargetAbiNoSignal(const Abi &abi)
|
2020-11-10 14:05:58 +01:00
|
|
|
{
|
|
|
|
|
d->m_targetAbi = abi;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
void Toolchain::setTargetAbiKey(const Key &abiKey)
|
2020-11-10 14:05:58 +01:00
|
|
|
{
|
|
|
|
|
d->m_targetAbiKey = abiKey;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
FilePath Toolchain::compilerCommand() const
|
2020-11-13 09:39:32 +01:00
|
|
|
{
|
|
|
|
|
return d->m_compilerCommand;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
void Toolchain::setCompilerCommand(const FilePath &command)
|
2020-11-13 09:39:32 +01:00
|
|
|
{
|
2022-09-29 13:07:41 +02:00
|
|
|
d->m_isValid.reset();
|
|
|
|
|
|
2020-11-13 09:39:32 +01:00
|
|
|
if (command == d->m_compilerCommand)
|
|
|
|
|
return;
|
|
|
|
|
d->m_compilerCommand = command;
|
|
|
|
|
toolChainUpdated();
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
bool Toolchain::matchesCompilerCommand(const FilePath &command) const
|
2022-06-08 16:00:13 +02:00
|
|
|
{
|
2022-11-21 12:29:17 +01:00
|
|
|
return compilerCommand().isSameExecutable(command);
|
2022-06-08 16:00:13 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
void Toolchain::setCompilerCommandKey(const Key &commandKey)
|
2020-11-13 09:39:32 +01:00
|
|
|
{
|
|
|
|
|
d->m_compilerCommandKey = commandKey;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
void Toolchain::setTypeDisplayName(const QString &typeName)
|
2019-06-19 17:28:20 +02:00
|
|
|
{
|
|
|
|
|
d->m_typeDisplayName = typeName;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-14 12:58:14 +02:00
|
|
|
/*!
|
2013-09-10 17:16:10 +02:00
|
|
|
Used by the tool chain manager to load user-generated tool chains.
|
2011-04-14 12:58:14 +02:00
|
|
|
|
2013-10-07 13:34:40 +02:00
|
|
|
Make sure to call this function when deriving.
|
2011-04-14 12:58:14 +02:00
|
|
|
*/
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
void Toolchain::fromMap(const Store &data)
|
2009-02-10 15:34:25 +01:00
|
|
|
{
|
2023-07-20 17:15:13 +02:00
|
|
|
AspectContainer::fromMap(data);
|
|
|
|
|
|
2023-08-24 16:14:26 +02:00
|
|
|
d->m_displayName = data.value(DISPLAY_NAME_KEY).toString();
|
2015-07-09 11:34:37 +02:00
|
|
|
|
2011-12-19 12:06:44 +01:00
|
|
|
// make sure we have new style ids:
|
2023-08-24 16:14:26 +02:00
|
|
|
const QString id = data.value(ID_KEY).toString();
|
2015-07-09 11:34:37 +02:00
|
|
|
int pos = id.indexOf(QLatin1Char(':'));
|
2023-07-21 19:15:02 +02:00
|
|
|
QTC_ASSERT(pos > 0, reportError(); return);
|
2023-07-07 14:34:35 +02:00
|
|
|
d->m_typeId = Id::fromString(id.left(pos));
|
2015-07-14 11:12:14 +02:00
|
|
|
d->m_id = id.mid(pos + 1).toUtf8();
|
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
|
|
|
d->m_bundleId = Id::fromSetting(data.value(BUNDLE_ID_KEY));
|
2015-07-09 11:34:37 +02:00
|
|
|
|
2023-08-24 16:14:26 +02:00
|
|
|
const bool autoDetect = data.value(AUTODETECT_KEY, false).toBool();
|
2019-05-10 16:58:30 +02:00
|
|
|
d->m_detection = autoDetect ? AutoDetection : ManualDetection;
|
2021-07-12 14:19:23 +02:00
|
|
|
d->m_detectionSource = data.value(DETECTION_SOURCE_KEY).toString();
|
2009-02-10 15:34:25 +01:00
|
|
|
|
2022-01-20 16:53:55 +01:00
|
|
|
d->m_explicitCodeModelTargetTriple = data.value(CODE_MODEL_TRIPLE_KEY).toString();
|
|
|
|
|
|
2017-01-23 16:30:06 +01:00
|
|
|
if (data.contains(LANGUAGE_KEY_V2)) {
|
|
|
|
|
// remove hack to trim language id in 4.4: This is to fix up broken language
|
|
|
|
|
// ids that happened in 4.3 master branch
|
2023-08-24 16:14:26 +02:00
|
|
|
const QString langId = data.value(LANGUAGE_KEY_V2).toString();
|
2017-01-23 16:30:06 +01:00
|
|
|
const int pos = langId.lastIndexOf('.');
|
|
|
|
|
if (pos >= 0)
|
2023-07-07 14:34:35 +02:00
|
|
|
d->m_language = Id::fromString(langId.mid(pos + 1));
|
2017-01-23 16:30:06 +01:00
|
|
|
else
|
2023-07-07 14:34:35 +02:00
|
|
|
d->m_language = Id::fromString(langId);
|
2021-04-30 10:11:16 +02:00
|
|
|
} else if (data.contains(LANGUAGE_KEY_V1)) { // Import from old settings
|
2023-08-24 16:14:26 +02:00
|
|
|
d->m_language = Internal::fromLanguageV1(data.value(LANGUAGE_KEY_V1).toInt());
|
2017-01-23 16:30:06 +01:00
|
|
|
}
|
2016-12-16 00:43:14 +01:00
|
|
|
|
|
|
|
|
if (!d->m_language.isValid())
|
2023-07-07 14:34:35 +02:00
|
|
|
d->m_language = Id(Constants::CXX_LANGUAGE_ID);
|
2016-07-12 10:22:09 +02:00
|
|
|
|
2020-11-10 14:05:58 +01:00
|
|
|
if (!d->m_targetAbiKey.isEmpty())
|
|
|
|
|
d->m_targetAbi = Abi::fromString(data.value(d->m_targetAbiKey).toString());
|
|
|
|
|
|
2023-01-03 12:31:52 +01:00
|
|
|
d->m_compilerCommand = FilePath::fromSettings(data.value(d->m_compilerCommandKey));
|
2022-09-29 13:07:41 +02:00
|
|
|
d->m_isValid.reset();
|
2023-07-21 19:15:02 +02:00
|
|
|
}
|
2020-11-13 09:39:32 +01:00
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
void Toolchain::reportError()
|
2023-07-21 19:15:02 +02:00
|
|
|
{
|
|
|
|
|
d->m_hasError = true;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
bool Toolchain::hasError() const
|
2023-07-21 19:15:02 +02:00
|
|
|
{
|
|
|
|
|
return d->m_hasError;
|
2009-12-09 13:54:46 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
const Toolchain::HeaderPathsCache &Toolchain::headerPathsCache() const
|
2019-05-09 11:24:54 +02:00
|
|
|
{
|
|
|
|
|
return d->m_headerPathsCache;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
const Toolchain::MacrosCache &Toolchain::predefinedMacrosCache() const
|
2019-05-09 11:24:54 +02:00
|
|
|
{
|
|
|
|
|
return d->m_predefinedMacrosCache;
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-27 10:18:44 +02:00
|
|
|
static long toLanguageVersionAsLong(QByteArray dateAsByteArray)
|
|
|
|
|
{
|
2022-04-25 12:02:56 +03:00
|
|
|
if (dateAsByteArray.endsWith('L'))
|
|
|
|
|
dateAsByteArray.chop(1); // Strip 'L'.
|
2018-11-26 12:22:57 +01:00
|
|
|
|
|
|
|
|
bool success = false;
|
|
|
|
|
const int result = dateAsByteArray.toLong(&success);
|
|
|
|
|
QTC_CHECK(success);
|
|
|
|
|
|
|
|
|
|
return result;
|
2018-09-27 10:18:44 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
LanguageVersion Toolchain::cxxLanguageVersion(const QByteArray &cplusplusMacroValue)
|
2018-09-27 10:18:44 +02:00
|
|
|
{
|
|
|
|
|
const long version = toLanguageVersionAsLong(cplusplusMacroValue);
|
|
|
|
|
|
|
|
|
|
if (version > 201703L)
|
2018-10-08 09:49:02 +02:00
|
|
|
return LanguageVersion::LatestCxx;
|
2018-10-09 09:16:26 +02:00
|
|
|
if (version > 201402L)
|
|
|
|
|
return LanguageVersion::CXX17;
|
|
|
|
|
if (version > 201103L)
|
|
|
|
|
return LanguageVersion::CXX14;
|
|
|
|
|
if (version == 201103L)
|
|
|
|
|
return LanguageVersion::CXX11;
|
|
|
|
|
|
|
|
|
|
return LanguageVersion::CXX03;
|
2018-09-27 10:18:44 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
LanguageVersion Toolchain::languageVersion(const Id &language, const Macros ¯os)
|
2018-09-27 10:18:44 +02:00
|
|
|
{
|
|
|
|
|
if (language == Constants::CXX_LANGUAGE_ID) {
|
|
|
|
|
for (const ProjectExplorer::Macro ¯o : macros) {
|
|
|
|
|
if (macro.key == "__cplusplus") // Check for the C++ identifying macro
|
|
|
|
|
return cxxLanguageVersion(macro.value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QTC_CHECK(false && "__cplusplus is not predefined, assuming latest C++ we support.");
|
2018-10-08 09:49:02 +02:00
|
|
|
return LanguageVersion::LatestCxx;
|
2018-09-27 10:18:44 +02:00
|
|
|
} else if (language == Constants::C_LANGUAGE_ID) {
|
|
|
|
|
for (const ProjectExplorer::Macro ¯o : macros) {
|
|
|
|
|
if (macro.key == "__STDC_VERSION__") {
|
|
|
|
|
const long version = toLanguageVersionAsLong(macro.value);
|
|
|
|
|
|
|
|
|
|
if (version > 201710L)
|
2018-10-08 09:49:02 +02:00
|
|
|
return LanguageVersion::LatestC;
|
2018-10-09 09:16:26 +02:00
|
|
|
if (version > 201112L)
|
|
|
|
|
return LanguageVersion::C18;
|
|
|
|
|
if (version > 199901L)
|
|
|
|
|
return LanguageVersion::C11;
|
|
|
|
|
if (version > 199409L)
|
|
|
|
|
return LanguageVersion::C99;
|
|
|
|
|
|
|
|
|
|
return LanguageVersion::C89;
|
2018-09-27 10:18:44 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The __STDC_VERSION__ macro was introduced after C89.
|
|
|
|
|
// We haven't seen it, so it must be C89.
|
|
|
|
|
return LanguageVersion::C89;
|
|
|
|
|
} else {
|
|
|
|
|
QTC_CHECK(false && "Unexpected toolchain language, assuming latest C++ we support.");
|
2018-10-08 09:49:02 +02:00
|
|
|
return LanguageVersion::LatestCxx;
|
2018-09-27 10:18:44 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
FilePath Toolchain::correspondingCompilerCommand(Utils::Id otherLanguage) const
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(language() != otherLanguage, return compilerCommand());
|
|
|
|
|
return factory()->correspondingCompilerCommand(compilerCommand(), otherLanguage);
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
FilePaths Toolchain::includedFiles(const QString &option,
|
2022-11-25 14:06:47 +01:00
|
|
|
const QStringList &flags,
|
|
|
|
|
const FilePath &directoryPath,
|
|
|
|
|
PossiblyConcatenatedFlag possiblyConcatenated)
|
2018-06-11 12:52:04 +02:00
|
|
|
{
|
2022-11-25 14:06:47 +01:00
|
|
|
FilePaths result;
|
2018-06-11 12:52:04 +02:00
|
|
|
|
|
|
|
|
for (int i = 0; i < flags.size(); ++i) {
|
2022-10-11 09:24:46 +03:00
|
|
|
QString includeFile;
|
|
|
|
|
const QString flag = flags[i];
|
|
|
|
|
if (possiblyConcatenated == PossiblyConcatenatedFlag::Yes
|
|
|
|
|
&& flag.startsWith(option)
|
|
|
|
|
&& flag.size() > option.size()) {
|
|
|
|
|
includeFile = flag.mid(option.size());
|
|
|
|
|
}
|
|
|
|
|
if (includeFile.isEmpty() && flag == option && i + 1 < flags.size())
|
|
|
|
|
includeFile = flags[++i];
|
|
|
|
|
|
2022-11-25 14:06:47 +01:00
|
|
|
if (!includeFile.isEmpty())
|
|
|
|
|
result.append(directoryPath.resolvePath(includeFile));
|
2018-06-11 12:52:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-21 12:27:18 +01:00
|
|
|
/*!
|
2013-09-10 17:16:10 +02:00
|
|
|
Used by the tool chain kit information to validate the kit.
|
2013-03-21 12:27:18 +01:00
|
|
|
*/
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
Tasks Toolchain::validateKit(const Kit *) const
|
2013-03-21 12:27:18 +01:00
|
|
|
{
|
2019-05-27 16:09:44 +02:00
|
|
|
return {};
|
2013-03-21 12:27:18 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
QString Toolchain::sysRoot() const
|
2019-01-07 12:15:40 +01:00
|
|
|
{
|
2023-08-01 20:52:58 +02:00
|
|
|
return {};
|
2019-01-07 12:15:40 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
QString Toolchain::explicitCodeModelTargetTriple() const
|
2022-01-20 16:53:55 +01:00
|
|
|
{
|
|
|
|
|
return d->m_explicitCodeModelTargetTriple;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
QString Toolchain::effectiveCodeModelTargetTriple() const
|
2022-01-20 16:53:55 +01:00
|
|
|
{
|
|
|
|
|
const QString overridden = explicitCodeModelTargetTriple();
|
|
|
|
|
if (!overridden.isEmpty())
|
|
|
|
|
return overridden;
|
|
|
|
|
return originalTargetTriple();
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
void Toolchain::setExplicitCodeModelTargetTriple(const QString &triple)
|
2022-01-20 16:53:55 +01:00
|
|
|
{
|
|
|
|
|
d->m_explicitCodeModelTargetTriple = triple;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-14 12:58:14 +02:00
|
|
|
/*!
|
2023-11-27 17:09:08 +01:00
|
|
|
\class ProjectExplorer::ToolchainFactory
|
|
|
|
|
\brief The ToolchainFactory class creates tool chains from settings or
|
2013-09-10 17:16:10 +02:00
|
|
|
autodetects them.
|
2011-04-14 12:58:14 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*!
|
2023-11-27 17:09:08 +01:00
|
|
|
\fn QString ProjectExplorer::ToolchainFactory::displayName() const = 0
|
2013-09-10 17:16:10 +02:00
|
|
|
Contains the name used to display the name of the tool chain that will be
|
|
|
|
|
created.
|
2011-04-14 12:58:14 +02:00
|
|
|
*/
|
|
|
|
|
|
2013-03-03 21:53:38 +04:00
|
|
|
/*!
|
2023-11-27 17:09:08 +01:00
|
|
|
\fn QStringList ProjectExplorer::Toolchain::clangParserFlags(const QStringList &cxxflags) const = 0
|
2013-09-10 17:16:10 +02:00
|
|
|
Converts tool chain specific flags to list flags that tune the libclang
|
|
|
|
|
parser.
|
2013-03-03 21:53:38 +04:00
|
|
|
*/
|
|
|
|
|
|
2011-04-14 12:58:14 +02:00
|
|
|
/*!
|
2023-11-27 17:09:08 +01:00
|
|
|
\fn bool ProjectExplorer::ToolchainFactory::canRestore(const Store &data)
|
2013-09-10 17:16:10 +02:00
|
|
|
Used by the tool chain manager to restore user-generated tool chains.
|
2011-04-14 12:58:14 +02:00
|
|
|
*/
|
2009-03-16 18:13:45 +01:00
|
|
|
|
2023-11-22 14:39:32 +01:00
|
|
|
ToolchainFactory::ToolchainFactory()
|
2017-12-08 17:20:48 +01:00
|
|
|
{
|
2023-11-22 14:39:32 +01:00
|
|
|
toolchainFactories().append(this);
|
2017-12-08 17:20:48 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-22 14:39:32 +01:00
|
|
|
ToolchainFactory::~ToolchainFactory()
|
2017-12-08 17:20:48 +01:00
|
|
|
{
|
2023-11-22 14:39:32 +01:00
|
|
|
toolchainFactories().removeOne(this);
|
2017-12-08 17:20:48 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-22 14:39:32 +01:00
|
|
|
const QList<ToolchainFactory *> ToolchainFactory::allToolchainFactories()
|
2017-12-08 17:20:48 +01:00
|
|
|
{
|
2023-11-22 14:39:32 +01:00
|
|
|
return toolchainFactories();
|
2017-12-08 17:20:48 +01:00
|
|
|
}
|
|
|
|
|
|
2024-07-11 13:03:12 +02:00
|
|
|
ToolchainFactory *ToolchainFactory::factoryForType(Id typeId)
|
|
|
|
|
{
|
|
|
|
|
return Utils::findOrDefault(allToolchainFactories(), [typeId](ToolchainFactory *factory) {
|
|
|
|
|
return factory->supportedToolchainType() == typeId;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-22 14:39:32 +01:00
|
|
|
Toolchains ToolchainFactory::autoDetect(const ToolchainDetector &detector) const
|
2009-02-10 15:34:25 +01:00
|
|
|
{
|
2022-01-14 17:29:02 +01:00
|
|
|
Q_UNUSED(detector)
|
2019-07-02 11:31:12 +02:00
|
|
|
return {};
|
2010-03-04 15:23:02 +01:00
|
|
|
}
|
2009-02-10 15:34:25 +01:00
|
|
|
|
2023-11-27 17:09:08 +01:00
|
|
|
Toolchains ToolchainFactory::detectForImport(const ToolchainDescription &tcd) const
|
2017-02-07 13:13:06 +01:00
|
|
|
{
|
2019-07-02 11:31:12 +02:00
|
|
|
Q_UNUSED(tcd)
|
|
|
|
|
return {};
|
2017-02-07 13:13:06 +01:00
|
|
|
}
|
|
|
|
|
|
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
|
|
|
FilePath ToolchainFactory::correspondingCompilerCommand(
|
|
|
|
|
const Utils::FilePath &srcPath, Utils::Id targetLang) const
|
|
|
|
|
{
|
|
|
|
|
Q_UNUSED(targetLang)
|
|
|
|
|
return srcPath;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-22 14:39:32 +01:00
|
|
|
bool ToolchainFactory::canCreate() const
|
2010-03-04 15:23:02 +01:00
|
|
|
{
|
2019-05-10 18:22:58 +02:00
|
|
|
return m_userCreatable;
|
2009-02-10 15:34:25 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
Toolchain *ToolchainFactory::create() const
|
2009-02-10 15:34:25 +01:00
|
|
|
{
|
2019-05-10 17:35:04 +02:00
|
|
|
return m_toolchainConstructor ? m_toolchainConstructor() : nullptr;
|
2009-02-10 15:34:25 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
Toolchain *ToolchainFactory::restore(const Store &data)
|
2009-02-10 15:34:25 +01:00
|
|
|
{
|
2019-05-10 17:35:04 +02:00
|
|
|
if (!m_toolchainConstructor)
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
Toolchain *tc = m_toolchainConstructor();
|
2019-05-10 17:35:04 +02:00
|
|
|
QTC_ASSERT(tc, return nullptr);
|
|
|
|
|
|
2023-07-21 19:15:02 +02:00
|
|
|
tc->fromMap(data);
|
|
|
|
|
if (!tc->hasError())
|
2019-05-10 17:35:04 +02:00
|
|
|
return tc;
|
|
|
|
|
|
|
|
|
|
delete tc;
|
2016-04-13 15:52:14 +02:00
|
|
|
return nullptr;
|
2009-02-10 15:34:25 +01:00
|
|
|
}
|
|
|
|
|
|
2023-08-24 12:41:45 +02:00
|
|
|
static QPair<QString, QString> rawIdData(const Store &data)
|
2015-07-07 14:20:12 +02:00
|
|
|
{
|
2023-08-24 16:14:26 +02:00
|
|
|
const QString raw = data.value(ID_KEY).toString();
|
2015-07-07 14:20:12 +02:00
|
|
|
const int pos = raw.indexOf(QLatin1Char(':'));
|
|
|
|
|
QTC_ASSERT(pos > 0, return qMakePair(QString::fromLatin1("unknown"), QString::fromLatin1("unknown")));
|
2022-09-30 15:57:27 +02:00
|
|
|
return {raw.mid(0, pos), raw.mid(pos + 1)};
|
2015-07-07 14:20:12 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-22 14:39:32 +01:00
|
|
|
QByteArray ToolchainFactory::idFromMap(const Store &data)
|
2009-02-10 15:34:25 +01:00
|
|
|
{
|
2015-07-07 14:20:12 +02:00
|
|
|
return rawIdData(data).second.toUtf8();
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-22 14:39:32 +01:00
|
|
|
Id ToolchainFactory::typeIdFromMap(const Store &data)
|
2015-07-07 14:20:12 +02:00
|
|
|
{
|
2023-07-07 14:34:35 +02:00
|
|
|
return Id::fromString(rawIdData(data).first);
|
2009-02-10 15:34:25 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-22 14:39:32 +01:00
|
|
|
void ToolchainFactory::autoDetectionToMap(Store &data, bool detected)
|
2012-06-20 15:45:37 +02:00
|
|
|
{
|
2023-08-24 16:14:26 +02:00
|
|
|
data.insert(AUTODETECT_KEY, detected);
|
2012-06-20 15:45:37 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-27 17:09:08 +01:00
|
|
|
Toolchain *ToolchainFactory::createToolchain(Id toolchainType)
|
2019-06-14 12:06:26 +02:00
|
|
|
{
|
2023-11-22 14:39:32 +01:00
|
|
|
for (ToolchainFactory *factory : std::as_const(toolchainFactories())) {
|
2023-11-27 17:09:08 +01:00
|
|
|
if (factory->m_supportedToolchainType == toolchainType) {
|
2023-11-24 15:53:31 +01:00
|
|
|
if (Toolchain *tc = factory->create()) {
|
2023-11-27 17:09:08 +01:00
|
|
|
tc->d->m_typeId = toolchainType;
|
2019-06-14 12:06:26 +02:00
|
|
|
return tc;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-22 14:39:32 +01:00
|
|
|
QList<Id> ToolchainFactory::supportedLanguages() const
|
2019-05-08 15:36:57 +02:00
|
|
|
{
|
2024-07-30 12:57:29 +02:00
|
|
|
return m_supportedLanguages;
|
2019-05-08 15:36:57 +02:00
|
|
|
}
|
|
|
|
|
|
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 ToolchainFactory::languageCategory() const
|
|
|
|
|
{
|
|
|
|
|
const QList<Id> langs = supportedLanguages();
|
|
|
|
|
if (langs.size() == 1
|
|
|
|
|
&& (langs.first() == Constants::C_LANGUAGE_ID
|
|
|
|
|
|| langs.first() == Constants::CXX_LANGUAGE_ID)) {
|
|
|
|
|
return {Constants::C_LANGUAGE_ID, Constants::CXX_LANGUAGE_ID};
|
|
|
|
|
}
|
|
|
|
|
return LanguageCategory(langs.cbegin(), langs.cend());
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-27 17:09:08 +01:00
|
|
|
Id ToolchainFactory::supportedToolchainType() const
|
2019-05-08 14:56:26 +02:00
|
|
|
{
|
2023-11-27 17:09:08 +01:00
|
|
|
return m_supportedToolchainType;
|
2019-05-08 14:56:26 +02:00
|
|
|
}
|
|
|
|
|
|
2024-01-02 09:05:37 +01:00
|
|
|
std::optional<AsyncToolchainDetector> ToolchainFactory::asyncAutoDetector(
|
|
|
|
|
const ToolchainDetector &) const
|
|
|
|
|
{
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-27 17:09:08 +01:00
|
|
|
void ToolchainFactory::setSupportedToolchainType(const Id &supportedToolchainType)
|
2019-05-08 14:56:26 +02:00
|
|
|
{
|
2023-11-27 17:09:08 +01:00
|
|
|
m_supportedToolchainType = supportedToolchainType;
|
2019-05-08 14:56:26 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-22 14:39:32 +01:00
|
|
|
void ToolchainFactory::setSupportedLanguages(const QList<Id> &supportedLanguages)
|
2019-05-08 15:36:57 +02:00
|
|
|
{
|
|
|
|
|
m_supportedLanguages = supportedLanguages;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-27 17:09:08 +01:00
|
|
|
void ToolchainFactory::setToolchainConstructor(const ToolchainConstructor &toolchainContructor)
|
2019-05-10 17:35:04 +02:00
|
|
|
{
|
|
|
|
|
m_toolchainConstructor = toolchainContructor;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-27 17:09:08 +01:00
|
|
|
ToolchainFactory::ToolchainConstructor ToolchainFactory::toolchainConstructor() const
|
2023-09-15 11:54:47 +02:00
|
|
|
{
|
|
|
|
|
return m_toolchainConstructor;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-22 14:39:32 +01:00
|
|
|
void ToolchainFactory::setUserCreatable(bool userCreatable)
|
2019-05-10 18:22:58 +02:00
|
|
|
{
|
|
|
|
|
m_userCreatable = userCreatable;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-14 16:37:57 +01:00
|
|
|
ToolchainDetector::ToolchainDetector(const Toolchains &alreadyKnown,
|
|
|
|
|
const IDevice::ConstPtr &device,
|
|
|
|
|
const FilePaths &searchPaths)
|
|
|
|
|
: alreadyKnown(alreadyKnown), device(device), searchPaths(searchPaths)
|
2023-04-17 10:12:53 +02:00
|
|
|
{
|
|
|
|
|
QTC_CHECK(device);
|
|
|
|
|
}
|
2022-01-14 17:29:02 +01:00
|
|
|
|
2023-07-07 14:34:35 +02:00
|
|
|
BadToolchain::BadToolchain(const FilePath &filePath)
|
2022-01-18 15:42:02 +01:00
|
|
|
: BadToolchain(filePath, filePath.symLinkTarget(), filePath.lastModified())
|
|
|
|
|
{}
|
|
|
|
|
|
2023-07-07 14:34:35 +02:00
|
|
|
BadToolchain::BadToolchain(const FilePath &filePath, const FilePath &symlinkTarget,
|
2022-01-18 15:42:02 +01:00
|
|
|
const QDateTime ×tamp)
|
|
|
|
|
: filePath(filePath), symlinkTarget(symlinkTarget), timestamp(timestamp)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
|
2023-08-24 16:14:26 +02:00
|
|
|
static Key badToolchainFilePathKey() { return {"FilePath"}; }
|
|
|
|
|
static Key badToolchainSymlinkTargetKey() { return {"TargetFilePath"}; }
|
|
|
|
|
static Key badToolchainTimestampKey() { return {"Timestamp"}; }
|
2022-01-18 15:42:02 +01:00
|
|
|
|
2023-08-24 12:41:45 +02:00
|
|
|
Store BadToolchain::toMap() const
|
2022-01-18 15:42:02 +01:00
|
|
|
{
|
2023-01-03 12:31:52 +01:00
|
|
|
return {{badToolchainFilePathKey(), filePath.toSettings()},
|
|
|
|
|
{badToolchainSymlinkTargetKey(), symlinkTarget.toSettings()},
|
2022-09-30 15:17:36 +02:00
|
|
|
{badToolchainTimestampKey(), timestamp.toMSecsSinceEpoch()}};
|
2022-01-18 15:42:02 +01:00
|
|
|
}
|
|
|
|
|
|
2023-08-23 16:53:06 +02:00
|
|
|
BadToolchain BadToolchain::fromMap(const Store &map)
|
2022-01-18 15:42:02 +01:00
|
|
|
{
|
|
|
|
|
return {
|
2023-01-03 12:31:52 +01:00
|
|
|
FilePath::fromSettings(map.value(badToolchainFilePathKey())),
|
|
|
|
|
FilePath::fromSettings(map.value(badToolchainSymlinkTargetKey())),
|
2022-01-18 15:42:02 +01:00
|
|
|
QDateTime::fromMSecsSinceEpoch(map.value(badToolchainTimestampKey()).toLongLong())
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BadToolchains::BadToolchains(const QList<BadToolchain> &toolchains)
|
|
|
|
|
: toolchains(Utils::filtered(toolchains, [](const BadToolchain &badTc) {
|
|
|
|
|
return badTc.filePath.lastModified() == badTc.timestamp
|
|
|
|
|
&& badTc.filePath.symLinkTarget() == badTc.symlinkTarget;
|
|
|
|
|
}))
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
bool BadToolchains::isBadToolchain(const FilePath &toolchain) const
|
|
|
|
|
{
|
|
|
|
|
return Utils::contains(toolchains, [toolchain](const BadToolchain &badTc) {
|
|
|
|
|
return badTc.filePath == toolchain.absoluteFilePath()
|
|
|
|
|
|| badTc.symlinkTarget == toolchain.absoluteFilePath();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QVariant BadToolchains::toVariant() const
|
|
|
|
|
{
|
2023-08-24 16:14:26 +02:00
|
|
|
return Utils::transform<QVariantList>(toolchains, [](const BadToolchain &bdc) {
|
2023-08-28 10:55:31 +02:00
|
|
|
return variantFromStore(bdc.toMap());
|
2023-08-24 16:14:26 +02:00
|
|
|
});
|
2022-01-18 15:42:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BadToolchains BadToolchains::fromVariant(const QVariant &v)
|
|
|
|
|
{
|
|
|
|
|
return Utils::transform<QList<BadToolchain>>(v.toList(),
|
2023-08-28 10:55:31 +02:00
|
|
|
[](const QVariant &e) { return BadToolchain::fromMap(storeFromVariant(e)); });
|
2022-01-18 15:42:02 +01:00
|
|
|
}
|
|
|
|
|
|
2024-01-02 09:05:37 +01:00
|
|
|
AsyncToolchainDetector::AsyncToolchainDetector(
|
|
|
|
|
const ToolchainDetector &detector,
|
|
|
|
|
const std::function<Toolchains(const ToolchainDetector &)> &func,
|
|
|
|
|
const std::function<bool(const Toolchain *, const Toolchains &)> &alreadyRegistered)
|
|
|
|
|
: m_detector(detector)
|
|
|
|
|
, m_func(func)
|
|
|
|
|
, m_alreadyRegistered(alreadyRegistered)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AsyncToolchainDetector::run()
|
|
|
|
|
{
|
|
|
|
|
auto watcher = new QFutureWatcher<Toolchains>();
|
|
|
|
|
QObject::connect(watcher,
|
|
|
|
|
&QFutureWatcher<Toolchains>::finished,
|
|
|
|
|
[watcher,
|
|
|
|
|
alreadyRegistered = m_alreadyRegistered]() {
|
|
|
|
|
Toolchains existingTcs = ToolchainManager::toolchains();
|
2024-07-18 11:10:24 +02:00
|
|
|
Toolchains toRegister;
|
2024-01-02 09:05:37 +01:00
|
|
|
for (Toolchain *tc : watcher->result()) {
|
|
|
|
|
if (tc->isValid() && !alreadyRegistered(tc, existingTcs)) {
|
2024-07-18 11:10:24 +02:00
|
|
|
toRegister << tc;
|
2024-01-02 09:05:37 +01:00
|
|
|
existingTcs << tc;
|
|
|
|
|
} else {
|
|
|
|
|
delete tc;
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-07-18 11:10:24 +02:00
|
|
|
ToolchainManager::registerToolchains(toRegister);
|
2024-01-02 09:05:37 +01:00
|
|
|
watcher->deleteLater();
|
|
|
|
|
});
|
|
|
|
|
watcher->setFuture(Utils::asyncRun(m_func, m_detector));
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
/*
|
|
|
|
|
* PRE:
|
|
|
|
|
* - The list of toolchains is not empty.
|
|
|
|
|
* - All toolchains in the list have the same bundle id.
|
|
|
|
|
* - All toolchains in the list have the same type (and thus were created by the same factory)
|
|
|
|
|
* and are also otherwise "compatible" (target ABI etc).
|
|
|
|
|
* - No two toolchains in the list are for the same language.
|
|
|
|
|
* POST:
|
|
|
|
|
* - PRE.
|
|
|
|
|
* - There is exactly one toolchain in the list for every language supported by the factory.
|
|
|
|
|
* - If there is a C compiler, it comes first in the list.
|
|
|
|
|
*/
|
|
|
|
|
ToolchainBundle::ToolchainBundle(const Toolchains &toolchains) : m_toolchains(toolchains)
|
|
|
|
|
{
|
|
|
|
|
// Check pre-conditions.
|
|
|
|
|
QTC_ASSERT(!m_toolchains.isEmpty(), return);
|
|
|
|
|
QTC_ASSERT(m_toolchains.size() <= factory()->supportedLanguages().size(), return);
|
|
|
|
|
for (const Toolchain * const tc : toolchains)
|
|
|
|
|
QTC_ASSERT(factory()->supportedLanguages().contains(tc->language()), return);
|
|
|
|
|
for (int i = 1; i < int(toolchains.size()); ++i) {
|
|
|
|
|
const Toolchain * const tc = toolchains.at(i);
|
|
|
|
|
QTC_ASSERT(tc->typeId() == toolchains.first()->typeId(), return);
|
|
|
|
|
QTC_ASSERT(tc->bundleId() == toolchains.first()->bundleId(), return);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addMissingToolchains();
|
|
|
|
|
|
|
|
|
|
// Check post-conditions.
|
|
|
|
|
QTC_ASSERT(m_toolchains.size() == m_toolchains.first()->factory()->supportedLanguages().size(),
|
|
|
|
|
return);
|
|
|
|
|
for (auto i = toolchains.size(); i < m_toolchains.size(); ++i)
|
|
|
|
|
QTC_ASSERT(m_toolchains.at(i)->typeId() == m_toolchains.first()->typeId(), return);
|
|
|
|
|
|
|
|
|
|
Utils::sort(m_toolchains, [](const Toolchain *tc1, const Toolchain *tc2) {
|
|
|
|
|
return tc1 != tc2 && tc1->language() == Constants::C_LANGUAGE_ID;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QList<ToolchainBundle> ToolchainBundle::collectBundles()
|
|
|
|
|
{
|
|
|
|
|
return collectBundles(ToolchainManager::toolchains());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QList<ToolchainBundle> ToolchainBundle::collectBundles(const Toolchains &toolchains)
|
|
|
|
|
{
|
|
|
|
|
QHash<Id, Toolchains> toolchainsPerBundleId;
|
|
|
|
|
for (Toolchain * const tc : toolchains)
|
|
|
|
|
toolchainsPerBundleId[tc->bundleId()] << tc;
|
|
|
|
|
|
|
|
|
|
QList<ToolchainBundle> bundles;
|
|
|
|
|
if (const auto unbundled = toolchainsPerBundleId.constFind(Id());
|
|
|
|
|
unbundled != toolchainsPerBundleId.constEnd()) {
|
|
|
|
|
bundles = bundleUnbundledToolchains(*unbundled);
|
|
|
|
|
toolchainsPerBundleId.erase(unbundled);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const Toolchains &tcs : toolchainsPerBundleId)
|
|
|
|
|
bundles << tcs;
|
|
|
|
|
return bundles;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ToolchainFactory *ToolchainBundle::factory() const
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(!m_toolchains.isEmpty(), return nullptr);
|
|
|
|
|
return m_toolchains.first()->factory();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString ToolchainBundle::displayName() const
|
|
|
|
|
{
|
|
|
|
|
if (!isAutoDetected() || !dynamic_cast<GccToolchain *>(m_toolchains.first()))
|
|
|
|
|
return get(&Toolchain::displayName);
|
|
|
|
|
|
|
|
|
|
// Auto-detected GCC toolchains encode language and compiler command in their display names.
|
|
|
|
|
// We need to omit the language and we always want to use the C compiler command
|
|
|
|
|
// for consistency.
|
|
|
|
|
FilePath cmd;
|
|
|
|
|
for (const Toolchain * const tc : std::as_const(m_toolchains)) {
|
|
|
|
|
if (!tc->isValid())
|
|
|
|
|
continue;
|
|
|
|
|
cmd = tc->compilerCommand();
|
|
|
|
|
if (tc->language() == Constants::C_LANGUAGE_ID)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString name = typeDisplayName();
|
|
|
|
|
const Abi abi = targetAbi();
|
|
|
|
|
if (abi.architecture() != Abi::UnknownArchitecture)
|
|
|
|
|
name.append(' ').append(Abi::toString(abi.architecture()));
|
|
|
|
|
if (abi.wordWidth() != 0)
|
|
|
|
|
name.append(' ').append(Abi::toString(abi.wordWidth()));
|
|
|
|
|
if (!cmd.exists())
|
|
|
|
|
return name;
|
|
|
|
|
return Tr::tr("%1 at %2").arg(name, cmd.toUserOutput());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ToolchainBundle::Valid ToolchainBundle::validity() const
|
|
|
|
|
{
|
|
|
|
|
if (Utils::allOf(m_toolchains, &Toolchain::isValid))
|
|
|
|
|
return Valid::All;
|
|
|
|
|
if (Utils::contains(m_toolchains, &Toolchain::isValid))
|
|
|
|
|
return Valid::Some;
|
|
|
|
|
return Valid::None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QList<ToolchainBundle> ToolchainBundle::bundleUnbundledToolchains(const Toolchains &unbundled)
|
|
|
|
|
{
|
|
|
|
|
QList<ToolchainBundle> bundles;
|
|
|
|
|
QHash<Id, QHash<Id, Toolchains>> unbundledByTypeAndLanguage;
|
|
|
|
|
for (Toolchain * const tc : unbundled)
|
|
|
|
|
unbundledByTypeAndLanguage[tc->typeId()][tc->language()] << tc;
|
|
|
|
|
for (const auto &tcsByLang : std::as_const(unbundledByTypeAndLanguage)) {
|
|
|
|
|
QList<Toolchains> remainingUnbundled;
|
|
|
|
|
for (const auto &tcs : tcsByLang)
|
|
|
|
|
remainingUnbundled << tcs;
|
|
|
|
|
while (true) {
|
|
|
|
|
Toolchains nextBundle;
|
|
|
|
|
for (Toolchains &list : remainingUnbundled) {
|
|
|
|
|
for (auto it = list.begin(); it != list.end(); ++it) {
|
|
|
|
|
if (nextBundle.isEmpty() || nextBundle.first()->canShareBundle((**it))) {
|
|
|
|
|
nextBundle << *it;
|
|
|
|
|
list.erase(it);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (nextBundle.isEmpty())
|
|
|
|
|
break;
|
|
|
|
|
const Id newBundleId = Id::generate();
|
|
|
|
|
for (Toolchain * const tc : nextBundle)
|
|
|
|
|
tc->setBundleId(newBundleId);
|
|
|
|
|
bundles << nextBundle;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return bundles;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ToolchainBundle::setCompilerCommand(Utils::Id language, const Utils::FilePath &cmd)
|
|
|
|
|
{
|
|
|
|
|
for (Toolchain *const tc : std::as_const(m_toolchains)) {
|
|
|
|
|
if (tc->language() == language) {
|
|
|
|
|
tc->setCompilerCommand(cmd);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FilePath ToolchainBundle::compilerCommand(Utils::Id language) const
|
|
|
|
|
{
|
|
|
|
|
for (Toolchain *const tc : std::as_const(m_toolchains)) {
|
|
|
|
|
if (tc->language() == language)
|
|
|
|
|
return tc->compilerCommand();
|
|
|
|
|
}
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ToolchainBundle::deleteToolchains()
|
|
|
|
|
{
|
|
|
|
|
qDeleteAll(m_toolchains);
|
|
|
|
|
m_toolchains.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ToolchainBundle ToolchainBundle::clone() const
|
|
|
|
|
{
|
|
|
|
|
const Toolchains clones = Utils::transform(m_toolchains, &Toolchain::clone);
|
|
|
|
|
const Id newBundleId = Id::generate();
|
|
|
|
|
for (Toolchain * const tc : clones)
|
|
|
|
|
tc->setBundleId(newBundleId);
|
|
|
|
|
return clones;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ToolchainBundle::addMissingToolchains()
|
|
|
|
|
{
|
|
|
|
|
const QList<Id> missingLanguages
|
|
|
|
|
= Utils::filtered(m_toolchains.first()->factory()->supportedLanguages(), [this](Id lang) {
|
|
|
|
|
return !Utils::contains(m_toolchains, [lang](const Toolchain *tc) {
|
|
|
|
|
return tc->language() == lang;
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
for (const Id lang : missingLanguages) {
|
|
|
|
|
Toolchain * const tc = m_toolchains.first()->clone();
|
|
|
|
|
tc->setLanguage(lang);
|
|
|
|
|
tc->setCompilerCommand(m_toolchains.first()->correspondingCompilerCommand(lang));
|
|
|
|
|
m_toolchains << tc;
|
|
|
|
|
m_createdToolchains << tc;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-01 18:36:00 +01:00
|
|
|
} // namespace ProjectExplorer
|