File indexing completed on 2024-05-05 16:46:01
0001 /* 0002 SPDX-FileCopyrightText: 2017 Aleix Pol Gonzalez <aleixpol@kde.org> 0003 SPDX-FileCopyrightText: 2018 Daniel Mensinger <daniel@mensinger-ka.de> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "mesonconfig.h" 0009 0010 #include "mesonmanager.h" 0011 #include <debug.h> 0012 0013 #include <interfaces/iproject.h> 0014 #include <project/interfaces/ibuildsystemmanager.h> 0015 #include <project/projectmodel.h> 0016 0017 #include <KLocalizedString> 0018 0019 #include <QFileDialog> 0020 0021 using namespace KDevelop; 0022 using namespace Meson; 0023 0024 static const QString ROOT_CONFIG = QStringLiteral("MesonManager"); 0025 static const QString NUM_BUILD_DIRS = QStringLiteral("Number of Build Directories"); 0026 static const QString CURRENT_INDEX = QStringLiteral("Current Build Directory Index"); 0027 0028 static const QString BUILD_DIR_SEC = QStringLiteral("BuildDir %1"); 0029 static const QString BUILD_DIR_PATH = QStringLiteral("Build Directory Path"); 0030 static const QString MESON_EXE = QStringLiteral("Meson executable"); 0031 static const QString EXTRA_ARGS = QStringLiteral("Additional meson arguments"); 0032 static const QString BACKEND = QStringLiteral("Meson Generator Backend"); 0033 0034 int MesonConfig::addBuildDir(BuildDir dir) 0035 { 0036 int newIndex = buildDirs.size(); 0037 dir.canonicalizePaths(); 0038 qCDebug(KDEV_Meson) << "BuildDirectories::addBuildDir()=" << dir.buildDir; 0039 buildDirs.push_back(dir); 0040 0041 // Make sure m_currentIndex is valid 0042 if (currentIndex < 0) { 0043 currentIndex = newIndex; 0044 } 0045 0046 return newIndex; 0047 } 0048 0049 bool MesonConfig::removeBuildDir(int index) 0050 { 0051 if (index > buildDirs.size() || index < 0) { 0052 return false; 0053 } 0054 0055 buildDirs.removeAt(index); 0056 0057 if (currentIndex >= buildDirs.size()) { 0058 currentIndex = buildDirs.size() - 1; 0059 } 0060 0061 return true; 0062 } 0063 0064 KConfigGroup Meson::rootGroup(IProject* project) 0065 { 0066 if (!project) { 0067 qCWarning(KDEV_Meson) << "Meson::rootGroup: IProject pointer is nullptr"; 0068 return KConfigGroup(); 0069 } 0070 0071 return project->projectConfiguration()->group(ROOT_CONFIG); 0072 } 0073 0074 MesonConfig Meson::getMesonConfig(IProject* project) 0075 { 0076 KConfigGroup root = rootGroup(project); 0077 MesonConfig result; 0078 0079 int numDirs = root.readEntry(NUM_BUILD_DIRS, 0); 0080 result.currentIndex = root.readEntry(CURRENT_INDEX, -1); 0081 0082 for (int i = 0; i < numDirs; ++i) { 0083 QString section = BUILD_DIR_SEC.arg(i); 0084 if (!root.hasGroup(section)) { 0085 continue; 0086 } 0087 0088 KConfigGroup current = root.group(section); 0089 BuildDir currBD; 0090 currBD.buildDir = Path(current.readEntry(BUILD_DIR_PATH, QString())); 0091 currBD.mesonExecutable = Path(current.readEntry(MESON_EXE, QString())); 0092 currBD.mesonBackend = current.readEntry(BACKEND, QString()); 0093 currBD.mesonArgs = current.readEntry(EXTRA_ARGS, QString()); 0094 0095 currBD.canonicalizePaths(); 0096 0097 // Try to find meson if the config is bad 0098 if (currBD.mesonExecutable.isEmpty()) { 0099 Q_ASSERT(project); 0100 IBuildSystemManager* ibsm = project->buildSystemManager(); 0101 auto* bsm = dynamic_cast<MesonManager*>(ibsm); 0102 if (bsm) { 0103 currBD.mesonExecutable = bsm->findMeson(); 0104 } 0105 } 0106 0107 result.buildDirs.push_back(currBD); 0108 } 0109 0110 if (result.buildDirs.isEmpty()) { 0111 result.currentIndex = -1; 0112 } else if (result.currentIndex < 0 || result.currentIndex >= result.buildDirs.size()) { 0113 result.currentIndex = 0; 0114 } 0115 0116 return result; 0117 } 0118 0119 void Meson::writeMesonConfig(IProject* project, const MesonConfig& cfg) 0120 { 0121 KConfigGroup root = rootGroup(project); 0122 0123 // Make sure that the config we write is valid 0124 int currentIndex = cfg.currentIndex; 0125 if (cfg.buildDirs.isEmpty()) { 0126 currentIndex = -1; 0127 } else if (currentIndex < 0 || currentIndex >= cfg.buildDirs.size()) { 0128 currentIndex = 0; 0129 } 0130 0131 root.writeEntry(NUM_BUILD_DIRS, cfg.buildDirs.size()); 0132 root.writeEntry(CURRENT_INDEX, currentIndex); 0133 0134 int counter = 0; 0135 for (const auto& i : cfg.buildDirs) { 0136 KConfigGroup current = root.group(BUILD_DIR_SEC.arg(counter++)); 0137 0138 current.writeEntry(BUILD_DIR_PATH, i.buildDir.path()); 0139 current.writeEntry(MESON_EXE, i.mesonExecutable.path()); 0140 current.writeEntry(BACKEND, i.mesonBackend); 0141 current.writeEntry(EXTRA_ARGS, i.mesonArgs); 0142 } 0143 } 0144 0145 BuildDir Meson::currentBuildDir(IProject* project) 0146 { 0147 Q_ASSERT(project); 0148 MesonConfig cfg = getMesonConfig(project); 0149 if (cfg.currentIndex < 0 || cfg.currentIndex >= cfg.buildDirs.size()) { 0150 cfg.currentIndex = 0; // Default to the first build dir 0151 0152 // Return an invalid build dir 0153 if (cfg.buildDirs.isEmpty()) { 0154 return BuildDir(); 0155 } 0156 } 0157 0158 return cfg.buildDirs[cfg.currentIndex]; 0159 } 0160 0161 bool Meson::BuildDir::isValid() const 0162 { 0163 return !(buildDir.isEmpty() || mesonExecutable.isEmpty()); 0164 } 0165 0166 void Meson::BuildDir::canonicalizePaths() 0167 { 0168 for (auto* i : { &buildDir }) { 0169 // canonicalFilePath checks if the file / directory exists and returns "" if it doesn't. 0170 QString tmp = QFileInfo(i->toLocalFile()).canonicalFilePath(); 0171 if (!tmp.isEmpty()) { 0172 *i = Path(tmp); 0173 } 0174 } 0175 }