qmakeparsernodes.h 12.5 KB
Newer Older
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
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** 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
** 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.
**
** 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.
**
****************************************************************************/

#pragma once

#include "qmakeprojectmanager_global.h"
#include "proparser/prowriter.h"
#include "proparser/profileevaluator.h"

#include <coreplugin/idocument.h>
#include <cpptools/generatedcodemodelsupport.h>

#include <QHash>
#include <QStringList>
#include <QMap>
#include <QFutureWatcher>

40 41
#include <memory>

42 43 44 45 46 47
namespace Utils { class FileName; }
namespace QtSupport { class ProFileReader; }
namespace ProjectExplorer { class RunConfiguration; }

namespace QmakeProjectManager {
class QmakeBuildConfiguration;
48
class QmakeProFile;
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
class QmakeProject;

//  Type of projects
enum class ProjectType {
    Invalid = 0,
    ApplicationTemplate,
    StaticLibraryTemplate,
    SharedLibraryTemplate,
    ScriptTemplate,
    AuxTemplate,
    SubDirsTemplate
};

// Other variables of interest
enum class Variable {
    Defines = 1,
    IncludePath,
    CppFlags,
    Source,
    ExactResource,
    CumulativeResource,
    UiDir,
    HeaderExtension,
    CppExtension,
    MocDir,
    PkgConfig,
    PrecompiledHeader,
    LibDirectories,
    Config,
    Qt,
    QmlImportPath,
    QmlDesignerImportPath,
    Makefile,
    ObjectExt,
    ObjectsDir,
    Version,
    TargetExt,
    TargetVersionExt,
    StaticLibExtension,
    ShLibExtension,
    AndroidArch,
    AndroidDeploySettingsFile,
    AndroidPackageSourceDir,
    AndroidExtraLibs,
    IsoIcons,
    QmakeProjectName,
    QmakeCc,
    QmakeCxx
};
uint qHash(Variable key, uint seed = 0);

namespace Internal {
class QmakeEvalInput;
class QmakeEvalResult;
class QmakePriFileEvalResult;
104
} // namespace Internal;
105

106
class InstallsParserList;
107 108

// Implements ProjectNode for qmake .pri files
109
class QMAKEPROJECTMANAGER_EXPORT QmakePriFile
110 111
{
public:
112
    QmakePriFile(QmakeProject *project, QmakeProFile *qmakeProFile, const Utils::FileName &filePath);
113
    virtual ~QmakePriFile();
114

115 116
    Utils::FileName filePath() const;
    Utils::FileName directoryPath() const;
117
    virtual QString displayName() const;
118

119
    QmakePriFile *parent() const;
120
    QmakeProject *project() const;
121
    QVector<QmakePriFile *> children() const;
122
    void makeEmpty();
123

124 125 126
    void update(const Internal::QmakePriFileEvalResult &result);

    // ProjectNode interface
127
    virtual bool canAddSubProject(const QString &proFilePath) const;
128

129 130
    virtual bool addSubProjects(const QStringList &proFilePaths);
    virtual bool removeSubProjects(const QStringList &proFilePaths);
131

132 133 134 135 136
    virtual bool addFiles(const QStringList &filePaths, QStringList *notAdded = nullptr);
    virtual bool removeFiles(const QStringList &filePaths, QStringList *notRemoved = nullptr);
    virtual bool deleteFiles(const QStringList &filePaths);
    virtual bool canRenameFile(const QString &filePath, const QString &newFilePath);
    virtual bool renameFile(const QString &filePath, const QString &newFilePath);
137 138 139 140 141 142 143

    bool setProVariable(const QString &var, const QStringList &values,
                        const QString &scope = QString(),
                        int flags = QmakeProjectManager::Internal::ProWriter::ReplaceValues);

    bool folderChanged(const QString &changedFolder, const QSet<Utils::FileName> &newFiles);

144 145
    virtual bool deploysFolder(const QString &folder) const;
    virtual QList<ProjectExplorer::RunConfiguration *> runConfigurations() const;
146

147
    QmakeProFile *proFile() const;
148
    QVector<QmakePriFile *> subPriFilesExact() const;
149 150 151 152 153 154

    // Set by parent
    bool includedInExactParse() const;

    static QSet<Utils::FileName> recursiveEnumerate(const QString &folder);

155 156
    void scheduleUpdate();

157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
protected:
    void setIncludedInExactParse(bool b);
    static QStringList varNames(ProjectExplorer::FileType type, QtSupport::ProFileReader *readerExact);
    static QStringList varNamesForRemoving();
    static QString varNameForAdding(const QString &mimeType);
    static QSet<Utils::FileName> filterFilesProVariables(ProjectExplorer::FileType fileType, const QSet<Utils::FileName> &files);
    static QSet<Utils::FileName> filterFilesRecursiveEnumerata(ProjectExplorer::FileType fileType, const QSet<Utils::FileName> &files);

    enum ChangeType {
        AddToProFile,
        RemoveFromProFile
    };

    enum class Change { Save, TestOnly };
    bool renameFile(const QString &oldName,
                    const QString &newName,
                    const QString &mimeType,
                    Change mode = Change::Save);
    void changeFiles(const QString &mimeType,
                     const QStringList &filePaths,
                     QStringList *notChanged,
                     ChangeType change,
                     Change mode = Change::Save);

181
    void addChild(QmakePriFile *pf);
182

183
private:
184 185
    void setParent(QmakePriFile *p);

186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
    bool prepareForChange();
    static bool ensureWriteableProFile(const QString &file);
    static QPair<ProFile *, QStringList> readProFile(const QString &file);
    static QPair<ProFile *, QStringList> readProFileFromContents(const QString &contents);
    void save(const QStringList &lines);
    bool priFileWritable(const QString &absoluteFilePath);
    bool saveModifiedEditors();
    QStringList formResources(const QString &formFile) const;
    static QStringList baseVPaths(QtSupport::ProFileReader *reader, const QString &projectDir, const QString &buildDir);
    static QStringList fullVPaths(const QStringList &baseVPaths, QtSupport::ProFileReader *reader, const QString &qmakeVariable, const QString &projectDir);
    static void extractSources(
            QHash<const ProFile *, Internal::QmakePriFileEvalResult *> proToResult,
            Internal::QmakePriFileEvalResult *fallback,
            QVector<ProFileEvaluator::SourceFile> sourceFiles, ProjectExplorer::FileType type);
    static void extractInstalls(
            QHash<const ProFile *, Internal::QmakePriFileEvalResult *> proToResult,
            Internal::QmakePriFileEvalResult *fallback,
            const InstallsParserList &installList);
    static void processValues(Internal::QmakePriFileEvalResult &result);
    void watchFolders(const QSet<QString> &folders);

207
    QmakeProject *m_project = nullptr;
208
    QmakeProFile *m_qmakeProFile = nullptr;
209 210
    QmakePriFile *m_parent = nullptr;
    QVector<QmakePriFile *> m_children;
211

212
    std::unique_ptr<Core::IDocument> m_priFileDocument;
213 214

    // Memory is cheap...
Tobias Hunger's avatar
Tobias Hunger committed
215
    QMap<ProjectExplorer::FileType, QSet<Utils::FileName>> m_files;
216 217 218 219
    QSet<Utils::FileName> m_recursiveEnumerateFiles;
    QSet<QString> m_watchedFolders;
    bool m_includedInExactParse = true;

220 221
    // managed by QmakeProFile
    friend class QmakeProjectManager::QmakeProFile;
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
};

class QMAKEPROJECTMANAGER_EXPORT TargetParserInformation
{
public:
    bool valid = false;
    QString target;
    QString destDir;
    QString buildDir;
    QString buildTarget;
    bool operator==(const TargetParserInformation &other) const
    {
        return target == other.target
                && valid == other.valid
                && destDir == other.destDir
                && buildDir == other.buildDir
                && buildTarget == other.buildTarget;
    }
    bool operator!=(const TargetParserInformation &other) const
    {
        return !(*this == other);
    }

    TargetParserInformation() = default;
    TargetParserInformation(const TargetParserInformation &other) = default;
};

249 250
class QMAKEPROJECTMANAGER_EXPORT InstallsParserItem {
public:
251 252 253 254 255 256 257 258
    InstallsParserItem() = default;
    InstallsParserItem(QString p, QVector<ProFileEvaluator::SourceFile> f, bool a)
        : path(p), files(f), active(a) {}
    QString path;
    QVector<ProFileEvaluator::SourceFile> files;
    bool active = false;
};

259 260
class QMAKEPROJECTMANAGER_EXPORT InstallsParserList {
public:
261 262 263 264 265 266
    void clear() { targetPath.clear(); items.clear(); }
    QString targetPath;
    QVector<InstallsParserItem> items;
};

// Implements ProjectNode for qmake .pro files
267
class QMAKEPROJECTMANAGER_EXPORT QmakeProFile : public QmakePriFile
268 269
{
public:
270 271
    QmakeProFile(QmakeProject *project, const Utils::FileName &filePath);
    ~QmakeProFile() override;
272

273
    bool isParent(QmakeProFile *node);
274
    QString displayName() const final;
275 276 277 278 279 280

    ProjectType projectType() const;

    QStringList variableValue(const Variable var) const;
    QString singleVariableValue(const Variable var) const;

281
    bool isSubProjectDeployable(const Utils::FileName &filePath) const {
282 283 284 285
        return !m_subProjectsNotToDeploy.contains(filePath);
    }

    QString sourceDir() const;
Tobias Hunger's avatar
Tobias Hunger committed
286
    QString buildDir(QmakeBuildConfiguration *bc = nullptr) const;
287 288 289 290 291

    QStringList generatedFiles(const QString &buildDirectory,
                               const ProjectExplorer::FileNode *sourceFile) const;
    QList<ProjectExplorer::ExtraCompiler *> extraCompilers() const;

292
    QmakeProFile *findProFileFor(const Utils::FileName &string) const;
293 294 295 296 297 298 299 300 301 302
    TargetParserInformation targetInformation() const;

    InstallsParserList installsList() const;

    QString makefile() const;
    QString objectExtension() const;
    QString objectsDirectory() const;
    QByteArray cxxDefines() const;

    enum AsyncUpdateDelay { ParseNow, ParseLater };
303
    using QmakePriFile::scheduleUpdate;
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
    void scheduleUpdate(AsyncUpdateDelay delay);

    bool validParse() const;
    bool parseInProgress() const;

    bool isDebugAndRelease() const;
    bool isQtcRunnable() const;

    void setParseInProgressRecursive(bool b);

    void asyncUpdate();

private:
    void setParseInProgress(bool b);
    void setValidParseRecursive(bool b);

    void applyAsyncEvaluate();

    void setupReader();
    Internal::QmakeEvalInput evalInput() const;

    static Internal::QmakeEvalResult *evaluate(const Internal::QmakeEvalInput &input);
    void applyEvaluate(Internal::QmakeEvalResult *parseResult);

    void asyncEvaluate(QFutureInterface<Internal::QmakeEvalResult *> &fi, Internal::QmakeEvalInput input);
    void cleanupProFileReaders();

    using VariablesHash = QHash<Variable, QStringList>;

    void updateGeneratedFiles(const QString &buildDir);

    static QString uiDirPath(QtSupport::ProFileReader *reader, const QString &buildDir);
    static QString mocDirPath(QtSupport::ProFileReader *reader, const QString &buildDir);
    static QString sysrootify(const QString &path, const QString &sysroot, const QString &baseDir, const QString &outputDir);
    static QStringList includePaths(QtSupport::ProFileReader *reader, const QString &sysroot, const QString &buildDir, const QString &projectDir);
    static QStringList libDirectories(QtSupport::ProFileReader *reader);
    static Utils::FileNameList subDirsPaths(QtSupport::ProFileReader *reader, const QString &projectDir, QStringList *subProjectsNotToDeploy, QStringList *errors);

    static TargetParserInformation targetInformation(QtSupport::ProFileReader *reader, QtSupport::ProFileReader *readerBuildPass, const QString &buildDir, const QString &projectFilePath);
    static InstallsParserList installsList(const QtSupport::ProFileReader *reader, const QString &projectFilePath, const QString &projectDir, const QString &buildDir);

    bool m_validParse = false;
    bool m_parseInProgress = false;

348
    QString m_displayName;
349 350 351 352 353
    ProjectType m_projectType = ProjectType::Invalid;
    VariablesHash m_varValues;
    QList<ProjectExplorer::ExtraCompiler *> m_extraCompilers;

    TargetParserInformation m_qmakeTargetInformation;
354
    Utils::FileNameList m_subProjectsNotToDeploy;
355 356 357 358 359 360 361 362 363
    InstallsParserList m_installsList;

    // Async stuff
    QFutureWatcher<Internal::QmakeEvalResult *> m_parseFutureWatcher;
    QtSupport::ProFileReader *m_readerExact = nullptr;
    QtSupport::ProFileReader *m_readerCumulative = nullptr;
};

} // namespace QmakeProjectManager