2012-09-06 22:38:25 +08:00
|
|
|
/****************************************************************************
|
|
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2012-09-06 22:38:25 +08:00
|
|
|
**
|
|
|
|
|
** This file is part of Qt Creator.
|
|
|
|
|
**
|
|
|
|
|
** Commercial License Usage
|
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
2016-01-15 14:57:40 +01:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
2012-09-06 22:38:25 +08:00
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** GNU General Public License Usage
|
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
|
** General Public License version 3 as published by the Free Software
|
|
|
|
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
|
|
|
** included in the packaging of this file. Please review the following
|
|
|
|
|
** information to ensure the GNU General Public License requirements will
|
|
|
|
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
2012-09-06 22:38:25 +08:00
|
|
|
**
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
2014-03-12 08:36:36 +01:00
|
|
|
#include "cmaketool.h"
|
2015-02-24 21:57:00 +01:00
|
|
|
#include "cmaketoolmanager.h"
|
2012-09-06 22:38:25 +08:00
|
|
|
|
2016-01-22 13:50:58 +01:00
|
|
|
#include <utils/algorithm.h>
|
|
|
|
|
#include <utils/environment.h>
|
2015-02-04 17:54:46 +01:00
|
|
|
#include <utils/qtcassert.h>
|
|
|
|
|
|
2012-09-06 22:38:25 +08:00
|
|
|
#include <QFileInfo>
|
2016-09-28 15:18:29 +02:00
|
|
|
#include <QJsonDocument>
|
|
|
|
|
#include <QJsonObject>
|
2016-01-22 13:50:58 +01:00
|
|
|
#include <QProcess>
|
2016-09-28 17:25:29 +02:00
|
|
|
#include <QRegularExpression>
|
2016-01-22 13:50:58 +01:00
|
|
|
#include <QSet>
|
2012-09-06 22:38:25 +08:00
|
|
|
#include <QTextDocument>
|
2015-02-04 17:54:46 +01:00
|
|
|
#include <QUuid>
|
2016-01-22 13:50:58 +01:00
|
|
|
#include <QVariantMap>
|
2015-02-04 17:54:46 +01:00
|
|
|
|
2016-02-12 12:30:55 +01:00
|
|
|
namespace CMakeProjectManager {
|
2012-09-06 22:38:25 +08:00
|
|
|
|
2015-02-04 17:54:46 +01:00
|
|
|
const char CMAKE_INFORMATION_ID[] = "Id";
|
|
|
|
|
const char CMAKE_INFORMATION_COMMAND[] = "Binary";
|
|
|
|
|
const char CMAKE_INFORMATION_DISPLAYNAME[] = "DisplayName";
|
2016-06-27 13:09:14 +02:00
|
|
|
const char CMAKE_INFORMATION_AUTORUN[] = "AutoRun";
|
2017-09-07 14:00:29 +02:00
|
|
|
const char CMAKE_INFORMATION_AUTO_CREATE_BUILD_DIRECTORY[] = "AutoCreateBuildDirectory";
|
2015-02-04 17:54:46 +01:00
|
|
|
const char CMAKE_INFORMATION_AUTODETECTED[] = "AutoDetected";
|
2012-09-06 22:38:25 +08:00
|
|
|
|
2016-09-28 12:24:06 +02:00
|
|
|
|
|
|
|
|
bool CMakeTool::Generator::matches(const QString &n, const QString &ex) const
|
|
|
|
|
{
|
|
|
|
|
return n == name && (ex.isEmpty() || extraGenerators.contains(ex));
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-10 14:17:12 +02:00
|
|
|
namespace Internal {
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
|
// CMakeIntrospectionData:
|
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
class IntrospectionData
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
bool m_didAttemptToRun = false;
|
|
|
|
|
bool m_didRun = false;
|
|
|
|
|
bool m_hasServerMode = false;
|
|
|
|
|
|
|
|
|
|
bool m_queriedServerMode = false;
|
|
|
|
|
bool m_triedCapabilities = false;
|
|
|
|
|
|
|
|
|
|
QList<CMakeTool::Generator> m_generators;
|
|
|
|
|
QMap<QString, QStringList> m_functionArgs;
|
|
|
|
|
QStringList m_variables;
|
|
|
|
|
QStringList m_functions;
|
|
|
|
|
CMakeTool::Version m_version;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
} // namespace Internal
|
|
|
|
|
|
2012-09-06 22:38:25 +08:00
|
|
|
///////////////////////////
|
2014-03-12 08:36:36 +01:00
|
|
|
// CMakeTool
|
2012-09-06 22:38:25 +08:00
|
|
|
///////////////////////////
|
2016-01-07 15:22:53 +01:00
|
|
|
CMakeTool::CMakeTool(Detection d, const Core::Id &id) :
|
2018-07-10 14:17:12 +02:00
|
|
|
m_id(id), m_isAutoDetected(d == AutoDetection),
|
|
|
|
|
m_introspection(std::make_unique<Internal::IntrospectionData>())
|
2012-09-06 22:38:25 +08:00
|
|
|
{
|
2016-01-22 13:50:58 +01:00
|
|
|
QTC_ASSERT(m_id.isValid(), m_id = Core::Id::fromString(QUuid::createUuid().toString()));
|
2015-02-04 17:54:46 +01:00
|
|
|
}
|
2012-09-06 22:38:25 +08:00
|
|
|
|
2018-07-10 14:17:12 +02:00
|
|
|
CMakeTool::CMakeTool(const QVariantMap &map, bool fromSdk) :
|
|
|
|
|
CMakeTool(fromSdk ? CMakeTool::AutoDetection : CMakeTool::ManualDetection,
|
|
|
|
|
Core::Id::fromSetting(map.value(CMAKE_INFORMATION_ID)))
|
2015-02-04 17:54:46 +01:00
|
|
|
{
|
2016-09-26 16:29:58 +02:00
|
|
|
m_displayName = map.value(CMAKE_INFORMATION_DISPLAYNAME).toString();
|
|
|
|
|
m_isAutoRun = map.value(CMAKE_INFORMATION_AUTORUN, true).toBool();
|
2017-09-07 14:00:29 +02:00
|
|
|
m_autoCreateBuildDirectory = map.value(CMAKE_INFORMATION_AUTO_CREATE_BUILD_DIRECTORY, false).toBool();
|
2015-02-04 17:54:46 +01:00
|
|
|
|
|
|
|
|
//loading a CMakeTool from SDK is always autodetection
|
|
|
|
|
if (!fromSdk)
|
2016-09-26 16:29:58 +02:00
|
|
|
m_isAutoDetected = map.value(CMAKE_INFORMATION_AUTODETECTED, false).toBool();
|
2015-02-04 17:54:46 +01:00
|
|
|
|
2016-09-26 16:29:58 +02:00
|
|
|
setCMakeExecutable(Utils::FileName::fromString(map.value(CMAKE_INFORMATION_COMMAND).toString()));
|
2012-09-06 22:38:25 +08:00
|
|
|
}
|
|
|
|
|
|
2018-07-10 14:17:12 +02:00
|
|
|
CMakeTool::~CMakeTool() = default;
|
|
|
|
|
|
2016-01-22 13:50:58 +01:00
|
|
|
Core::Id CMakeTool::createId()
|
2012-09-06 22:38:25 +08:00
|
|
|
{
|
2016-01-22 13:50:58 +01:00
|
|
|
return Core::Id::fromString(QUuid::createUuid().toString());
|
2012-09-06 22:38:25 +08:00
|
|
|
}
|
|
|
|
|
|
2015-02-04 17:54:46 +01:00
|
|
|
void CMakeTool::setCMakeExecutable(const Utils::FileName &executable)
|
2012-09-06 22:38:25 +08:00
|
|
|
{
|
2016-01-22 13:50:58 +01:00
|
|
|
if (m_executable == executable)
|
|
|
|
|
return;
|
2012-09-06 22:38:25 +08:00
|
|
|
|
2018-07-10 14:17:12 +02:00
|
|
|
m_introspection->m_didRun = false;
|
|
|
|
|
m_introspection->m_didAttemptToRun = false;
|
2015-02-24 21:57:00 +01:00
|
|
|
|
2016-01-22 13:50:58 +01:00
|
|
|
m_executable = executable;
|
2015-02-24 21:57:00 +01:00
|
|
|
CMakeToolManager::notifyAboutUpdate(this);
|
2012-09-06 22:38:25 +08:00
|
|
|
}
|
|
|
|
|
|
2016-06-27 13:09:14 +02:00
|
|
|
void CMakeTool::setAutorun(bool autoRun)
|
|
|
|
|
{
|
|
|
|
|
if (m_isAutoRun == autoRun)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
m_isAutoRun = autoRun;
|
|
|
|
|
CMakeToolManager::notifyAboutUpdate(this);
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-07 14:00:29 +02:00
|
|
|
void CMakeTool::setAutoCreateBuildDirectory(bool autoBuildDir)
|
|
|
|
|
{
|
|
|
|
|
if (m_autoCreateBuildDirectory == autoBuildDir)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
m_autoCreateBuildDirectory = autoBuildDir;
|
|
|
|
|
CMakeToolManager::notifyAboutUpdate(this);
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-22 13:50:58 +01:00
|
|
|
bool CMakeTool::isValid() const
|
2012-09-06 22:38:25 +08:00
|
|
|
{
|
2016-01-22 13:50:58 +01:00
|
|
|
if (!m_id.isValid())
|
|
|
|
|
return false;
|
2012-09-06 22:38:25 +08:00
|
|
|
|
2018-07-10 14:17:12 +02:00
|
|
|
if (!m_introspection->m_didAttemptToRun)
|
2016-01-22 13:50:58 +01:00
|
|
|
supportedGenerators();
|
2012-09-06 22:38:25 +08:00
|
|
|
|
2018-07-10 14:17:12 +02:00
|
|
|
return m_introspection->m_didRun;
|
2012-09-06 22:38:25 +08:00
|
|
|
}
|
|
|
|
|
|
2016-09-28 15:18:29 +02:00
|
|
|
Utils::SynchronousProcessResponse CMakeTool::run(const QStringList &args, bool mayFail) const
|
2012-09-06 22:38:25 +08:00
|
|
|
{
|
2018-07-10 14:17:12 +02:00
|
|
|
if (m_introspection->m_didAttemptToRun && !m_introspection->m_didRun) {
|
2016-01-22 13:50:58 +01:00
|
|
|
Utils::SynchronousProcessResponse response;
|
|
|
|
|
response.result = Utils::SynchronousProcessResponse::StartFailed;
|
|
|
|
|
return response;
|
2015-02-04 17:54:46 +01:00
|
|
|
}
|
2012-09-06 22:38:25 +08:00
|
|
|
|
2016-01-22 13:50:58 +01:00
|
|
|
Utils::SynchronousProcess cmake;
|
|
|
|
|
cmake.setTimeoutS(1);
|
|
|
|
|
cmake.setFlags(Utils::SynchronousProcess::UnixTerminalDisabled);
|
|
|
|
|
Utils::Environment env = Utils::Environment::systemEnvironment();
|
2016-04-07 13:06:01 +02:00
|
|
|
Utils::Environment::setupEnglishOutput(&env);
|
2016-01-22 13:50:58 +01:00
|
|
|
cmake.setProcessEnvironment(env.toProcessEnvironment());
|
|
|
|
|
cmake.setTimeOutMessageBoxEnabled(false);
|
|
|
|
|
|
2016-09-28 15:18:29 +02:00
|
|
|
Utils::SynchronousProcessResponse response = cmake.runBlocking(m_executable.toString(), args);
|
2018-07-10 14:17:12 +02:00
|
|
|
m_introspection->m_didAttemptToRun = true;
|
|
|
|
|
m_introspection->m_didRun = mayFail ? true : (response.result == Utils::SynchronousProcessResponse::Finished);
|
2016-01-22 13:50:58 +01:00
|
|
|
return response;
|
2015-02-04 17:54:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QVariantMap CMakeTool::toMap() const
|
|
|
|
|
{
|
|
|
|
|
QVariantMap data;
|
2016-09-26 16:29:58 +02:00
|
|
|
data.insert(CMAKE_INFORMATION_DISPLAYNAME, m_displayName);
|
|
|
|
|
data.insert(CMAKE_INFORMATION_ID, m_id.toSetting());
|
|
|
|
|
data.insert(CMAKE_INFORMATION_COMMAND, m_executable.toString());
|
|
|
|
|
data.insert(CMAKE_INFORMATION_AUTORUN, m_isAutoRun);
|
2017-09-07 14:00:29 +02:00
|
|
|
data.insert(CMAKE_INFORMATION_AUTO_CREATE_BUILD_DIRECTORY, m_autoCreateBuildDirectory);
|
2016-09-26 16:29:58 +02:00
|
|
|
data.insert(CMAKE_INFORMATION_AUTODETECTED, m_isAutoDetected);
|
2015-02-04 17:54:46 +01:00
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Utils::FileName CMakeTool::cmakeExecutable() const
|
2012-09-06 22:38:25 +08:00
|
|
|
{
|
2016-09-14 12:56:32 +02:00
|
|
|
if (Utils::HostOsInfo::isMacHost() && m_executable.endsWith(".app")) {
|
2019-05-17 12:32:05 +02:00
|
|
|
const Utils::FileName toTest = m_executable.pathAppended("Contents/bin/cmake");
|
2016-09-14 12:56:32 +02:00
|
|
|
if (toTest.exists())
|
|
|
|
|
return toTest;
|
|
|
|
|
}
|
2012-09-06 22:38:25 +08:00
|
|
|
return m_executable;
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-27 13:09:14 +02:00
|
|
|
bool CMakeTool::isAutoRun() const
|
|
|
|
|
{
|
|
|
|
|
return m_isAutoRun;
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-07 14:00:29 +02:00
|
|
|
bool CMakeTool::autoCreateBuildDirectory() const
|
|
|
|
|
{
|
|
|
|
|
return m_autoCreateBuildDirectory;
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-28 12:24:06 +02:00
|
|
|
QList<CMakeTool::Generator> CMakeTool::supportedGenerators() const
|
2012-09-06 22:38:25 +08:00
|
|
|
{
|
2016-09-28 17:25:29 +02:00
|
|
|
readInformation(QueryType::GENERATORS);
|
2018-07-10 14:17:12 +02:00
|
|
|
return m_introspection->m_generators;
|
2012-09-06 22:38:25 +08:00
|
|
|
}
|
|
|
|
|
|
2016-01-22 13:50:58 +01:00
|
|
|
TextEditor::Keywords CMakeTool::keywords()
|
2012-09-06 22:38:25 +08:00
|
|
|
{
|
2018-07-10 14:17:12 +02:00
|
|
|
if (m_introspection->m_functions.isEmpty()) {
|
2016-01-22 13:50:58 +01:00
|
|
|
Utils::SynchronousProcessResponse response;
|
2017-02-22 15:09:35 +01:00
|
|
|
response = run({"--help-command-list"});
|
2016-01-22 13:50:58 +01:00
|
|
|
if (response.result == Utils::SynchronousProcessResponse::Finished)
|
2018-07-10 14:17:12 +02:00
|
|
|
m_introspection->m_functions = response.stdOut().split('\n');
|
2016-01-22 13:50:58 +01:00
|
|
|
|
2017-02-22 15:09:35 +01:00
|
|
|
response = run({"--help-commands"});
|
2016-01-22 13:50:58 +01:00
|
|
|
if (response.result == Utils::SynchronousProcessResponse::Finished)
|
2016-07-05 12:00:59 +02:00
|
|
|
parseFunctionDetailsOutput(response.stdOut());
|
2016-01-22 13:50:58 +01:00
|
|
|
|
2017-02-22 15:09:35 +01:00
|
|
|
response = run({"--help-property-list"});
|
2016-01-22 13:50:58 +01:00
|
|
|
if (response.result == Utils::SynchronousProcessResponse::Finished)
|
2018-07-10 14:17:12 +02:00
|
|
|
m_introspection->m_variables = parseVariableOutput(response.stdOut());
|
2016-01-22 13:50:58 +01:00
|
|
|
|
2017-02-22 15:09:35 +01:00
|
|
|
response = run({"--help-variable-list"});
|
2016-01-22 13:50:58 +01:00
|
|
|
if (response.result == Utils::SynchronousProcessResponse::Finished) {
|
2018-07-10 14:17:12 +02:00
|
|
|
m_introspection->m_variables.append(parseVariableOutput(response.stdOut()));
|
|
|
|
|
m_introspection->m_variables = Utils::filteredUnique(m_introspection->m_variables);
|
|
|
|
|
Utils::sort(m_introspection->m_variables);
|
2016-01-22 13:50:58 +01:00
|
|
|
}
|
2012-09-06 22:38:25 +08:00
|
|
|
}
|
2016-01-22 13:50:58 +01:00
|
|
|
|
2018-07-10 14:17:12 +02:00
|
|
|
return TextEditor::Keywords(m_introspection->m_variables,
|
|
|
|
|
m_introspection->m_functions,
|
|
|
|
|
m_introspection->m_functionArgs);
|
2012-09-06 22:38:25 +08:00
|
|
|
}
|
|
|
|
|
|
2016-09-28 15:48:10 +02:00
|
|
|
bool CMakeTool::hasServerMode() const
|
|
|
|
|
{
|
2016-09-28 17:25:29 +02:00
|
|
|
readInformation(QueryType::SERVER_MODE);
|
2018-07-10 14:17:12 +02:00
|
|
|
return m_introspection->m_hasServerMode;
|
2016-09-28 15:48:10 +02:00
|
|
|
}
|
|
|
|
|
|
2016-09-28 17:25:29 +02:00
|
|
|
CMakeTool::Version CMakeTool::version() const
|
|
|
|
|
{
|
|
|
|
|
readInformation(QueryType::VERSION);
|
2018-07-10 14:17:12 +02:00
|
|
|
return m_introspection->m_version;
|
2016-09-28 17:25:29 +02:00
|
|
|
}
|
|
|
|
|
|
2016-01-22 13:50:58 +01:00
|
|
|
bool CMakeTool::isAutoDetected() const
|
2012-09-06 22:38:25 +08:00
|
|
|
{
|
2016-01-22 13:50:58 +01:00
|
|
|
return m_isAutoDetected;
|
2012-09-06 22:38:25 +08:00
|
|
|
}
|
|
|
|
|
|
2015-02-04 17:54:46 +01:00
|
|
|
QString CMakeTool::displayName() const
|
|
|
|
|
{
|
|
|
|
|
return m_displayName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CMakeTool::setDisplayName(const QString &displayName)
|
|
|
|
|
{
|
|
|
|
|
m_displayName = displayName;
|
2015-02-24 21:57:00 +01:00
|
|
|
CMakeToolManager::notifyAboutUpdate(this);
|
2015-02-04 17:54:46 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-10 15:47:09 +01:00
|
|
|
void CMakeTool::setPathMapper(const CMakeTool::PathMapper &pathMapper)
|
|
|
|
|
{
|
|
|
|
|
m_pathMapper = pathMapper;
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-13 11:36:00 +02:00
|
|
|
CMakeTool::PathMapper CMakeTool::pathMapper() const
|
2015-03-10 15:47:09 +01:00
|
|
|
{
|
|
|
|
|
if (m_pathMapper)
|
2016-10-13 11:36:00 +02:00
|
|
|
return m_pathMapper;
|
2016-10-13 12:02:52 +02:00
|
|
|
return [](const Utils::FileName &fn) { return fn; };
|
2015-03-10 15:47:09 +01:00
|
|
|
}
|
2015-02-04 17:54:46 +01:00
|
|
|
|
2016-09-28 17:25:29 +02:00
|
|
|
void CMakeTool::readInformation(CMakeTool::QueryType type) const
|
|
|
|
|
{
|
2018-07-10 14:17:12 +02:00
|
|
|
if ((type == QueryType::GENERATORS && !m_introspection->m_generators.isEmpty())
|
|
|
|
|
|| (type == QueryType::SERVER_MODE && m_introspection->m_queriedServerMode)
|
|
|
|
|
|| (type == QueryType::VERSION && !m_introspection->m_version.fullVersion.isEmpty()))
|
2016-09-28 17:25:29 +02:00
|
|
|
return;
|
|
|
|
|
|
2018-07-10 14:17:12 +02:00
|
|
|
if (!m_introspection->m_triedCapabilities) {
|
2016-09-28 17:25:29 +02:00
|
|
|
fetchFromCapabilities();
|
2018-07-10 14:17:12 +02:00
|
|
|
m_introspection->m_triedCapabilities = true;
|
|
|
|
|
m_introspection->m_queriedServerMode = true; // Got added after "-E capabilities" support!
|
|
|
|
|
if (type == QueryType::GENERATORS && !m_introspection->m_generators.isEmpty())
|
2016-09-28 17:25:29 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (type == QueryType::GENERATORS) {
|
|
|
|
|
fetchGeneratorsFromHelp();
|
|
|
|
|
} else if (type == QueryType::SERVER_MODE) {
|
|
|
|
|
// Nothing to do...
|
|
|
|
|
} else if (type == QueryType::VERSION) {
|
|
|
|
|
fetchVersionFromVersionOutput();
|
|
|
|
|
} else {
|
|
|
|
|
QTC_ASSERT(false, return);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-22 13:50:58 +01:00
|
|
|
static QStringList parseDefinition(const QString &definition)
|
2012-09-06 22:38:25 +08:00
|
|
|
{
|
2016-01-22 13:50:58 +01:00
|
|
|
QStringList result;
|
|
|
|
|
QString word;
|
|
|
|
|
bool ignoreWord = false;
|
|
|
|
|
QVector<QChar> braceStack;
|
|
|
|
|
|
|
|
|
|
foreach (const QChar &c, definition) {
|
2016-09-26 16:29:58 +02:00
|
|
|
if (c == '[' || c == '<' || c == '(') {
|
2016-01-22 13:50:58 +01:00
|
|
|
braceStack.append(c);
|
|
|
|
|
ignoreWord = false;
|
2016-09-26 16:29:58 +02:00
|
|
|
} else if (c == ']' || c == '>' || c == ')') {
|
|
|
|
|
if (braceStack.isEmpty() || braceStack.takeLast() == '<')
|
2016-01-22 13:50:58 +01:00
|
|
|
ignoreWord = true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-26 16:29:58 +02:00
|
|
|
if (c == ' ' || c == '[' || c == '<' || c == '('
|
|
|
|
|
|| c == ']' || c == '>' || c == ')') {
|
2016-01-22 13:50:58 +01:00
|
|
|
if (!ignoreWord && !word.isEmpty()) {
|
2016-09-26 16:29:58 +02:00
|
|
|
if (result.isEmpty() || Utils::allOf(word, [](const QChar &c) { return c.isUpper() || c == '_'; }))
|
2016-01-22 13:50:58 +01:00
|
|
|
result.append(word);
|
2012-09-06 22:38:25 +08:00
|
|
|
}
|
2016-01-22 13:50:58 +01:00
|
|
|
word.clear();
|
|
|
|
|
ignoreWord = false;
|
|
|
|
|
} else {
|
|
|
|
|
word.append(c);
|
2012-09-06 22:38:25 +08:00
|
|
|
}
|
|
|
|
|
}
|
2016-01-22 13:50:58 +01:00
|
|
|
return result;
|
2013-02-16 22:37:31 +08:00
|
|
|
}
|
|
|
|
|
|
2016-01-22 13:50:58 +01:00
|
|
|
void CMakeTool::parseFunctionDetailsOutput(const QString &output)
|
2013-02-16 22:37:31 +08:00
|
|
|
{
|
2016-01-22 13:50:58 +01:00
|
|
|
QSet<QString> functionSet;
|
2018-07-10 14:17:12 +02:00
|
|
|
functionSet.fromList(m_introspection->m_functions);
|
2016-01-22 13:50:58 +01:00
|
|
|
|
|
|
|
|
bool expectDefinition = false;
|
|
|
|
|
QString currentDefinition;
|
|
|
|
|
|
2016-09-26 16:29:58 +02:00
|
|
|
const QStringList lines = output.split('\n');
|
2016-01-22 13:50:58 +01:00
|
|
|
for (int i = 0; i < lines.count(); ++i) {
|
|
|
|
|
const QString line = lines.at(i);
|
|
|
|
|
|
2016-09-26 16:29:58 +02:00
|
|
|
if (line == "::") {
|
2016-01-22 13:50:58 +01:00
|
|
|
expectDefinition = true;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (expectDefinition) {
|
2016-09-26 16:29:58 +02:00
|
|
|
if (!line.startsWith(' ') && !line.isEmpty()) {
|
2016-01-22 13:50:58 +01:00
|
|
|
expectDefinition = false;
|
|
|
|
|
QStringList words = parseDefinition(currentDefinition);
|
|
|
|
|
if (!words.isEmpty()) {
|
|
|
|
|
const QString command = words.takeFirst();
|
|
|
|
|
if (functionSet.contains(command)) {
|
2018-07-10 14:17:12 +02:00
|
|
|
QStringList tmp = words + m_introspection->m_functionArgs[command];
|
2016-01-22 13:50:58 +01:00
|
|
|
Utils::sort(tmp);
|
2018-07-10 14:17:12 +02:00
|
|
|
m_introspection->m_functionArgs[command] = Utils::filteredUnique(tmp);
|
2016-01-22 13:50:58 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!words.isEmpty() && functionSet.contains(words.at(0)))
|
2018-07-10 14:17:12 +02:00
|
|
|
m_introspection->m_functionArgs[words.at(0)];
|
2016-01-22 13:50:58 +01:00
|
|
|
currentDefinition.clear();
|
|
|
|
|
} else {
|
2016-09-26 16:29:58 +02:00
|
|
|
currentDefinition.append(line.trimmed() + ' ');
|
2013-02-16 22:37:31 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-22 13:50:58 +01:00
|
|
|
QStringList CMakeTool::parseVariableOutput(const QString &output)
|
2013-02-16 22:37:31 +08:00
|
|
|
{
|
2016-09-26 16:29:58 +02:00
|
|
|
const QStringList variableList = output.split('\n');
|
2016-01-22 13:50:58 +01:00
|
|
|
QStringList result;
|
|
|
|
|
foreach (const QString &v, variableList) {
|
2016-09-14 12:28:14 +02:00
|
|
|
if (v.startsWith("CMAKE_COMPILER_IS_GNU<LANG>")) { // This key takes a compiler name :-/
|
|
|
|
|
result << "CMAKE_COMPILER_IS_GNUCC" << "CMAKE_COMPILER_IS_GNUCXX";
|
|
|
|
|
} else if (v.contains("<CONFIG>")) {
|
2016-09-14 12:26:13 +02:00
|
|
|
const QString tmp = QString(v).replace("<CONFIG>", "%1");
|
|
|
|
|
result << tmp.arg("DEBUG") << tmp.arg("RELEASE")
|
|
|
|
|
<< tmp.arg("MINSIZEREL") << tmp.arg("RELWITHDEBINFO");
|
|
|
|
|
} else if (v.contains("<LANG>")) {
|
|
|
|
|
const QString tmp = QString(v).replace("<LANG>", "%1");
|
|
|
|
|
result << tmp.arg("C") << tmp.arg("CXX");
|
2016-09-26 16:29:58 +02:00
|
|
|
} else if (!v.contains('<') && !v.contains('[')) {
|
2016-01-22 13:50:58 +01:00
|
|
|
result << v;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result;
|
2012-09-06 22:38:25 +08:00
|
|
|
}
|
2016-02-12 12:30:55 +01:00
|
|
|
|
2016-09-28 12:24:06 +02:00
|
|
|
void CMakeTool::fetchGeneratorsFromHelp() const
|
|
|
|
|
{
|
2017-02-22 15:09:35 +01:00
|
|
|
Utils::SynchronousProcessResponse response = run({"--help"});
|
2016-09-28 12:24:06 +02:00
|
|
|
if (response.result != Utils::SynchronousProcessResponse::Finished)
|
|
|
|
|
return;
|
2018-07-10 14:03:55 +02:00
|
|
|
parseGeneratorsFromHelp(response.stdOut().split('\n'));
|
|
|
|
|
}
|
2016-09-28 12:24:06 +02:00
|
|
|
|
2018-07-10 14:03:55 +02:00
|
|
|
void CMakeTool::parseGeneratorsFromHelp(const QStringList &lines) const
|
|
|
|
|
{
|
2016-09-28 12:24:06 +02:00
|
|
|
bool inGeneratorSection = false;
|
|
|
|
|
QHash<QString, QStringList> generatorInfo;
|
|
|
|
|
foreach (const QString &line, lines) {
|
|
|
|
|
if (line.isEmpty())
|
|
|
|
|
continue;
|
|
|
|
|
if (line == "Generators") {
|
|
|
|
|
inGeneratorSection = true;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (!inGeneratorSection)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (line.startsWith(" ") && line.at(3) != ' ') {
|
|
|
|
|
int pos = line.indexOf('=');
|
|
|
|
|
if (pos < 0)
|
|
|
|
|
pos = line.length();
|
|
|
|
|
if (pos >= 0) {
|
|
|
|
|
--pos;
|
|
|
|
|
while (pos > 2 && line.at(pos).isSpace())
|
|
|
|
|
--pos;
|
|
|
|
|
}
|
|
|
|
|
if (pos > 2) {
|
|
|
|
|
const QString fullName = line.mid(2, pos - 1);
|
|
|
|
|
const int dashPos = fullName.indexOf(" - ");
|
|
|
|
|
QString generator;
|
|
|
|
|
QString extra;
|
|
|
|
|
if (dashPos < 0) {
|
|
|
|
|
generator = fullName;
|
|
|
|
|
} else {
|
|
|
|
|
extra = fullName.mid(0, dashPos);
|
|
|
|
|
generator = fullName.mid(dashPos + 3);
|
|
|
|
|
}
|
|
|
|
|
QStringList value = generatorInfo.value(generator);
|
|
|
|
|
if (!extra.isEmpty())
|
|
|
|
|
value.append(extra);
|
|
|
|
|
generatorInfo.insert(generator, value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Populate genertor list:
|
2016-09-28 15:18:29 +02:00
|
|
|
for (auto it = generatorInfo.constBegin(); it != generatorInfo.constEnd(); ++it)
|
2018-07-10 14:17:12 +02:00
|
|
|
m_introspection->m_generators.append(Generator(it.key(), it.value()));
|
2016-09-28 15:18:29 +02:00
|
|
|
}
|
|
|
|
|
|
2016-09-28 17:25:29 +02:00
|
|
|
void CMakeTool::fetchVersionFromVersionOutput() const
|
|
|
|
|
{
|
2017-02-22 15:09:35 +01:00
|
|
|
Utils::SynchronousProcessResponse response = run({"--version" });
|
2016-09-28 17:25:29 +02:00
|
|
|
if (response.result != Utils::SynchronousProcessResponse::Finished)
|
|
|
|
|
return;
|
|
|
|
|
|
2018-07-10 14:03:55 +02:00
|
|
|
parseVersionFormVersionOutput(response.stdOut().split('\n'));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CMakeTool::parseVersionFormVersionOutput(const QStringList &lines) const
|
|
|
|
|
{
|
2018-03-25 04:21:24 +02:00
|
|
|
QRegularExpression versionLine("^cmake.* version ((\\d+).(\\d+).(\\d+).*)$");
|
2018-07-10 14:03:55 +02:00
|
|
|
for (const QString &line : lines) {
|
2016-09-28 17:25:29 +02:00
|
|
|
QRegularExpressionMatch match = versionLine.match(line);
|
|
|
|
|
if (!match.hasMatch())
|
|
|
|
|
continue;
|
|
|
|
|
|
2018-07-10 14:17:12 +02:00
|
|
|
m_introspection->m_version.major = match.captured(2).toInt();
|
|
|
|
|
m_introspection->m_version.minor = match.captured(3).toInt();
|
|
|
|
|
m_introspection->m_version.patch = match.captured(4).toInt();
|
|
|
|
|
m_introspection->m_version.fullVersion = match.captured(1).toUtf8();
|
2016-09-28 17:25:29 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CMakeTool::fetchFromCapabilities() const
|
2016-09-28 15:18:29 +02:00
|
|
|
{
|
2017-02-22 15:09:35 +01:00
|
|
|
Utils::SynchronousProcessResponse response = run({"-E", "capabilities" }, true);
|
2016-09-28 15:18:29 +02:00
|
|
|
if (response.result != Utils::SynchronousProcessResponse::Finished)
|
|
|
|
|
return;
|
|
|
|
|
|
2018-07-10 14:03:55 +02:00
|
|
|
parseFromCapabilities(response.stdOut());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CMakeTool::parseFromCapabilities(const QString &input) const
|
|
|
|
|
{
|
|
|
|
|
auto doc = QJsonDocument::fromJson(input.toUtf8());
|
2016-09-28 15:18:29 +02:00
|
|
|
if (!doc.isObject())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
const QVariantMap data = doc.object().toVariantMap();
|
2018-07-10 14:17:12 +02:00
|
|
|
m_introspection->m_hasServerMode = data.value("serverMode").toBool();
|
2016-09-28 15:18:29 +02:00
|
|
|
const QVariantList generatorList = data.value("generators").toList();
|
|
|
|
|
for (const QVariant &v : generatorList) {
|
|
|
|
|
const QVariantMap gen = v.toMap();
|
2018-07-10 14:17:12 +02:00
|
|
|
m_introspection->m_generators.append(Generator(gen.value("name").toString(),
|
|
|
|
|
gen.value("extraGenerators").toStringList(),
|
|
|
|
|
gen.value("platformSupport").toBool(),
|
|
|
|
|
gen.value("toolsetSupport").toBool()));
|
2016-09-28 12:24:06 +02:00
|
|
|
}
|
2016-09-28 17:25:29 +02:00
|
|
|
|
|
|
|
|
const QVariantMap versionInfo = data.value("version").toMap();
|
2018-07-10 14:17:12 +02:00
|
|
|
m_introspection->m_version.major = versionInfo.value("major").toInt();
|
|
|
|
|
m_introspection->m_version.minor = versionInfo.value("minor").toInt();
|
|
|
|
|
m_introspection->m_version.patch = versionInfo.value("patch").toInt();
|
|
|
|
|
m_introspection->m_version.fullVersion = versionInfo.value("string").toByteArray();
|
2016-09-28 12:24:06 +02:00
|
|
|
}
|
|
|
|
|
|
2016-02-12 12:30:55 +01:00
|
|
|
} // namespace CMakeProjectManager
|