/************************************************************************ * KDevelop4 Custom Buildsystem Support * * * * Copyright 2010 Andreas Pakulat * * * * 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 . * ************************************************************************/ #include "custombuildjob.h" #include #include #include #include #include #include #include #include #include #include #include #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( 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"