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
|
2016-08-25 14:33:44 +02:00
|
|
|
|
|
|
|
|
#include "cmakeprojectimporter.h"
|
|
|
|
|
|
|
|
|
|
#include "cmakebuildconfiguration.h"
|
2023-08-21 17:20:02 +02:00
|
|
|
#include "cmakekitaspect.h"
|
2023-05-09 18:22:47 +02:00
|
|
|
#include "cmakeproject.h"
|
2020-12-02 19:16:40 +01:00
|
|
|
#include "cmakeprojectconstants.h"
|
2022-09-29 15:26:31 +02:00
|
|
|
#include "cmakeprojectmanagertr.h"
|
2016-08-25 14:33:44 +02:00
|
|
|
#include "cmaketoolmanager.h"
|
2022-05-30 19:04:54 +02:00
|
|
|
#include "presetsmacros.h"
|
2016-08-25 14:33:44 +02:00
|
|
|
|
2020-12-02 19:16:40 +01:00
|
|
|
#include <coreplugin/messagemanager.h>
|
|
|
|
|
|
2019-01-29 16:51:17 +01:00
|
|
|
#include <projectexplorer/buildinfo.h>
|
2023-08-11 09:18:56 +02:00
|
|
|
#include <projectexplorer/kitaspects.h>
|
2016-08-25 14:33:44 +02:00
|
|
|
#include <projectexplorer/projectexplorerconstants.h>
|
2023-05-09 18:22:47 +02:00
|
|
|
#include <projectexplorer/target.h>
|
2020-12-09 12:41:11 +01:00
|
|
|
#include <projectexplorer/toolchainmanager.h>
|
2016-08-25 14:33:44 +02:00
|
|
|
|
2023-08-11 11:23:12 +02:00
|
|
|
#include <qtsupport/qtkitaspect.h>
|
2016-08-25 14:33:44 +02:00
|
|
|
|
|
|
|
|
#include <utils/algorithm.h>
|
2023-05-03 17:05:35 +02:00
|
|
|
#include <utils/process.h>
|
2016-08-25 14:33:44 +02:00
|
|
|
#include <utils/qtcassert.h>
|
2020-08-18 11:34:44 +01:00
|
|
|
#include <utils/stringutils.h>
|
2022-07-08 17:07:33 +02:00
|
|
|
#include <utils/temporarydirectory.h>
|
2016-08-25 14:33:44 +02:00
|
|
|
|
2022-05-30 19:04:54 +02:00
|
|
|
#include <QApplication>
|
2016-08-25 14:33:44 +02:00
|
|
|
#include <QLoggingCategory>
|
|
|
|
|
|
|
|
|
|
using namespace ProjectExplorer;
|
|
|
|
|
using namespace QtSupport;
|
2019-05-17 13:28:38 +02:00
|
|
|
using namespace Utils;
|
2016-08-25 14:33:44 +02:00
|
|
|
|
2022-09-26 14:21:12 +02:00
|
|
|
namespace CMakeProjectManager::Internal {
|
2016-08-25 14:33:44 +02:00
|
|
|
|
2020-01-15 14:39:23 +01:00
|
|
|
static Q_LOGGING_CATEGORY(cmInputLog, "qtc.cmake.import", QtWarningMsg);
|
2016-08-25 14:33:44 +02:00
|
|
|
|
|
|
|
|
struct DirectoryData
|
|
|
|
|
{
|
|
|
|
|
// Project Stuff:
|
|
|
|
|
QByteArray cmakeBuildType;
|
2021-01-04 13:48:21 +01:00
|
|
|
FilePath buildDirectory;
|
2020-12-02 19:16:40 +01:00
|
|
|
FilePath cmakeHomeDirectory;
|
CMake: Add 'Profile' configuration
Get rid of the hardcoded QML Debugging for Debug & RelWithDebInfo from
the project template, because RelWithDebInfo is actually a good
configuration for doing releases (we use it for Qt Creator), and
enabling QML debugging for releases is a bad idea.
Instead enable QML Debugging in Qt Creator for the Debug configuration,
and add a 'Profile' configuration that is 'RelWithDebInfo + QML
Debugging'.
When importing a build, we only set the "QML debugging" option of the
build configuration, if it is enabled in the imported build, even if it
uses CMAKE_BUILD_TYPE=Debug .
One drawback: When not importing a build, but just setting the build
directory of a "Profile" or "Debug" configuration to an existing build,
Qt Creator asks if it should apply "-DCMAKE_CXX_FLAGS=-DQT_QML_DEBUG".
The user can choose not to, but then is asked the next time again, and
it is not obvious that the "QML debugging" option is responsible for
this.
That is somewhat orthogonal to this change though: Even without this
change, if the user changes the QML debugging option from "Leave at
Default" to "Enable", the same happens, and it is also not clear to the
user how to get rid of it. The user might not even have realized that
they changed the option (e.g. on platforms where the mouse wheel cycles
combo box values).
I think the correct solution is to 1. make clearer where the CMake flags
came from in that dialog, 2. allow the user to cancel a build from that
dialog, 3. allow the user to discard these changes (by changing the
setting) from that dialog. But that is for another patch.
Amends 3300182d405bffe062a0f2be900f35822a9e20b0
Amends 77fed0b0fdce2a93f465c20cd87c41900117dcda
Change-Id: I95de59473b67c5afd6a53ea7f49838dbaef770d4
Reviewed-by: Artem Sokolovskii <artem.sokolovskii@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Cristian Adam <cristian.adam@qt.io>
2022-05-18 10:40:31 +02:00
|
|
|
bool hasQmlDebugging = false;
|
2016-08-25 14:33:44 +02:00
|
|
|
|
2022-05-30 19:04:54 +02:00
|
|
|
QString cmakePresetDisplayname;
|
|
|
|
|
QString cmakePreset;
|
|
|
|
|
|
2016-08-25 14:33:44 +02:00
|
|
|
// Kit Stuff
|
2021-01-04 13:48:21 +01:00
|
|
|
FilePath cmakeBinary;
|
2021-07-06 09:50:01 +02:00
|
|
|
QString generator;
|
|
|
|
|
QString platform;
|
|
|
|
|
QString toolset;
|
|
|
|
|
FilePath sysroot;
|
2016-08-25 14:33:44 +02:00
|
|
|
QtProjectImporter::QtVersionData qt;
|
2023-12-11 11:42:00 +01:00
|
|
|
QVector<ToolchainDescription> toolchains;
|
2016-08-25 14:33:44 +02:00
|
|
|
};
|
|
|
|
|
|
2022-09-26 14:30:46 +02:00
|
|
|
static FilePaths scanDirectory(const FilePath &path, const QString &prefix)
|
2016-08-25 14:33:44 +02:00
|
|
|
{
|
2022-09-26 14:30:46 +02:00
|
|
|
FilePaths result;
|
2020-06-18 14:21:09 +02:00
|
|
|
qCDebug(cmInputLog) << "Scanning for directories matching" << prefix << "in" << path;
|
2016-08-25 14:33:44 +02:00
|
|
|
|
2022-07-21 15:58:09 +02:00
|
|
|
const FilePaths entries = path.dirEntries({{prefix + "*"}, QDir::Dirs | QDir::NoDotAndDotDot});
|
2022-05-18 12:28:04 +02:00
|
|
|
for (const FilePath &entry : entries) {
|
2021-09-09 08:27:28 +02:00
|
|
|
QTC_ASSERT(entry.isDir(), continue);
|
2022-09-26 14:30:46 +02:00
|
|
|
result.append(entry);
|
2016-08-25 14:33:44 +02:00
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-04 13:48:21 +01:00
|
|
|
static QString baseCMakeToolDisplayName(CMakeTool &tool)
|
2020-08-18 11:34:44 +01:00
|
|
|
{
|
2022-06-28 16:50:21 +02:00
|
|
|
if (!tool.isValid())
|
|
|
|
|
return QString("CMake");
|
|
|
|
|
|
2021-01-04 13:48:21 +01:00
|
|
|
CMakeTool::Version version = tool.version();
|
2020-08-18 11:34:44 +01:00
|
|
|
return QString("CMake %1.%2.%3").arg(version.major).arg(version.minor).arg(version.patch);
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-04 13:48:21 +01:00
|
|
|
static QString uniqueCMakeToolDisplayName(CMakeTool &tool)
|
2020-08-18 11:34:44 +01:00
|
|
|
{
|
|
|
|
|
QString baseName = baseCMakeToolDisplayName(tool);
|
|
|
|
|
|
|
|
|
|
QStringList existingNames;
|
2021-01-04 13:48:21 +01:00
|
|
|
for (const CMakeTool *t : CMakeToolManager::cmakeTools())
|
2020-08-18 11:34:44 +01:00
|
|
|
existingNames << t->displayName();
|
|
|
|
|
return Utils::makeUniquelyNumbered(baseName, existingNames);
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-04 13:48:21 +01:00
|
|
|
// CMakeProjectImporter
|
2016-08-25 14:33:44 +02:00
|
|
|
|
2023-05-09 18:22:47 +02:00
|
|
|
CMakeProjectImporter::CMakeProjectImporter(const FilePath &path, const CMakeProject *project)
|
2022-05-30 19:04:54 +02:00
|
|
|
: QtProjectImporter(path)
|
2023-05-09 18:22:47 +02:00
|
|
|
, m_project(project)
|
2022-05-30 19:04:54 +02:00
|
|
|
, m_presetsTempDir("qtc-cmake-presets-XXXXXXXX")
|
2016-08-25 14:33:44 +02:00
|
|
|
{
|
2019-02-06 12:50:51 +01:00
|
|
|
useTemporaryKitAspect(CMakeKitAspect::id(),
|
2016-08-25 14:33:44 +02:00
|
|
|
[this](Kit *k, const QVariantList &vl) { cleanupTemporaryCMake(k, vl); },
|
|
|
|
|
[this](Kit *k, const QVariantList &vl) { persistTemporaryCMake(k, vl); });
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-13 20:48:08 +02:00
|
|
|
using CharToHexList = QList<QPair<QString, QString>>;
|
|
|
|
|
static const CharToHexList &charToHexList()
|
|
|
|
|
{
|
|
|
|
|
static const CharToHexList list = {
|
|
|
|
|
{"<", "{3C}"},
|
|
|
|
|
{">", "{3E}"},
|
|
|
|
|
{":", "{3A}"},
|
|
|
|
|
{"\"", "{22}"},
|
|
|
|
|
{"\\", "{5C}"},
|
|
|
|
|
{"/", "{2F}"},
|
|
|
|
|
{"|", "{7C}"},
|
|
|
|
|
{"?", "{3F}"},
|
|
|
|
|
{"*", "{2A}"},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static QString presetNameToFileName(const QString &name)
|
|
|
|
|
{
|
|
|
|
|
QString fileName = name;
|
|
|
|
|
for (const auto &p : charToHexList())
|
|
|
|
|
fileName.replace(p.first, p.second);
|
|
|
|
|
return fileName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static QString fileNameToPresetName(const QString &fileName)
|
|
|
|
|
{
|
|
|
|
|
QString name = fileName;
|
|
|
|
|
for (const auto &p : charToHexList())
|
|
|
|
|
name.replace(p.second, p.first);
|
|
|
|
|
return name;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-26 14:21:12 +02:00
|
|
|
FilePaths CMakeProjectImporter::importCandidates()
|
2016-08-25 14:33:44 +02:00
|
|
|
{
|
2022-09-26 14:30:46 +02:00
|
|
|
FilePaths candidates;
|
2016-08-25 14:33:44 +02:00
|
|
|
|
2021-09-09 08:27:28 +02:00
|
|
|
candidates << scanDirectory(projectFilePath().absolutePath(), "build");
|
2016-08-25 14:33:44 +02:00
|
|
|
|
2022-05-18 12:28:04 +02:00
|
|
|
const QList<Kit *> kits = KitManager::kits();
|
|
|
|
|
for (const Kit *k : kits) {
|
2021-09-09 08:27:28 +02:00
|
|
|
FilePath shadowBuildDirectory
|
|
|
|
|
= CMakeBuildConfiguration::shadowBuildDirectory(projectFilePath(),
|
|
|
|
|
k,
|
|
|
|
|
QString(),
|
|
|
|
|
BuildConfiguration::Unknown);
|
|
|
|
|
candidates << scanDirectory(shadowBuildDirectory.absolutePath(), QString());
|
2016-08-25 14:33:44 +02:00
|
|
|
}
|
2022-05-30 19:04:54 +02:00
|
|
|
|
2023-05-09 18:22:47 +02:00
|
|
|
for (const auto &configPreset : m_project->presetsData().configurePresets) {
|
2022-05-30 19:04:54 +02:00
|
|
|
if (configPreset.hidden.value())
|
|
|
|
|
continue;
|
|
|
|
|
|
2022-09-26 18:59:04 +02:00
|
|
|
if (configPreset.condition) {
|
|
|
|
|
if (!CMakePresets::Macros::evaluatePresetCondition(configPreset, projectFilePath()))
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-13 20:48:08 +02:00
|
|
|
const FilePath configPresetDir = m_presetsTempDir.filePath(
|
|
|
|
|
presetNameToFileName(configPreset.name));
|
2022-09-21 12:50:27 +02:00
|
|
|
configPresetDir.createDir();
|
2022-09-26 14:30:46 +02:00
|
|
|
candidates << configPresetDir;
|
2022-10-05 21:08:54 +02:00
|
|
|
|
|
|
|
|
// If the binaryFilePath exists, do not try to import the existing build, so that
|
|
|
|
|
// we don't have duplicates, one from the preset and one from the previous configuration.
|
|
|
|
|
if (configPreset.binaryDir) {
|
2022-10-18 18:23:50 +02:00
|
|
|
Environment env = projectDirectory().deviceEnvironment();
|
2022-10-05 21:08:54 +02:00
|
|
|
CMakePresets::Macros::expand(configPreset, env, projectDirectory());
|
|
|
|
|
|
|
|
|
|
QString binaryDir = configPreset.binaryDir.value();
|
|
|
|
|
CMakePresets::Macros::expand(configPreset, env, projectDirectory(), binaryDir);
|
|
|
|
|
|
|
|
|
|
const FilePath binaryFilePath = FilePath::fromString(binaryDir);
|
2022-12-07 15:37:42 +01:00
|
|
|
candidates.removeIf([&binaryFilePath](const FilePath &path)
|
|
|
|
|
{ return path == binaryFilePath; });
|
2022-10-05 21:08:54 +02:00
|
|
|
}
|
2022-05-30 19:04:54 +02:00
|
|
|
}
|
|
|
|
|
|
2022-09-26 14:30:46 +02:00
|
|
|
const FilePaths finalists = Utils::filteredUnique(candidates);
|
2020-06-18 14:21:09 +02:00
|
|
|
qCInfo(cmInputLog) << "import candidates:" << finalists;
|
2022-09-26 18:09:03 +02:00
|
|
|
return finalists;
|
2016-08-25 14:33:44 +02:00
|
|
|
}
|
|
|
|
|
|
2023-05-09 18:22:47 +02:00
|
|
|
Target *CMakeProjectImporter::preferredTarget(const QList<Target *> &possibleTargets)
|
|
|
|
|
{
|
|
|
|
|
for (Kit *kit : m_project->oldPresetKits()) {
|
|
|
|
|
const bool haveKit = Utils::contains(possibleTargets, [kit](const auto &target) {
|
|
|
|
|
return target->kit() == kit;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!haveKit)
|
|
|
|
|
KitManager::deregisterKit(kit);
|
|
|
|
|
}
|
|
|
|
|
m_project->setOldPresetKits({});
|
|
|
|
|
|
|
|
|
|
return ProjectImporter::preferredTarget(possibleTargets);
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-30 19:04:54 +02:00
|
|
|
static CMakeConfig configurationFromPresetProbe(
|
2023-03-10 20:11:59 +01:00
|
|
|
const FilePath &importPath,
|
|
|
|
|
const FilePath &sourceDirectory,
|
|
|
|
|
const PresetsDetails::ConfigurePreset &configurePreset)
|
2022-05-30 19:04:54 +02:00
|
|
|
{
|
2022-09-21 12:50:27 +02:00
|
|
|
const FilePath cmakeListTxt = importPath / "CMakeLists.txt";
|
|
|
|
|
cmakeListTxt.writeFileContents(QByteArray("cmake_minimum_required(VERSION 3.15)\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"project(preset-probe)\n"
|
|
|
|
|
"\n"));
|
2022-05-30 19:04:54 +02:00
|
|
|
|
2023-05-03 16:00:22 +02:00
|
|
|
Process cmake;
|
2022-05-30 19:04:54 +02:00
|
|
|
cmake.setTimeoutS(30);
|
|
|
|
|
cmake.setDisableUnixTerminal();
|
|
|
|
|
|
2022-10-18 18:23:50 +02:00
|
|
|
const FilePath cmakeExecutable = FilePath::fromString(configurePreset.cmakeExecutable.value());
|
|
|
|
|
|
|
|
|
|
Environment env = cmakeExecutable.deviceEnvironment();
|
2023-03-10 20:11:59 +01:00
|
|
|
CMakePresets::Macros::expand(configurePreset, env, sourceDirectory);
|
2022-05-30 19:04:54 +02:00
|
|
|
|
|
|
|
|
env.setupEnglishOutput();
|
|
|
|
|
cmake.setEnvironment(env);
|
|
|
|
|
|
|
|
|
|
QStringList args;
|
|
|
|
|
args.emplace_back("-S");
|
|
|
|
|
args.emplace_back(importPath.path());
|
|
|
|
|
args.emplace_back("-B");
|
|
|
|
|
args.emplace_back(importPath.pathAppended("build/").path());
|
|
|
|
|
|
|
|
|
|
if (configurePreset.generator) {
|
|
|
|
|
args.emplace_back("-G");
|
|
|
|
|
args.emplace_back(configurePreset.generator.value());
|
|
|
|
|
}
|
2022-09-29 15:47:05 +02:00
|
|
|
if (configurePreset.architecture && configurePreset.architecture.value().value) {
|
2023-02-03 21:24:27 +01:00
|
|
|
if (!configurePreset.architecture->strategy
|
|
|
|
|
|| configurePreset.architecture->strategy
|
|
|
|
|
!= PresetsDetails::ValueStrategyPair::Strategy::external) {
|
|
|
|
|
args.emplace_back("-A");
|
|
|
|
|
args.emplace_back(configurePreset.architecture.value().value.value());
|
|
|
|
|
}
|
2022-09-29 15:47:05 +02:00
|
|
|
}
|
|
|
|
|
if (configurePreset.toolset && configurePreset.toolset.value().value) {
|
2023-02-03 21:24:27 +01:00
|
|
|
if (!configurePreset.toolset->strategy
|
|
|
|
|
|| configurePreset.toolset->strategy
|
|
|
|
|
!= PresetsDetails::ValueStrategyPair::Strategy::external) {
|
|
|
|
|
args.emplace_back("-T");
|
|
|
|
|
args.emplace_back(configurePreset.toolset.value().value.value());
|
|
|
|
|
}
|
2022-09-29 15:47:05 +02:00
|
|
|
}
|
2022-05-30 19:04:54 +02:00
|
|
|
|
|
|
|
|
if (configurePreset.cacheVariables) {
|
|
|
|
|
const CMakeConfig cache = configurePreset.cacheVariables
|
|
|
|
|
? configurePreset.cacheVariables.value()
|
|
|
|
|
: CMakeConfig();
|
2022-10-23 18:42:20 +02:00
|
|
|
|
2023-03-31 19:53:45 +02:00
|
|
|
const QString cmakeMakeProgram = cache.stringValueOf("CMAKE_MAKE_PROGRAM");
|
|
|
|
|
const QString toolchainFile = cache.stringValueOf("CMAKE_TOOLCHAIN_FILE");
|
|
|
|
|
const QString prefixPath = cache.stringValueOf("CMAKE_PREFIX_PATH");
|
|
|
|
|
const QString findRootPath = cache.stringValueOf("CMAKE_FIND_ROOT_PATH");
|
|
|
|
|
const QString qtHostPath = cache.stringValueOf("QT_HOST_PATH");
|
2023-10-22 14:22:20 +02:00
|
|
|
const QString sysRoot = cache.stringValueOf("CMAKE_SYSROOT");
|
2022-05-30 19:04:54 +02:00
|
|
|
|
|
|
|
|
if (!cmakeMakeProgram.isEmpty()) {
|
|
|
|
|
args.emplace_back(
|
2022-10-23 18:42:20 +02:00
|
|
|
QStringLiteral("-DCMAKE_MAKE_PROGRAM=%1").arg(cmakeMakeProgram));
|
2022-05-30 19:04:54 +02:00
|
|
|
}
|
|
|
|
|
if (!toolchainFile.isEmpty()) {
|
|
|
|
|
args.emplace_back(
|
2022-10-23 18:42:20 +02:00
|
|
|
QStringLiteral("-DCMAKE_TOOLCHAIN_FILE=%1").arg(toolchainFile));
|
2022-05-30 19:04:54 +02:00
|
|
|
}
|
|
|
|
|
if (!prefixPath.isEmpty()) {
|
|
|
|
|
args.emplace_back(QStringLiteral("-DCMAKE_PREFIX_PATH=%1").arg(prefixPath));
|
|
|
|
|
}
|
|
|
|
|
if (!findRootPath.isEmpty()) {
|
|
|
|
|
args.emplace_back(QStringLiteral("-DCMAKE_FIND_ROOT_PATH=%1").arg(findRootPath));
|
|
|
|
|
}
|
|
|
|
|
if (!qtHostPath.isEmpty()) {
|
|
|
|
|
args.emplace_back(QStringLiteral("-DQT_HOST_PATH=%1").arg(qtHostPath));
|
|
|
|
|
}
|
2023-10-22 14:22:20 +02:00
|
|
|
if (!sysRoot.isEmpty()) {
|
|
|
|
|
args.emplace_back(QStringLiteral("-DCMAKE_SYSROOT=%1").arg(sysRoot));
|
|
|
|
|
}
|
2022-05-30 19:04:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
qCDebug(cmInputLog) << "CMake probing for compilers: " << cmakeExecutable.toUserOutput()
|
|
|
|
|
<< args;
|
|
|
|
|
cmake.setCommand({cmakeExecutable, args});
|
|
|
|
|
cmake.runBlocking();
|
|
|
|
|
|
|
|
|
|
QString errorMessage;
|
|
|
|
|
const CMakeConfig config = CMakeConfig::fromFile(importPath.pathAppended(
|
|
|
|
|
"build/CMakeCache.txt"),
|
|
|
|
|
&errorMessage);
|
|
|
|
|
|
|
|
|
|
return config;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-02 20:50:44 +02:00
|
|
|
struct QMakeAndCMakePrefixPath
|
|
|
|
|
{
|
|
|
|
|
FilePath qmakePath;
|
|
|
|
|
QString cmakePrefixPath; // can be a semicolon-separated list
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static QMakeAndCMakePrefixPath qtInfoFromCMakeCache(const CMakeConfig &config,
|
|
|
|
|
const Environment &env)
|
2016-08-25 14:33:44 +02:00
|
|
|
{
|
|
|
|
|
// Qt4 way to define things (more convenient for us, so try this first;-)
|
2021-07-06 10:29:29 +02:00
|
|
|
const FilePath qmake = config.filePathValueOf("QT_QMAKE_EXECUTABLE");
|
2020-06-18 14:21:09 +02:00
|
|
|
qCDebug(cmInputLog) << "QT_QMAKE_EXECUTABLE=" << qmake.toUserOutput();
|
2016-08-25 14:33:44 +02:00
|
|
|
|
|
|
|
|
// Check Qt5 settings: oh, the horror!
|
2023-05-02 20:50:44 +02:00
|
|
|
const FilePath qtCMakeDir = [config, env] {
|
|
|
|
|
FilePath tmp;
|
|
|
|
|
// Check the CMake "<package-name>_DIR" variable
|
|
|
|
|
for (const auto &var : {"Qt6", "Qt6Core", "Qt5", "Qt5Core"}) {
|
|
|
|
|
tmp = config.filePathValueOf(QByteArray(var) + "_DIR");
|
|
|
|
|
if (!tmp.isEmpty())
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-06-17 10:45:09 +02:00
|
|
|
return tmp;
|
|
|
|
|
}();
|
2020-06-18 14:21:09 +02:00
|
|
|
qCDebug(cmInputLog) << "QtXCore_DIR=" << qtCMakeDir.toUserOutput();
|
2021-01-04 13:48:21 +01:00
|
|
|
const FilePath canQtCMakeDir = FilePath::fromString(qtCMakeDir.toFileInfo().canonicalFilePath());
|
2020-06-18 14:21:09 +02:00
|
|
|
qCInfo(cmInputLog) << "QtXCore_DIR (canonical)=" << canQtCMakeDir.toUserOutput();
|
2023-05-02 20:50:44 +02:00
|
|
|
|
|
|
|
|
const QString prefixPath = [qtCMakeDir, canQtCMakeDir, config, env] {
|
|
|
|
|
QString result;
|
|
|
|
|
if (!qtCMakeDir.isEmpty()) {
|
|
|
|
|
result = canQtCMakeDir.parentDir().parentDir().parentDir().path(); // Up 3 levels...
|
|
|
|
|
} else {
|
|
|
|
|
// Check the CMAKE_PREFIX_PATH and "<package-name>_ROOT" CMake or environment variables
|
|
|
|
|
// This can be a single value or a semicolon-separated list
|
|
|
|
|
for (const auto &var : {"CMAKE_PREFIX_PATH", "Qt6_ROOT", "Qt5_ROOT"}) {
|
|
|
|
|
result = config.stringValueOf(var);
|
|
|
|
|
if (result.isEmpty())
|
|
|
|
|
result = env.value(QString::fromUtf8(var));
|
|
|
|
|
if (!result.isEmpty())
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}();
|
2022-05-30 19:04:54 +02:00
|
|
|
qCDebug(cmInputLog) << "PrefixPath:" << prefixPath;
|
2022-09-29 15:47:05 +02:00
|
|
|
|
2023-05-02 20:50:44 +02:00
|
|
|
if (!qmake.isEmpty() && !prefixPath.isEmpty())
|
|
|
|
|
return {qmake, prefixPath};
|
|
|
|
|
|
2022-09-29 15:47:05 +02:00
|
|
|
FilePath toolchainFile = config.filePathValueOf(QByteArray("CMAKE_TOOLCHAIN_FILE"));
|
|
|
|
|
if (prefixPath.isEmpty() && toolchainFile.isEmpty())
|
2023-05-02 20:50:44 +02:00
|
|
|
return {qmake, QString()};
|
2016-08-25 14:33:44 +02:00
|
|
|
|
2020-12-31 14:08:16 +01:00
|
|
|
// Run a CMake project that would do qmake probing
|
|
|
|
|
TemporaryDirectory qtcQMakeProbeDir("qtc-cmake-qmake-probe-XXXXXXXX");
|
2016-08-25 14:33:44 +02:00
|
|
|
|
2023-05-02 20:50:44 +02:00
|
|
|
FilePath cmakeListTxt(qtcQMakeProbeDir.filePath("CMakeLists.txt"));
|
|
|
|
|
|
|
|
|
|
cmakeListTxt.writeFileContents(QByteArray(R"(
|
2023-05-02 15:38:45 +02:00
|
|
|
cmake_minimum_required(VERSION 3.15)
|
|
|
|
|
|
|
|
|
|
project(qmake-probe LANGUAGES NONE)
|
|
|
|
|
|
|
|
|
|
# Bypass Qt6's usage of find_dependency, which would require compiler
|
|
|
|
|
# and source code probing, which slows things unnecessarily
|
|
|
|
|
file(WRITE "${CMAKE_SOURCE_DIR}/CMakeFindDependencyMacro.cmake"
|
|
|
|
|
[=[
|
|
|
|
|
macro(find_dependency dep)
|
|
|
|
|
endmacro()
|
|
|
|
|
]=])
|
|
|
|
|
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}")
|
|
|
|
|
|
|
|
|
|
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
|
|
|
|
|
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED)
|
|
|
|
|
|
|
|
|
|
if (CMAKE_CROSSCOMPILING)
|
|
|
|
|
find_program(qmake_binary
|
|
|
|
|
NAMES qmake qmake.bat
|
|
|
|
|
PATHS "${Qt${QT_VERSION_MAJOR}_DIR}/../../../bin"
|
|
|
|
|
NO_DEFAULT_PATH)
|
|
|
|
|
file(WRITE "${CMAKE_SOURCE_DIR}/qmake-location.txt" "${qmake_binary}")
|
|
|
|
|
else()
|
|
|
|
|
file(GENERATE
|
|
|
|
|
OUTPUT "${CMAKE_SOURCE_DIR}/qmake-location.txt"
|
|
|
|
|
CONTENT "$<TARGET_PROPERTY:Qt${QT_VERSION_MAJOR}::qmake,IMPORTED_LOCATION>")
|
|
|
|
|
endif()
|
2023-05-02 20:50:44 +02:00
|
|
|
|
|
|
|
|
# Remove a Qt CMake hack that adds lib/cmake at the end of every path in CMAKE_PREFIX_PATH
|
|
|
|
|
list(REMOVE_DUPLICATES CMAKE_PREFIX_PATH)
|
|
|
|
|
list(TRANSFORM CMAKE_PREFIX_PATH REPLACE "/lib/cmake$" "")
|
|
|
|
|
file(WRITE "${CMAKE_SOURCE_DIR}/cmake-prefix-path.txt" "${CMAKE_PREFIX_PATH}")
|
2023-05-02 15:38:45 +02:00
|
|
|
)"));
|
2020-12-31 14:08:16 +01:00
|
|
|
|
2023-05-03 16:00:22 +02:00
|
|
|
Process cmake;
|
2020-12-31 14:08:16 +01:00
|
|
|
cmake.setTimeoutS(5);
|
2021-05-05 15:23:34 +02:00
|
|
|
cmake.setDisableUnixTerminal();
|
2023-05-02 20:50:44 +02:00
|
|
|
|
|
|
|
|
Environment cmakeEnv(env);
|
|
|
|
|
cmakeEnv.setupEnglishOutput();
|
|
|
|
|
cmake.setEnvironment(cmakeEnv);
|
2020-12-31 14:08:16 +01:00
|
|
|
|
2021-07-06 10:29:29 +02:00
|
|
|
QString cmakeGenerator = config.stringValueOf(QByteArray("CMAKE_GENERATOR"));
|
2022-09-29 15:47:05 +02:00
|
|
|
QString cmakeGeneratorPlatform = config.stringValueOf(QByteArray("CMAKE_GENERATOR_PLATFORM"));
|
|
|
|
|
QString cmakeGeneratorToolset = config.stringValueOf(QByteArray("CMAKE_GENERATOR_TOOLSET"));
|
2021-07-06 10:29:29 +02:00
|
|
|
FilePath cmakeExecutable = config.filePathValueOf(QByteArray("CMAKE_COMMAND"));
|
|
|
|
|
FilePath cmakeMakeProgram = config.filePathValueOf(QByteArray("CMAKE_MAKE_PROGRAM"));
|
|
|
|
|
FilePath hostPath = config.filePathValueOf(QByteArray("QT_HOST_PATH"));
|
2023-05-19 15:21:51 +02:00
|
|
|
const QString findRootPath = config.stringValueOf("CMAKE_FIND_ROOT_PATH");
|
2020-12-31 14:08:16 +01:00
|
|
|
|
|
|
|
|
QStringList args;
|
|
|
|
|
args.push_back("-S");
|
2021-07-01 09:58:48 +02:00
|
|
|
args.push_back(qtcQMakeProbeDir.path().path());
|
2020-12-31 14:08:16 +01:00
|
|
|
args.push_back("-B");
|
2021-07-01 09:58:48 +02:00
|
|
|
args.push_back(qtcQMakeProbeDir.filePath("build").path());
|
2023-07-05 15:31:25 +02:00
|
|
|
if (!cmakeGenerator.isEmpty()) {
|
|
|
|
|
args.push_back("-G");
|
|
|
|
|
args.push_back(cmakeGenerator);
|
|
|
|
|
}
|
2022-09-29 15:47:05 +02:00
|
|
|
if (!cmakeGeneratorPlatform.isEmpty()) {
|
|
|
|
|
args.push_back("-A");
|
|
|
|
|
args.push_back(cmakeGeneratorPlatform);
|
|
|
|
|
}
|
|
|
|
|
if (!cmakeGeneratorToolset.isEmpty()) {
|
|
|
|
|
args.push_back("-T");
|
|
|
|
|
args.push_back(cmakeGeneratorToolset);
|
|
|
|
|
}
|
2020-12-31 14:08:16 +01:00
|
|
|
|
|
|
|
|
if (!cmakeMakeProgram.isEmpty()) {
|
|
|
|
|
args.push_back(QStringLiteral("-DCMAKE_MAKE_PROGRAM=%1").arg(cmakeMakeProgram.toString()));
|
|
|
|
|
}
|
2023-05-19 15:21:51 +02:00
|
|
|
|
|
|
|
|
if (!toolchainFile.isEmpty()) {
|
2020-12-31 14:08:16 +01:00
|
|
|
args.push_back(QStringLiteral("-DCMAKE_TOOLCHAIN_FILE=%1").arg(toolchainFile.toString()));
|
|
|
|
|
}
|
2023-05-19 15:21:51 +02:00
|
|
|
if (!prefixPath.isEmpty()) {
|
|
|
|
|
args.push_back(QStringLiteral("-DCMAKE_PREFIX_PATH=%1").arg(prefixPath));
|
|
|
|
|
}
|
|
|
|
|
if (!findRootPath.isEmpty()) {
|
|
|
|
|
args.push_back(QStringLiteral("-DCMAKE_FIND_ROOT_PATH=%1").arg(findRootPath));
|
|
|
|
|
}
|
2020-12-31 14:08:16 +01:00
|
|
|
if (!hostPath.isEmpty()) {
|
|
|
|
|
args.push_back(QStringLiteral("-DQT_HOST_PATH=%1").arg(hostPath.toString()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
qCDebug(cmInputLog) << "CMake probing for qmake path: " << cmakeExecutable.toUserOutput() << args;
|
2021-05-17 12:02:42 +02:00
|
|
|
cmake.setCommand({cmakeExecutable, args});
|
|
|
|
|
cmake.runBlocking();
|
2020-12-31 14:08:16 +01:00
|
|
|
|
2023-05-02 20:50:44 +02:00
|
|
|
const FilePath qmakeLocationTxt = qtcQMakeProbeDir.filePath("qmake-location.txt");
|
|
|
|
|
const FilePath qmakeLocation = FilePath::fromUtf8(
|
|
|
|
|
qmakeLocationTxt.fileContents().value_or(QByteArray()));
|
2020-12-31 14:08:16 +01:00
|
|
|
qCDebug(cmInputLog) << "qmake location: " << qmakeLocation.toUserOutput();
|
2016-08-25 14:33:44 +02:00
|
|
|
|
2023-05-02 20:50:44 +02:00
|
|
|
const FilePath prefixPathTxt = qtcQMakeProbeDir.filePath("cmake-prefix-path.txt");
|
|
|
|
|
const QString resultedPrefixPath = QString::fromUtf8(
|
|
|
|
|
prefixPathTxt.fileContents().value_or(QByteArray()));
|
|
|
|
|
qCDebug(cmInputLog) << "PrefixPath [after qmake probe]: " << resultedPrefixPath;
|
|
|
|
|
|
|
|
|
|
return {qmakeLocation, resultedPrefixPath};
|
2016-08-25 14:33:44 +02:00
|
|
|
}
|
|
|
|
|
|
2023-12-11 11:42:00 +01:00
|
|
|
static QVector<ToolchainDescription> extractToolchainsFromCache(const CMakeConfig &config)
|
2016-08-25 14:33:44 +02:00
|
|
|
{
|
2023-11-27 17:09:08 +01:00
|
|
|
QVector<ToolchainDescription> result;
|
2021-02-01 19:19:45 +01:00
|
|
|
bool haveCCxxCompiler = false;
|
2016-08-25 14:33:44 +02:00
|
|
|
for (const CMakeConfigItem &i : config) {
|
|
|
|
|
if (!i.key.startsWith("CMAKE_") || !i.key.endsWith("_COMPILER"))
|
|
|
|
|
continue;
|
2023-06-06 16:42:31 +02:00
|
|
|
const QByteArray language = i.key.mid(6, i.key.size() - 6 - 9); // skip "CMAKE_" and "_COMPILER"
|
2021-01-04 13:48:21 +01:00
|
|
|
Id languageId;
|
2021-02-01 19:19:45 +01:00
|
|
|
if (language == "CXX") {
|
|
|
|
|
haveCCxxCompiler = true;
|
2019-07-02 11:31:12 +02:00
|
|
|
languageId = ProjectExplorer::Constants::CXX_LANGUAGE_ID;
|
2021-02-01 19:19:45 +01:00
|
|
|
}
|
|
|
|
|
else if (language == "C") {
|
|
|
|
|
haveCCxxCompiler = true;
|
2019-07-02 11:31:12 +02:00
|
|
|
languageId = ProjectExplorer::Constants::C_LANGUAGE_ID;
|
2021-02-01 19:19:45 +01:00
|
|
|
}
|
2019-07-02 11:31:12 +02:00
|
|
|
else
|
2021-01-04 13:48:21 +01:00
|
|
|
languageId = Id::fromName(language);
|
|
|
|
|
result.append({FilePath::fromUtf8(i.value), languageId});
|
2016-08-25 14:33:44 +02:00
|
|
|
}
|
2021-02-01 19:19:45 +01:00
|
|
|
|
|
|
|
|
if (!haveCCxxCompiler) {
|
2021-07-06 10:29:29 +02:00
|
|
|
const QByteArray generator = config.valueOf("CMAKE_GENERATOR");
|
2021-02-01 19:19:45 +01:00
|
|
|
QString cCompilerName;
|
|
|
|
|
QString cxxCompilerName;
|
|
|
|
|
if (generator.contains("Visual Studio")) {
|
|
|
|
|
cCompilerName = "cl.exe";
|
|
|
|
|
cxxCompilerName = "cl.exe";
|
|
|
|
|
} else if (generator.contains("Xcode")) {
|
|
|
|
|
cCompilerName = "clang";
|
|
|
|
|
cxxCompilerName = "clang++";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!cCompilerName.isEmpty() && !cxxCompilerName.isEmpty()) {
|
2021-07-06 10:29:29 +02:00
|
|
|
const FilePath linker = config.filePathValueOf("CMAKE_LINKER");
|
2021-02-01 19:19:45 +01:00
|
|
|
if (!linker.isEmpty()) {
|
|
|
|
|
const FilePath compilerPath = linker.parentDir();
|
|
|
|
|
result.append({compilerPath.pathAppended(cCompilerName),
|
|
|
|
|
ProjectExplorer::Constants::C_LANGUAGE_ID});
|
|
|
|
|
result.append({compilerPath.pathAppended(cxxCompilerName),
|
|
|
|
|
ProjectExplorer::Constants::CXX_LANGUAGE_ID});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-25 14:33:44 +02:00
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-23 14:36:47 +02:00
|
|
|
static QString extractVisualStudioPlatformFromConfig(const CMakeConfig &config)
|
|
|
|
|
{
|
|
|
|
|
const QString cmakeGenerator = config.stringValueOf(QByteArray("CMAKE_GENERATOR"));
|
|
|
|
|
QString platform;
|
|
|
|
|
if (cmakeGenerator.contains("Visual Studio")) {
|
|
|
|
|
const FilePath linker = config.filePathValueOf("CMAKE_LINKER");
|
|
|
|
|
const QString toolsDir = linker.parentDir().fileName();
|
|
|
|
|
if (toolsDir.compare("x64", Qt::CaseInsensitive) == 0) {
|
|
|
|
|
platform = "x64";
|
|
|
|
|
} else if (toolsDir.compare("x86", Qt::CaseInsensitive) == 0) {
|
|
|
|
|
platform = "Win32";
|
|
|
|
|
} else if (toolsDir.compare("arm64", Qt::CaseInsensitive) == 0) {
|
|
|
|
|
platform = "ARM64";
|
|
|
|
|
} else if (toolsDir.compare("arm", Qt::CaseInsensitive) == 0) {
|
|
|
|
|
platform = "ARM";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return platform;
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-16 14:32:54 +01:00
|
|
|
void updateCompilerPaths(CMakeConfig &config, const Environment &env)
|
|
|
|
|
{
|
|
|
|
|
auto updateRelativePath = [&config, env](const QByteArray &key) {
|
|
|
|
|
FilePath pathValue = config.filePathValueOf(key);
|
|
|
|
|
|
|
|
|
|
if (pathValue.isAbsolutePath() || pathValue.isEmpty())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
pathValue = env.searchInPath(pathValue.fileName());
|
|
|
|
|
|
|
|
|
|
auto it = std::find_if(config.begin(), config.end(), [&key](const CMakeConfigItem &item) {
|
|
|
|
|
return item.key == key;
|
|
|
|
|
});
|
|
|
|
|
QTC_ASSERT(it != config.end(), return);
|
|
|
|
|
|
|
|
|
|
it->value = pathValue.path().toUtf8();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
updateRelativePath("CMAKE_C_COMPILER");
|
|
|
|
|
updateRelativePath("CMAKE_CXX_COMPILER");
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-31 16:14:36 +01:00
|
|
|
void updateConfigWithDirectoryData(CMakeConfig &config, const std::unique_ptr<DirectoryData> &data)
|
|
|
|
|
{
|
|
|
|
|
auto updateCompilerValue = [&config, &data](const QByteArray &key, const Utils::Id &language) {
|
|
|
|
|
auto it = std::find_if(config.begin(), config.end(), [&key](const CMakeConfigItem &ci) {
|
|
|
|
|
return ci.key == key;
|
|
|
|
|
});
|
|
|
|
|
|
2023-12-11 11:42:00 +01:00
|
|
|
auto tcd = Utils::findOrDefault(data->toolchains,
|
2023-11-27 17:09:08 +01:00
|
|
|
[&language](const ToolchainDescription &t) {
|
2023-01-31 16:14:36 +01:00
|
|
|
return t.language == language;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (it != config.end() && it->value.isEmpty())
|
|
|
|
|
it->value = tcd.compilerPath.toString().toUtf8();
|
|
|
|
|
else
|
|
|
|
|
config << CMakeConfigItem(key,
|
|
|
|
|
CMakeConfigItem::FILEPATH,
|
|
|
|
|
tcd.compilerPath.toString().toUtf8());
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
updateCompilerValue("CMAKE_C_COMPILER", ProjectExplorer::Constants::C_LANGUAGE_ID);
|
|
|
|
|
updateCompilerValue("CMAKE_CXX_COMPILER", ProjectExplorer::Constants::CXX_LANGUAGE_ID);
|
|
|
|
|
|
|
|
|
|
if (data->qt.qt)
|
|
|
|
|
config << CMakeConfigItem("QT_QMAKE_EXECUTABLE",
|
|
|
|
|
CMakeConfigItem::FILEPATH,
|
|
|
|
|
data->qt.qt->qmakeFilePath().toString().toUtf8());
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
Toolchain *findExternalToolchain(const QString &presetArchitecture, const QString &presetToolset)
|
2023-02-03 21:24:27 +01:00
|
|
|
{
|
2024-01-18 16:09:25 +01:00
|
|
|
// A compiler path example. Note that the compiler version is not the same version from MsvcToolchain
|
2023-02-03 21:24:27 +01:00
|
|
|
// ... \MSVC\14.29.30133\bin\Hostx64\x64\cl.exe
|
|
|
|
|
//
|
|
|
|
|
// And the CMakePresets.json
|
|
|
|
|
//
|
|
|
|
|
// "toolset": {
|
|
|
|
|
// "value": "v142,host=x64,version=14.29.30133",
|
|
|
|
|
// "strategy": "external"
|
|
|
|
|
// },
|
|
|
|
|
// "architecture": {
|
|
|
|
|
// "value": "x64",
|
|
|
|
|
// "strategy": "external"
|
|
|
|
|
// }
|
|
|
|
|
|
2023-11-27 16:42:42 +01:00
|
|
|
auto msvcToolchains = ToolchainManager::toolchains([](const Toolchain *tc) {
|
2023-02-03 21:24:27 +01:00
|
|
|
return tc->typeId() == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID;
|
|
|
|
|
});
|
|
|
|
|
|
2023-11-24 15:53:31 +01:00
|
|
|
const QSet<Abi::OSFlavor> msvcFlavors = Utils::toSet(Utils::transform(msvcToolchains, [](const Toolchain *tc) {
|
2023-02-03 21:24:27 +01:00
|
|
|
return tc->targetAbi().osFlavor();
|
|
|
|
|
}));
|
|
|
|
|
|
2023-11-27 16:54:38 +01:00
|
|
|
return ToolchainManager::toolchain(
|
2023-11-24 15:53:31 +01:00
|
|
|
[presetArchitecture, presetToolset, msvcFlavors](const Toolchain *tc) -> bool {
|
2023-02-03 21:24:27 +01:00
|
|
|
if (tc->typeId() != ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
const FilePath compilerPath = tc->compilerCommand();
|
|
|
|
|
const QString architecture = compilerPath.parentDir().fileName().toLower();
|
|
|
|
|
const QString host
|
|
|
|
|
= compilerPath.parentDir().parentDir().fileName().toLower().replace("host", "host=");
|
|
|
|
|
const QString version
|
|
|
|
|
= QString("version=%1")
|
|
|
|
|
.arg(compilerPath.parentDir().parentDir().parentDir().parentDir().fileName());
|
|
|
|
|
|
|
|
|
|
static std::pair<QString, Abi::OSFlavor> abiTable[] = {
|
|
|
|
|
{QStringLiteral("v143"), Abi::WindowsMsvc2022Flavor},
|
|
|
|
|
{QStringLiteral("v142"), Abi::WindowsMsvc2019Flavor},
|
|
|
|
|
{QStringLiteral("v141"), Abi::WindowsMsvc2017Flavor},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Abi::OSFlavor toolsetAbi = Abi::UnknownFlavor;
|
2023-02-21 08:57:39 +02:00
|
|
|
for (const auto &abiPair : abiTable) {
|
2023-02-03 21:24:27 +01:00
|
|
|
if (presetToolset.contains(abiPair.first)) {
|
|
|
|
|
toolsetAbi = abiPair.second;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// User didn't specify any flavor, so pick the highest toolchain available
|
|
|
|
|
if (toolsetAbi == Abi::UnknownFlavor) {
|
2023-02-21 08:57:39 +02:00
|
|
|
for (const auto &abiPair : abiTable) {
|
2023-02-03 21:24:27 +01:00
|
|
|
if (msvcFlavors.contains(abiPair.second)) {
|
|
|
|
|
toolsetAbi = abiPair.second;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (toolsetAbi != tc->targetAbi().osFlavor())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (presetToolset.contains("host=") && !presetToolset.contains(host))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
// Make sure we match also version=14.29
|
|
|
|
|
auto versionIndex = presetToolset.indexOf("version=");
|
|
|
|
|
if (versionIndex != -1 && !version.startsWith(presetToolset.mid(versionIndex)))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (presetArchitecture != architecture)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
qCDebug(cmInputLog) << "For external architecture" << presetArchitecture
|
|
|
|
|
<< "and toolset" << presetToolset
|
|
|
|
|
<< "the following toolchain was selected:\n"
|
|
|
|
|
<< compilerPath.toString();
|
|
|
|
|
return true;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-02 19:16:40 +01:00
|
|
|
QList<void *> CMakeProjectImporter::examineDirectory(const FilePath &importPath,
|
|
|
|
|
QString *warningMessage) const
|
2016-08-25 14:33:44 +02:00
|
|
|
{
|
2022-05-30 19:04:54 +02:00
|
|
|
QList<void *> result;
|
2020-06-18 14:21:09 +02:00
|
|
|
qCInfo(cmInputLog) << "Examining directory:" << importPath.toUserOutput();
|
2022-05-30 19:04:54 +02:00
|
|
|
|
|
|
|
|
if (importPath.isChildOf(m_presetsTempDir.path())) {
|
|
|
|
|
auto data = std::make_unique<DirectoryData>();
|
|
|
|
|
|
2023-10-13 20:48:08 +02:00
|
|
|
const QString presetName = fileNameToPresetName(importPath.fileName());
|
2022-05-30 19:04:54 +02:00
|
|
|
PresetsDetails::ConfigurePreset configurePreset
|
2023-05-09 18:22:47 +02:00
|
|
|
= Utils::findOrDefault(m_project->presetsData().configurePresets,
|
2022-05-30 19:04:54 +02:00
|
|
|
[presetName](const PresetsDetails::ConfigurePreset &preset) {
|
|
|
|
|
return preset.name == presetName;
|
|
|
|
|
});
|
|
|
|
|
|
2022-10-18 18:23:50 +02:00
|
|
|
Environment env = projectDirectory().deviceEnvironment();
|
2022-09-26 18:59:04 +02:00
|
|
|
CMakePresets::Macros::expand(configurePreset, env, projectDirectory());
|
|
|
|
|
|
2022-05-30 19:04:54 +02:00
|
|
|
if (configurePreset.displayName)
|
|
|
|
|
data->cmakePresetDisplayname = configurePreset.displayName.value();
|
|
|
|
|
else
|
|
|
|
|
data->cmakePresetDisplayname = configurePreset.name;
|
|
|
|
|
data->cmakePreset = configurePreset.name;
|
|
|
|
|
|
|
|
|
|
if (!configurePreset.cmakeExecutable) {
|
|
|
|
|
const CMakeTool *cmakeTool = CMakeToolManager::defaultCMakeTool();
|
|
|
|
|
if (cmakeTool)
|
|
|
|
|
configurePreset.cmakeExecutable = cmakeTool->cmakeExecutable().toString();
|
2023-10-13 19:03:43 +02:00
|
|
|
} else {
|
|
|
|
|
QString cmakeExecutable = configurePreset.cmakeExecutable.value();
|
|
|
|
|
CMakePresets::Macros::expand(configurePreset, env, projectDirectory(), cmakeExecutable);
|
|
|
|
|
|
|
|
|
|
configurePreset.cmakeExecutable = FilePath::fromUserInput(cmakeExecutable).path();
|
2022-05-30 19:04:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data->cmakeBinary = Utils::FilePath::fromString(configurePreset.cmakeExecutable.value());
|
|
|
|
|
if (configurePreset.generator)
|
|
|
|
|
data->generator = configurePreset.generator.value();
|
|
|
|
|
|
|
|
|
|
if (configurePreset.binaryDir) {
|
2022-10-07 15:08:33 +02:00
|
|
|
QString binaryDir = configurePreset.binaryDir.value();
|
2022-09-26 18:59:04 +02:00
|
|
|
CMakePresets::Macros::expand(configurePreset, env, projectDirectory(), binaryDir);
|
2022-10-07 15:08:33 +02:00
|
|
|
data->buildDirectory = Utils::FilePath::fromString(binaryDir);
|
2022-05-30 19:04:54 +02:00
|
|
|
}
|
|
|
|
|
|
2023-02-03 21:24:27 +01:00
|
|
|
const bool architectureExternalStrategy
|
|
|
|
|
= configurePreset.architecture && configurePreset.architecture->strategy
|
|
|
|
|
&& configurePreset.architecture->strategy
|
|
|
|
|
== PresetsDetails::ValueStrategyPair::Strategy::external;
|
|
|
|
|
|
|
|
|
|
const bool toolsetExternalStrategy
|
|
|
|
|
= configurePreset.toolset && configurePreset.toolset->strategy
|
|
|
|
|
&& configurePreset.toolset->strategy
|
|
|
|
|
== PresetsDetails::ValueStrategyPair::Strategy::external;
|
|
|
|
|
|
|
|
|
|
if (!architectureExternalStrategy && configurePreset.architecture
|
|
|
|
|
&& configurePreset.architecture.value().value)
|
|
|
|
|
data->platform = configurePreset.architecture.value().value.value();
|
|
|
|
|
|
|
|
|
|
if (!toolsetExternalStrategy && configurePreset.toolset && configurePreset.toolset.value().value)
|
|
|
|
|
data->toolset = configurePreset.toolset.value().value.value();
|
|
|
|
|
|
|
|
|
|
if (architectureExternalStrategy && toolsetExternalStrategy) {
|
2023-11-24 15:53:31 +01:00
|
|
|
const Toolchain *tc
|
2023-02-03 21:24:27 +01:00
|
|
|
= findExternalToolchain(configurePreset.architecture->value.value_or(QString()),
|
|
|
|
|
configurePreset.toolset->value.value_or(QString()));
|
|
|
|
|
if (tc)
|
|
|
|
|
tc->addToEnvironment(env);
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-26 18:59:04 +02:00
|
|
|
CMakePresets::Macros::updateToolchainFile(configurePreset,
|
|
|
|
|
env,
|
|
|
|
|
projectDirectory(),
|
|
|
|
|
data->buildDirectory);
|
|
|
|
|
|
2023-03-31 19:53:45 +02:00
|
|
|
CMakePresets::Macros::updateCacheVariables(configurePreset, env, projectDirectory());
|
|
|
|
|
|
2022-05-30 19:04:54 +02:00
|
|
|
const CMakeConfig cache = configurePreset.cacheVariables
|
|
|
|
|
? configurePreset.cacheVariables.value()
|
|
|
|
|
: CMakeConfig();
|
|
|
|
|
CMakeConfig config;
|
2023-07-05 15:31:25 +02:00
|
|
|
const bool noCompilers = cache.valueOf("CMAKE_C_COMPILER").isEmpty()
|
|
|
|
|
&& cache.valueOf("CMAKE_CXX_COMPILER").isEmpty();
|
|
|
|
|
if (noCompilers || !configurePreset.generator) {
|
2022-05-30 19:04:54 +02:00
|
|
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
2023-03-10 20:11:59 +01:00
|
|
|
config = configurationFromPresetProbe(importPath, projectDirectory(), configurePreset);
|
2022-05-30 19:04:54 +02:00
|
|
|
QApplication::restoreOverrideCursor();
|
2022-10-23 14:36:47 +02:00
|
|
|
|
|
|
|
|
if (!configurePreset.generator) {
|
|
|
|
|
QString cmakeGenerator = config.stringValueOf(QByteArray("CMAKE_GENERATOR"));
|
|
|
|
|
configurePreset.generator = cmakeGenerator;
|
|
|
|
|
data->generator = cmakeGenerator;
|
|
|
|
|
data->platform = extractVisualStudioPlatformFromConfig(config);
|
|
|
|
|
if (!data->platform.isEmpty()) {
|
|
|
|
|
configurePreset.architecture = PresetsDetails::ValueStrategyPair();
|
|
|
|
|
configurePreset.architecture->value = data->platform;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-05-30 19:04:54 +02:00
|
|
|
} else {
|
|
|
|
|
config = cache;
|
2022-12-16 14:32:54 +01:00
|
|
|
updateCompilerPaths(config, env);
|
2022-05-30 19:04:54 +02:00
|
|
|
config << CMakeConfigItem("CMAKE_COMMAND",
|
|
|
|
|
CMakeConfigItem::PATH,
|
|
|
|
|
configurePreset.cmakeExecutable.value().toUtf8());
|
|
|
|
|
if (configurePreset.generator)
|
|
|
|
|
config << CMakeConfigItem("CMAKE_GENERATOR",
|
|
|
|
|
CMakeConfigItem::STRING,
|
|
|
|
|
configurePreset.generator.value().toUtf8());
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-22 14:22:20 +02:00
|
|
|
data->sysroot = config.filePathValueOf("CMAKE_SYSROOT");
|
|
|
|
|
|
2023-05-02 20:50:44 +02:00
|
|
|
const auto [qmake, cmakePrefixPath] = qtInfoFromCMakeCache(config, env);
|
2022-05-30 19:04:54 +02:00
|
|
|
if (!qmake.isEmpty())
|
|
|
|
|
data->qt = findOrCreateQtVersion(qmake);
|
|
|
|
|
|
2023-05-02 20:50:44 +02:00
|
|
|
if (!cmakePrefixPath.isEmpty() && config.valueOf("CMAKE_PREFIX_PATH").isEmpty())
|
|
|
|
|
config << CMakeConfigItem("CMAKE_PREFIX_PATH",
|
|
|
|
|
CMakeConfigItem::PATH,
|
|
|
|
|
cmakePrefixPath.toUtf8());
|
|
|
|
|
|
2023-12-11 11:42:00 +01:00
|
|
|
// Toolchains:
|
|
|
|
|
data->toolchains = extractToolchainsFromCache(config);
|
2022-05-30 19:04:54 +02:00
|
|
|
|
2023-01-31 16:14:36 +01:00
|
|
|
// Update QT_QMAKE_EXECUTABLE and CMAKE_C|XX_COMPILER config values
|
|
|
|
|
updateConfigWithDirectoryData(config, data);
|
|
|
|
|
|
2023-07-04 12:40:19 +02:00
|
|
|
data->hasQmlDebugging = CMakeBuildConfiguration::hasQmlDebugging(config);
|
|
|
|
|
|
2023-03-31 19:53:45 +02:00
|
|
|
QByteArrayList buildConfigurationTypes = {cache.valueOf("CMAKE_BUILD_TYPE")};
|
2022-10-10 19:33:48 +02:00
|
|
|
if (buildConfigurationTypes.front().isEmpty()) {
|
|
|
|
|
buildConfigurationTypes.clear();
|
|
|
|
|
QByteArray buildConfigurationTypesString = cache.valueOf("CMAKE_CONFIGURATION_TYPES");
|
|
|
|
|
if (!buildConfigurationTypesString.isEmpty()) {
|
|
|
|
|
buildConfigurationTypes = buildConfigurationTypesString.split(';');
|
|
|
|
|
} else {
|
|
|
|
|
for (int type = CMakeBuildConfigurationFactory::BuildTypeDebug;
|
|
|
|
|
type != CMakeBuildConfigurationFactory::BuildTypeLast;
|
|
|
|
|
++type) {
|
|
|
|
|
BuildInfo info = CMakeBuildConfigurationFactory::createBuildInfo(
|
|
|
|
|
CMakeBuildConfigurationFactory::BuildType(type));
|
|
|
|
|
buildConfigurationTypes << info.typeName.toUtf8();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (const auto &buildType : buildConfigurationTypes) {
|
|
|
|
|
DirectoryData *newData = new DirectoryData(*data);
|
|
|
|
|
newData->cmakeBuildType = buildType;
|
|
|
|
|
|
2023-07-04 12:40:19 +02:00
|
|
|
// Handle QML Debugging
|
|
|
|
|
auto type = CMakeBuildConfigurationFactory::buildTypeFromByteArray(
|
|
|
|
|
newData->cmakeBuildType);
|
|
|
|
|
if (type == CMakeBuildConfigurationFactory::BuildTypeDebug
|
|
|
|
|
|| type == CMakeBuildConfigurationFactory::BuildTypeProfile)
|
|
|
|
|
newData->hasQmlDebugging = true;
|
|
|
|
|
|
2022-10-10 19:33:48 +02:00
|
|
|
result.emplace_back(newData);
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-30 19:04:54 +02:00
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-28 13:49:26 +02:00
|
|
|
const FilePath cacheFile = importPath.pathAppended("CMakeCache.txt");
|
2016-08-25 14:33:44 +02:00
|
|
|
|
|
|
|
|
if (!cacheFile.exists()) {
|
2020-06-18 14:21:09 +02:00
|
|
|
qCDebug(cmInputLog) << cacheFile.toUserOutput() << "does not exist, returning.";
|
2022-05-30 19:04:54 +02:00
|
|
|
return result;
|
2016-08-25 14:33:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString errorMessage;
|
2022-05-05 15:51:11 +02:00
|
|
|
const CMakeConfig config = CMakeConfig::fromFile(cacheFile, &errorMessage);
|
2016-08-25 14:33:44 +02:00
|
|
|
if (config.isEmpty() || !errorMessage.isEmpty()) {
|
2020-06-18 14:21:09 +02:00
|
|
|
qCDebug(cmInputLog) << "Failed to read configuration from" << cacheFile << errorMessage;
|
2022-05-30 19:04:54 +02:00
|
|
|
return result;
|
2016-08-25 14:33:44 +02:00
|
|
|
}
|
2021-01-14 16:38:55 +01:00
|
|
|
|
2021-07-06 10:29:29 +02:00
|
|
|
QByteArrayList buildConfigurationTypes = {config.valueOf("CMAKE_BUILD_TYPE")};
|
2021-01-14 16:38:55 +01:00
|
|
|
if (buildConfigurationTypes.front().isEmpty()) {
|
2021-07-06 10:29:29 +02:00
|
|
|
QByteArray buildConfigurationTypesString = config.valueOf("CMAKE_CONFIGURATION_TYPES");
|
|
|
|
|
if (!buildConfigurationTypesString.isEmpty())
|
2021-01-14 16:38:55 +01:00
|
|
|
buildConfigurationTypes = buildConfigurationTypesString.split(';');
|
2016-08-25 14:33:44 +02:00
|
|
|
}
|
|
|
|
|
|
2023-05-02 20:50:44 +02:00
|
|
|
const Environment env = projectDirectory().deviceEnvironment();
|
|
|
|
|
|
2022-10-07 14:46:06 +02:00
|
|
|
for (auto const &buildType: std::as_const(buildConfigurationTypes)) {
|
2021-01-14 16:38:55 +01:00
|
|
|
auto data = std::make_unique<DirectoryData>();
|
|
|
|
|
|
2021-07-06 09:50:01 +02:00
|
|
|
data->cmakeHomeDirectory =
|
2021-07-06 10:29:29 +02:00
|
|
|
FilePath::fromUserInput(config.stringValueOf("CMAKE_HOME_DIRECTORY"))
|
2021-07-06 09:50:01 +02:00
|
|
|
.canonicalPath();
|
2021-01-14 16:38:55 +01:00
|
|
|
const FilePath canonicalProjectDirectory = projectDirectory().canonicalPath();
|
|
|
|
|
if (data->cmakeHomeDirectory != canonicalProjectDirectory) {
|
2022-09-29 15:26:31 +02:00
|
|
|
*warningMessage = Tr::tr("Unexpected source directory \"%1\", expected \"%2\". "
|
2021-01-14 16:38:55 +01:00
|
|
|
"This can be correct in some situations, for example when "
|
|
|
|
|
"importing a standalone Qt test, but usually this is an error. "
|
|
|
|
|
"Import the build anyway?")
|
|
|
|
|
.arg(data->cmakeHomeDirectory.toUserOutput(),
|
|
|
|
|
canonicalProjectDirectory.toUserOutput());
|
|
|
|
|
}
|
2016-08-25 14:33:44 +02:00
|
|
|
|
CMake: Make QML debugging state reflect build system state
After parsing the CMake response, we make the configuration variables
table reflect the actual configuration in the build directory. It is one
of our "promises" that we do not break an existing build configuration,
to avoid unexpected rebuilds.
This was not quite true for the "QML debugging and profiling" setting.
When that setting and the actual build directory disagreed, the user
would get a dialog asking for running CMake with additional parameters,
and when running CMake via the button in projects mode or the menu, it
would just change these configuration parameters, potentially leading to
an unexpected complete rebuild of the application.
So, after parsing check if the actual CMake configuration matches our
QML debugging setting, and if not, change the setting to "Leave at
Default", to ensure that we don't mess with the build.
Fix the "Run CMake" button state (in the "Current Configuration") when
changing the QML debugging option, which should become bold, if the
CMake parameters change.
Amends 2577ce8ba1a69ad716c2fc2a5d0d5cc742c3c4cf and fixes the drawback
mentioned there, i.e. setting the build directory of a "Debug" build
configuration to an existing build directory with QML debugging
disabled, will now simply set the QML debugging option to "Leave at
Default" instead of forcing it to "Enabled".
Change-Id: Ie6d4875d59319687d94e44e459ca76038e5813c0
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Reviewed-by: Cristian Adam <cristian.adam@qt.io>
2022-06-07 10:18:34 +02:00
|
|
|
data->hasQmlDebugging = CMakeBuildConfiguration::hasQmlDebugging(config);
|
CMake: Add 'Profile' configuration
Get rid of the hardcoded QML Debugging for Debug & RelWithDebInfo from
the project template, because RelWithDebInfo is actually a good
configuration for doing releases (we use it for Qt Creator), and
enabling QML debugging for releases is a bad idea.
Instead enable QML Debugging in Qt Creator for the Debug configuration,
and add a 'Profile' configuration that is 'RelWithDebInfo + QML
Debugging'.
When importing a build, we only set the "QML debugging" option of the
build configuration, if it is enabled in the imported build, even if it
uses CMAKE_BUILD_TYPE=Debug .
One drawback: When not importing a build, but just setting the build
directory of a "Profile" or "Debug" configuration to an existing build,
Qt Creator asks if it should apply "-DCMAKE_CXX_FLAGS=-DQT_QML_DEBUG".
The user can choose not to, but then is asked the next time again, and
it is not obvious that the "QML debugging" option is responsible for
this.
That is somewhat orthogonal to this change though: Even without this
change, if the user changes the QML debugging option from "Leave at
Default" to "Enable", the same happens, and it is also not clear to the
user how to get rid of it. The user might not even have realized that
they changed the option (e.g. on platforms where the mouse wheel cycles
combo box values).
I think the correct solution is to 1. make clearer where the CMake flags
came from in that dialog, 2. allow the user to cancel a build from that
dialog, 3. allow the user to discard these changes (by changing the
setting) from that dialog. But that is for another patch.
Amends 3300182d405bffe062a0f2be900f35822a9e20b0
Amends 77fed0b0fdce2a93f465c20cd87c41900117dcda
Change-Id: I95de59473b67c5afd6a53ea7f49838dbaef770d4
Reviewed-by: Artem Sokolovskii <artem.sokolovskii@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Cristian Adam <cristian.adam@qt.io>
2022-05-18 10:40:31 +02:00
|
|
|
|
2021-01-14 16:38:55 +01:00
|
|
|
data->buildDirectory = importPath;
|
|
|
|
|
data->cmakeBuildType = buildType;
|
2016-08-25 14:33:44 +02:00
|
|
|
|
2021-07-06 10:29:29 +02:00
|
|
|
data->cmakeBinary = config.filePathValueOf("CMAKE_COMMAND");
|
|
|
|
|
data->generator = config.stringValueOf("CMAKE_GENERATOR");
|
|
|
|
|
data->platform = config.stringValueOf("CMAKE_GENERATOR_PLATFORM");
|
2022-10-23 14:36:47 +02:00
|
|
|
if (data->platform.isEmpty())
|
|
|
|
|
data->platform = extractVisualStudioPlatformFromConfig(config);
|
2021-07-06 10:29:29 +02:00
|
|
|
data->toolset = config.stringValueOf("CMAKE_GENERATOR_TOOLSET");
|
|
|
|
|
data->sysroot = config.filePathValueOf("CMAKE_SYSROOT");
|
2016-08-25 14:33:44 +02:00
|
|
|
|
2021-01-14 16:38:55 +01:00
|
|
|
// Qt:
|
2023-05-02 20:50:44 +02:00
|
|
|
const auto [qmake, cmakePrefixPath] = qtInfoFromCMakeCache(config, env);
|
2021-01-14 16:38:55 +01:00
|
|
|
if (!qmake.isEmpty())
|
|
|
|
|
data->qt = findOrCreateQtVersion(qmake);
|
2016-08-25 14:33:44 +02:00
|
|
|
|
2023-12-11 11:42:00 +01:00
|
|
|
// Toolchains:
|
|
|
|
|
data->toolchains = extractToolchainsFromCache(config);
|
2021-01-14 16:38:55 +01:00
|
|
|
|
|
|
|
|
qCInfo(cmInputLog) << "Offering to import" << importPath.toUserOutput();
|
|
|
|
|
result.push_back(static_cast<void *>(data.release()));
|
|
|
|
|
}
|
|
|
|
|
return result;
|
2016-08-25 14:33:44 +02:00
|
|
|
}
|
|
|
|
|
|
2022-10-07 15:08:33 +02:00
|
|
|
void CMakeProjectImporter::ensureBuildDirectory(DirectoryData &data, const Kit *k) const
|
|
|
|
|
{
|
|
|
|
|
if (!data.buildDirectory.isEmpty())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
const auto cmakeBuildType = CMakeBuildConfigurationFactory::buildTypeFromByteArray(
|
|
|
|
|
data.cmakeBuildType);
|
|
|
|
|
auto buildInfo = CMakeBuildConfigurationFactory::createBuildInfo(cmakeBuildType);
|
|
|
|
|
|
|
|
|
|
data.buildDirectory = CMakeBuildConfiguration::shadowBuildDirectory(projectFilePath(),
|
|
|
|
|
k,
|
|
|
|
|
buildInfo.typeName,
|
|
|
|
|
buildInfo.buildType);
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-25 14:33:44 +02:00
|
|
|
bool CMakeProjectImporter::matchKit(void *directoryData, const Kit *k) const
|
|
|
|
|
{
|
2022-10-07 15:08:33 +02:00
|
|
|
DirectoryData *data = static_cast<DirectoryData *>(directoryData);
|
2016-08-25 14:33:44 +02:00
|
|
|
|
2019-02-06 12:50:51 +01:00
|
|
|
CMakeTool *cm = CMakeKitAspect::cmakeTool(k);
|
2016-08-25 14:33:44 +02:00
|
|
|
if (!cm || cm->cmakeExecutable() != data->cmakeBinary)
|
|
|
|
|
return false;
|
|
|
|
|
|
2021-07-06 09:50:01 +02:00
|
|
|
if (CMakeGeneratorKitAspect::generator(k) != data->generator
|
|
|
|
|
|| CMakeGeneratorKitAspect::platform(k) != data->platform
|
|
|
|
|
|| CMakeGeneratorKitAspect::toolset(k) != data->toolset)
|
2016-08-25 14:33:44 +02:00
|
|
|
return false;
|
|
|
|
|
|
2021-07-06 09:50:01 +02:00
|
|
|
if (SysRootKitAspect::sysRoot(k) != data->sysroot)
|
2016-08-25 14:33:44 +02:00
|
|
|
return false;
|
|
|
|
|
|
2019-02-06 12:50:51 +01:00
|
|
|
if (data->qt.qt && QtSupport::QtKitAspect::qtVersionId(k) != data->qt.qt->uniqueId())
|
2016-08-25 14:33:44 +02:00
|
|
|
return false;
|
|
|
|
|
|
2023-05-03 19:13:07 +02:00
|
|
|
const bool compilersMatch = [k, data] {
|
2023-11-27 16:42:42 +01:00
|
|
|
const QList<Id> allLanguages = ToolchainManager::allLanguages();
|
2023-12-11 11:42:00 +01:00
|
|
|
for (const ToolchainDescription &tcd : data->toolchains) {
|
2023-05-03 19:13:07 +02:00
|
|
|
if (!Utils::contains(allLanguages,
|
|
|
|
|
[&tcd](const Id &language) { return language == tcd.language; }))
|
|
|
|
|
continue;
|
2023-12-11 11:42:00 +01:00
|
|
|
Toolchain *tc = ToolchainKitAspect::toolchain(k, tcd.language);
|
2023-05-03 19:13:07 +02:00
|
|
|
if ((!tc || !tc->matchesCompilerCommand(tcd.compilerPath))) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}();
|
|
|
|
|
const bool noCompilers = [k, data] {
|
2023-11-27 16:42:42 +01:00
|
|
|
const QList<Id> allLanguages = ToolchainManager::allLanguages();
|
2023-12-11 11:42:00 +01:00
|
|
|
for (const ToolchainDescription &tcd : data->toolchains) {
|
2023-05-03 19:13:07 +02:00
|
|
|
if (!Utils::contains(allLanguages,
|
|
|
|
|
[&tcd](const Id &language) { return language == tcd.language; }))
|
|
|
|
|
continue;
|
2023-12-11 11:42:00 +01:00
|
|
|
Toolchain *tc = ToolchainKitAspect::toolchain(k, tcd.language);
|
2023-05-03 19:13:07 +02:00
|
|
|
if (tc && tc->matchesCompilerCommand(tcd.compilerPath)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}();
|
|
|
|
|
|
2022-10-23 16:11:52 +02:00
|
|
|
bool haveCMakePreset = false;
|
|
|
|
|
if (!data->cmakePreset.isEmpty()) {
|
2022-12-16 19:20:33 +01:00
|
|
|
const auto presetConfigItem = CMakeConfigurationKitAspect::cmakePresetConfigItem(k);
|
|
|
|
|
|
|
|
|
|
const QString presetName = presetConfigItem.expandedValue(k);
|
2023-05-03 19:13:07 +02:00
|
|
|
if (data->cmakePreset != presetName)
|
2022-10-23 16:11:52 +02:00
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
ensureBuildDirectory(*data, k);
|
|
|
|
|
haveCMakePreset = true;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-03 19:13:07 +02:00
|
|
|
if (!compilersMatch && !(haveCMakePreset && noCompilers))
|
|
|
|
|
return false;
|
2016-08-25 14:33:44 +02:00
|
|
|
|
2020-06-18 14:21:09 +02:00
|
|
|
qCDebug(cmInputLog) << k->displayName()
|
2023-05-03 19:13:07 +02:00
|
|
|
<< "matches directoryData for" << data->buildDirectory.toUserOutput();
|
2016-08-25 14:33:44 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Kit *CMakeProjectImporter::createKit(void *directoryData) const
|
|
|
|
|
{
|
2022-10-07 15:08:33 +02:00
|
|
|
DirectoryData *data = static_cast<DirectoryData *>(directoryData);
|
2016-08-25 14:33:44 +02:00
|
|
|
|
|
|
|
|
return QtProjectImporter::createTemporaryKit(data->qt, [&data, this](Kit *k) {
|
|
|
|
|
const CMakeToolData cmtd = findOrCreateCMakeTool(data->cmakeBinary);
|
|
|
|
|
QTC_ASSERT(cmtd.cmakeTool, return);
|
|
|
|
|
if (cmtd.isTemporary)
|
2019-02-06 12:50:51 +01:00
|
|
|
addTemporaryData(CMakeKitAspect::id(), cmtd.cmakeTool->id().toSetting(), k);
|
2020-08-18 11:34:44 +01:00
|
|
|
CMakeKitAspect::setCMakeTool(k, cmtd.cmakeTool->id());
|
2016-08-25 14:33:44 +02:00
|
|
|
|
2021-07-06 09:50:01 +02:00
|
|
|
CMakeGeneratorKitAspect::setGenerator(k, data->generator);
|
|
|
|
|
CMakeGeneratorKitAspect::setPlatform(k, data->platform);
|
|
|
|
|
CMakeGeneratorKitAspect::setToolset(k, data->toolset);
|
2016-08-25 14:33:44 +02:00
|
|
|
|
2021-07-06 09:50:01 +02:00
|
|
|
SysRootKitAspect::setSysRoot(k, data->sysroot);
|
2016-08-25 14:33:44 +02:00
|
|
|
|
2023-12-11 11:42:00 +01:00
|
|
|
for (const ToolchainDescription &cmtcd : data->toolchains) {
|
2024-01-18 16:09:25 +01:00
|
|
|
const ToolchainData tcd = findOrCreateToolchains(cmtcd);
|
2016-08-25 14:33:44 +02:00
|
|
|
QTC_ASSERT(!tcd.tcs.isEmpty(), continue);
|
|
|
|
|
|
|
|
|
|
if (tcd.areTemporary) {
|
2023-11-24 15:53:31 +01:00
|
|
|
for (Toolchain *tc : tcd.tcs)
|
2023-11-24 17:55:50 +01:00
|
|
|
addTemporaryData(ToolchainKitAspect::id(), tc->id(), k);
|
2016-08-25 14:33:44 +02:00
|
|
|
}
|
|
|
|
|
|
2023-12-11 11:42:00 +01:00
|
|
|
ToolchainKitAspect::setToolchain(k, tcd.tcs.at(0));
|
2016-08-25 14:33:44 +02:00
|
|
|
}
|
|
|
|
|
|
2022-12-16 19:20:33 +01:00
|
|
|
if (!data->cmakePresetDisplayname.isEmpty()) {
|
|
|
|
|
k->setUnexpandedDisplayName(
|
|
|
|
|
QString("%1 (CMake preset)").arg(data->cmakePresetDisplayname));
|
|
|
|
|
|
|
|
|
|
CMakeConfigurationKitAspect::setCMakePreset(k, data->cmakePreset);
|
|
|
|
|
}
|
|
|
|
|
if (!data->cmakePreset.isEmpty())
|
|
|
|
|
ensureBuildDirectory(*data, k);
|
|
|
|
|
|
2020-06-18 14:21:09 +02:00
|
|
|
qCInfo(cmInputLog) << "Temporary Kit created.";
|
2016-08-25 14:33:44 +02:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-09 18:42:28 +01:00
|
|
|
const QList<BuildInfo> CMakeProjectImporter::buildInfoList(void *directoryData) const
|
2016-08-25 14:33:44 +02:00
|
|
|
{
|
2018-11-04 23:09:41 +01:00
|
|
|
auto data = static_cast<const DirectoryData *>(directoryData);
|
2016-08-25 14:33:44 +02:00
|
|
|
|
|
|
|
|
// create info:
|
CMake: Add 'Profile' configuration
Get rid of the hardcoded QML Debugging for Debug & RelWithDebInfo from
the project template, because RelWithDebInfo is actually a good
configuration for doing releases (we use it for Qt Creator), and
enabling QML debugging for releases is a bad idea.
Instead enable QML Debugging in Qt Creator for the Debug configuration,
and add a 'Profile' configuration that is 'RelWithDebInfo + QML
Debugging'.
When importing a build, we only set the "QML debugging" option of the
build configuration, if it is enabled in the imported build, even if it
uses CMAKE_BUILD_TYPE=Debug .
One drawback: When not importing a build, but just setting the build
directory of a "Profile" or "Debug" configuration to an existing build,
Qt Creator asks if it should apply "-DCMAKE_CXX_FLAGS=-DQT_QML_DEBUG".
The user can choose not to, but then is asked the next time again, and
it is not obvious that the "QML debugging" option is responsible for
this.
That is somewhat orthogonal to this change though: Even without this
change, if the user changes the QML debugging option from "Leave at
Default" to "Enable", the same happens, and it is also not clear to the
user how to get rid of it. The user might not even have realized that
they changed the option (e.g. on platforms where the mouse wheel cycles
combo box values).
I think the correct solution is to 1. make clearer where the CMake flags
came from in that dialog, 2. allow the user to cancel a build from that
dialog, 3. allow the user to discard these changes (by changing the
setting) from that dialog. But that is for another patch.
Amends 3300182d405bffe062a0f2be900f35822a9e20b0
Amends 77fed0b0fdce2a93f465c20cd87c41900117dcda
Change-Id: I95de59473b67c5afd6a53ea7f49838dbaef770d4
Reviewed-by: Artem Sokolovskii <artem.sokolovskii@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Cristian Adam <cristian.adam@qt.io>
2022-05-18 10:40:31 +02:00
|
|
|
CMakeBuildConfigurationFactory::BuildType buildType
|
|
|
|
|
= CMakeBuildConfigurationFactory::buildTypeFromByteArray(data->cmakeBuildType);
|
|
|
|
|
// RelWithDebInfo + QML Debugging = Profile
|
|
|
|
|
if (buildType == CMakeBuildConfigurationFactory::BuildTypeRelWithDebInfo
|
|
|
|
|
&& data->hasQmlDebugging)
|
|
|
|
|
buildType = CMakeBuildConfigurationFactory::BuildTypeProfile;
|
|
|
|
|
BuildInfo info = CMakeBuildConfigurationFactory::createBuildInfo(buildType);
|
2019-01-29 16:51:17 +01:00
|
|
|
info.buildDirectory = data->buildDirectory;
|
2016-08-25 14:33:44 +02:00
|
|
|
|
CMake: Add 'Profile' configuration
Get rid of the hardcoded QML Debugging for Debug & RelWithDebInfo from
the project template, because RelWithDebInfo is actually a good
configuration for doing releases (we use it for Qt Creator), and
enabling QML debugging for releases is a bad idea.
Instead enable QML Debugging in Qt Creator for the Debug configuration,
and add a 'Profile' configuration that is 'RelWithDebInfo + QML
Debugging'.
When importing a build, we only set the "QML debugging" option of the
build configuration, if it is enabled in the imported build, even if it
uses CMAKE_BUILD_TYPE=Debug .
One drawback: When not importing a build, but just setting the build
directory of a "Profile" or "Debug" configuration to an existing build,
Qt Creator asks if it should apply "-DCMAKE_CXX_FLAGS=-DQT_QML_DEBUG".
The user can choose not to, but then is asked the next time again, and
it is not obvious that the "QML debugging" option is responsible for
this.
That is somewhat orthogonal to this change though: Even without this
change, if the user changes the QML debugging option from "Leave at
Default" to "Enable", the same happens, and it is also not clear to the
user how to get rid of it. The user might not even have realized that
they changed the option (e.g. on platforms where the mouse wheel cycles
combo box values).
I think the correct solution is to 1. make clearer where the CMake flags
came from in that dialog, 2. allow the user to cancel a build from that
dialog, 3. allow the user to discard these changes (by changing the
setting) from that dialog. But that is for another patch.
Amends 3300182d405bffe062a0f2be900f35822a9e20b0
Amends 77fed0b0fdce2a93f465c20cd87c41900117dcda
Change-Id: I95de59473b67c5afd6a53ea7f49838dbaef770d4
Reviewed-by: Artem Sokolovskii <artem.sokolovskii@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Cristian Adam <cristian.adam@qt.io>
2022-05-18 10:40:31 +02:00
|
|
|
QVariantMap config = info.extraInfo.toMap(); // new empty, or existing one from createBuildInfo
|
2023-01-03 12:31:52 +01:00
|
|
|
config.insert(Constants::CMAKE_HOME_DIR, data->cmakeHomeDirectory.toVariant());
|
CMake: Add 'Profile' configuration
Get rid of the hardcoded QML Debugging for Debug & RelWithDebInfo from
the project template, because RelWithDebInfo is actually a good
configuration for doing releases (we use it for Qt Creator), and
enabling QML debugging for releases is a bad idea.
Instead enable QML Debugging in Qt Creator for the Debug configuration,
and add a 'Profile' configuration that is 'RelWithDebInfo + QML
Debugging'.
When importing a build, we only set the "QML debugging" option of the
build configuration, if it is enabled in the imported build, even if it
uses CMAKE_BUILD_TYPE=Debug .
One drawback: When not importing a build, but just setting the build
directory of a "Profile" or "Debug" configuration to an existing build,
Qt Creator asks if it should apply "-DCMAKE_CXX_FLAGS=-DQT_QML_DEBUG".
The user can choose not to, but then is asked the next time again, and
it is not obvious that the "QML debugging" option is responsible for
this.
That is somewhat orthogonal to this change though: Even without this
change, if the user changes the QML debugging option from "Leave at
Default" to "Enable", the same happens, and it is also not clear to the
user how to get rid of it. The user might not even have realized that
they changed the option (e.g. on platforms where the mouse wheel cycles
combo box values).
I think the correct solution is to 1. make clearer where the CMake flags
came from in that dialog, 2. allow the user to cancel a build from that
dialog, 3. allow the user to discard these changes (by changing the
setting) from that dialog. But that is for another patch.
Amends 3300182d405bffe062a0f2be900f35822a9e20b0
Amends 77fed0b0fdce2a93f465c20cd87c41900117dcda
Change-Id: I95de59473b67c5afd6a53ea7f49838dbaef770d4
Reviewed-by: Artem Sokolovskii <artem.sokolovskii@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Cristian Adam <cristian.adam@qt.io>
2022-05-18 10:40:31 +02:00
|
|
|
// Potentially overwrite the default QML Debugging settings for the build type as set by
|
|
|
|
|
// createBuildInfo, in case we are importing a "Debug" CMake configuration without QML Debugging
|
|
|
|
|
config.insert(Constants::QML_DEBUG_SETTING,
|
|
|
|
|
data->hasQmlDebugging ? TriState::Enabled.toVariant()
|
|
|
|
|
: TriState::Default.toVariant());
|
2020-12-02 19:16:40 +01:00
|
|
|
info.extraInfo = config;
|
|
|
|
|
|
2020-06-18 14:21:09 +02:00
|
|
|
qCDebug(cmInputLog) << "BuildInfo configured.";
|
2019-01-30 12:10:24 +01:00
|
|
|
return {info};
|
2016-08-25 14:33:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CMakeProjectImporter::CMakeToolData
|
2021-01-04 13:48:21 +01:00
|
|
|
CMakeProjectImporter::findOrCreateCMakeTool(const FilePath &cmakeToolPath) const
|
2016-08-25 14:33:44 +02:00
|
|
|
{
|
|
|
|
|
CMakeToolData result;
|
|
|
|
|
result.cmakeTool = CMakeToolManager::findByCommand(cmakeToolPath);
|
|
|
|
|
if (!result.cmakeTool) {
|
2020-06-18 14:21:09 +02:00
|
|
|
qCDebug(cmInputLog) << "Creating temporary CMakeTool for" << cmakeToolPath.toUserOutput();
|
2020-08-18 11:34:44 +01:00
|
|
|
|
|
|
|
|
UpdateGuard guard(*this);
|
|
|
|
|
|
|
|
|
|
auto newTool = std::make_unique<CMakeTool>(CMakeTool::ManualDetection, CMakeTool::createId());
|
|
|
|
|
newTool->setFilePath(cmakeToolPath);
|
|
|
|
|
newTool->setDisplayName(uniqueCMakeToolDisplayName(*newTool));
|
|
|
|
|
|
|
|
|
|
result.cmakeTool = newTool.get();
|
2016-08-25 14:33:44 +02:00
|
|
|
result.isTemporary = true;
|
2020-08-18 11:34:44 +01:00
|
|
|
CMakeToolManager::registerCMakeTool(std::move(newTool));
|
2016-08-25 14:33:44 +02:00
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CMakeProjectImporter::deleteDirectoryData(void *directoryData) const
|
|
|
|
|
{
|
|
|
|
|
delete static_cast<DirectoryData *>(directoryData);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CMakeProjectImporter::cleanupTemporaryCMake(Kit *k, const QVariantList &vl)
|
|
|
|
|
{
|
|
|
|
|
if (vl.isEmpty())
|
|
|
|
|
return; // No temporary CMake
|
|
|
|
|
QTC_ASSERT(vl.count() == 1, return);
|
2021-01-04 13:48:21 +01:00
|
|
|
CMakeKitAspect::setCMakeTool(k, Id()); // Always mark Kit as not using this Qt
|
|
|
|
|
CMakeToolManager::deregisterCMakeTool(Id::fromSetting(vl.at(0)));
|
2020-06-18 14:21:09 +02:00
|
|
|
qCDebug(cmInputLog) << "Temporary CMake tool cleaned up.";
|
2016-08-25 14:33:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CMakeProjectImporter::persistTemporaryCMake(Kit *k, const QVariantList &vl)
|
|
|
|
|
{
|
|
|
|
|
if (vl.isEmpty())
|
|
|
|
|
return; // No temporary CMake
|
|
|
|
|
QTC_ASSERT(vl.count() == 1, return);
|
2023-10-20 14:46:33 +02:00
|
|
|
const QVariant &data = vl.at(0);
|
2021-01-04 13:48:21 +01:00
|
|
|
CMakeTool *tmpCmake = CMakeToolManager::findById(Id::fromSetting(data));
|
2019-02-06 12:50:51 +01:00
|
|
|
CMakeTool *actualCmake = CMakeKitAspect::cmakeTool(k);
|
2016-08-25 14:33:44 +02:00
|
|
|
|
|
|
|
|
// User changed Kit away from temporary CMake that was set up:
|
|
|
|
|
if (tmpCmake && actualCmake != tmpCmake)
|
|
|
|
|
CMakeToolManager::deregisterCMakeTool(tmpCmake->id());
|
|
|
|
|
|
2020-06-18 14:21:09 +02:00
|
|
|
qCDebug(cmInputLog) << "Temporary CMake tool made persistent.";
|
2016-08-25 14:33:44 +02:00
|
|
|
}
|
|
|
|
|
|
2022-09-26 14:21:12 +02:00
|
|
|
} // CMakeProjectManager::Internal
|
2016-08-25 14:33:44 +02:00
|
|
|
|
|
|
|
|
#ifdef WITH_TESTS
|
|
|
|
|
|
|
|
|
|
#include <QTest>
|
|
|
|
|
|
2024-01-12 12:52:29 +01:00
|
|
|
namespace CMakeProjectManager::Internal {
|
|
|
|
|
|
|
|
|
|
class CMakeProjectImporterTest final : public QObject
|
|
|
|
|
{
|
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
|
|
private slots:
|
|
|
|
|
void testCMakeProjectImporterQt_data();
|
|
|
|
|
void testCMakeProjectImporterQt();
|
|
|
|
|
|
|
|
|
|
void testCMakeProjectImporterToolchain_data();
|
|
|
|
|
void testCMakeProjectImporterToolchain();
|
|
|
|
|
};
|
2016-08-25 14:33:44 +02:00
|
|
|
|
2024-01-12 12:52:29 +01:00
|
|
|
void CMakeProjectImporterTest::testCMakeProjectImporterQt_data()
|
2016-08-25 14:33:44 +02:00
|
|
|
{
|
|
|
|
|
QTest::addColumn<QStringList>("cache");
|
|
|
|
|
QTest::addColumn<QString>("expectedQmake");
|
|
|
|
|
|
|
|
|
|
QTest::newRow("Empty input")
|
|
|
|
|
<< QStringList() << QString();
|
|
|
|
|
|
|
|
|
|
QTest::newRow("Qt4")
|
2017-02-22 15:09:35 +01:00
|
|
|
<< QStringList({QString::fromLatin1("QT_QMAKE_EXECUTABLE=/usr/bin/xxx/qmake")})
|
2016-08-25 14:33:44 +02:00
|
|
|
<< "/usr/bin/xxx/qmake";
|
|
|
|
|
|
|
|
|
|
// Everything else will require Qt installations!
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-12 12:52:29 +01:00
|
|
|
void CMakeProjectImporterTest::testCMakeProjectImporterQt()
|
2016-08-25 14:33:44 +02:00
|
|
|
{
|
|
|
|
|
QFETCH(QStringList, cache);
|
|
|
|
|
QFETCH(QString, expectedQmake);
|
|
|
|
|
|
|
|
|
|
CMakeConfig config;
|
2022-10-07 14:46:06 +02:00
|
|
|
for (const QString &c : std::as_const(cache)) {
|
2016-08-25 14:33:44 +02:00
|
|
|
const int pos = c.indexOf('=');
|
|
|
|
|
Q_ASSERT(pos > 0);
|
|
|
|
|
const QString key = c.left(pos);
|
|
|
|
|
const QString value = c.mid(pos + 1);
|
|
|
|
|
config.append(CMakeConfigItem(key.toUtf8(), value.toUtf8()));
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-02 20:50:44 +02:00
|
|
|
auto [realQmake, cmakePrefixPath] = qtInfoFromCMakeCache(config,
|
|
|
|
|
Environment::systemEnvironment());
|
|
|
|
|
QCOMPARE(realQmake.path(), expectedQmake);
|
2016-08-25 14:33:44 +02:00
|
|
|
}
|
2024-01-12 12:52:29 +01:00
|
|
|
void CMakeProjectImporterTest::testCMakeProjectImporterToolchain_data()
|
2016-08-25 14:33:44 +02:00
|
|
|
{
|
|
|
|
|
QTest::addColumn<QStringList>("cache");
|
|
|
|
|
QTest::addColumn<QByteArrayList>("expectedLanguages");
|
2023-12-11 11:42:00 +01:00
|
|
|
QTest::addColumn<QStringList>("expectedToolchains");
|
2016-08-25 14:33:44 +02:00
|
|
|
|
|
|
|
|
QTest::newRow("Empty input")
|
|
|
|
|
<< QStringList() << QByteArrayList() << QStringList();
|
|
|
|
|
|
|
|
|
|
QTest::newRow("Unrelated input")
|
|
|
|
|
<< QStringList("CMAKE_SOMETHING_ELSE=/tmp") << QByteArrayList() << QStringList();
|
|
|
|
|
QTest::newRow("CXX compiler")
|
2017-02-22 15:09:35 +01:00
|
|
|
<< QStringList({"CMAKE_CXX_COMPILER=/usr/bin/g++"})
|
2019-07-02 11:31:12 +02:00
|
|
|
<< QByteArrayList({"Cxx"})
|
2017-02-22 15:09:35 +01:00
|
|
|
<< QStringList({"/usr/bin/g++"});
|
2016-08-25 14:33:44 +02:00
|
|
|
QTest::newRow("CXX compiler, C compiler")
|
2017-02-22 15:09:35 +01:00
|
|
|
<< QStringList({"CMAKE_CXX_COMPILER=/usr/bin/g++", "CMAKE_C_COMPILER=/usr/bin/clang"})
|
2019-07-02 11:31:12 +02:00
|
|
|
<< QByteArrayList({"Cxx", "C"})
|
2017-02-22 15:09:35 +01:00
|
|
|
<< QStringList({"/usr/bin/g++", "/usr/bin/clang"});
|
2016-08-25 14:33:44 +02:00
|
|
|
QTest::newRow("CXX compiler, C compiler, strange compiler")
|
2017-02-22 15:09:35 +01:00
|
|
|
<< QStringList({"CMAKE_CXX_COMPILER=/usr/bin/g++",
|
2016-08-25 14:33:44 +02:00
|
|
|
"CMAKE_C_COMPILER=/usr/bin/clang",
|
2017-02-22 15:09:35 +01:00
|
|
|
"CMAKE_STRANGE_LANGUAGE_COMPILER=/tmp/strange/compiler"})
|
2019-07-02 11:31:12 +02:00
|
|
|
<< QByteArrayList({"Cxx", "C", "STRANGE_LANGUAGE"})
|
2017-02-22 15:09:35 +01:00
|
|
|
<< QStringList({"/usr/bin/g++", "/usr/bin/clang", "/tmp/strange/compiler"});
|
2016-08-25 14:33:44 +02:00
|
|
|
QTest::newRow("CXX compiler, C compiler, strange compiler (with junk)")
|
2017-02-22 15:09:35 +01:00
|
|
|
<< QStringList({"FOO=test",
|
2016-08-25 14:33:44 +02:00
|
|
|
"CMAKE_CXX_COMPILER=/usr/bin/g++",
|
|
|
|
|
"CMAKE_BUILD_TYPE=debug",
|
|
|
|
|
"CMAKE_C_COMPILER=/usr/bin/clang",
|
|
|
|
|
"SOMETHING_COMPILER=/usr/bin/something",
|
|
|
|
|
"CMAKE_STRANGE_LANGUAGE_COMPILER=/tmp/strange/compiler",
|
2017-02-22 15:09:35 +01:00
|
|
|
"BAR=more test"})
|
2019-07-02 11:31:12 +02:00
|
|
|
<< QByteArrayList({"Cxx", "C", "STRANGE_LANGUAGE"})
|
2017-02-22 15:09:35 +01:00
|
|
|
<< QStringList({"/usr/bin/g++", "/usr/bin/clang", "/tmp/strange/compiler"});
|
2016-08-25 14:33:44 +02:00
|
|
|
}
|
|
|
|
|
|
2024-01-12 12:52:29 +01:00
|
|
|
void CMakeProjectImporterTest::testCMakeProjectImporterToolchain()
|
2016-08-25 14:33:44 +02:00
|
|
|
{
|
|
|
|
|
QFETCH(QStringList, cache);
|
|
|
|
|
QFETCH(QByteArrayList, expectedLanguages);
|
2023-12-11 11:42:00 +01:00
|
|
|
QFETCH(QStringList, expectedToolchains);
|
2016-08-25 14:33:44 +02:00
|
|
|
|
2023-12-11 11:42:00 +01:00
|
|
|
QCOMPARE(expectedLanguages.count(), expectedToolchains.count());
|
2016-08-25 14:33:44 +02:00
|
|
|
|
|
|
|
|
CMakeConfig config;
|
2022-10-07 14:46:06 +02:00
|
|
|
for (const QString &c : std::as_const(cache)) {
|
2016-08-25 14:33:44 +02:00
|
|
|
const int pos = c.indexOf('=');
|
|
|
|
|
Q_ASSERT(pos > 0);
|
|
|
|
|
const QString key = c.left(pos);
|
|
|
|
|
const QString value = c.mid(pos + 1);
|
|
|
|
|
config.append(CMakeConfigItem(key.toUtf8(), value.toUtf8()));
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-11 11:42:00 +01:00
|
|
|
const QVector<ToolchainDescription> tcs = extractToolchainsFromCache(config);
|
2016-08-25 14:33:44 +02:00
|
|
|
QCOMPARE(tcs.count(), expectedLanguages.count());
|
|
|
|
|
for (int i = 0; i < tcs.count(); ++i) {
|
2019-07-02 11:31:12 +02:00
|
|
|
QCOMPARE(tcs.at(i).language, expectedLanguages.at(i));
|
2023-12-11 11:42:00 +01:00
|
|
|
QCOMPARE(tcs.at(i).compilerPath.toString(), expectedToolchains.at(i));
|
2016-08-25 14:33:44 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-12 12:52:29 +01:00
|
|
|
QObject *createCMakeProjectImporterTest()
|
|
|
|
|
{
|
|
|
|
|
return new CMakeProjectImporterTest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // CMakeProjectManager::Internal
|
2016-08-25 14:33:44 +02:00
|
|
|
|
|
|
|
|
#endif
|
2024-01-12 12:52:29 +01:00
|
|
|
|
|
|
|
|
#include "cmakeprojectimporter.moc"
|