cmakeprojectmanager.cpp 7.73 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
con's avatar
con committed
2
**
3 4
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
con's avatar
con committed
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
con's avatar
con committed
7
**
hjk's avatar
hjk committed
8 9 10 11
** 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
12 13 14
** 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.
15
**
16 17 18 19 20 21 22
** 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.
con's avatar
con committed
23
**
hjk's avatar
hjk committed
24
****************************************************************************/
hjk's avatar
hjk committed
25

con's avatar
con committed
26
#include "cmakeprojectmanager.h"
27 28 29
#include "builddirmanager.h"
#include "cmakebuildconfiguration.h"
#include "cmakekitinformation.h"
con's avatar
con committed
30 31
#include "cmakeprojectconstants.h"
#include "cmakeproject.h"
32
#include "cmakesettingspage.h"
33
#include "cmaketoolmanager.h"
con's avatar
con committed
34

dt's avatar
dt committed
35
#include <coreplugin/icore.h>
36 37 38
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/actionmanager/actioncontainer.h>
39
#include <projectexplorer/buildmanager.h>
40 41
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorerconstants.h>
42
#include <projectexplorer/projecttree.h>
43
#include <projectexplorer/session.h>
44
#include <projectexplorer/target.h>
45

46
#include <utils/qtcprocess.h>
47 48 49
#include <utils/synchronousprocess.h>

#include <QAction>
50
#include <QDateTime>
51
#include <QIcon>
con's avatar
con committed
52

Tobias Hunger's avatar
Tobias Hunger committed
53
using namespace ProjectExplorer;
con's avatar
con committed
54 55
using namespace CMakeProjectManager::Internal;

Tobias Hunger's avatar
Tobias Hunger committed
56 57
CMakeManager::CMakeManager() :
    m_runCMakeAction(new QAction(QIcon(), tr("Run CMake"), this)),
58
    m_clearCMakeCacheAction(new QAction(QIcon(), tr("Clear CMake Configuration"), this)),
Tobias Hunger's avatar
Tobias Hunger committed
59
    m_runCMakeActionContextMenu(new QAction(QIcon(), tr("Run CMake"), this))
con's avatar
con committed
60
{
61
    Core::ActionContainer *mbuild =
Eike Ziller's avatar
Eike Ziller committed
62
            Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_BUILDPROJECT);
63
    Core::ActionContainer *mproject =
Eike Ziller's avatar
Eike Ziller committed
64
            Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_PROJECTCONTEXT);
65
    Core::ActionContainer *msubproject =
Eike Ziller's avatar
Eike Ziller committed
66
            Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_SUBPROJECTCONTEXT);
67

68
    const Core::Context projectContext(CMakeProjectManager::Constants::PROJECTCONTEXT);
69
    const Core::Context globalContext(Core::Constants::C_GLOBAL);
70

Eike Ziller's avatar
Eike Ziller committed
71
    Core::Command *command = Core::ActionManager::registerAction(m_runCMakeAction,
72
                                                                 Constants::RUNCMAKE, globalContext);
73
    command->setAttribute(Core::Command::CA_Hide);
74
    mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_DEPLOY);
75
    connect(m_runCMakeAction, &QAction::triggered, [this]() {
Tobias Hunger's avatar
Tobias Hunger committed
76
        runCMake(SessionManager::startupProject());
77
    });
78

79 80 81 82 83 84 85 86
    command = Core::ActionManager::registerAction(m_clearCMakeCacheAction,
                                                  Constants::CLEARCMAKECACHE, globalContext);
    command->setAttribute(Core::Command::CA_Hide);
    mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_DEPLOY);
    connect(m_clearCMakeCacheAction, &QAction::triggered, [this]() {
        clearCMakeCache(SessionManager::startupProject());
    });

Eike Ziller's avatar
Eike Ziller committed
87 88
    command = Core::ActionManager::registerAction(m_runCMakeActionContextMenu,
                                                  Constants::RUNCMAKECONTEXTMENU, projectContext);
89 90 91
    command->setAttribute(Core::Command::CA_Hide);
    mproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD);
    msubproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD);
92
    connect(m_runCMakeActionContextMenu, &QAction::triggered, [this]() {
Tobias Hunger's avatar
Tobias Hunger committed
93
        runCMake(ProjectTree::currentProject());
94
    });
95

Tobias Hunger's avatar
Tobias Hunger committed
96
    connect(SessionManager::instance(), &SessionManager::startupProjectChanged,
97
            this, &CMakeManager::updateCmakeActions);
Tobias Hunger's avatar
Tobias Hunger committed
98
    connect(BuildManager::instance(), &BuildManager::buildStateChanged,
99
            this, &CMakeManager::updateCmakeActions);
100

101
    updateCmakeActions();
102 103
}

104
void CMakeManager::updateCmakeActions()
105
{
Tobias Hunger's avatar
Tobias Hunger committed
106
    auto project = qobject_cast<CMakeProject *>(SessionManager::startupProject());
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
    const bool visible = project && !BuildManager::isBuilding(project);
    m_runCMakeAction->setVisible(visible);
    m_clearCMakeCacheAction->setVisible(visible);
}

void CMakeManager::clearCMakeCache(Project *project)
{
    if (!project || !project->activeTarget())
        return;
    auto bc = qobject_cast<CMakeBuildConfiguration *>(project->activeTarget()->activeBuildConfiguration());
    if (!bc)
        return;

    bc->setCMakeConfiguration(CMakeConfigurationKitInformation::configuration(bc->target()->kit()));
    bc->buildDirManager()->clearCache();
122 123
}

Tobias Hunger's avatar
Tobias Hunger committed
124
void CMakeManager::runCMake(Project *project)
125 126 127 128
{
    if (!project)
        return;
    CMakeProject *cmakeProject = qobject_cast<CMakeProject *>(project);
Tobias Hunger's avatar
Tobias Hunger committed
129
    if (!cmakeProject || !cmakeProject->activeTarget() || !cmakeProject->activeTarget()->activeBuildConfiguration())
130
        return;
131

Tobias Hunger's avatar
Tobias Hunger committed
132
    if (!ProjectExplorerPlugin::saveModifiedFiles())
133
        return;
134

135
    cmakeProject->runCMake();
136 137
}

Tobias Hunger's avatar
Tobias Hunger committed
138
Project *CMakeManager::openProject(const QString &fileName, QString *errorString)
con's avatar
con committed
139
{
140 141
    Utils::FileName file = Utils::FileName::fromString(fileName);
    if (!file.toFileInfo().isFile()) {
142
        if (errorString)
143
            *errorString = tr("Failed opening project \"%1\": Project is not a file")
144
                .arg(file.toUserOutput());
145 146 147
        return 0;
    }

148
    return new CMakeProject(this, file);
con's avatar
con committed
149 150 151 152
}

QString CMakeManager::mimeType() const
{
153
    return QLatin1String(Constants::CMAKEPROJECTMIMETYPE);
con's avatar
con committed
154
}
155

156
// need to refactor this out
dt's avatar
dt committed
157 158 159
// we probably want the process instead of this function
// cmakeproject then could even run the cmake process in the background, adding the files afterwards
// sounds like a plan
160 161
void CMakeManager::createXmlFile(Utils::QtcProcess *proc, const QString &executable,
                                 const QString &arguments, const QString &sourceDirectory,
162
                                 const QDir &buildDirectory, const Utils::Environment &env)
dt's avatar
dt committed
163 164 165
{
    QString buildDirectoryPath = buildDirectory.absolutePath();
    buildDirectory.mkpath(buildDirectoryPath);
166
    proc->setWorkingDirectory(buildDirectoryPath);
167
    proc->setEnvironment(env);
168

169 170
    const QString srcdir = buildDirectory.exists(QLatin1String("CMakeCache.txt")) ?
                QString(QLatin1Char('.')) : sourceDirectory;
171 172 173
    QString args;
    Utils::QtcProcess::addArg(&args, srcdir);
    Utils::QtcProcess::addArgs(&args, arguments);
174

175
    proc->setCommand(executable, args);
176
    proc->start();
dt's avatar
dt committed
177 178
}

179 180 181
QString CMakeManager::findCbpFile(const QDir &directory)
{
    // Find the cbp file
182
    //   the cbp file is named like the project() command in the CMakeList.txt file
183
    //   so this function below could find the wrong cbp file, if the user changes the project()
184
    //   2name
185 186
    QDateTime t;
    QString file;
187
    foreach (const QString &cbpFile , directory.entryList()) {
188 189 190 191 192 193 194
        if (cbpFile.endsWith(QLatin1String(".cbp"))) {
            QFileInfo fi(directory.path() + QLatin1Char('/') + cbpFile);
            if (t.isNull() || fi.lastModified() > t) {
                file = directory.path() + QLatin1Char('/') + cbpFile;
                t = fi.lastModified();
            }
        }
195
    }
196
    return file;
197
}