aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/projectexplorer/buildsystem.h
blob: c406f0a4e5965bfe17967bfd9a9ecdb05764e87c (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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
// Copyright (C) 2019 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0

#pragma once

#include "projectexplorer_export.h"

#include "buildtargetinfo.h"
#include "project.h"
#include "projectnodes.h"

#include <QObject>

namespace Utils {
class CommandLine;
}

namespace ProjectExplorer {

class BuildConfiguration;
class BuildStepList;
class ExtraCompiler;
class Node;

struct TestCaseInfo
{
    QString name;
    int number = -1;
    Utils::FilePath path;
    int line = 0;
};

struct TestCaseEnvironment
{
    Utils::FilePath workingDirectory;
    Utils::Environment environment;
};

// Extra infomation needed by QmlJS tools and editor.
class QmlCodeModelInfo
{
public:
    bool isValid() const { return !sourceFiles.isEmpty(); }

    Utils::FilePaths sourceFiles;
    Utils::FilePaths qmlImportPaths;
    Utils::FilePaths activeResourceFiles;
    Utils::FilePaths allResourceFiles;
    Utils::FilePaths generatedQrcFiles;
    QHash<Utils::FilePath, QString> resourceFileContents;
    Utils::FilePaths applicationDirectories;
    QHash<QString, QString> moduleMappings; // E.g.: QtQuick.Controls -> MyProject.MyControls

    // whether trying to run qmldump makes sense
    bool tryQmlDump = false;
    bool qmlDumpHasRelocatableFlag = true;
    Utils::FilePath qmlDumpPath;
    Utils::Environment qmlDumpEnvironment;

    Utils::FilePath qtQmlPath;
    Utils::FilePath qmllsPath;
    QString qtVersionString;
};

// --------------------------------------------------------------------
// BuildSystem:
// --------------------------------------------------------------------

// Check buildsystem.md for more information
class PROJECTEXPLORER_EXPORT BuildSystem : public QObject
{
    Q_OBJECT

public:
    explicit BuildSystem(BuildConfiguration *bc);
    ~BuildSystem() override;

    QString name() const;
    Project *project() const;
    Target *target() const;
    Kit *kit() const;
    BuildConfiguration *buildConfiguration() const;

    Utils::FilePath projectFilePath() const;
    Utils::FilePath projectDirectory() const;

    bool isWaitingForParse() const;

    void requestParse();
    void requestDelayedParse();
    void cancelDelayedParseRequest();

    bool isParsing() const;
    bool hasParsingData() const;

    Utils::Environment activeParseEnvironment() const;

    virtual void requestDebugging() {}
    virtual bool addFiles(Node *context,
                          const Utils::FilePaths &filePaths,
                          Utils::FilePaths *notAdded = nullptr);
    virtual RemovedFilesFromProject removeFiles(Node *context,
                                                const Utils::FilePaths &filePaths,
                                                Utils::FilePaths *notRemoved = nullptr);
    virtual bool deleteFiles(Node *context, const Utils::FilePaths &filePaths);
    virtual bool canRenameFile(Node *context,
                               const Utils::FilePath &oldFilePath,
                               const Utils::FilePath &newFilePath);
    virtual bool renameFiles(
        Node *context, const Utils::FilePairs &filesToRename, Utils::FilePaths *notRenamed);
    virtual bool addDependencies(Node *context, const QStringList &dependencies);
    virtual bool supportsAction(Node *context, ProjectAction action, const Node *node) const;
    virtual void buildNamedTarget(const QString &target) { Q_UNUSED(target) }

    // Owned by the build system. Use only in main thread. Can go away at any time.
    ExtraCompiler *extraCompilerForSource(const Utils::FilePath &source) const;
    ExtraCompiler *extraCompilerForTarget(const Utils::FilePath &target) const;

    virtual MakeInstallCommand makeInstallCommand(const Utils::FilePath &installRoot) const;

    virtual Utils::FilePaths filesGeneratedFrom(const Utils::FilePath &sourceFile) const;
    virtual QVariant additionalData(Utils::Id id) const;
    virtual QList<QPair<Utils::Id, QString>> generators() const { return {}; }
    virtual void runGenerator(Utils::Id) {}

    void setDeploymentData(const DeploymentData &deploymentData);
    DeploymentData deploymentData() const;

    void setApplicationTargets(const QList<BuildTargetInfo> &appTargets);
    const QList<BuildTargetInfo> applicationTargets() const;
    BuildTargetInfo buildTarget(const QString &buildKey) const;

    void setRootProjectNode(std::unique_ptr<ProjectNode> &&root);

    virtual const QList<TestCaseInfo> testcasesInfo() const { return {}; }
    virtual Utils::CommandLine commandLineForTests(const QStringList &tests,
                                                   const QStringList &options) const;

    class PROJECTEXPLORER_EXPORT ParseGuard
    {
        friend class BuildSystem;
        explicit ParseGuard(BuildSystem *p);

        void release();

    public:
        ParseGuard() = default;
        ~ParseGuard() { release(); }

        void markAsSuccess() const { m_success = true; }
        bool isSuccess() const { return m_success; }
        bool guardsProject() const { return m_buildSystem; }

        ParseGuard(const ParseGuard &other) = delete;
        ParseGuard &operator=(const ParseGuard &other) = delete;
        ParseGuard(ParseGuard &&other);
        ParseGuard &operator=(ParseGuard &&other);

    private:
        BuildSystem *m_buildSystem = nullptr;
        mutable bool m_success = false;
    };

    void emitBuildSystemUpdated();

    void setExtraData(const QString &buildKey, Utils::Id dataKey, const QVariant &data);
    QVariant extraData(const QString &buildKey, Utils::Id dataKey) const;

    static void startNewBuildSystemOutput(const QString &message);
    static void appendBuildSystemOutput(const QString &message);

public:
    // FIXME: Make this private and the BuildSystem a friend
    ParseGuard guardParsingRun() { return ParseGuard(this); }

    QString disabledReason(const QString &buildKey) const;

    virtual void triggerParsing() = 0;

    void updateQmlCodeModel();
    virtual void updateQmlCodeModelInfo(QmlCodeModelInfo &projectInfo);

    virtual bool addTargetProperty(Node *context, const QString &property, const QString &value,
                                   const std::string &condition);

signals:
    void parsingStarted();
    void parsingFinished(bool success);
    void updated(); // FIXME: Redundant with parsingFinished()?
    void testInformationUpdated();
    void testRunRequested(const TestCaseInfo &testInfo, const QStringList &additionalOptions,
                          const TestCaseEnvironment &env);
    void debuggingStarted();
    void errorOccurred(const QString &message);
    void warningOccurred(const QString &message);
    void deploymentDataChanged();

protected:
    // Helper methods to manage parsing state and signalling
    // Call in GUI thread before the actual parsing starts
    void emitParsingStarted();
    // Call in GUI thread right after the actual parsing is done
    void emitParsingFinished(bool success);

    using ExtraCompilerFilter = std::function<bool(const ExtraCompiler *)>;

private:
    void requestParseHelper(int delay); // request a (delayed!) parser run.

    virtual ExtraCompiler *findExtraCompiler(const ExtraCompilerFilter &filter) const;

    class BuildSystemPrivate *d = nullptr;
};

PROJECTEXPLORER_EXPORT BuildSystem *activeBuildSystem(const Project *project);
PROJECTEXPLORER_EXPORT BuildSystem *activeBuildSystemForActiveProject();
PROJECTEXPLORER_EXPORT BuildSystem *activeBuildSystemForCurrentProject();

} // namespace ProjectExplorer