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 **************************************************************************/
34 #include "qt4buildconfiguration.h"
36 #include "qt4project.h"
37 #include "qt4target.h"
38 #include "qt4projectmanagerconstants.h"
40 #include "qmakestep.h"
43 #include <utils/qtcassert.h>
44 #include <utils/qtcprocess.h>
46 #include <projectexplorer/buildsteplist.h>
47 #include <projectexplorer/projectexplorerconstants.h>
49 #include <QtCore/QDebug>
51 #include <QtGui/QInputDialog>
53 using namespace Qt4ProjectManager;
54 using namespace Qt4ProjectManager::Internal;
55 using namespace ProjectExplorer;
58 const char * const QT4_BC_ID_PREFIX("Qt4ProjectManager.Qt4BuildConfiguration.");
59 const char * const QT4_BC_ID("Qt4ProjectManager.Qt4BuildConfiguration");
61 const char * const USE_SHADOW_BUILD_KEY("Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild");
62 const char * const BUILD_DIRECTORY_KEY("Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory");
63 const char * const TOOLCHAIN_KEY("Qt4ProjectManager.Qt4BuildConfiguration.ToolChain");
64 const char * const BUILD_CONFIGURATION_KEY("Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration");
65 const char * const QT_VERSION_ID_KEY("Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId");
70 Qt4BuildConfiguration::Qt4BuildConfiguration(Qt4BaseTarget *target) :
71 BuildConfiguration(target, QLatin1String(QT4_BC_ID)),
75 m_toolChainType(-1), // toolChainType() makes sure to return the default toolchainType
76 m_qmakeBuildConfiguration(0),
82 Qt4BuildConfiguration::Qt4BuildConfiguration(Qt4BaseTarget *target, const QString &id) :
83 BuildConfiguration(target, id),
87 m_toolChainType(-1), // toolChainType() makes sure to return the default toolchainType
88 m_qmakeBuildConfiguration(0),
94 Qt4BuildConfiguration::Qt4BuildConfiguration(Qt4BaseTarget *target, Qt4BuildConfiguration *source) :
95 BuildConfiguration(target, source),
96 m_shadowBuild(source->m_shadowBuild),
98 m_buildDirectory(source->m_buildDirectory),
99 m_qtVersionId(source->m_qtVersionId),
100 m_toolChainType(source->m_toolChainType),
101 m_qmakeBuildConfiguration(source->m_qmakeBuildConfiguration),
102 m_subNodeBuild(0) // temporary value, so not copied
108 Qt4BuildConfiguration::~Qt4BuildConfiguration()
112 QVariantMap Qt4BuildConfiguration::toMap() const
114 QVariantMap map(BuildConfiguration::toMap());
115 map.insert(QLatin1String(USE_SHADOW_BUILD_KEY), m_shadowBuild);
116 map.insert(QLatin1String(BUILD_DIRECTORY_KEY), m_buildDirectory);
117 map.insert(QLatin1String(QT_VERSION_ID_KEY), m_qtVersionId);
118 map.insert(QLatin1String(TOOLCHAIN_KEY), m_toolChainType);
119 map.insert(QLatin1String(BUILD_CONFIGURATION_KEY), int(m_qmakeBuildConfiguration));
124 bool Qt4BuildConfiguration::fromMap(const QVariantMap &map)
126 if (!BuildConfiguration::fromMap(map))
129 m_shadowBuild = map.value(QLatin1String(USE_SHADOW_BUILD_KEY), true).toBool();
130 m_buildDirectory = map.value(QLatin1String(BUILD_DIRECTORY_KEY), qt4Target()->defaultBuildDirectory()).toString();
131 m_qtVersionId = map.value(QLatin1String(QT_VERSION_ID_KEY)).toInt();
132 m_toolChainType = map.value(QLatin1String(TOOLCHAIN_KEY)).toInt();
133 m_qmakeBuildConfiguration = QtVersion::QmakeBuildConfigs(map.value(QLatin1String(BUILD_CONFIGURATION_KEY)).toInt());
135 // Pick a Qt version if the default version is used:
136 // We assume that the default Qt version was used in earlier versions of Qt creator.
137 // Pick a Qt version that is supporting a desktop.
138 if (m_qtVersionId == 0) {
139 QList<QtVersion *> versions = QtVersionManager::instance()->versions();
140 foreach (QtVersion *v, versions) {
141 if (v->isValid() && v->supportsTargetId(QLatin1String(Constants::DESKTOP_TARGET_ID))) {
142 m_qtVersionId = v->uniqueId();
146 if (m_qtVersionId == 0)
147 m_qtVersionId = versions.at(0)->uniqueId();
150 QtVersion *version = qtVersion();
151 if (!map.contains(QLatin1String("Qt4ProjectManager.Qt4BuildConfiguration.NeedsV0Update"))) { // we are not upgrading from pre-targets!
152 if (version->isValid() && !version->supportedTargetIds().contains(target()->id())) {
153 qWarning() << "Buildconfiguration" << displayName() << ": Qt" << version->displayName() << "not supported by target" << target()->id();
157 if (!version->isValid() || !version->supportedTargetIds().contains(target()->id())) {
158 qWarning() << "Buildconfiguration" << displayName() << ": Qt" << version->displayName() << "not supported by target" << target()->id();
163 if (version->isValid())
164 m_shadowBuild = (m_shadowBuild && version->supportsShadowBuilds());
166 QList<ProjectExplorer::ToolChainType> possibleTcs(qt4Target()->filterToolChainTypes(qtVersion()->possibleToolChainTypes()));
167 if (!possibleTcs.contains(toolChainType()))
168 setToolChainType(qt4Target()->preferredToolChainType(possibleTcs));
170 if (toolChainType() == ProjectExplorer::ToolChain_INVALID) {
171 qWarning() << "No toolchain available for" << qtVersion()->displayName() << "used in" << target()->id() << "!";
178 void Qt4BuildConfiguration::ctor()
180 m_buildDirectory = qt4Target()->defaultBuildDirectory();
181 if (m_buildDirectory == target()->project()->projectDirectory())
182 m_shadowBuild = false;
184 m_lastEmmitedBuildDirectory = buildDirectory();
186 connect(this, SIGNAL(environmentChanged()),
187 this, SLOT(emitBuildDirectoryChanged()));
189 QtVersionManager *vm = QtVersionManager::instance();
190 connect(vm, SIGNAL(qtVersionsChanged(QList<int>)),
191 this, SLOT(qtVersionsChanged(QList<int>)));
194 void Qt4BuildConfiguration::emitBuildDirectoryChanged()
196 if (buildDirectory() != m_lastEmmitedBuildDirectory) {
197 m_lastEmmitedBuildDirectory = buildDirectory();
198 emit buildDirectoryChanged();
202 void Qt4BuildConfiguration::pickValidQtVersion()
204 QList<QtVersion *> versions = QtVersionManager::instance()->versionsForTargetId(qt4Target()->id());
205 if (!versions.isEmpty())
206 setQtVersion(versions.at(0));
208 setQtVersion(QtVersionManager::instance()->emptyVersion());
211 Qt4BaseTarget *Qt4BuildConfiguration::qt4Target() const
213 return static_cast<Qt4BaseTarget *>(target());
216 Utils::Environment Qt4BuildConfiguration::baseEnvironment() const
218 Utils::Environment env = BuildConfiguration::baseEnvironment();
219 qtVersion()->addToEnvironment(env);
221 ToolChain *tc = toolChain();
223 tc->addToEnvironment(env);
227 /// returns the unexpanded build directory
228 QString Qt4BuildConfiguration::rawBuildDirectory() const
230 QString workingDirectory;
232 if (!m_buildDirectory.isEmpty())
233 workingDirectory = m_buildDirectory;
235 workingDirectory = qt4Target()->defaultBuildDirectory();
237 if (workingDirectory.isEmpty())
238 workingDirectory = target()->project()->projectDirectory();
239 return workingDirectory;
242 /// returns the build directory
243 QString Qt4BuildConfiguration::buildDirectory() const
245 return QDir::cleanPath(environment().expandVariables(rawBuildDirectory()));
248 /// If only a sub tree should be build this function returns which sub node
250 /// \see Qt4BuildConfiguration::setSubNodeBuild
251 Qt4ProjectManager::Internal::Qt4ProFileNode *Qt4BuildConfiguration::subNodeBuild() const
253 return m_subNodeBuild;
256 /// A sub node build on builds a sub node of the project
257 /// That is triggered by a right click in the project explorer tree
258 /// The sub node to be build is set via this function immediately before
259 /// calling BuildManager::buildProject( BuildConfiguration * )
260 /// and reset immediately afterwards
261 /// That is m_subNodesBuild is set only temporarly
262 void Qt4BuildConfiguration::setSubNodeBuild(Qt4ProjectManager::Internal::Qt4ProFileNode *node)
264 m_subNodeBuild = node;
267 /// returns whether this is a shadow build configuration or not
268 /// note, even if shadowBuild() returns true, it might be using the
269 /// source directory as the shadow build directory, thus it
270 /// still is a in-source build
271 bool Qt4BuildConfiguration::shadowBuild() const
273 return m_shadowBuild;
276 /// returns the shadow build directory if set
277 /// \note buildDirectory() is probably the function you want to call
278 QString Qt4BuildConfiguration::shadowBuildDirectory() const
280 if (m_buildDirectory.isEmpty())
281 return qt4Target()->defaultBuildDirectory();
282 return m_buildDirectory;
285 void Qt4BuildConfiguration::setShadowBuildAndDirectory(bool shadowBuild, const QString &buildDirectory)
287 QtVersion *version = qtVersion();
288 QString directoryToSet = buildDirectory;
289 bool toSet = (shadowBuild && version->isValid() && version->supportsShadowBuilds());
290 if (m_shadowBuild == toSet && m_buildDirectory == directoryToSet)
293 m_shadowBuild = toSet;
294 m_buildDirectory = directoryToSet;
296 emit environmentChanged();
297 emitBuildDirectoryChanged();
298 emit proFileEvaluateNeeded(this);
301 ProjectExplorer::ToolChain *Qt4BuildConfiguration::toolChain() const
303 const ProjectExplorer::ToolChainType tct = toolChainType();
304 return qtVersion()->toolChain(tct);
307 QString Qt4BuildConfiguration::makeCommand() const
309 ToolChain *tc = toolChain();
310 return tc ? tc->makeCommand() : "make";
313 static inline QString symbianMakeTarget(QtVersion::QmakeBuildConfigs buildConfig,
316 QString rc = (buildConfig & QtVersion::DebugBuild) ?
317 QLatin1String("debug-") : QLatin1String("release-");
322 QString Qt4BuildConfiguration::defaultMakeTarget() const
324 ToolChain *tc = toolChain();
327 const QtVersion::QmakeBuildConfigs buildConfig = qmakeBuildConfiguration();
329 switch (tc->type()) {
330 case ProjectExplorer::ToolChain_GCCE:
331 return symbianMakeTarget(buildConfig, QLatin1String("gcce"));
332 case ProjectExplorer::ToolChain_RVCT2_ARMV5:
333 case ProjectExplorer::ToolChain_RVCT4_ARMV5:
334 return symbianMakeTarget(buildConfig, QLatin1String("armv5"));
335 case ProjectExplorer::ToolChain_RVCT2_ARMV6:
336 case ProjectExplorer::ToolChain_RVCT4_ARMV6:
337 return symbianMakeTarget(buildConfig, QLatin1String("armv6"));
338 case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC:
339 case ProjectExplorer::ToolChain_GCCE_GNUPOC:
346 QString Qt4BuildConfiguration::makefile() const
348 return qt4Target()->qt4Project()->rootProjectNode()->makefile();
351 QtVersion *Qt4BuildConfiguration::qtVersion() const
353 QtVersionManager *vm = QtVersionManager::instance();
354 return vm->version(m_qtVersionId);
357 void Qt4BuildConfiguration::setQtVersion(QtVersion *version)
361 if (m_qtVersionId == version->uniqueId())
364 m_qtVersionId = version->uniqueId();
366 if (!version->possibleToolChainTypes().contains(ProjectExplorer::ToolChainType(m_toolChainType))) {
367 QList<ProjectExplorer::ToolChainType> candidates =
368 qt4Target()->filterToolChainTypes(qtVersion()->possibleToolChainTypes());
369 if (candidates.isEmpty())
370 m_toolChainType = ProjectExplorer::ToolChain_INVALID;
372 m_toolChainType = candidates.first();
375 m_shadowBuild = m_shadowBuild && qtVersion()->supportsShadowBuilds();
377 emit proFileEvaluateNeeded(this);
378 emit qtVersionChanged();
379 emit environmentChanged();
380 emitBuildDirectoryChanged();
383 void Qt4BuildConfiguration::setToolChainType(ProjectExplorer::ToolChainType type)
385 if (!qt4Target()->filterToolChainTypes(qtVersion()->possibleToolChainTypes()).contains(type)
386 || m_toolChainType == type)
389 m_toolChainType = type;
391 emit proFileEvaluateNeeded(this);
392 emit toolChainTypeChanged();
393 emit environmentChanged();
394 emitBuildDirectoryChanged();
397 ProjectExplorer::ToolChainType Qt4BuildConfiguration::toolChainType() const
399 return ProjectExplorer::ToolChainType(m_toolChainType);
402 QtVersion::QmakeBuildConfigs Qt4BuildConfiguration::qmakeBuildConfiguration() const
404 return m_qmakeBuildConfiguration;
407 void Qt4BuildConfiguration::setQMakeBuildConfiguration(QtVersion::QmakeBuildConfigs config)
409 if (m_qmakeBuildConfiguration == config)
411 m_qmakeBuildConfiguration = config;
413 emit proFileEvaluateNeeded(this);
414 emit qmakeBuildConfigurationChanged();
417 void Qt4BuildConfiguration::emitProFileEvaluteNeeded()
419 emit proFileEvaluateNeeded(this);
422 void Qt4BuildConfiguration::emitQMakeBuildConfigurationChanged()
424 emit qmakeBuildConfigurationChanged();
427 void Qt4BuildConfiguration::emitBuildDirectoryInitialized()
429 emit buildDirectoryInitialized();
432 void Qt4BuildConfiguration::emitS60CreatesSmartInstallerChanged()
434 emit s60CreatesSmartInstallerChanged();
438 QStringList Qt4BuildConfiguration::configCommandLineArguments() const
441 QtVersion::QmakeBuildConfigs defaultBuildConfiguration = qtVersion()->defaultBuildConfig();
442 QtVersion::QmakeBuildConfigs userBuildConfiguration = m_qmakeBuildConfiguration;
443 if ((defaultBuildConfiguration & QtVersion::BuildAll) && !(userBuildConfiguration & QtVersion::BuildAll))
444 result << "CONFIG-=debug_and_release";
446 if (!(defaultBuildConfiguration & QtVersion::BuildAll) && (userBuildConfiguration & QtVersion::BuildAll))
447 result << "CONFIG+=debug_and_release";
448 if ((defaultBuildConfiguration & QtVersion::DebugBuild)
449 && !(userBuildConfiguration & QtVersion::DebugBuild)
450 && !(userBuildConfiguration & QtVersion::BuildAll))
451 result << "CONFIG+=release";
452 if (!(defaultBuildConfiguration & QtVersion::DebugBuild)
453 && (userBuildConfiguration & QtVersion::DebugBuild)
454 && !(userBuildConfiguration & QtVersion::BuildAll))
455 result << "CONFIG+=debug";
459 QMakeStep *Qt4BuildConfiguration::qmakeStep() const
462 BuildStepList *bsl = stepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD);
464 for (int i = 0; i < bsl->count(); ++i)
465 if ((qs = qobject_cast<QMakeStep *>(bsl->at(i))) != 0)
470 MakeStep *Qt4BuildConfiguration::makeStep() const
473 BuildStepList *bsl = stepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD);
475 for (int i = 0; i < bsl->count(); ++i)
476 if ((ms = qobject_cast<MakeStep *>(bsl->at(i))) != 0)
481 void Qt4BuildConfiguration::qtVersionsChanged(const QList<int> &changedVersions)
483 if (!changedVersions.contains(m_qtVersionId) ||
484 qtVersion()->isValid())
487 pickValidQtVersion();
490 // returns true if both are equal
491 bool Qt4BuildConfiguration::compareToImportFrom(const QString &makefile)
493 QMakeStep *qs = qmakeStep();
494 if (QFileInfo(makefile).exists() && qs) {
495 QString qmakePath = QtVersionManager::findQMakeBinaryFromMakefile(makefile);
496 QtVersion *version = qtVersion();
497 if (version->qmakeCommand() == qmakePath) {
499 QPair<QtVersion::QmakeBuildConfigs, QString> result =
500 QtVersionManager::scanMakeFile(makefile, version->defaultBuildConfig());
501 if (qmakeBuildConfiguration() == result.first) {
502 // The qmake Build Configuration are the same,
503 // now compare arguments lists
504 // we have to compare without the spec/platform cmd argument
505 // and compare that on its own
506 QString workingDirectory = QFileInfo(makefile).absolutePath();
507 QString userArgs = qs->userArguments();
508 QStringList actualArgs;
509 QString actualSpec = extractSpecFromArguments(&userArgs, workingDirectory, version, &actualArgs);
510 if (actualSpec.isEmpty()) {
511 // Easy one: the user has chosen not to override the settings
512 actualSpec = version->mkspec();
514 actualArgs += qs->moreArguments();
516 QString qmakeArgs = result.second;
517 QStringList parsedArgs;
518 QString parsedSpec = extractSpecFromArguments(&qmakeArgs, workingDirectory, version, &parsedArgs);
521 qDebug()<<"Actual args:"<<actualArgs;
522 qDebug()<<"Parsed args:"<<parsedArgs;
523 qDebug()<<"Actual spec:"<<actualSpec;
524 qDebug()<<"Parsed spec:"<<parsedSpec;
527 // Comparing the sorted list is obviously wrong
528 // Though haven written a more complete version
529 // that managed had around 200 lines and yet faild
530 // to be actually foolproof at all, I think it's
531 // not feasible without actually taking the qmake
532 // command line parsing code
534 // Things, sorting gets wrong:
535 // parameters to positional parameters matter
536 // e.g. -o -spec is different from -spec -o
537 // -o 1 -spec 2 is diffrent from -spec 1 -o 2
538 // variable assignment order matters
539 // variable assignment vs -after
540 // -norecursive vs. recursive
543 if (actualArgs == parsedArgs) {
544 // Specs match exactly
545 if (actualSpec == parsedSpec)
547 // Actual spec is the default one
548 // qDebug()<<"AS vs VS"<<actualSpec<<version->mkspec();
549 if ((actualSpec == version->mkspec() || actualSpec == "default")
550 && (parsedSpec == version->mkspec() || parsedSpec == "default" || parsedSpec.isEmpty()))
554 qDebug()<<"different qmake buildconfigurations buildconfiguration:"<<qmakeBuildConfiguration()<<" Makefile:"<<result.first;
557 qDebug()<<"diffrent qt versions, buildconfiguration:"<<version->qmakeCommand()<<" Makefile:"<<qmakePath;
563 void Qt4BuildConfiguration::removeQMLInspectorFromArguments(QString *args)
565 for (Utils::QtcProcess::ArgIterator ait(args); ait.next(); )
566 if (ait.value().contains(QLatin1String(Constants::QMAKEVAR_QMLJSDEBUGGER_PATH)))
570 QString Qt4BuildConfiguration::extractSpecFromArguments(QString *args,
571 const QString &directory, const QtVersion *version,
572 QStringList *outArgs)
576 bool ignoreNext = false;
577 bool nextIsSpec = false;
578 for (Utils::QtcProcess::ArgIterator ait(args); ait.next(); ) {
582 } else if (nextIsSpec) {
584 parsedSpec = QDir::cleanPath(ait.value());
586 } else if (ait.value() == QLatin1String("-spec") || ait.value() == QLatin1String("-platform")) {
589 } else if (ait.value() == QLatin1String("-cache")) {
590 // We ignore -cache, because qmake contained a bug that it didn't
591 // mention the -cache in the Makefile.
592 // That means changing the -cache option in the additional arguments
593 // does not automatically rerun qmake. Alas, we could try more
594 // intelligent matching for -cache, but i guess people rarely
598 } else if (outArgs && ait.isSimple()) {
599 outArgs->append(ait.value());
603 if (parsedSpec.isEmpty())
606 QString baseMkspecDir = version->versionInfo().value("QMAKE_MKSPECS");
607 if (baseMkspecDir.isEmpty())
608 baseMkspecDir = version->versionInfo().value("QT_INSTALL_DATA") + "/mkspecs";
611 baseMkspecDir = baseMkspecDir.toLower();
612 parsedSpec = parsedSpec.toLower();
614 // if the path is relative it can be
615 // relative to the working directory (as found in the Makefiles)
616 // or relatively to the mkspec directory
617 // if it is the former we need to get the canonical form
618 // for the other one we don't need to do anything
619 if (QFileInfo(parsedSpec).isRelative()) {
620 if(QFileInfo(directory + QLatin1Char('/') + parsedSpec).exists()) {
621 parsedSpec = QDir::cleanPath(directory + QLatin1Char('/') + parsedSpec);
623 parsedSpec = parsedSpec.toLower();
626 parsedSpec = baseMkspecDir + QLatin1Char('/') + parsedSpec;
630 QFileInfo f2(parsedSpec);
631 while (f2.isSymLink()) {
632 parsedSpec = f2.symLinkTarget();
633 f2.setFile(parsedSpec);
636 if (parsedSpec.startsWith(baseMkspecDir)) {
637 parsedSpec = parsedSpec.mid(baseMkspecDir.length() + 1);
639 QString sourceMkSpecPath = version->sourcePath() + "/mkspecs";
640 if (parsedSpec.startsWith(sourceMkSpecPath)) {
641 parsedSpec = parsedSpec.mid(sourceMkSpecPath.length() + 1);
645 parsedSpec = parsedSpec.toLower();
650 ProjectExplorer::IOutputParser *Qt4BuildConfiguration::createOutputParser() const
652 ToolChain *tc = toolChain();
654 return toolChain()->outputParser();
658 bool Qt4BuildConfiguration::isEnabled() const
663 void Qt4BuildConfiguration::setEnabled(bool enabled)
665 if (m_isEnabled == enabled)
667 m_isEnabled = enabled;
668 emit enabledChanged();
672 \class Qt4BuildConfigurationFactory
675 Qt4BuildConfigurationFactory::Qt4BuildConfigurationFactory(QObject *parent) :
676 ProjectExplorer::IBuildConfigurationFactory(parent)
680 QtVersionManager *vm = QtVersionManager::instance();
681 connect(vm, SIGNAL(qtVersionsChanged(QList<int>)),
682 this, SLOT(update()));
685 Qt4BuildConfigurationFactory::~Qt4BuildConfigurationFactory()
689 void Qt4BuildConfigurationFactory::update()
692 QtVersionManager *vm = QtVersionManager::instance();
693 foreach (const QtVersion *version, vm->versions()) {
694 if (version->isValid()) {
695 QString key = QString::fromLatin1(QT4_BC_ID_PREFIX)
696 + QString::fromLatin1("Qt%1").arg(version->uniqueId());
697 VersionInfo info(tr("Using Qt Version \"%1\"").arg(version->displayName()), version->uniqueId());
698 m_versions.insert(key, info);
701 emit availableCreationIdsChanged();
704 QStringList Qt4BuildConfigurationFactory::availableCreationIds(ProjectExplorer::Target *parent) const
706 if (!qobject_cast<Qt4BaseTarget *>(parent))
707 return QStringList();
710 QtVersionManager *vm = QtVersionManager::instance();
711 for (QMap<QString, VersionInfo>::const_iterator i = m_versions.constBegin();
712 i != m_versions.constEnd(); ++i) {
713 if (vm->version(i.value().versionId)->supportsTargetId(parent->id()))
714 results.append(i.key());
719 QString Qt4BuildConfigurationFactory::displayNameForId(const QString &id) const
721 if (!m_versions.contains(id))
723 return m_versions.value(id).displayName;
726 bool Qt4BuildConfigurationFactory::canCreate(ProjectExplorer::Target *parent, const QString &id) const
728 if (!qobject_cast<Qt4BaseTarget *>(parent))
730 if (!m_versions.contains(id))
732 const VersionInfo &info = m_versions.value(id);
733 QtVersion *version = QtVersionManager::instance()->version(info.versionId);
735 !version->supportsTargetId(parent->id()))
740 BuildConfiguration *Qt4BuildConfigurationFactory::create(ProjectExplorer::Target *parent, const QString &id)
742 if (!canCreate(parent, id))
745 const VersionInfo &info = m_versions.value(id);
746 QtVersion *version = QtVersionManager::instance()->version(info.versionId);
749 Qt4BaseTarget *qt4Target = static_cast<Qt4BaseTarget *>(parent);
752 QString buildConfigurationName = QInputDialog::getText(0,
753 tr("New Configuration"),
754 tr("New configuration name:"),
756 version->displayName(),
758 buildConfigurationName = buildConfigurationName.trimmed();
759 if (!ok || buildConfigurationName.isEmpty())
762 //: Debug build configuration. We recommend not translating it.
763 qt4Target->addQt4BuildConfiguration(tr("%1 Debug").arg(buildConfigurationName),
765 (version->defaultBuildConfig() | QtVersion::DebugBuild),
766 QString(), QString());
767 BuildConfiguration *bc =
768 //: Release build configuration. We recommend not translating it.
769 qt4Target->addQt4BuildConfiguration(tr("%1 Release").arg(buildConfigurationName),
771 (version->defaultBuildConfig() & ~QtVersion::DebugBuild),
772 QString(), QString());
776 bool Qt4BuildConfigurationFactory::canClone(ProjectExplorer::Target *parent, ProjectExplorer::BuildConfiguration *source) const
778 if (!qobject_cast<Qt4BaseTarget *>(parent))
780 Qt4BuildConfiguration *qt4bc(qobject_cast<Qt4BuildConfiguration *>(source));
784 QtVersion *version = qt4bc->qtVersion();
786 !version->supportsTargetId(parent->id()))
791 BuildConfiguration *Qt4BuildConfigurationFactory::clone(Target *parent, BuildConfiguration *source)
793 if (!canClone(parent, source))
795 Qt4BaseTarget *target = static_cast<Qt4BaseTarget *>(parent);
796 Qt4BuildConfiguration *oldbc(static_cast<Qt4BuildConfiguration *>(source));
797 return new Qt4BuildConfiguration(target, oldbc);
800 bool Qt4BuildConfigurationFactory::canRestore(Target *parent, const QVariantMap &map) const
802 QString id = ProjectExplorer::idFromMap(map);
803 if (!qobject_cast<Qt4BaseTarget *>(parent))
805 return id.startsWith(QLatin1String(QT4_BC_ID_PREFIX)) ||
806 id == QLatin1String(QT4_BC_ID);
809 BuildConfiguration *Qt4BuildConfigurationFactory::restore(Target *parent, const QVariantMap &map)
811 if (!canRestore(parent, map))
813 Qt4BaseTarget *target = static_cast<Qt4BaseTarget *>(parent);
814 Qt4BuildConfiguration *bc = new Qt4BuildConfiguration(target);
815 if (bc->fromMap(map))
821 void Qt4BuildConfiguration::importFromBuildDirectory()
823 QString directory = buildDirectory();
824 if (!directory.isEmpty()) {
825 QString mkfile = directory;
826 if (makefile().isEmpty())
827 mkfile.append("/Makefile");
829 mkfile.append(makefile());
831 QString qmakePath = QtVersionManager::findQMakeBinaryFromMakefile(mkfile);
832 if (!qmakePath.isEmpty()) {
833 QtVersionManager *vm = QtVersionManager::instance();
834 QtVersion *version = vm->qtVersionForQMakeBinary(qmakePath);
836 version = new QtVersion(qmakePath);
837 vm->addVersion(version);
840 QPair<QtVersion::QmakeBuildConfigs, QString> result =
841 QtVersionManager::scanMakeFile(directory, version->defaultBuildConfig());
842 QtVersion::QmakeBuildConfigs qmakeBuildConfig = result.first;
844 QString aa = result.second;
845 QString parsedSpec = Qt4BuildConfiguration::extractSpecFromArguments(&aa, directory, version);
846 QString versionSpec = version->mkspec();
847 QString additionalArguments;
848 if (parsedSpec.isEmpty() || parsedSpec == versionSpec || parsedSpec == "default") {
849 // using the default spec, don't modify additional arguments
851 additionalArguments = "-spec " + Utils::QtcProcess::quoteArg(parsedSpec);
853 Utils::QtcProcess::addArgs(&additionalArguments, aa);
855 Qt4BuildConfiguration::removeQMLInspectorFromArguments(&additionalArguments);
857 // So we got all the information now apply it...
858 setQtVersion(version);
860 qmakeStep()->setUserArguments(additionalArguments);
862 setQMakeBuildConfiguration(qmakeBuildConfig);
863 // Adjust command line arguments, this is ugly as hell
864 // If we are switching to BuildAll we want "release" in there and no "debug"
865 // or "debug" in there and no "release"
866 // If we are switching to not BuildAl we want neither "release" nor "debug" in there
867 bool debug = qmakeBuildConfig & QtVersion::DebugBuild;
868 bool haveTag = !(qmakeBuildConfig & QtVersion::BuildAll);
869 QString makeCmdArguments = makeStep()->userArguments();
870 Utils::QtcProcess::ArgIterator ait(&makeCmdArguments);
872 if (ait.value() == QLatin1String("debug")) {
873 if (!haveTag && debug)
877 } else if (ait.value() == QLatin1String("release")) {
878 if (!haveTag && !debug)
885 ait.appendArg(QLatin1String(debug ? "debug" : "release"));
886 makeStep()->setUserArguments(makeCmdArguments);