cmake/Source/QtDialog/QCMake.cxx

473 lines
13 KiB
C++
Raw Normal View History

2016-10-30 18:24:19 +01:00
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "QCMake.h"
#include <QCoreApplication>
2016-07-09 11:21:54 +02:00
#include <QDir>
2016-07-09 11:21:54 +02:00
#include "cmExternalMakefileProjectGenerator.h"
2015-08-17 11:37:30 +02:00
#include "cmState.h"
#include "cmSystemTools.h"
2009-11-06 22:07:41 +02:00
#ifdef Q_OS_WIN
2016-07-09 11:21:54 +02:00
#include "qt_windows.h" // For SetErrorMode
2009-11-06 22:07:41 +02:00
#endif
QCMake::QCMake(QObject* p)
: QObject(p)
{
2011-02-07 16:37:25 +01:00
this->WarnUninitializedMode = false;
this->WarnUnusedMode = false;
qRegisterMetaType<QCMakeProperty>();
qRegisterMetaType<QCMakePropertyList>();
2013-03-16 19:13:01 +02:00
cmSystemTools::DisableRunCommandOutput();
cmSystemTools::SetRunCommandHideConsole(true);
2015-04-27 22:25:09 +02:00
cmSystemTools::SetMessageCallback(QCMake::messageCallback, this);
cmSystemTools::SetStdoutCallback(QCMake::stdoutCallback, this);
cmSystemTools::SetStderrCallback(QCMake::stderrCallback, this);
2017-07-20 19:35:53 +02:00
this->CMakeInstance = new cmake(cmake::RoleProject);
2014-08-03 19:52:23 +02:00
this->CMakeInstance->SetCMakeEditCommand(
cmSystemTools::GetCMakeGUICommand());
this->CMakeInstance->SetProgressCallback(QCMake::progressCallback, this);
2012-04-19 19:04:21 +03:00
cmSystemTools::SetInterruptCallback(QCMake::interruptCallback, this);
2016-03-13 13:35:51 +01:00
std::vector<cmake::GeneratorInfo> generators;
this->CMakeInstance->GetRegisteredGenerators(generators);
2016-03-13 13:35:51 +01:00
std::vector<cmake::GeneratorInfo>::const_iterator it;
2016-07-09 11:21:54 +02:00
for (it = generators.begin(); it != generators.end(); ++it) {
2016-03-13 13:35:51 +01:00
this->AvailableGenerators.push_back(*it);
2016-07-09 11:21:54 +02:00
}
}
QCMake::~QCMake()
{
delete this->CMakeInstance;
2016-07-09 11:21:54 +02:00
// cmDynamicLoader::FlushCache();
}
void QCMake::loadCache(const QString& dir)
{
this->setBinaryDirectory(dir);
}
2009-10-04 10:30:41 +03:00
void QCMake::setSourceDirectory(const QString& _dir)
{
2016-07-09 11:21:54 +02:00
QString dir = QString::fromLocal8Bit(
cmSystemTools::GetActualCaseForPath(_dir.toLocal8Bit().data()).c_str());
if (this->SourceDirectory != dir) {
this->SourceDirectory = QDir::fromNativeSeparators(dir);
emit this->sourceDirChanged(this->SourceDirectory);
2016-07-09 11:21:54 +02:00
}
}
2009-10-04 10:30:41 +03:00
void QCMake::setBinaryDirectory(const QString& _dir)
{
2016-07-09 11:21:54 +02:00
QString dir = QString::fromLocal8Bit(
cmSystemTools::GetActualCaseForPath(_dir.toLocal8Bit().data()).c_str());
if (this->BinaryDirectory != dir) {
this->BinaryDirectory = QDir::fromNativeSeparators(dir);
emit this->binaryDirChanged(this->BinaryDirectory);
2015-08-17 11:37:30 +02:00
cmState* state = this->CMakeInstance->GetState();
this->setGenerator(QString());
2016-03-13 13:35:51 +01:00
this->setToolset(QString());
2016-07-09 11:21:54 +02:00
if (!this->CMakeInstance->LoadCache(
this->BinaryDirectory.toLocal8Bit().data())) {
QDir testDir(this->BinaryDirectory);
2016-07-09 11:21:54 +02:00
if (testDir.exists("CMakeCache.txt")) {
cmSystemTools::Error(
"There is a CMakeCache.txt file for the current binary "
"tree but cmake does not have permission to read it. "
"Please check the permissions of the directory you are trying to "
"run CMake on.");
}
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
QCMakePropertyList props = this->properties();
emit this->propertiesChanged(props);
2015-08-17 11:37:30 +02:00
const char* homeDir = state->GetCacheEntryValue("CMAKE_HOME_DIRECTORY");
2016-07-09 11:21:54 +02:00
if (homeDir) {
2015-08-17 11:37:30 +02:00
setSourceDirectory(QString::fromLocal8Bit(homeDir));
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
const char* gen = state->GetCacheEntryValue("CMAKE_GENERATOR");
2016-07-09 11:21:54 +02:00
if (gen) {
const char* extraGen =
state->GetInitializedCacheValue("CMAKE_EXTRA_GENERATOR");
std::string curGen =
cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
gen, extraGen ? extraGen : "");
2012-08-04 10:26:08 +03:00
this->setGenerator(QString::fromLocal8Bit(curGen.c_str()));
2016-07-09 11:21:54 +02:00
}
2016-03-13 13:35:51 +01:00
const char* toolset = state->GetCacheEntryValue("CMAKE_GENERATOR_TOOLSET");
2016-07-09 11:21:54 +02:00
if (toolset) {
2016-03-13 13:35:51 +01:00
this->setToolset(QString::fromLocal8Bit(toolset));
}
2018-04-23 21:13:27 +02:00
checkOpenPossible();
2016-07-09 11:21:54 +02:00
}
}
void QCMake::setGenerator(const QString& gen)
{
2016-07-09 11:21:54 +02:00
if (this->Generator != gen) {
this->Generator = gen;
emit this->generatorChanged(this->Generator);
2016-07-09 11:21:54 +02:00
}
}
2016-03-13 13:35:51 +01:00
void QCMake::setToolset(const QString& toolset)
{
2016-07-09 11:21:54 +02:00
if (this->Toolset != toolset) {
2016-03-13 13:35:51 +01:00
this->Toolset = toolset;
emit this->toolsetChanged(this->Toolset);
2016-07-09 11:21:54 +02:00
}
2016-03-13 13:35:51 +01:00
}
void QCMake::configure()
{
2009-11-06 22:07:41 +02:00
#ifdef Q_OS_WIN
UINT lastErrorMode = SetErrorMode(0);
#endif
2016-07-09 11:21:54 +02:00
this->CMakeInstance->SetHomeDirectory(
this->SourceDirectory.toLocal8Bit().data());
this->CMakeInstance->SetHomeOutputDirectory(
this->BinaryDirectory.toLocal8Bit().data());
this->CMakeInstance->SetGlobalGenerator(
2016-07-09 11:21:54 +02:00
this->CMakeInstance->CreateGlobalGenerator(
this->Generator.toLocal8Bit().data()));
2015-04-27 22:25:09 +02:00
this->CMakeInstance->SetGeneratorPlatform("");
2016-03-13 13:35:51 +01:00
this->CMakeInstance->SetGeneratorToolset(this->Toolset.toLocal8Bit().data());
this->CMakeInstance->LoadCache();
2011-02-07 16:37:25 +01:00
this->CMakeInstance->SetWarnUninitialized(this->WarnUninitializedMode);
this->CMakeInstance->SetWarnUnused(this->WarnUnusedMode);
this->CMakeInstance->PreLoadCMakeFiles();
2012-04-19 19:04:21 +03:00
InterruptFlag = 0;
cmSystemTools::ResetErrorOccuredFlag();
int err = this->CMakeInstance->Configure();
2009-11-06 22:07:41 +02:00
#ifdef Q_OS_WIN
SetErrorMode(lastErrorMode);
#endif
emit this->propertiesChanged(this->properties());
emit this->configureDone(err);
}
void QCMake::generate()
{
2009-11-06 22:07:41 +02:00
#ifdef Q_OS_WIN
UINT lastErrorMode = SetErrorMode(0);
#endif
2012-04-19 19:04:21 +03:00
InterruptFlag = 0;
cmSystemTools::ResetErrorOccuredFlag();
2012-04-19 19:04:21 +03:00
int err = this->CMakeInstance->Generate();
2009-11-06 22:07:41 +02:00
#ifdef Q_OS_WIN
SetErrorMode(lastErrorMode);
#endif
emit this->generateDone(err);
2018-04-23 21:13:27 +02:00
checkOpenPossible();
}
void QCMake::open()
{
#ifdef Q_OS_WIN
UINT lastErrorMode = SetErrorMode(0);
#endif
InterruptFlag = 0;
cmSystemTools::ResetErrorOccuredFlag();
auto successful = this->CMakeInstance->Open(
this->BinaryDirectory.toLocal8Bit().data(), false);
#ifdef Q_OS_WIN
SetErrorMode(lastErrorMode);
#endif
emit this->openDone(successful);
}
2013-03-16 19:13:01 +02:00
void QCMake::setProperties(const QCMakePropertyList& newProps)
{
QCMakePropertyList props = newProps;
QStringList toremove;
// set the value of properties
2015-08-17 11:37:30 +02:00
cmState* state = this->CMakeInstance->GetState();
std::vector<std::string> cacheKeys = state->GetCacheEntryKeys();
2016-07-09 11:21:54 +02:00
for (std::vector<std::string>::const_iterator it = cacheKeys.begin();
it != cacheKeys.end(); ++it) {
2017-04-14 19:02:05 +02:00
cmStateEnums::CacheEntryType t = state->GetCacheEntryType(*it);
if (t == cmStateEnums::INTERNAL || t == cmStateEnums::STATIC) {
continue;
2016-07-09 11:21:54 +02:00
}
QCMakeProperty prop;
2015-08-17 11:37:30 +02:00
prop.Key = QString::fromLocal8Bit(it->c_str());
int idx = props.indexOf(prop);
2016-07-09 11:21:54 +02:00
if (idx == -1) {
2015-08-17 11:37:30 +02:00
toremove.append(QString::fromLocal8Bit(it->c_str()));
2016-07-09 11:21:54 +02:00
} else {
prop = props[idx];
2016-07-09 11:21:54 +02:00
if (prop.Value.type() == QVariant::Bool) {
2015-08-17 11:37:30 +02:00
state->SetCacheEntryValue(*it, prop.Value.toBool() ? "ON" : "OFF");
2016-07-09 11:21:54 +02:00
} else {
2015-08-17 11:37:30 +02:00
state->SetCacheEntryValue(*it,
2016-07-09 11:21:54 +02:00
prop.Value.toString().toLocal8Bit().data());
}
2016-07-09 11:21:54 +02:00
props.removeAt(idx);
}
2016-07-09 11:21:54 +02:00
}
// remove some properites
2017-07-20 19:35:53 +02:00
foreach (QString const& s, toremove) {
2012-08-04 10:26:08 +03:00
this->CMakeInstance->UnwatchUnusedCli(s.toLocal8Bit().data());
2011-02-07 16:37:25 +01:00
2015-08-17 11:37:30 +02:00
state->RemoveCacheEntry(s.toLocal8Bit().data());
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
// add some new properites
2017-07-20 19:35:53 +02:00
foreach (QCMakeProperty const& s, props) {
2012-08-04 10:26:08 +03:00
this->CMakeInstance->WatchUnusedCli(s.Key.toLocal8Bit().data());
2011-02-07 16:37:25 +01:00
2016-07-09 11:21:54 +02:00
if (s.Type == QCMakeProperty::BOOL) {
this->CMakeInstance->AddCacheEntry(
s.Key.toLocal8Bit().data(), s.Value.toBool() ? "ON" : "OFF",
2017-04-14 19:02:05 +02:00
s.Help.toLocal8Bit().data(), cmStateEnums::BOOL);
2016-07-09 11:21:54 +02:00
} else if (s.Type == QCMakeProperty::STRING) {
this->CMakeInstance->AddCacheEntry(
s.Key.toLocal8Bit().data(), s.Value.toString().toLocal8Bit().data(),
2017-04-14 19:02:05 +02:00
s.Help.toLocal8Bit().data(), cmStateEnums::STRING);
2016-07-09 11:21:54 +02:00
} else if (s.Type == QCMakeProperty::PATH) {
this->CMakeInstance->AddCacheEntry(
s.Key.toLocal8Bit().data(), s.Value.toString().toLocal8Bit().data(),
2017-04-14 19:02:05 +02:00
s.Help.toLocal8Bit().data(), cmStateEnums::PATH);
2016-07-09 11:21:54 +02:00
} else if (s.Type == QCMakeProperty::FILEPATH) {
this->CMakeInstance->AddCacheEntry(
s.Key.toLocal8Bit().data(), s.Value.toString().toLocal8Bit().data(),
2017-04-14 19:02:05 +02:00
s.Help.toLocal8Bit().data(), cmStateEnums::FILEPATH);
}
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
2015-08-17 11:37:30 +02:00
this->CMakeInstance->SaveCache(this->BinaryDirectory.toLocal8Bit().data());
}
QCMakePropertyList QCMake::properties() const
{
QCMakePropertyList ret;
2015-08-17 11:37:30 +02:00
cmState* state = this->CMakeInstance->GetState();
std::vector<std::string> cacheKeys = state->GetCacheEntryKeys();
for (std::vector<std::string>::const_iterator i = cacheKeys.begin();
2016-07-09 11:21:54 +02:00
i != cacheKeys.end(); ++i) {
2017-04-14 19:02:05 +02:00
cmStateEnums::CacheEntryType t = state->GetCacheEntryType(*i);
if (t == cmStateEnums::INTERNAL || t == cmStateEnums::STATIC ||
t == cmStateEnums::UNINITIALIZED) {
continue;
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
const char* cachedValue = state->GetCacheEntryValue(*i);
2015-08-17 11:37:30 +02:00
QCMakeProperty prop;
prop.Key = QString::fromLocal8Bit(i->c_str());
2016-07-09 11:21:54 +02:00
prop.Help =
QString::fromLocal8Bit(state->GetCacheEntryProperty(*i, "HELPSTRING"));
2015-08-17 11:37:30 +02:00
prop.Value = QString::fromLocal8Bit(cachedValue);
prop.Advanced = state->GetCacheEntryPropertyAsBool(*i, "ADVANCED");
2017-04-14 19:02:05 +02:00
if (t == cmStateEnums::BOOL) {
prop.Type = QCMakeProperty::BOOL;
2015-08-17 11:37:30 +02:00
prop.Value = cmSystemTools::IsOn(cachedValue);
2017-04-14 19:02:05 +02:00
} else if (t == cmStateEnums::PATH) {
prop.Type = QCMakeProperty::PATH;
2017-04-14 19:02:05 +02:00
} else if (t == cmStateEnums::FILEPATH) {
prop.Type = QCMakeProperty::FILEPATH;
2017-04-14 19:02:05 +02:00
} else if (t == cmStateEnums::STRING) {
prop.Type = QCMakeProperty::STRING;
2015-08-17 11:37:30 +02:00
const char* stringsProperty =
2016-07-09 11:21:54 +02:00
state->GetCacheEntryProperty(*i, "STRINGS");
if (stringsProperty) {
2015-08-17 11:37:30 +02:00
prop.Strings = QString::fromLocal8Bit(stringsProperty).split(";");
}
2016-07-09 11:21:54 +02:00
}
ret.append(prop);
2016-07-09 11:21:54 +02:00
}
return ret;
}
2013-03-16 19:13:01 +02:00
void QCMake::interrupt()
{
2012-04-19 19:04:21 +03:00
this->InterruptFlag.ref();
}
bool QCMake::interruptCallback(void* cd)
{
QCMake* self = reinterpret_cast<QCMake*>(cd);
2013-03-16 19:13:01 +02:00
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
2012-04-19 19:04:21 +03:00
return self->InterruptFlag;
2013-03-16 19:13:01 +02:00
#else
return self->InterruptFlag.load();
#endif
}
void QCMake::progressCallback(const char* msg, float percent, void* cd)
{
QCMake* self = reinterpret_cast<QCMake*>(cd);
2016-07-09 11:21:54 +02:00
if (percent >= 0) {
2012-08-04 10:26:08 +03:00
emit self->progressChanged(QString::fromLocal8Bit(msg), percent);
2016-07-09 11:21:54 +02:00
} else {
2012-08-04 10:26:08 +03:00
emit self->outputMessage(QString::fromLocal8Bit(msg));
2016-07-09 11:21:54 +02:00
}
QCoreApplication::processEvents();
}
2015-04-27 22:25:09 +02:00
void QCMake::messageCallback(const char* msg, const char* /*title*/,
bool& /*stop*/, void* cd)
{
QCMake* self = reinterpret_cast<QCMake*>(cd);
2012-08-04 10:26:08 +03:00
emit self->errorMessage(QString::fromLocal8Bit(msg));
QCoreApplication::processEvents();
}
2015-04-27 22:25:09 +02:00
void QCMake::stdoutCallback(const char* msg, size_t len, void* cd)
{
QCMake* self = reinterpret_cast<QCMake*>(cd);
2016-07-09 11:21:54 +02:00
emit self->outputMessage(QString::fromLocal8Bit(msg, int(len)));
2015-04-27 22:25:09 +02:00
QCoreApplication::processEvents();
}
void QCMake::stderrCallback(const char* msg, size_t len, void* cd)
{
QCMake* self = reinterpret_cast<QCMake*>(cd);
2016-07-09 11:21:54 +02:00
emit self->outputMessage(QString::fromLocal8Bit(msg, int(len)));
2015-04-27 22:25:09 +02:00
QCoreApplication::processEvents();
}
QString QCMake::binaryDirectory() const
{
return this->BinaryDirectory;
}
QString QCMake::sourceDirectory() const
{
return this->SourceDirectory;
}
QString QCMake::generator() const
{
return this->Generator;
}
2016-03-13 13:35:51 +01:00
std::vector<cmake::GeneratorInfo> const& QCMake::availableGenerators() const
{
2016-03-13 13:35:51 +01:00
return AvailableGenerators;
}
void QCMake::deleteCache()
{
// delete cache
2015-08-17 11:37:30 +02:00
this->CMakeInstance->DeleteCache(this->BinaryDirectory.toLocal8Bit().data());
// reload to make our cache empty
2015-08-17 11:37:30 +02:00
this->CMakeInstance->LoadCache(this->BinaryDirectory.toLocal8Bit().data());
// emit no generator and no properties
this->setGenerator(QString());
2016-03-13 13:35:51 +01:00
this->setToolset(QString());
QCMakePropertyList props = this->properties();
emit this->propertiesChanged(props);
}
void QCMake::reloadCache()
{
// emit that the cache was cleaned out
QCMakePropertyList props;
emit this->propertiesChanged(props);
// reload
2015-08-17 11:37:30 +02:00
this->CMakeInstance->LoadCache(this->BinaryDirectory.toLocal8Bit().data());
// emit new cache properties
props = this->properties();
emit this->propertiesChanged(props);
}
2013-03-16 19:13:01 +02:00
void QCMake::setDebugOutput(bool flag)
{
2016-07-09 11:21:54 +02:00
if (flag != this->CMakeInstance->GetDebugOutput()) {
this->CMakeInstance->SetDebugOutputOn(flag);
emit this->debugOutputChanged(flag);
2016-07-09 11:21:54 +02:00
}
}
bool QCMake::getDebugOutput() const
{
return this->CMakeInstance->GetDebugOutput();
}
2016-03-13 13:35:51 +01:00
bool QCMake::getSuppressDevWarnings()
{
return this->CMakeInstance->GetSuppressDevWarnings();
}
void QCMake::setSuppressDevWarnings(bool value)
{
2016-03-13 13:35:51 +01:00
this->CMakeInstance->SetSuppressDevWarnings(value);
}
bool QCMake::getSuppressDeprecatedWarnings()
{
return this->CMakeInstance->GetSuppressDeprecatedWarnings();
}
void QCMake::setSuppressDeprecatedWarnings(bool value)
{
this->CMakeInstance->SetSuppressDeprecatedWarnings(value);
}
bool QCMake::getDevWarningsAsErrors()
{
return this->CMakeInstance->GetDevWarningsAsErrors();
}
void QCMake::setDevWarningsAsErrors(bool value)
{
this->CMakeInstance->SetDevWarningsAsErrors(value);
}
bool QCMake::getDeprecatedWarningsAsErrors()
{
return this->CMakeInstance->GetDeprecatedWarningsAsErrors();
}
void QCMake::setDeprecatedWarningsAsErrors(bool value)
{
this->CMakeInstance->SetDeprecatedWarningsAsErrors(value);
}
2011-02-07 16:37:25 +01:00
void QCMake::setWarnUninitializedMode(bool value)
{
this->WarnUninitializedMode = value;
}
void QCMake::setWarnUnusedMode(bool value)
{
this->WarnUnusedMode = value;
}
2018-04-23 21:13:27 +02:00
void QCMake::checkOpenPossible()
{
auto data = this->BinaryDirectory.toLocal8Bit().data();
auto possible = this->CMakeInstance->Open(data, true);
emit openPossible(possible);
}