kde-extraapps/kdevelop/projectmanagers/custom-buildsystem/custombuildjob.cpp

185 lines
7.2 KiB
C++
Raw Normal View History

/************************************************************************
* KDevelop4 Custom Buildsystem Support *
* *
* Copyright 2010 Andreas Pakulat <apaku@gmx.de> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 or version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, see <http://www.gnu.org/licenses/>. *
************************************************************************/
#include "custombuildjob.h"
#include <KLocale>
#include <KProcess>
#include <KConfigGroup>
#include <KGlobal>
#include <KShell>
#include <outputview/outputmodel.h>
#include <outputview/outputdelegate.h>
#include <util/processlinemaker.h>
#include <util/environmentgrouplist.h>
#include <util/commandexecutor.h>
#include <project/projectmodel.h>
#include "custombuildsystemplugin.h"
#include "configconstants.h"
CustomBuildJob::CustomBuildJob( CustomBuildSystem* plugin, KDevelop::ProjectBaseItem* item, CustomBuildSystemTool::ActionType t )
: OutputJob( plugin )
, type( t )
, exec(nullptr)
, killed( false )
, enabled( false )
{
setCapabilities( Killable );
QString subgrpname;
QString title;
switch( type ) {
case CustomBuildSystemTool::Build:
title = i18n( "Building:" );
subgrpname = QString( "%1Build" ).arg( ConfigConstants::toolGroupPrefix );
break;
case CustomBuildSystemTool::Clean:
title = i18n( "Cleaning:" );
subgrpname = QString( "%1Clean" ).arg( ConfigConstants::toolGroupPrefix );
break;
case CustomBuildSystemTool::Install:
title = i18n( "Installing:" );
subgrpname = QString( "%1Install" ).arg( ConfigConstants::toolGroupPrefix );
break;
case CustomBuildSystemTool::Configure:
title = i18n( "Configuring:" );
subgrpname = QString( "%1Configure" ).arg( ConfigConstants::toolGroupPrefix );
break;
case CustomBuildSystemTool::Prune:
title = i18n( "Pruning:" );
subgrpname = QString( "%1Prune" ).arg( ConfigConstants::toolGroupPrefix );
break;
case CustomBuildSystemTool::Undefined:
return;
}
setTitle( QString("%1 %2").arg( cmd ).arg( item->text() ) );
setObjectName( QString("%1 %2").arg( cmd ).arg( item->text() ) );
builddir = plugin->buildDirectory( item ).toLocalFile();
KConfigGroup g = plugin->configuration( item->project() );
if(g.isValid()) {
KConfigGroup grp = g.group( subgrpname );
enabled = grp.readEntry( ConfigConstants::toolEnabled, false );
cmd = grp.readEntry( ConfigConstants::toolExecutable, KUrl() ).toLocalFile();
environment = grp.readEntry( ConfigConstants::toolEnvironment, "" );
arguments = grp.readEntry( ConfigConstants::toolArguments, "" );
}
setDelegate( new KDevelop::OutputDelegate );
}
void CustomBuildJob::start()
{
if( type == CustomBuildSystemTool::Undefined ) {
setError( UndefinedBuildType );
setErrorText( i18n( "Undefined Build type" ) );
emitResult();
} else if( cmd.isEmpty() ) {
setError( NoCommand );
setErrorText( i18n( "No command given" ) );
emitResult();
} else if( !enabled ) {
setError( ToolDisabled );
setErrorText( i18n( "This command is disabled" ) );
emitResult();
} else {
// prepend the command name to the argument string
// so that splitArgs works correctly
const QString allargv = KShell::quoteArg(cmd) + " " + arguments;
KShell::Errors err;
QStringList strargs = KShell::splitArgs( allargv, KShell::AbortOnMeta, &err );
if( err != KShell::NoError ) {
setError( WrongArgs );
setErrorText( i18n( "The given arguments would need a real shell, this is not supported currently." ) );
emitResult();
}
// and remove the command name back out of the split argument list
Q_ASSERT(!strargs.isEmpty());
strargs.removeFirst();
setStandardToolView( KDevelop::IOutputView::BuildView );
setBehaviours( KDevelop::IOutputView::AllowUserClose | KDevelop::IOutputView::AutoScroll );
KDevelop::OutputModel* model = new KDevelop::OutputModel( builddir );
model->setFilteringStrategy( KDevelop::OutputModel::CompilerFilter );
setModel( model );
startOutput();
exec = new KDevelop::CommandExecutor( cmd, this );
exec->setArguments( strargs );
exec->setEnvironment( KDevelop::EnvironmentGroupList( KGlobal::config() ).createEnvironment( environment, KProcess::systemEnvironment() ) );
exec->setWorkingDirectory( builddir );
connect( exec, SIGNAL(completed(int)), SLOT(procFinished(int)) );
connect( exec, SIGNAL(failed( QProcess::ProcessError )), SLOT(procError( QProcess::ProcessError )) );
connect( exec, SIGNAL(receivedStandardError(QStringList)), model, SLOT(appendLines(QStringList)) );
connect( exec, SIGNAL(receivedStandardOutput(QStringList)), model, SLOT(appendLines(QStringList)) );
model->appendLine( QString("%1>%2 %3").arg( builddir ).arg( cmd ).arg( arguments ) );
exec->start();
}
}
bool CustomBuildJob::doKill()
{
killed = true;
exec->kill();
return true;
}
void CustomBuildJob::procError( QProcess::ProcessError err )
{
if( !killed ) {
if( err == QProcess::FailedToStart ) {
setError( FailedToStart );
setErrorText( i18n( "Failed to start command." ) );
} else if( err == QProcess::Crashed ) {
setError( Crashed );
setErrorText( i18n( "Command crashed." ) );
} else {
setError( UnknownExecError );
setErrorText( i18n( "Unknown error executing command." ) );
}
}
emitResult();
}
KDevelop::OutputModel* CustomBuildJob::model()
{
return qobject_cast<KDevelop::OutputModel*>( OutputJob::model() );
}
void CustomBuildJob::procFinished(int code)
{
//TODO: Make this configurable when the first report comes in from a tool
// where non-zero does not indicate error status
if( code != 0 ) {
setError( FailedShownError );
model()->appendLine( i18n( "*** Failed ***" ) );
} else {
model()->appendLine( i18n( "*** Finished ***" ) );
}
emitResult();
}
#include "moc_custombuildjob.cpp"