2022-08-19 15:59:36 +02:00
|
|
|
// Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
2016-08-25 14:33:44 +02:00
|
|
|
|
|
|
|
|
#include "cmakeprojectimporter.h"
|
|
|
|
|
|
|
|
|
|
#include "cmakebuildconfiguration.h"
|
|
|
|
|
#include "cmakekitinformation.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>
|
2020-04-17 15:30:05 +02:00
|
|
|
#include <projectexplorer/kitinformation.h>
|
2016-08-25 14:33:44 +02:00
|
|
|
#include <projectexplorer/projectexplorerconstants.h>
|
2020-12-09 12:41:11 +01:00
|
|
|
#include <projectexplorer/toolchainmanager.h>
|
2016-08-25 14:33:44 +02:00
|
|
|
|
|
|
|
|
#include <qtsupport/qtkitinformation.h>
|
|
|
|
|
|
|
|
|
|
#include <utils/algorithm.h>
|
|
|
|
|
#include <utils/qtcassert.h>
|
2022-03-02 04:12:25 +01:00
|
|
|
#include <utils/qtcprocess.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 extraGenerator;
|
|
|
|
|
QString platform;
|
|
|
|
|
QString toolset;
|
|
|
|
|
FilePath sysroot;
|
2016-08-25 14:33:44 +02:00
|
|
|
QtProjectImporter::QtVersionData qt;
|
2019-07-02 11:31:12 +02: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
|
|
|
|
2022-05-30 19:04:54 +02:00
|
|
|
CMakeProjectImporter::CMakeProjectImporter(const FilePath &path, const PresetsData &presetsData)
|
|
|
|
|
: QtProjectImporter(path)
|
|
|
|
|
, m_presetsData(presetsData)
|
|
|
|
|
, 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); });
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
for (const auto &configPreset : m_presetsData.configurePresets) {
|
|
|
|
|
if (configPreset.hidden.value())
|
|
|
|
|
continue;
|
|
|
|
|
|
2022-09-26 18:59:04 +02:00
|
|
|
if (configPreset.condition) {
|
|
|
|
|
if (!CMakePresets::Macros::evaluatePresetCondition(configPreset, projectFilePath()))
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-21 12:50:27 +02:00
|
|
|
const FilePath configPresetDir = m_presetsTempDir.filePath(configPreset.name);
|
|
|
|
|
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);
|
|
|
|
|
candidates.removeIf(
|
|
|
|
|
[&binaryFilePath] (const FilePath &path) { return path == binaryFilePath; });
|
|
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
|
2022-05-30 19:04:54 +02:00
|
|
|
static CMakeConfig configurationFromPresetProbe(
|
|
|
|
|
const FilePath &importPath, const PresetsDetails::ConfigurePreset &configurePreset)
|
|
|
|
|
{
|
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
|
|
|
|
|
|
|
|
QtcProcess cmake;
|
|
|
|
|
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();
|
2022-05-30 19:04:54 +02:00
|
|
|
CMakePresets::Macros::expand(configurePreset, env, importPath);
|
|
|
|
|
|
|
|
|
|
env.setupEnglishOutput();
|
|
|
|
|
cmake.setEnvironment(env);
|
|
|
|
|
cmake.setTimeOutMessageBoxEnabled(false);
|
|
|
|
|
|
|
|
|
|
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) {
|
|
|
|
|
args.emplace_back("-A");
|
|
|
|
|
args.emplace_back(configurePreset.architecture.value().value.value());
|
|
|
|
|
}
|
|
|
|
|
if (configurePreset.toolset && configurePreset.toolset.value().value) {
|
|
|
|
|
args.emplace_back("-T");
|
|
|
|
|
args.emplace_back(configurePreset.toolset.value().value.value());
|
|
|
|
|
}
|
2022-05-30 19:04:54 +02:00
|
|
|
|
|
|
|
|
if (configurePreset.cacheVariables) {
|
|
|
|
|
const CMakeConfig cache = configurePreset.cacheVariables
|
|
|
|
|
? configurePreset.cacheVariables.value()
|
|
|
|
|
: CMakeConfig();
|
|
|
|
|
const FilePath cmakeMakeProgram = cache.filePathValueOf(QByteArray("CMAKE_MAKE_PROGRAM"));
|
|
|
|
|
const FilePath toolchainFile = cache.filePathValueOf(QByteArray("CMAKE_TOOLCHAIN_FILE"));
|
|
|
|
|
const QString prefixPath = cache.stringValueOf(QByteArray("CMAKE_PREFIX_PATH"));
|
|
|
|
|
const QString findRootPath = cache.stringValueOf(QByteArray("CMAKE_FIND_ROOT_PATH"));
|
|
|
|
|
const QString qtHostPath = cache.stringValueOf(QByteArray("QT_HOST_PATH"));
|
|
|
|
|
|
|
|
|
|
if (!cmakeMakeProgram.isEmpty()) {
|
|
|
|
|
args.emplace_back(
|
|
|
|
|
QStringLiteral("-DCMAKE_MAKE_PROGRAM=%1").arg(cmakeMakeProgram.toString()));
|
|
|
|
|
}
|
|
|
|
|
if (!toolchainFile.isEmpty()) {
|
|
|
|
|
args.emplace_back(
|
|
|
|
|
QStringLiteral("-DCMAKE_TOOLCHAIN_FILE=%1").arg(toolchainFile.toString()));
|
|
|
|
|
}
|
|
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-04 13:48:21 +01:00
|
|
|
static FilePath qmakeFromCMakeCache(const CMakeConfig &config)
|
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
|
|
|
if (!qmake.isEmpty())
|
|
|
|
|
return qmake;
|
|
|
|
|
|
|
|
|
|
// Check Qt5 settings: oh, the horror!
|
2021-01-04 13:48:21 +01:00
|
|
|
const FilePath qtCMakeDir = [config] {
|
2021-07-06 10:29:29 +02:00
|
|
|
FilePath tmp = config.filePathValueOf("Qt5Core_DIR");
|
|
|
|
|
if (tmp.isEmpty())
|
|
|
|
|
tmp = config.filePathValueOf("Qt6Core_DIR");
|
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();
|
2022-05-30 19:04:54 +02:00
|
|
|
QString prefixPath;
|
|
|
|
|
if (!qtCMakeDir.isEmpty()) {
|
|
|
|
|
prefixPath = canQtCMakeDir.parentDir().parentDir().parentDir().toString(); // Up 3 levels...
|
|
|
|
|
} else {
|
|
|
|
|
prefixPath = config.stringValueOf("CMAKE_PREFIX_PATH");
|
|
|
|
|
}
|
|
|
|
|
qCDebug(cmInputLog) << "PrefixPath:" << prefixPath;
|
2022-09-29 15:47:05 +02:00
|
|
|
|
|
|
|
|
FilePath toolchainFile = config.filePathValueOf(QByteArray("CMAKE_TOOLCHAIN_FILE"));
|
|
|
|
|
if (prefixPath.isEmpty() && toolchainFile.isEmpty())
|
2021-01-04 13:48:21 +01:00
|
|
|
return FilePath();
|
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
|
|
|
|
2021-07-01 09:58:48 +02:00
|
|
|
QFile cmakeListTxt(qtcQMakeProbeDir.filePath("CMakeLists.txt").toString());
|
2020-12-31 14:08:16 +01:00
|
|
|
if (!cmakeListTxt.open(QIODevice::WriteOnly)) {
|
|
|
|
|
return FilePath();
|
|
|
|
|
}
|
2021-04-28 11:23:56 +02:00
|
|
|
// FIXME replace by raw string when gcc 8+ is minimum
|
|
|
|
|
cmakeListTxt.write(QByteArray(
|
|
|
|
|
"cmake_minimum_required(VERSION 3.15)\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"project(qmake-probe LANGUAGES NONE)\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"# Bypass Qt6's usage of find_dependency, which would require compiler\n"
|
2021-11-04 16:57:22 +01:00
|
|
|
"# and source code probing, which slows things unnecessarily\n"
|
2021-04-28 11:23:56 +02:00
|
|
|
"file(WRITE \"${CMAKE_SOURCE_DIR}/CMakeFindDependencyMacro.cmake\"\n"
|
|
|
|
|
"[=["
|
|
|
|
|
" macro(find_dependency dep)\n"
|
|
|
|
|
" endmacro()\n"
|
|
|
|
|
"]=])\n"
|
|
|
|
|
"set(CMAKE_MODULE_PATH \"${CMAKE_SOURCE_DIR}\")\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)\n"
|
|
|
|
|
"find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED)\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"if (CMAKE_CROSSCOMPILING)\n"
|
|
|
|
|
" find_program(qmake_binary\n"
|
|
|
|
|
" NAMES qmake qmake.bat\n"
|
|
|
|
|
" PATHS \"${Qt${QT_VERSION_MAJOR}_DIR}/../../../bin\"\n"
|
|
|
|
|
" NO_DEFAULT_PATH)\n"
|
|
|
|
|
" file(WRITE \"${CMAKE_SOURCE_DIR}/qmake-location.txt\" \"${qmake_binary}\")\n"
|
|
|
|
|
"else()\n"
|
|
|
|
|
" file(GENERATE\n"
|
|
|
|
|
" OUTPUT \"${CMAKE_SOURCE_DIR}/qmake-location.txt\"\n"
|
|
|
|
|
" CONTENT \"$<TARGET_PROPERTY:Qt${QT_VERSION_MAJOR}::qmake,IMPORTED_LOCATION>\")\n"
|
|
|
|
|
"endif()\n"
|
|
|
|
|
));
|
2020-12-31 14:08:16 +01:00
|
|
|
cmakeListTxt.close();
|
|
|
|
|
|
2021-06-22 04:33:47 +02:00
|
|
|
QtcProcess cmake;
|
2020-12-31 14:08:16 +01:00
|
|
|
cmake.setTimeoutS(5);
|
2021-05-05 15:23:34 +02:00
|
|
|
cmake.setDisableUnixTerminal();
|
2020-12-31 14:08:16 +01:00
|
|
|
Environment env = Environment::systemEnvironment();
|
2021-05-20 11:57:21 +02:00
|
|
|
env.setupEnglishOutput();
|
2021-04-30 18:26:57 +02:00
|
|
|
cmake.setEnvironment(env);
|
2020-12-31 14:08:16 +01:00
|
|
|
cmake.setTimeOutMessageBoxEnabled(false);
|
|
|
|
|
|
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"));
|
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());
|
2020-12-31 14:08:16 +01:00
|
|
|
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()));
|
|
|
|
|
}
|
|
|
|
|
if (toolchainFile.isEmpty()) {
|
2022-05-30 19:04:54 +02:00
|
|
|
args.push_back(QStringLiteral("-DCMAKE_PREFIX_PATH=%1").arg(prefixPath));
|
2020-12-31 14:08:16 +01:00
|
|
|
} else {
|
2022-09-29 15:47:05 +02:00
|
|
|
if (!prefixPath.isEmpty())
|
|
|
|
|
args.push_back(QStringLiteral("-DCMAKE_FIND_ROOT_PATH=%1").arg(prefixPath));
|
2020-12-31 14:08:16 +01:00
|
|
|
args.push_back(QStringLiteral("-DCMAKE_TOOLCHAIN_FILE=%1").arg(toolchainFile.toString()));
|
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2021-07-01 09:58:48 +02:00
|
|
|
QFile qmakeLocationTxt(qtcQMakeProbeDir.filePath("qmake-location.txt").path());
|
2020-12-31 14:08:16 +01:00
|
|
|
if (!qmakeLocationTxt.open(QIODevice::ReadOnly)) {
|
|
|
|
|
return FilePath();
|
2016-08-25 14:33:44 +02:00
|
|
|
}
|
2021-02-15 00:49:15 +01:00
|
|
|
FilePath qmakeLocation = FilePath::fromUtf8(qmakeLocationTxt.readLine().constData());
|
2020-12-31 14:08:16 +01:00
|
|
|
qCDebug(cmInputLog) << "qmake location: " << qmakeLocation.toUserOutput();
|
2016-08-25 14:33:44 +02:00
|
|
|
|
2020-12-31 14:08:16 +01:00
|
|
|
return qmakeLocation;
|
2016-08-25 14:33:44 +02:00
|
|
|
}
|
|
|
|
|
|
2019-07-02 11:31:12 +02:00
|
|
|
static QVector<ToolChainDescription> extractToolChainsFromCache(const CMakeConfig &config)
|
2016-08-25 14:33:44 +02:00
|
|
|
{
|
2019-07-02 11:31:12 +02: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;
|
|
|
|
|
const QByteArray language = i.key.mid(6, i.key.count() - 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;
|
|
|
|
|
}
|
|
|
|
|
|
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>();
|
|
|
|
|
|
|
|
|
|
const QString presetName = importPath.fileName();
|
|
|
|
|
PresetsDetails::ConfigurePreset configurePreset
|
|
|
|
|
= Utils::findOrDefault(m_presetsData.configurePresets,
|
|
|
|
|
[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();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data->cmakeBinary = Utils::FilePath::fromString(configurePreset.cmakeExecutable.value());
|
|
|
|
|
if (configurePreset.generator)
|
|
|
|
|
data->generator = configurePreset.generator.value();
|
|
|
|
|
|
|
|
|
|
if (configurePreset.architecture && configurePreset.architecture.value().value)
|
|
|
|
|
data->platform = configurePreset.architecture.value().value.value();
|
|
|
|
|
|
|
|
|
|
if (configurePreset.toolset && configurePreset.toolset.value().value)
|
|
|
|
|
data->toolset = configurePreset.toolset.value().value.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
|
|
|
}
|
|
|
|
|
|
2022-09-26 18:59:04 +02:00
|
|
|
CMakePresets::Macros::updateToolchainFile(configurePreset,
|
|
|
|
|
env,
|
|
|
|
|
projectDirectory(),
|
|
|
|
|
data->buildDirectory);
|
|
|
|
|
|
2022-05-30 19:04:54 +02:00
|
|
|
const CMakeConfig cache = configurePreset.cacheVariables
|
|
|
|
|
? configurePreset.cacheVariables.value()
|
|
|
|
|
: CMakeConfig();
|
|
|
|
|
|
|
|
|
|
data->sysroot = cache.filePathValueOf("CMAKE_SYSROOT");
|
|
|
|
|
|
|
|
|
|
CMakeConfig config;
|
|
|
|
|
if (cache.valueOf("CMAKE_C_COMPILER").isEmpty()
|
|
|
|
|
&& cache.valueOf("CMAKE_CXX_COMPILER").isEmpty()) {
|
|
|
|
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
|
|
|
|
config = configurationFromPresetProbe(importPath, configurePreset);
|
|
|
|
|
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;
|
|
|
|
|
config << CMakeConfigItem("CMAKE_COMMAND",
|
|
|
|
|
CMakeConfigItem::PATH,
|
|
|
|
|
configurePreset.cmakeExecutable.value().toUtf8());
|
|
|
|
|
if (configurePreset.generator)
|
|
|
|
|
config << CMakeConfigItem("CMAKE_GENERATOR",
|
|
|
|
|
CMakeConfigItem::STRING,
|
|
|
|
|
configurePreset.generator.value().toUtf8());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const FilePath qmake = qmakeFromCMakeCache(config);
|
|
|
|
|
if (!qmake.isEmpty())
|
|
|
|
|
data->qt = findOrCreateQtVersion(qmake);
|
|
|
|
|
|
|
|
|
|
// ToolChains:
|
|
|
|
|
data->toolChains = extractToolChainsFromCache(config);
|
|
|
|
|
|
2022-10-10 19:33:48 +02:00
|
|
|
QByteArrayList buildConfigurationTypes = {cache.valueOf("CMAKE_BUILD_TYPE")};
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
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->extraGenerator = config.stringValueOf("CMAKE_EXTRA_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:
|
|
|
|
|
const FilePath qmake = qmakeFromCMakeCache(config);
|
|
|
|
|
if (!qmake.isEmpty())
|
|
|
|
|
data->qt = findOrCreateQtVersion(qmake);
|
2016-08-25 14:33:44 +02:00
|
|
|
|
2021-01-14 16:38:55 +01:00
|
|
|
// ToolChains:
|
|
|
|
|
data->toolChains = extractToolChainsFromCache(config);
|
|
|
|
|
|
|
|
|
|
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::extraGenerator(k) != data->extraGenerator
|
|
|
|
|
|| 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;
|
|
|
|
|
|
2022-10-23 16:11:52 +02:00
|
|
|
bool haveCMakePreset = false;
|
|
|
|
|
if (!data->cmakePreset.isEmpty()) {
|
|
|
|
|
auto presetConfigItem = CMakeConfigurationKitAspect::cmakePresetConfigItem(k);
|
|
|
|
|
if (data->cmakePreset != presetConfigItem.expandedValue(k))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
ensureBuildDirectory(*data, k);
|
|
|
|
|
haveCMakePreset = true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-09 12:41:11 +01:00
|
|
|
const QList<Id> allLanguages = ToolChainManager::allLanguages();
|
2019-07-02 11:31:12 +02:00
|
|
|
for (const ToolChainDescription &tcd : data->toolChains) {
|
2020-12-09 12:41:11 +01:00
|
|
|
if (!Utils::contains(allLanguages, [&tcd](const Id& language) {return language == tcd.language;}))
|
|
|
|
|
continue;
|
2019-07-02 11:31:12 +02:00
|
|
|
ToolChain *tc = ToolChainKitAspect::toolChain(k, tcd.language);
|
2022-10-23 16:11:52 +02:00
|
|
|
if ((!tc || !tc->matchesCompilerCommand(tcd.compilerPath)) && !haveCMakePreset) {
|
2016-08-25 14:33:44 +02:00
|
|
|
return false;
|
2021-02-01 19:19:45 +01:00
|
|
|
}
|
2016-08-25 14:33:44 +02:00
|
|
|
}
|
|
|
|
|
|
2020-06-18 14:21:09 +02:00
|
|
|
qCDebug(cmInputLog) << k->displayName()
|
2016-08-25 14:33:44 +02:00
|
|
|
<< "matches directoryData for" << data->buildDirectory.toUserOutput();
|
|
|
|
|
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::setExtraGenerator(k, data->extraGenerator);
|
|
|
|
|
CMakeGeneratorKitAspect::setPlatform(k, data->platform);
|
|
|
|
|
CMakeGeneratorKitAspect::setToolset(k, data->toolset);
|
2016-08-25 14:33:44 +02:00
|
|
|
|
2022-05-30 19:04:54 +02:00
|
|
|
if (!data->cmakePresetDisplayname.isEmpty()) {
|
|
|
|
|
k->setUnexpandedDisplayName(
|
|
|
|
|
QString("%1 (CMake preset)").arg(data->cmakePresetDisplayname));
|
|
|
|
|
|
|
|
|
|
CMakeConfigurationKitAspect::setCMakePreset(k, data->cmakePreset);
|
|
|
|
|
}
|
2022-10-07 15:08:33 +02:00
|
|
|
if (!data->cmakePreset.isEmpty())
|
|
|
|
|
ensureBuildDirectory(*data, k);
|
2022-05-30 19:04:54 +02:00
|
|
|
|
2021-07-06 09:50:01 +02:00
|
|
|
SysRootKitAspect::setSysRoot(k, data->sysroot);
|
2016-08-25 14:33:44 +02:00
|
|
|
|
2019-07-02 11:31:12 +02:00
|
|
|
for (const ToolChainDescription &cmtcd : data->toolChains) {
|
|
|
|
|
const ToolChainData tcd = findOrCreateToolChains(cmtcd);
|
2016-08-25 14:33:44 +02:00
|
|
|
QTC_ASSERT(!tcd.tcs.isEmpty(), continue);
|
|
|
|
|
|
|
|
|
|
if (tcd.areTemporary) {
|
|
|
|
|
for (ToolChain *tc : tcd.tcs)
|
2019-02-06 12:50:51 +01:00
|
|
|
addTemporaryData(ToolChainKitAspect::id(), tc->id(), k);
|
2016-08-25 14:33:44 +02:00
|
|
|
}
|
|
|
|
|
|
2019-02-06 12:50:51 +01:00
|
|
|
ToolChainKitAspect::setToolChain(k, tcd.tcs.at(0));
|
2016-08-25 14:33:44 +02:00
|
|
|
}
|
|
|
|
|
|
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
|
2020-12-02 19:16:40 +01:00
|
|
|
config.insert(Constants::CMAKE_HOME_DIR, data->cmakeHomeDirectory.toString());
|
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);
|
|
|
|
|
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 "cmakeprojectplugin.h"
|
|
|
|
|
|
|
|
|
|
#include <QTest>
|
|
|
|
|
|
|
|
|
|
namespace CMakeProjectManager {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
|
|
|
|
|
void CMakeProjectPlugin::testCMakeProjectImporterQt_data()
|
|
|
|
|
{
|
|
|
|
|
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!
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CMakeProjectPlugin::testCMakeProjectImporterQt()
|
|
|
|
|
{
|
|
|
|
|
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()));
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-04 13:48:21 +01:00
|
|
|
FilePath realQmake = qmakeFromCMakeCache(config);
|
2016-08-25 14:33:44 +02:00
|
|
|
QCOMPARE(realQmake.toString(), expectedQmake);
|
|
|
|
|
}
|
|
|
|
|
void CMakeProjectPlugin::testCMakeProjectImporterToolChain_data()
|
|
|
|
|
{
|
|
|
|
|
QTest::addColumn<QStringList>("cache");
|
|
|
|
|
QTest::addColumn<QByteArrayList>("expectedLanguages");
|
|
|
|
|
QTest::addColumn<QStringList>("expectedToolChains");
|
|
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CMakeProjectPlugin::testCMakeProjectImporterToolChain()
|
|
|
|
|
{
|
|
|
|
|
QFETCH(QStringList, cache);
|
|
|
|
|
QFETCH(QByteArrayList, expectedLanguages);
|
|
|
|
|
QFETCH(QStringList, expectedToolChains);
|
|
|
|
|
|
|
|
|
|
QCOMPARE(expectedLanguages.count(), expectedToolChains.count());
|
|
|
|
|
|
|
|
|
|
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()));
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-02 11:31:12 +02: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));
|
2016-08-25 14:33:44 +02:00
|
|
|
QCOMPARE(tcs.at(i).compilerPath.toString(), expectedToolChains.at(i));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace Internal
|
|
|
|
|
} // namespace CMakeProjectManager
|
|
|
|
|
|
|
|
|
|
#endif
|