1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
5 #include <QCoreApplication>
8 #include "cmExternalMakefileProjectGenerator.h"
9 #include "cmGlobalGenerator.h"
11 #include "cmStringAlgorithms.h"
12 #include "cmSystemTools.h"
15 # include "qt_windows.h" // For SetErrorMode
18 QCMake::QCMake(QObject* p)
21 this->WarnUninitializedMode = false;
22 this->WarnUnusedMode = false;
23 qRegisterMetaType<QCMakeProperty>();
24 qRegisterMetaType<QCMakePropertyList>();
26 cmSystemTools::DisableRunCommandOutput();
27 cmSystemTools::SetRunCommandHideConsole(true);
29 cmSystemTools::SetMessageCallback(
30 [this](std::string const& msg, const char* title) {
31 this->messageCallback(msg, title);
33 cmSystemTools::SetStdoutCallback(
34 [this](std::string const& msg) { this->stdoutCallback(msg); });
35 cmSystemTools::SetStderrCallback(
36 [this](std::string const& msg) { this->stderrCallback(msg); });
38 this->CMakeInstance = new cmake(cmake::RoleProject, cmState::Project);
39 this->CMakeInstance->SetCMakeEditCommand(
40 cmSystemTools::GetCMakeGUICommand());
41 this->CMakeInstance->SetProgressCallback(
42 [this](const std::string& msg, float percent) {
43 this->progressCallback(msg, percent);
46 cmSystemTools::SetInterruptCallback(
47 [this] { return this->interruptCallback(); });
49 std::vector<cmake::GeneratorInfo> generators;
50 this->CMakeInstance->GetRegisteredGenerators(
51 generators, /*includeNamesWithPlatform=*/false);
53 for (cmake::GeneratorInfo const& gen : generators) {
54 this->AvailableGenerators.push_back(gen);
60 delete this->CMakeInstance;
61 // cmDynamicLoader::FlushCache();
64 void QCMake::loadCache(const QString& dir)
66 this->setBinaryDirectory(dir);
69 void QCMake::setSourceDirectory(const QString& _dir)
71 QString dir = QString::fromLocal8Bit(
72 cmSystemTools::GetActualCaseForPath(_dir.toLocal8Bit().data()).c_str());
73 if (this->SourceDirectory != dir) {
74 this->SourceDirectory = QDir::fromNativeSeparators(dir);
75 emit this->sourceDirChanged(this->SourceDirectory);
79 void QCMake::setBinaryDirectory(const QString& _dir)
81 QString dir = QString::fromLocal8Bit(
82 cmSystemTools::GetActualCaseForPath(_dir.toLocal8Bit().data()).c_str());
83 if (this->BinaryDirectory != dir) {
84 this->BinaryDirectory = QDir::fromNativeSeparators(dir);
85 emit this->binaryDirChanged(this->BinaryDirectory);
86 cmState* state = this->CMakeInstance->GetState();
87 this->setGenerator(QString());
88 this->setToolset(QString());
89 this->setPlatform(QString());
90 if (!this->CMakeInstance->LoadCache(
91 this->BinaryDirectory.toLocal8Bit().data())) {
92 QDir testDir(this->BinaryDirectory);
93 if (testDir.exists("CMakeCache.txt")) {
95 "There is a CMakeCache.txt file for the current binary "
96 "tree but cmake does not have permission to read it. "
97 "Please check the permissions of the directory you are trying to "
102 QCMakePropertyList props = this->properties();
103 emit this->propertiesChanged(props);
104 const char* homeDir = state->GetCacheEntryValue("CMAKE_HOME_DIRECTORY");
106 setSourceDirectory(QString::fromLocal8Bit(homeDir));
108 const char* gen = state->GetCacheEntryValue("CMAKE_GENERATOR");
110 const std::string* extraGen =
111 state->GetInitializedCacheValue("CMAKE_EXTRA_GENERATOR");
113 cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
114 gen, extraGen ? *extraGen : "");
115 this->setGenerator(QString::fromLocal8Bit(curGen.c_str()));
118 const char* platform =
119 state->GetCacheEntryValue("CMAKE_GENERATOR_PLATFORM");
121 this->setPlatform(QString::fromLocal8Bit(platform));
124 const char* toolset = state->GetCacheEntryValue("CMAKE_GENERATOR_TOOLSET");
126 this->setToolset(QString::fromLocal8Bit(toolset));
133 void QCMake::setGenerator(const QString& gen)
135 if (this->Generator != gen) {
136 this->Generator = gen;
137 emit this->generatorChanged(this->Generator);
141 void QCMake::setPlatform(const QString& platform)
143 if (this->Platform != platform) {
144 this->Platform = platform;
145 emit this->platformChanged(this->Platform);
149 void QCMake::setToolset(const QString& toolset)
151 if (this->Toolset != toolset) {
152 this->Toolset = toolset;
153 emit this->toolsetChanged(this->Toolset);
157 void QCMake::configure()
160 UINT lastErrorMode = SetErrorMode(0);
163 this->CMakeInstance->SetHomeDirectory(
164 this->SourceDirectory.toLocal8Bit().data());
165 this->CMakeInstance->SetHomeOutputDirectory(
166 this->BinaryDirectory.toLocal8Bit().data());
167 this->CMakeInstance->SetGlobalGenerator(
168 this->CMakeInstance->CreateGlobalGenerator(
169 this->Generator.toLocal8Bit().data()));
170 this->CMakeInstance->SetGeneratorPlatform(
171 this->Platform.toLocal8Bit().data());
172 this->CMakeInstance->SetGeneratorToolset(this->Toolset.toLocal8Bit().data());
173 this->CMakeInstance->LoadCache();
174 this->CMakeInstance->SetWarnUninitialized(this->WarnUninitializedMode);
175 this->CMakeInstance->SetWarnUnused(this->WarnUnusedMode);
176 this->CMakeInstance->PreLoadCMakeFiles();
179 cmSystemTools::ResetErrorOccuredFlag();
181 int err = this->CMakeInstance->Configure();
184 SetErrorMode(lastErrorMode);
187 emit this->propertiesChanged(this->properties());
188 emit this->configureDone(err);
191 void QCMake::generate()
194 UINT lastErrorMode = SetErrorMode(0);
198 cmSystemTools::ResetErrorOccuredFlag();
200 int err = this->CMakeInstance->Generate();
203 SetErrorMode(lastErrorMode);
206 emit this->generateDone(err);
213 UINT lastErrorMode = SetErrorMode(0);
217 cmSystemTools::ResetErrorOccuredFlag();
219 auto successful = this->CMakeInstance->Open(
220 this->BinaryDirectory.toLocal8Bit().data(), false);
223 SetErrorMode(lastErrorMode);
226 emit this->openDone(successful);
229 void QCMake::setProperties(const QCMakePropertyList& newProps)
231 QCMakePropertyList props = newProps;
233 QStringList toremove;
235 // set the value of properties
236 cmState* state = this->CMakeInstance->GetState();
237 std::vector<std::string> cacheKeys = state->GetCacheEntryKeys();
238 for (std::string const& key : cacheKeys) {
239 cmStateEnums::CacheEntryType t = state->GetCacheEntryType(key);
240 if (t == cmStateEnums::INTERNAL || t == cmStateEnums::STATIC) {
245 prop.Key = QString::fromLocal8Bit(key.c_str());
246 int idx = props.indexOf(prop);
248 toremove.append(QString::fromLocal8Bit(key.c_str()));
251 if (prop.Value.type() == QVariant::Bool) {
252 state->SetCacheEntryValue(key, prop.Value.toBool() ? "ON" : "OFF");
254 state->SetCacheEntryValue(key,
255 prop.Value.toString().toLocal8Bit().data());
261 // remove some properties
262 foreach (QString const& s, toremove) {
263 this->CMakeInstance->UnwatchUnusedCli(s.toLocal8Bit().data());
265 state->RemoveCacheEntry(s.toLocal8Bit().data());
268 // add some new properties
269 foreach (QCMakeProperty const& s, props) {
270 this->CMakeInstance->WatchUnusedCli(s.Key.toLocal8Bit().data());
272 if (s.Type == QCMakeProperty::BOOL) {
273 this->CMakeInstance->AddCacheEntry(
274 s.Key.toLocal8Bit().data(), s.Value.toBool() ? "ON" : "OFF",
275 s.Help.toLocal8Bit().data(), cmStateEnums::BOOL);
276 } else if (s.Type == QCMakeProperty::STRING) {
277 this->CMakeInstance->AddCacheEntry(
278 s.Key.toLocal8Bit().data(), s.Value.toString().toLocal8Bit().data(),
279 s.Help.toLocal8Bit().data(), cmStateEnums::STRING);
280 } else if (s.Type == QCMakeProperty::PATH) {
281 this->CMakeInstance->AddCacheEntry(
282 s.Key.toLocal8Bit().data(), s.Value.toString().toLocal8Bit().data(),
283 s.Help.toLocal8Bit().data(), cmStateEnums::PATH);
284 } else if (s.Type == QCMakeProperty::FILEPATH) {
285 this->CMakeInstance->AddCacheEntry(
286 s.Key.toLocal8Bit().data(), s.Value.toString().toLocal8Bit().data(),
287 s.Help.toLocal8Bit().data(), cmStateEnums::FILEPATH);
291 this->CMakeInstance->SaveCache(this->BinaryDirectory.toLocal8Bit().data());
294 QCMakePropertyList QCMake::properties() const
296 QCMakePropertyList ret;
298 cmState* state = this->CMakeInstance->GetState();
299 std::vector<std::string> cacheKeys = state->GetCacheEntryKeys();
300 for (std::string const& key : cacheKeys) {
301 cmStateEnums::CacheEntryType t = state->GetCacheEntryType(key);
302 if (t == cmStateEnums::INTERNAL || t == cmStateEnums::STATIC ||
303 t == cmStateEnums::UNINITIALIZED) {
307 const char* cachedValue = state->GetCacheEntryValue(key);
310 prop.Key = QString::fromLocal8Bit(key.c_str());
312 QString::fromLocal8Bit(state->GetCacheEntryProperty(key, "HELPSTRING"));
313 prop.Value = QString::fromLocal8Bit(cachedValue);
314 prop.Advanced = state->GetCacheEntryPropertyAsBool(key, "ADVANCED");
315 if (t == cmStateEnums::BOOL) {
316 prop.Type = QCMakeProperty::BOOL;
317 prop.Value = cmIsOn(cachedValue);
318 } else if (t == cmStateEnums::PATH) {
319 prop.Type = QCMakeProperty::PATH;
320 } else if (t == cmStateEnums::FILEPATH) {
321 prop.Type = QCMakeProperty::FILEPATH;
322 } else if (t == cmStateEnums::STRING) {
323 prop.Type = QCMakeProperty::STRING;
324 const char* stringsProperty =
325 state->GetCacheEntryProperty(key, "STRINGS");
326 if (stringsProperty) {
327 prop.Strings = QString::fromLocal8Bit(stringsProperty).split(";");
337 void QCMake::interrupt()
339 this->InterruptFlag.ref();
342 bool QCMake::interruptCallback()
344 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
345 return this->InterruptFlag;
347 return this->InterruptFlag.load();
351 void QCMake::progressCallback(const std::string& msg, float percent)
354 emit this->progressChanged(QString::fromStdString(msg), percent);
356 emit this->outputMessage(QString::fromStdString(msg));
358 QCoreApplication::processEvents();
361 void QCMake::messageCallback(std::string const& msg, const char* /*title*/)
363 emit this->errorMessage(QString::fromStdString(msg));
364 QCoreApplication::processEvents();
367 void QCMake::stdoutCallback(std::string const& msg)
369 emit this->outputMessage(QString::fromStdString(msg));
370 QCoreApplication::processEvents();
373 void QCMake::stderrCallback(std::string const& msg)
375 emit this->outputMessage(QString::fromStdString(msg));
376 QCoreApplication::processEvents();
379 QString QCMake::binaryDirectory() const
381 return this->BinaryDirectory;
384 QString QCMake::sourceDirectory() const
386 return this->SourceDirectory;
389 QString QCMake::generator() const
391 return this->Generator;
394 std::vector<cmake::GeneratorInfo> const& QCMake::availableGenerators() const
396 return AvailableGenerators;
399 void QCMake::deleteCache()
402 this->CMakeInstance->DeleteCache(this->BinaryDirectory.toLocal8Bit().data());
403 // reload to make our cache empty
404 this->CMakeInstance->LoadCache(this->BinaryDirectory.toLocal8Bit().data());
405 // emit no generator and no properties
406 this->setGenerator(QString());
407 this->setToolset(QString());
408 QCMakePropertyList props = this->properties();
409 emit this->propertiesChanged(props);
412 void QCMake::reloadCache()
414 // emit that the cache was cleaned out
415 QCMakePropertyList props;
416 emit this->propertiesChanged(props);
418 this->CMakeInstance->LoadCache(this->BinaryDirectory.toLocal8Bit().data());
419 // emit new cache properties
420 props = this->properties();
421 emit this->propertiesChanged(props);
424 void QCMake::setDebugOutput(bool flag)
426 if (flag != this->CMakeInstance->GetDebugOutput()) {
427 this->CMakeInstance->SetDebugOutputOn(flag);
428 emit this->debugOutputChanged(flag);
432 bool QCMake::getDebugOutput() const
434 return this->CMakeInstance->GetDebugOutput();
437 bool QCMake::getSuppressDevWarnings()
439 return this->CMakeInstance->GetSuppressDevWarnings();
442 void QCMake::setSuppressDevWarnings(bool value)
444 this->CMakeInstance->SetSuppressDevWarnings(value);
447 bool QCMake::getSuppressDeprecatedWarnings()
449 return this->CMakeInstance->GetSuppressDeprecatedWarnings();
452 void QCMake::setSuppressDeprecatedWarnings(bool value)
454 this->CMakeInstance->SetSuppressDeprecatedWarnings(value);
457 bool QCMake::getDevWarningsAsErrors()
459 return this->CMakeInstance->GetDevWarningsAsErrors();
462 void QCMake::setDevWarningsAsErrors(bool value)
464 this->CMakeInstance->SetDevWarningsAsErrors(value);
467 bool QCMake::getDeprecatedWarningsAsErrors()
469 return this->CMakeInstance->GetDeprecatedWarningsAsErrors();
472 void QCMake::setDeprecatedWarningsAsErrors(bool value)
474 this->CMakeInstance->SetDeprecatedWarningsAsErrors(value);
477 void QCMake::setWarnUninitializedMode(bool value)
479 this->WarnUninitializedMode = value;
482 void QCMake::setWarnUnusedMode(bool value)
484 this->WarnUnusedMode = value;
487 void QCMake::checkOpenPossible()
489 auto data = this->BinaryDirectory.toLocal8Bit().data();
490 auto possible = this->CMakeInstance->Open(data, true);
491 emit openPossible(possible);