File indexing completed on 2024-04-28 04:38:20

0001 /*
0002     SPDX-FileCopyrightText: 2006-2007 Andreas Pakulat <apaku@gmx.de>
0003     SPDX-FileCopyrightText: 2008 Hamish Rodda <rodda@kde.org>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 
0009 #include "cmakejob.h"
0010 
0011 #include <cmakebuilderconfig.h>
0012 #include <cmakebuilder.h>
0013 
0014 #include <QDir>
0015 
0016 #include <project/projectmodel.h>
0017 
0018 #include <interfaces/iproject.h>
0019 #include <interfaces/icore.h>
0020 #include <interfaces/iruntime.h>
0021 #include <interfaces/iruntimecontroller.h>
0022 
0023 #include <cmakeutils.h>
0024 #include <cmakefileapi.h>
0025 #include "debug.h"
0026 
0027 #include <KShell>
0028 #include <KLocalizedString>
0029 
0030 using namespace KDevelop;
0031 
0032 CMakeJob::CMakeJob(QObject* parent)
0033     : OutputExecuteJob(parent)
0034 {
0035     setCapabilities( Killable );
0036     setFilteringStrategy( OutputModel::CompilerFilter );
0037     setProperties( NeedWorkingDirectory | PortableMessages | DisplayStderr | IsBuilderHint );
0038     setToolTitle( i18n("CMake") );
0039     setStandardToolView( KDevelop::IOutputView::BuildView );
0040     setBehaviours(KDevelop::IOutputView::AllowUserClose | KDevelop::IOutputView::AutoScroll );
0041 }
0042 
0043 void CMakeJob::start()
0044 {
0045     qCDebug(KDEV_CMAKEBUILDER) << "Configuring cmake" << workingDirectory();
0046 
0047     auto error = [this](ErrorTypes error, const QString &message)
0048     {
0049         qCWarning(KDEV_CMAKEBUILDER) << "failed" << error << message;
0050         setError(error);
0051         setErrorText(message);
0052         emitResult();
0053     };
0054 
0055     if( !m_project ) {
0056         error(NoProjectError, i18n("Internal error: no project specified to configure."));
0057         return;
0058     }
0059 
0060     const auto workingDir = workingDirectory().toLocalFile();
0061     QDir dir;
0062     if (!dir.mkpath(workingDir)) {
0063         error(FailedError, i18n("Failed to create build directory %1.", workingDir));
0064         return;
0065     }
0066     CMake::FileApi::writeClientQueryFile(workingDir);
0067     CMake::updateConfig( m_project, CMake::currentBuildDirIndex(m_project) );
0068 
0069     OutputExecuteJob::start();
0070 }
0071 
0072 QUrl CMakeJob::workingDirectory() const
0073 {
0074     KDevelop::Path path = CMake::currentBuildDir( m_project );
0075     qCDebug(KDEV_CMAKEBUILDER) << "builddir: " << path;
0076     Q_ASSERT(path.isValid()); //We cannot get the project folder as a build directory!
0077     return path.toUrl();
0078 }
0079 
0080 QStringList CMakeJob::commandLine() const
0081 {
0082     QStringList args;
0083     args << CMake::currentCMakeExecutable( m_project ).toLocalFile();
0084 
0085     args << QStringLiteral("-DCMAKE_EXPORT_COMPILE_COMMANDS=ON");
0086 
0087     QString installDir = CMake::currentInstallDir( m_project ).toLocalFile();
0088     if( !installDir.isEmpty() )
0089     {
0090         args << QStringLiteral("-DCMAKE_INSTALL_PREFIX=%1").arg(installDir);
0091     }
0092     QString buildType = CMake::currentBuildType( m_project );
0093     if( !buildType.isEmpty() )
0094     {
0095         args << QStringLiteral("-DCMAKE_BUILD_TYPE=%1").arg(buildType);
0096     }
0097     QVariantMap cacheArgs = property("extraCMakeCacheValues").toMap();
0098     for( auto it = cacheArgs.constBegin(), itEnd = cacheArgs.constEnd(); it!=itEnd; ++it) {
0099         args << QStringLiteral("-D%1=%2").arg(it.key(), it.value().toString());
0100     }
0101 
0102     auto rt = ICore::self()->runtimeController()->currentRuntime();
0103     //if we are creating a new build directory, we'll want to specify the generator
0104     QDir builddir(rt->pathInRuntime(CMake::currentBuildDir( m_project )).toLocalFile());
0105     if(!builddir.exists() || !builddir.exists(QStringLiteral("CMakeCache.txt"))) {
0106         CMakeBuilderSettings::self()->load();
0107         args << QStringLiteral("-G") << CMake::defaultGenerator();
0108     }
0109     QString cmakeargs = CMake::currentExtraArguments( m_project );
0110     if( !cmakeargs.isEmpty() ) {
0111         KShell::Errors err;
0112         QStringList tmp = KShell::splitArgs( cmakeargs, KShell::TildeExpand | KShell::AbortOnMeta, &err );
0113         if( err == KShell::NoError ) {
0114             args += tmp;
0115         } else {
0116             qCWarning(KDEV_CMAKEBUILDER) << "Ignoring cmake Extra arguments";
0117             if( err == KShell::BadQuoting ) {
0118                 qCWarning(KDEV_CMAKEBUILDER) << "CMake arguments badly quoted:" << cmakeargs;
0119             } else {
0120                 qCWarning(KDEV_CMAKEBUILDER) << "CMake arguments had meta character:" << cmakeargs;
0121             }
0122         }
0123     }
0124     args << rt->pathInRuntime(CMake::projectRoot( m_project )).toLocalFile();
0125 
0126     return args;
0127 }
0128 
0129 QString CMakeJob::environmentProfile() const
0130 {
0131     return CMake::currentEnvironment( m_project );
0132 }
0133 
0134 void CMakeJob::setProject(KDevelop::IProject* project)
0135 {
0136     m_project = project;
0137 
0138     if (m_project)
0139         setJobName( i18n("CMake: %1", m_project->name()) );
0140 }
0141 
0142 #include "moc_cmakejob.cpp"