aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/qbsprojectmanager/qbsprojectparser.cpp
blob: 1620b747ac3820d5f1b778e65152a07d5cd03e2a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0

#include "qbsprojectparser.h"

#include "qbsproject.h"
#include "qbsprojectmanagerconstants.h"
#include "qbssettings.h"

#include <utils/qtcassert.h>

#include <QDir>
#include <QFileInfo>
#include <QFutureWatcher>
#include <QJsonArray>

using namespace Utils;

namespace QbsProjectManager::Internal {

// --------------------------------------------------------------------
// QbsProjectParser:
// --------------------------------------------------------------------

QbsProjectParser::QbsProjectParser(QbsBuildSystem *buildSystem, QFutureInterface<bool> *fi)
    : m_projectFilePath(buildSystem->project()->projectFilePath()),
      m_session(buildSystem->session()),
      m_fi(fi)
{
    auto * const watcher = new QFutureWatcher<bool>(this);
    connect(watcher, &QFutureWatcher<bool>::canceled, this, &QbsProjectParser::cancel);
    watcher->setFuture(fi->future());
}

QbsProjectParser::~QbsProjectParser()
{
    if (m_session && m_parsing)
        m_session->cancelCurrentJob();
    m_fi = nullptr; // we do not own m_fi, do not delete
}

void QbsProjectParser::parse(const QVariantMap &config, const Environment &env,
                             const FilePath &dir, const QString &configName)
{
    QTC_ASSERT(m_session, return);
    QTC_ASSERT(!dir.isEmpty(), return);

    m_environment = env;
    QJsonObject request;
    request.insert("type", "resolve-project");
    QVariantMap userConfig = config;
    request.insert("top-level-profile",
                   userConfig.take(Constants::QBS_CONFIG_PROFILE_KEY).toString());
    request.insert("configuration-name", configName);
    request.insert("force-probe-execution",
                   userConfig.take(Constants::QBS_FORCE_PROBES_KEY).toBool());
    if (QbsSettings::useCreatorSettingsDirForQbs())
        request.insert("settings-directory", QbsSettings::qbsSettingsBaseDir());
    request.insert("overridden-properties", QJsonObject::fromVariantMap(userConfig));

    // People don't like it when files are created as a side effect of opening a project,
    // so do not store the build graph if the build directory does not exist yet.
    request.insert("dry-run", !dir.exists());

    request.insert("build-root", dir.path());
    request.insert("project-file-path", m_projectFilePath.path());
    request.insert("override-build-graph-data", true);
    static const auto envToJson = [](const Environment &env) {
        QJsonObject envObj;
        for (auto it = env.constBegin(); it != env.constEnd(); ++it) {
            if (env.isEnabled(it))
                envObj.insert(env.key(it), env.value(it));
        }
        return envObj;
    };
    request.insert("environment", envToJson(env));
    request.insert("error-handling-mode", "relaxed");
    request.insert("data-mode", "only-if-changed");
    QbsSession::insertRequestedModuleProperties(request);

    connect(m_session, &QbsSession::projectResolved, this, [this](const ErrorInfo &error) {
        m_error = error;
        m_projectData = m_session->projectData();
        emit done(!m_error.hasError());
    });
    connect(m_session, &QbsSession::errorOccurred, this, [this] { emit done(false); });
    connect(m_session, &QbsSession::taskStarted, this,
            [this](const QString &description, int maxProgress) {
        Q_UNUSED(description)
        if (m_fi)
            m_fi->setProgressRange(0, maxProgress);
    });
    connect(m_session, &QbsSession::maxProgressChanged, this, [this](int maxProgress) {
        if (m_fi)
            m_fi->setProgressRange(0, maxProgress);
    });
    connect(m_session, &QbsSession::taskProgress, this, [this](int progress) {
        if (m_fi)
            m_fi->setProgressValue(progress);
    });
    m_session->sendRequest(request);
}

void QbsProjectParser::cancel()
{
    if (m_session)
        m_session->cancelCurrentJob();
}

} // QbsProjectManager::Internal