1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights. These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
32 **************************************************************************/
35 #include "ui_makestep.h"
37 #include "qt4project.h"
38 #include "qt4target.h"
39 #include "qt4buildconfiguration.h"
40 #include "qt4projectmanagerconstants.h"
43 #include <projectexplorer/toolchain.h>
44 #include <projectexplorer/buildsteplist.h>
45 #include <projectexplorer/projectexplorer.h>
46 #include <extensionsystem/pluginmanager.h>
47 #include <utils/qtcprocess.h>
49 #include <QtCore/QDir>
50 #include <QtCore/QFileInfo>
52 using ExtensionSystem::PluginManager;
53 using namespace Qt4ProjectManager;
54 using namespace Qt4ProjectManager::Internal;
57 const char * const MAKESTEP_BS_ID("Qt4ProjectManager.MakeStep");
59 const char * const MAKE_ARGUMENTS_KEY("Qt4ProjectManager.MakeStep.MakeArguments");
60 const char * const MAKE_COMMAND_KEY("Qt4ProjectManager.MakeStep.MakeCommand");
61 const char * const CLEAN_KEY("Qt4ProjectManager.MakeStep.Clean");
64 MakeStep::MakeStep(ProjectExplorer::BuildStepList *bsl) :
65 AbstractProcessStep(bsl, QLatin1String(MAKESTEP_BS_ID)),
71 MakeStep::MakeStep(ProjectExplorer::BuildStepList *bsl, MakeStep *bs) :
72 AbstractProcessStep(bsl, bs),
74 m_userArgs(bs->m_userArgs),
75 m_makeCmd(bs->m_makeCmd)
80 MakeStep::MakeStep(ProjectExplorer::BuildStepList *bsl, const QString &id) :
81 AbstractProcessStep(bsl, id),
89 setDefaultDisplayName(tr("Make", "Qt4 MakeStep display name."));
96 Qt4BuildConfiguration *MakeStep::qt4BuildConfiguration() const
98 return static_cast<Qt4BuildConfiguration *>(buildConfiguration());
101 void MakeStep::setClean(bool clean)
106 QVariantMap MakeStep::toMap() const
108 QVariantMap map(ProjectExplorer::AbstractProcessStep::toMap());
109 map.insert(QLatin1String(MAKE_ARGUMENTS_KEY), m_userArgs);
110 map.insert(QLatin1String(MAKE_COMMAND_KEY), m_makeCmd);
111 map.insert(QLatin1String(CLEAN_KEY), m_clean);
115 bool MakeStep::fromMap(const QVariantMap &map)
117 m_makeCmd = map.value(QLatin1String(MAKE_COMMAND_KEY)).toString();
118 m_userArgs = map.value(QLatin1String(MAKE_ARGUMENTS_KEY)).toString();
119 m_clean = map.value(QLatin1String(CLEAN_KEY)).toBool();
121 return ProjectExplorer::AbstractProcessStep::fromMap(map);
124 bool MakeStep::init()
126 Qt4BuildConfiguration *bc = qt4BuildConfiguration();
127 ProjectExplorer::ProcessParameters *pp = processParameters();
128 pp->setMacroExpander(bc->macroExpander());
130 Utils::Environment environment = bc->environment();
131 pp->setEnvironment(environment);
133 QString workingDirectory;
134 if (bc->subNodeBuild())
135 workingDirectory = bc->subNodeBuild()->buildDir();
137 workingDirectory = bc->buildDirectory();
138 pp->setWorkingDirectory(workingDirectory);
140 QString makeCmd = bc->makeCommand();
141 if (!m_makeCmd.isEmpty())
143 pp->setCommand(makeCmd);
145 // If we are cleaning, then make can fail with a error code, but that doesn't mean
146 // we should stop the clean queue
147 // That is mostly so that rebuild works on a already clean project
148 setIgnoreReturnValue(m_clean);
152 ProjectExplorer::ToolChain *toolchain = bc->toolChain();
154 if (bc->subNodeBuild()){
155 if(!bc->subNodeBuild()->makefile().isEmpty()) {
156 Utils::QtcProcess::addArg(&args, QLatin1String("-f"));
157 Utils::QtcProcess::addArg(&args, bc->subNodeBuild()->makefile());
159 } else if (!bc->makefile().isEmpty()) {
160 Utils::QtcProcess::addArg(&args, QLatin1String("-f"));
161 Utils::QtcProcess::addArg(&args, bc->makefile());
164 Utils::QtcProcess::addArgs(&args, m_userArgs);
167 if (!bc->defaultMakeTarget().isEmpty())
168 Utils::QtcProcess::addArg(&args, bc->defaultMakeTarget());
170 // -w option enables "Enter"/"Leaving directory" messages, which we need for detecting the
171 // absolute file path
172 // FIXME doing this without the user having a way to override this is rather bad
173 // so we only do it for unix and if the user didn't override the make command
174 // but for now this is the least invasive change
177 if (toolchain->type() != ProjectExplorer::ToolChain_MSVC &&
178 toolchain->type() != ProjectExplorer::ToolChain_WINCE) {
179 if (m_makeCmd.isEmpty())
180 Utils::QtcProcess::addArg(&args, QLatin1String("-w"));
185 pp->setArguments(args);
187 ProjectExplorer::IOutputParser *parser = bc->qtVersion()->createOutputParser();
189 parser->appendOutputParser(new QtParser);
191 parser->appendOutputParser(toolchain->outputParser());
193 parser->setWorkingDirectory(workingDirectory);
195 setOutputParser(parser);
197 return AbstractProcessStep::init();
200 void MakeStep::run(QFutureInterface<bool> & fi)
202 if (qt4BuildConfiguration()->qt4Target()->qt4Project()->rootProjectNode()->projectType() == ScriptTemplate) {
203 fi.reportResult(true);
207 AbstractProcessStep::run(fi);
210 bool MakeStep::processSucceeded(int exitCode, QProcess::ExitStatus status)
212 // Symbian does retun 0, even on failed makes! So we check for fatal make errors here.
213 if (outputParser() && outputParser()->hasFatalErrors())
216 return AbstractProcessStep::processSucceeded(exitCode, status);
219 bool MakeStep::immutable() const
224 ProjectExplorer::BuildStepConfigWidget *MakeStep::createConfigWidget()
226 return new MakeStepConfigWidget(this);
229 QString MakeStep::userArguments()
234 void MakeStep::setUserArguments(const QString &arguments)
236 m_userArgs = arguments;
237 emit userArgumentsChanged();
240 MakeStepConfigWidget::MakeStepConfigWidget(MakeStep *makeStep)
241 : BuildStepConfigWidget(), m_ui(new Ui::MakeStep), m_makeStep(makeStep), m_ignoreChange(false)
245 m_ui->makePathChooser->setExpectedKind(Utils::PathChooser::ExistingCommand);
246 m_ui->makePathChooser->setBaseDirectory(Utils::PathChooser::homePath());
248 connect(m_ui->makePathChooser, SIGNAL(changed(QString)),
249 this, SLOT(makeEdited()));
250 connect(m_ui->makeArgumentsLineEdit, SIGNAL(textEdited(QString)),
251 this, SLOT(makeArgumentsLineEdited()));
253 connect(makeStep, SIGNAL(userArgumentsChanged()),
254 this, SLOT(userArgumentsChanged()));
255 connect(makeStep->buildConfiguration(), SIGNAL(buildDirectoryChanged()),
256 this, SLOT(updateDetails()));
258 connect(makeStep->qt4BuildConfiguration(), SIGNAL(qtVersionChanged()),
259 this, SLOT(qtVersionChanged()));
261 connect(ProjectExplorer::ProjectExplorerPlugin::instance(), SIGNAL(settingsChanged()),
262 this, SLOT(updateMakeOverrideLabel()));
263 connect(ProjectExplorer::ProjectExplorerPlugin::instance(), SIGNAL(settingsChanged()),
264 this, SLOT(updateDetails()));
267 MakeStepConfigWidget::~MakeStepConfigWidget()
272 void MakeStepConfigWidget::qtVersionChanged()
274 updateMakeOverrideLabel();
278 void MakeStepConfigWidget::updateMakeOverrideLabel()
280 Qt4BuildConfiguration *qt4bc = m_makeStep->qt4BuildConfiguration();
281 m_ui->makeLabel->setText(tr("Override %1:").arg(qt4bc->makeCommand()));
284 void MakeStepConfigWidget::updateDetails()
286 Qt4BuildConfiguration *bc = m_makeStep->qt4BuildConfiguration();
288 ProjectExplorer::ProcessParameters param;
289 param.setMacroExpander(bc->macroExpander());
290 param.setWorkingDirectory(bc->buildDirectory());
291 param.setEnvironment(bc->environment());
292 QString makeCmd = bc->makeCommand();
293 if (!m_makeStep->m_makeCmd.isEmpty())
294 makeCmd = m_makeStep->m_makeCmd;
295 param.setCommand(makeCmd);
296 if (param.commandMissing()) {
297 m_summaryText = tr("<b>Make:</b> %1 not found in the environment.").arg(makeCmd);
298 emit updateSummary();
301 // -w option enables "Enter"/"Leaving directory" messages, which we need for detecting the
302 // absolute file path
303 // FIXME doing this without the user having a way to override this is rather bad
304 // so we only do it for unix and if the user didn't override the make command
305 // but for now this is the least invasive change
306 QString args = m_makeStep->userArguments();
307 ProjectExplorer::ToolChainType t = ProjectExplorer::ToolChain_UNKNOWN;
308 ProjectExplorer::ToolChain *toolChain = bc->toolChain();
310 t = toolChain->type();
311 if (t != ProjectExplorer::ToolChain_MSVC && t != ProjectExplorer::ToolChain_WINCE) {
312 if (m_makeStep->m_makeCmd.isEmpty())
313 Utils::QtcProcess::addArg(&args, QLatin1String("-w"));
315 param.setArguments(args);
316 m_summaryText = param.summaryInWorkdir(displayName());
317 emit updateSummary();
320 QString MakeStepConfigWidget::summaryText() const
322 return m_summaryText;
325 QString MakeStepConfigWidget::displayName() const
327 return m_makeStep->displayName();
330 void MakeStepConfigWidget::userArgumentsChanged()
334 m_ui->makeArgumentsLineEdit->setText(m_makeStep->userArguments());
338 void MakeStepConfigWidget::init()
340 updateMakeOverrideLabel();
342 const QString &makeCmd = m_makeStep->m_makeCmd;
343 m_ui->makePathChooser->setPath(makeCmd);
345 m_ui->makeArgumentsLineEdit->setText(m_makeStep->userArguments());
349 void MakeStepConfigWidget::makeEdited()
351 m_makeStep->m_makeCmd = m_ui->makePathChooser->rawPath();
355 void MakeStepConfigWidget::makeArgumentsLineEdited()
357 m_ignoreChange = true;
358 m_makeStep->setUserArguments(m_ui->makeArgumentsLineEdit->text());
359 m_ignoreChange = false;
367 MakeStepFactory::MakeStepFactory(QObject *parent) :
368 ProjectExplorer::IBuildStepFactory(parent)
372 MakeStepFactory::~MakeStepFactory()
376 bool MakeStepFactory::canCreate(ProjectExplorer::BuildStepList *parent, const QString &id) const
378 if (parent->target()->project()->id() != QLatin1String(Constants::QT4PROJECT_ID))
380 return (id == QLatin1String(MAKESTEP_BS_ID));
383 ProjectExplorer::BuildStep *MakeStepFactory::create(ProjectExplorer::BuildStepList *parent, const QString &id)
385 if (!canCreate(parent, id))
387 return new MakeStep(parent);
390 bool MakeStepFactory::canClone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *source) const
392 return canCreate(parent, source->id());
395 ProjectExplorer::BuildStep *MakeStepFactory::clone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *source)
397 if (!canClone(parent, source))
399 return new MakeStep(parent, static_cast<MakeStep *>(source));
402 bool MakeStepFactory::canRestore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) const
404 QString id(ProjectExplorer::idFromMap(map));
405 return canCreate(parent, id);
408 ProjectExplorer::BuildStep *MakeStepFactory::restore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map)
410 if (!canRestore(parent, map))
412 MakeStep *bs(new MakeStep(parent));
413 if (bs->fromMap(map))
419 QStringList MakeStepFactory::availableCreationIds(ProjectExplorer::BuildStepList *parent) const
421 if (parent->target()->project()->id() == QLatin1String(Constants::QT4PROJECT_ID))
422 return QStringList() << QLatin1String(MAKESTEP_BS_ID);
423 return QStringList();
426 QString MakeStepFactory::displayNameForId(const QString &id) const
428 if (id == QLatin1String(MAKESTEP_BS_ID))