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
|
2019-06-05 18:09:02 +02:00
|
|
|
|
|
|
|
|
#include "cmakeprocess.h"
|
|
|
|
|
|
2022-05-14 02:27:28 +02:00
|
|
|
#include "builddirparameters.h"
|
2019-06-05 18:09:02 +02:00
|
|
|
#include "cmakeparser.h"
|
2023-02-07 18:15:58 +01:00
|
|
|
#include "cmakeprojectconstants.h"
|
2022-09-29 15:26:31 +02:00
|
|
|
#include "cmakeprojectmanagertr.h"
|
2023-02-07 18:15:58 +01:00
|
|
|
#include "cmakespecificsettings.h"
|
2019-06-05 18:09:02 +02:00
|
|
|
|
2022-10-10 12:28:29 +02:00
|
|
|
#include <coreplugin/progressmanager/processprogress.h>
|
2021-06-01 16:21:03 +02:00
|
|
|
#include <projectexplorer/buildsystem.h>
|
2019-06-05 18:09:02 +02:00
|
|
|
#include <projectexplorer/projectexplorerconstants.h>
|
|
|
|
|
#include <projectexplorer/taskhub.h>
|
2023-06-27 16:57:51 +02:00
|
|
|
#include <projectexplorer/kitchooser.h>
|
|
|
|
|
|
|
|
|
|
#include <extensionsystem/invoker.h>
|
|
|
|
|
#include <extensionsystem/pluginmanager.h>
|
2019-06-05 18:09:02 +02:00
|
|
|
|
2023-10-04 17:31:20 +02:00
|
|
|
#include <utils/algorithm.h>
|
2023-05-03 17:05:35 +02:00
|
|
|
#include <utils/process.h>
|
2023-06-27 16:57:51 +02:00
|
|
|
#include <utils/processinfo.h>
|
2022-05-13 18:22:03 +02:00
|
|
|
#include <utils/processinterface.h>
|
2020-02-28 15:09:35 +01:00
|
|
|
#include <utils/stringutils.h>
|
2023-10-05 17:00:03 +02:00
|
|
|
#include <utils/stylehelper.h>
|
|
|
|
|
#include <utils/theme/theme.h>
|
2019-06-05 18:09:02 +02:00
|
|
|
|
2022-10-10 12:28:29 +02:00
|
|
|
using namespace Core;
|
2022-09-29 15:26:31 +02:00
|
|
|
using namespace ProjectExplorer;
|
2021-05-14 15:21:54 +02:00
|
|
|
using namespace Utils;
|
|
|
|
|
|
2022-09-29 15:26:31 +02:00
|
|
|
namespace CMakeProjectManager::Internal {
|
2019-06-05 18:09:02 +02:00
|
|
|
|
2021-06-14 12:06:23 +02:00
|
|
|
static QString stripTrailingNewline(QString str)
|
2019-06-05 18:09:02 +02:00
|
|
|
{
|
2021-06-14 12:06:23 +02:00
|
|
|
if (str.endsWith('\n'))
|
|
|
|
|
str.chop(1);
|
|
|
|
|
return str;
|
2019-06-05 18:09:02 +02:00
|
|
|
}
|
|
|
|
|
|
2022-05-14 02:27:28 +02:00
|
|
|
CMakeProcess::CMakeProcess() = default;
|
2019-06-05 18:09:02 +02:00
|
|
|
|
|
|
|
|
CMakeProcess::~CMakeProcess()
|
|
|
|
|
{
|
2020-04-15 14:59:51 +02:00
|
|
|
m_parser.flush();
|
2019-06-05 18:09:02 +02:00
|
|
|
}
|
|
|
|
|
|
2023-05-09 22:49:14 +02:00
|
|
|
static const int failedToStartExitCode = 0xFF; // See ProcessPrivate::handleDone() impl
|
2022-10-10 13:16:01 +02:00
|
|
|
|
2019-06-05 18:09:02 +02:00
|
|
|
void CMakeProcess::run(const BuildDirParameters ¶meters, const QStringList &arguments)
|
|
|
|
|
{
|
2022-05-18 21:13:48 +02:00
|
|
|
QTC_ASSERT(!m_process, return);
|
2019-06-05 18:09:02 +02:00
|
|
|
|
|
|
|
|
CMakeTool *cmake = parameters.cmakeTool();
|
|
|
|
|
QTC_ASSERT(parameters.isValid() && cmake, return);
|
|
|
|
|
|
2021-10-18 10:23:35 +02:00
|
|
|
const FilePath cmakeExecutable = cmake->cmakeExecutable();
|
|
|
|
|
|
2022-09-30 17:06:53 +02:00
|
|
|
if (!cmakeExecutable.ensureReachable(parameters.sourceDirectory)) {
|
2022-10-10 13:16:01 +02:00
|
|
|
const QString msg = ::CMakeProjectManager::Tr::tr(
|
2022-09-30 17:06:53 +02:00
|
|
|
"The source directory %1 is not reachable by the CMake executable %2.")
|
|
|
|
|
.arg(parameters.sourceDirectory.displayName()).arg(cmakeExecutable.displayName());
|
2023-10-04 17:31:20 +02:00
|
|
|
BuildSystem::appendBuildSystemOutput(addCMakePrefix({msg, QString()}).join('\n'));
|
2022-10-10 13:16:01 +02:00
|
|
|
emit finished(failedToStartExitCode);
|
2022-09-30 17:06:53 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!cmakeExecutable.ensureReachable(parameters.buildDirectory)) {
|
2022-10-10 13:16:01 +02:00
|
|
|
const QString msg = ::CMakeProjectManager::Tr::tr(
|
2022-09-30 17:06:53 +02:00
|
|
|
"The build directory %1 is not reachable by the CMake executable %2.")
|
|
|
|
|
.arg(parameters.buildDirectory.displayName()).arg(cmakeExecutable.displayName());
|
2023-10-04 17:31:20 +02:00
|
|
|
BuildSystem::appendBuildSystemOutput(addCMakePrefix({msg, QString()}).join('\n'));
|
2022-10-10 13:16:01 +02:00
|
|
|
emit finished(failedToStartExitCode);
|
2022-09-14 16:04:30 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-29 13:45:42 +02:00
|
|
|
const FilePath sourceDirectory = cmakeExecutable.withNewMappedPath(parameters.sourceDirectory);
|
2023-04-04 10:39:20 +02:00
|
|
|
const FilePath buildDirectory = parameters.buildDirectory;
|
2021-10-18 10:23:35 +02:00
|
|
|
|
2021-08-25 12:09:10 +02:00
|
|
|
if (!buildDirectory.exists()) {
|
2022-10-10 13:16:01 +02:00
|
|
|
const QString msg = ::CMakeProjectManager::Tr::tr(
|
|
|
|
|
"The build directory \"%1\" does not exist").arg(buildDirectory.toUserOutput());
|
2023-10-04 17:31:20 +02:00
|
|
|
BuildSystem::appendBuildSystemOutput(addCMakePrefix({msg, QString()}).join('\n'));
|
2022-10-10 13:16:01 +02:00
|
|
|
emit finished(failedToStartExitCode);
|
2021-08-25 12:09:10 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (buildDirectory.needsDevice()) {
|
2023-08-08 13:43:19 +02:00
|
|
|
if (!cmake->cmakeExecutable().isSameDevice(buildDirectory)) {
|
2022-10-10 13:16:01 +02:00
|
|
|
const QString msg = ::CMakeProjectManager::Tr::tr(
|
|
|
|
|
"CMake executable \"%1\" and build directory \"%2\" must be on the same device.")
|
|
|
|
|
.arg(cmake->cmakeExecutable().toUserOutput(), buildDirectory.toUserOutput());
|
2023-10-04 17:31:20 +02:00
|
|
|
BuildSystem::appendBuildSystemOutput(addCMakePrefix({msg, QString()}).join('\n'));
|
2022-10-10 13:16:01 +02:00
|
|
|
emit finished(failedToStartExitCode);
|
2021-08-25 12:09:10 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-06-05 18:09:02 +02:00
|
|
|
|
2023-02-07 18:15:58 +01:00
|
|
|
// Copy the "package-manager" CMake code from the ${IDE:ResourcePath} to the build directory
|
2023-07-06 17:06:20 +02:00
|
|
|
if (settings().packageManagerAutoSetup()) {
|
2023-02-07 18:15:58 +01:00
|
|
|
const FilePath localPackageManagerDir = buildDirectory.pathAppended(Constants::PACKAGE_MANAGER_DIR);
|
|
|
|
|
const FilePath idePackageManagerDir = FilePath::fromString(
|
|
|
|
|
parameters.expander->expand(QStringLiteral("%{IDE:ResourcePath}/package-manager")));
|
|
|
|
|
|
|
|
|
|
if (!localPackageManagerDir.exists() && idePackageManagerDir.exists())
|
|
|
|
|
idePackageManagerDir.copyRecursively(localPackageManagerDir);
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-15 14:59:51 +02:00
|
|
|
const auto parser = new CMakeParser;
|
2022-09-30 17:21:09 +02:00
|
|
|
parser->setSourceDirectory(parameters.sourceDirectory);
|
2020-04-15 14:59:51 +02:00
|
|
|
m_parser.addLineParser(parser);
|
2019-06-05 18:09:02 +02:00
|
|
|
|
|
|
|
|
// Always use the sourceDir: If we are triggered because the build directory is getting deleted
|
|
|
|
|
// then we are racing against CMakeCache.txt also getting deleted.
|
|
|
|
|
|
2023-05-03 16:00:22 +02:00
|
|
|
m_process.reset(new Process);
|
2019-06-14 16:42:41 +02:00
|
|
|
|
2022-05-13 18:22:03 +02:00
|
|
|
m_process->setWorkingDirectory(buildDirectory);
|
|
|
|
|
m_process->setEnvironment(parameters.environment);
|
2019-06-05 18:09:02 +02:00
|
|
|
|
2023-07-04 16:32:37 +02:00
|
|
|
m_process->setStdOutLineCallback([this](const QString &s) {
|
2023-10-04 17:31:20 +02:00
|
|
|
BuildSystem::appendBuildSystemOutput(addCMakePrefix(stripTrailingNewline(s)));
|
2023-07-04 16:32:37 +02:00
|
|
|
emit stdOutReady(s);
|
2021-06-14 12:06:23 +02:00
|
|
|
});
|
|
|
|
|
|
2022-05-13 18:22:03 +02:00
|
|
|
m_process->setStdErrLineCallback([this](const QString &s) {
|
2021-06-14 12:06:23 +02:00
|
|
|
m_parser.appendMessage(s, StdErrFormat);
|
2023-10-04 17:31:20 +02:00
|
|
|
BuildSystem::appendBuildSystemOutput(addCMakePrefix(stripTrailingNewline(s)));
|
2021-06-14 12:06:23 +02:00
|
|
|
});
|
|
|
|
|
|
2023-05-03 16:00:22 +02:00
|
|
|
connect(m_process.get(), &Process::done, this, [this] {
|
2022-05-13 18:22:03 +02:00
|
|
|
handleProcessDone(m_process->resultData());
|
|
|
|
|
});
|
2019-06-05 18:09:02 +02:00
|
|
|
|
2021-10-12 13:51:44 +02:00
|
|
|
CommandLine commandLine(cmakeExecutable);
|
2021-10-18 10:23:35 +02:00
|
|
|
commandLine.addArgs({"-S", sourceDirectory.path(), "-B", buildDirectory.path()});
|
2021-10-12 13:51:44 +02:00
|
|
|
commandLine.addArgs(arguments);
|
2019-06-05 18:09:02 +02:00
|
|
|
|
|
|
|
|
TaskHub::clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
|
|
|
|
|
|
2023-10-04 17:31:20 +02:00
|
|
|
BuildSystem::startNewBuildSystemOutput(
|
|
|
|
|
addCMakePrefix(::CMakeProjectManager::Tr::tr("Running %1 in %2.")
|
|
|
|
|
.arg(commandLine.toUserOutput(), buildDirectory.toUserOutput())));
|
2019-06-05 18:09:02 +02:00
|
|
|
|
2022-10-10 12:28:29 +02:00
|
|
|
ProcessProgress *progress = new ProcessProgress(m_process.get());
|
|
|
|
|
progress->setDisplayName(::CMakeProjectManager::Tr::tr("Configuring \"%1\"")
|
|
|
|
|
.arg(parameters.projectName));
|
|
|
|
|
m_process->setTimeoutS(10); // for process progress timeout estimation
|
2022-05-13 18:22:03 +02:00
|
|
|
m_process->setCommand(commandLine);
|
2020-02-28 12:44:00 +01:00
|
|
|
m_elapsed.start();
|
2022-05-13 18:22:03 +02:00
|
|
|
m_process->start();
|
2019-06-05 18:09:02 +02:00
|
|
|
}
|
|
|
|
|
|
2022-05-13 18:22:03 +02:00
|
|
|
void CMakeProcess::stop()
|
2021-12-22 15:18:00 +01:00
|
|
|
{
|
2022-10-10 12:28:29 +02:00
|
|
|
if (m_process)
|
|
|
|
|
m_process->stop();
|
2021-12-22 15:18:00 +01:00
|
|
|
}
|
|
|
|
|
|
2022-05-13 18:22:03 +02:00
|
|
|
void CMakeProcess::handleProcessDone(const Utils::ProcessResultData &resultData)
|
2019-06-05 18:09:02 +02:00
|
|
|
{
|
2022-05-13 18:22:03 +02:00
|
|
|
const int code = resultData.m_exitCode;
|
2019-06-05 18:09:02 +02:00
|
|
|
QString msg;
|
2022-05-13 18:22:03 +02:00
|
|
|
if (resultData.m_error == QProcess::FailedToStart) {
|
2022-09-29 15:26:31 +02:00
|
|
|
msg = ::CMakeProjectManager::Tr::tr("CMake process failed to start.");
|
2022-05-13 18:22:03 +02:00
|
|
|
} else if (resultData.m_exitStatus != QProcess::NormalExit) {
|
2022-10-10 12:28:29 +02:00
|
|
|
if (resultData.m_canceledByUser)
|
2022-09-29 15:26:31 +02:00
|
|
|
msg = ::CMakeProjectManager::Tr::tr("CMake process was canceled by the user.");
|
2022-06-24 13:19:04 +02:00
|
|
|
else
|
2022-09-29 15:26:31 +02:00
|
|
|
msg = ::CMakeProjectManager::Tr::tr("CMake process crashed.");
|
2019-06-14 16:42:41 +02:00
|
|
|
} else if (code != 0) {
|
2022-10-10 13:16:01 +02:00
|
|
|
msg = ::CMakeProjectManager::Tr::tr("CMake process exited with exit code %1.").arg(code);
|
2019-06-14 16:42:41 +02:00
|
|
|
}
|
2019-06-05 18:09:02 +02:00
|
|
|
|
|
|
|
|
if (!msg.isEmpty()) {
|
2023-10-04 17:31:20 +02:00
|
|
|
BuildSystem::appendBuildSystemOutput(addCMakePrefix({msg, QString()}).join('\n'));
|
2020-01-15 08:56:11 +01:00
|
|
|
TaskHub::addTask(BuildSystemTask(Task::Error, msg));
|
2019-06-05 18:09:02 +02:00
|
|
|
}
|
|
|
|
|
|
2022-10-10 13:16:01 +02:00
|
|
|
emit finished(code);
|
2020-02-28 12:44:00 +01:00
|
|
|
|
2020-02-28 15:09:35 +01:00
|
|
|
const QString elapsedTime = Utils::formatElapsedTime(m_elapsed.elapsed());
|
2023-10-04 17:31:20 +02:00
|
|
|
BuildSystem::appendBuildSystemOutput(addCMakePrefix({elapsedTime, QString()}).join('\n'));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString addCMakePrefix(const QString &str)
|
|
|
|
|
{
|
2023-10-05 17:00:03 +02:00
|
|
|
auto qColorToAnsiCode = [] (const QColor &color) {
|
|
|
|
|
return QString::fromLatin1("\033[38;2;%1;%2;%3m")
|
|
|
|
|
.arg(color.red()).arg(color.green()).arg(color.blue());
|
|
|
|
|
};
|
|
|
|
|
static const QColor bgColor = creatorTheme()->color(Theme::BackgroundColorNormal);
|
|
|
|
|
static const QColor fgColor = creatorTheme()->color(Theme::TextColorNormal);
|
|
|
|
|
static const QColor grey = StyleHelper::mergedColors(fgColor, bgColor, 80);
|
|
|
|
|
static const QString prefixString = qColorToAnsiCode(grey) + Constants::OUTPUT_PREFIX
|
|
|
|
|
+ qColorToAnsiCode(fgColor);
|
|
|
|
|
return QString("%1%2").arg(prefixString, str);
|
2023-10-04 17:31:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QStringList addCMakePrefix(const QStringList &list)
|
|
|
|
|
{
|
|
|
|
|
return Utils::transform(list, [](const QString &str) { return addCMakePrefix(str); });
|
2019-06-05 18:09:02 +02:00
|
|
|
}
|
|
|
|
|
|
2022-09-29 15:26:31 +02:00
|
|
|
} // CMakeProjectManager::Internal
|