diff options
Diffstat (limited to 'src/plugins/qmakeprojectmanager/qmakemakestep.cpp')
-rw-r--r-- | src/plugins/qmakeprojectmanager/qmakemakestep.cpp | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/src/plugins/qmakeprojectmanager/qmakemakestep.cpp b/src/plugins/qmakeprojectmanager/qmakemakestep.cpp new file mode 100644 index 0000000000..43498a2c45 --- /dev/null +++ b/src/plugins/qmakeprojectmanager/qmakemakestep.cpp @@ -0,0 +1,214 @@ +/**************************************************************************** +** +** 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. +** +****************************************************************************/ + +#include "qmakemakestep.h" + +#include "qmakeparser.h" +#include "qmakeproject.h" +#include "qmakenodes.h" +#include "qmakebuildconfiguration.h" +#include "qmakeprojectmanagerconstants.h" + +#include <coreplugin/variablechooser.h> +#include <projectexplorer/target.h> +#include <projectexplorer/toolchain.h> +#include <projectexplorer/buildsteplist.h> +#include <projectexplorer/gnumakeparser.h> +#include <projectexplorer/projectexplorer.h> +#include <projectexplorer/kitinformation.h> +#include <projectexplorer/xcodebuildparser.h> +#include <utils/qtcprocess.h> + +#include <QDir> +#include <QFileInfo> + +using ExtensionSystem::PluginManager; +using namespace ProjectExplorer; +using namespace QmakeProjectManager; +using namespace QmakeProjectManager::Internal; + +const char MAKESTEP_BS_ID[] = "Qt4ProjectManager.MakeStep"; + +QmakeMakeStep::QmakeMakeStep(BuildStepList *bsl) + : MakeStep(bsl, MAKESTEP_BS_ID) +{ + setDefaultDisplayName(tr("Make", "Qt MakeStep display name.")); + if (bsl->id() == ProjectExplorer::Constants::BUILDSTEPS_CLEAN) { + setClean(true); + setUserArguments("clean"); + } +} + +QmakeBuildConfiguration *QmakeMakeStep::qmakeBuildConfiguration() const +{ + return static_cast<QmakeBuildConfiguration *>(buildConfiguration()); +} + +bool QmakeMakeStep::init(QList<const BuildStep *> &earlierSteps) +{ + QmakeBuildConfiguration *bc = qmakeBuildConfiguration(); + if (!bc) + bc = qobject_cast<QmakeBuildConfiguration *>(target()->activeBuildConfiguration()); + if (!bc) + emit addTask(Task::buildConfigurationMissingTask()); + + ToolChain *tc = ToolChainKitInformation::toolChain(target()->kit(), ProjectExplorer::Constants::CXX_LANGUAGE_ID); + if (!tc) + emit addTask(Task::compilerMissingTask()); + + if (!bc || !tc) { + emitFaultyConfigurationMessage(); + return false; + } + + ProcessParameters *pp = processParameters(); + pp->setMacroExpander(bc->macroExpander()); + + QString workingDirectory; + if (bc->subNodeBuild()) + workingDirectory = bc->subNodeBuild()->buildDir(); + else + workingDirectory = bc->buildDirectory().toString(); + pp->setWorkingDirectory(workingDirectory); + + pp->setCommand(effectiveMakeCommand()); + + // If we are cleaning, then make can fail with a error code, but that doesn't mean + // we should stop the clean queue + // That is mostly so that rebuild works on a already clean project + setIgnoreReturnValue(isClean()); + + QString args; + + QmakeProjectManager::QmakeProFileNode *subNode = bc->subNodeBuild(); + QmakeProjectManager::QmakeProFile *subProFile = subNode ? subNode->proFile() : nullptr; + if (subProFile) { + QString makefile = subProFile->makefile(); + if (makefile.isEmpty()) + makefile = "Makefile"; + // Use Makefile.Debug and Makefile.Release + // for file builds, since the rules for that are + // only in those files. + if (subProFile->isDebugAndRelease() && bc->fileNodeBuild()) { + if (bc->buildType() == QmakeBuildConfiguration::Debug) + makefile += ".Debug"; + else + makefile += ".Release"; + } + if (makefile != "Makefile") { + Utils::QtcProcess::addArg(&args, "-f"); + Utils::QtcProcess::addArg(&args, makefile); + } + m_makeFileToCheck = QDir(workingDirectory).filePath(makefile); + } else { + if (!bc->makefile().isEmpty()) { + Utils::QtcProcess::addArg(&args, "-f"); + Utils::QtcProcess::addArg(&args, bc->makefile()); + m_makeFileToCheck = QDir(workingDirectory).filePath(bc->makefile()); + } else { + m_makeFileToCheck = QDir(workingDirectory).filePath("Makefile"); + } + } + + Utils::QtcProcess::addArgs(&args, userArguments()); + if (bc->fileNodeBuild() && subProFile) { + QString objectsDir = subProFile->objectsDirectory(); + if (objectsDir.isEmpty()) { + objectsDir = subProFile->buildDir(bc).toString(); + if (subProFile->isDebugAndRelease()) { + if (bc->buildType() == QmakeBuildConfiguration::Debug) + objectsDir += "/debug"; + else + objectsDir += "/release"; + } + } + QString relObjectsDir = QDir(pp->workingDirectory()).relativeFilePath(objectsDir); + if (relObjectsDir == ".") + relObjectsDir.clear(); + if (!relObjectsDir.isEmpty()) + relObjectsDir += '/'; + QString objectFile = relObjectsDir + + bc->fileNodeBuild()->filePath().toFileInfo().baseName() + + subProFile->objectExtension(); + Utils::QtcProcess::addArg(&args, objectFile); + } + Utils::Environment env = bc->environment(); + Utils::Environment::setupEnglishOutput(&env); + // We also prepend "L" to the MAKEFLAGS, so that nmake / jom are less verbose + if (tc && makeCommand().isEmpty()) { + if (tc->targetAbi().os() == Abi::WindowsOS + && tc->targetAbi().osFlavor() != Abi::WindowsMSysFlavor) { + const QString makeFlags = "MAKEFLAGS"; + env.set(makeFlags, 'L' + env.value(makeFlags)); + } + } + + pp->setEnvironment(env); + pp->setArguments(args); + pp->resolveAll(); + + setOutputParser(new ProjectExplorer::GnuMakeParser()); + if (tc && tc->targetAbi().os() == Abi::DarwinOS) + appendOutputParser(new XcodebuildParser); + IOutputParser *parser = target()->kit()->createOutputParser(); + if (parser) + appendOutputParser(parser); + outputParser()->setWorkingDirectory(pp->effectiveWorkingDirectory()); + appendOutputParser(new QMakeParser); // make may cause qmake to be run, add last to make sure + // it has a low priority. + + m_scriptTarget = (static_cast<QmakeProject *>(bc->target()->project())->rootProjectNode()->projectType() == ProjectType::ScriptTemplate); + + return AbstractProcessStep::init(earlierSteps); +} + +void QmakeMakeStep::run(QFutureInterface<bool> & fi) +{ + if (m_scriptTarget) { + reportRunResult(fi, true); + return; + } + + if (!QFileInfo::exists(m_makeFileToCheck)) { + if (!ignoreReturnValue()) + emit addOutput(tr("Cannot find Makefile. Check your build settings."), BuildStep::OutputFormat::NormalMessage); + const bool success = ignoreReturnValue(); + reportRunResult(fi, success); + return; + } + + AbstractProcessStep::run(fi); +} + +/// +// QmakeMakeStepFactory +/// + +QmakeMakeStepFactory::QmakeMakeStepFactory() +{ + registerStep<QmakeMakeStep>(MAKESTEP_BS_ID); + setSupportedProjectType(Constants::QMAKEPROJECT_ID); + setDisplayName(tr("Make")); +} |