forked from qt-creator/qt-creator
CMakePM: Do not add sources to globbed targets
If a class is being added to a target that has a variable resulted from a `file(GLOB|_RECURSE)` call, we skip adding the files to the target. Do not add the files, just run CMake which would gather the new sources into the project. Adding sources to a globbed target will no longer open the CMakeLists.txt file, since nothing has changed. CMake will be run after adding, renaming and removing of sources files. Fixes: QTCREATORBUG-30445 Change-Id: I82e126737789f215a6400f5a43f303dcc57de005 Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
@@ -642,6 +642,25 @@ bool CMakeBuildSystem::addTsFiles(Node *context, const FilePaths &filePaths, Fil
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isGlobbingFunction(const cmListFile &cmakeListFile, const cmListFileFunction &func)
|
||||||
|
{
|
||||||
|
// Check if the filename is part of globbing variable result
|
||||||
|
const auto globFunctions = std::get<0>(
|
||||||
|
Utils::partition(cmakeListFile.Functions, [](const auto &f) {
|
||||||
|
return f.LowerCaseName() == "file" && f.Arguments().size() > 2
|
||||||
|
&& (f.Arguments().front().Value == "GLOB"
|
||||||
|
|| f.Arguments().front().Value == "GLOB_RECURSE");
|
||||||
|
}));
|
||||||
|
|
||||||
|
const auto globVariables = Utils::transform<QSet>(globFunctions, [](const auto &func) {
|
||||||
|
return std::string("${") + func.Arguments()[1].Value + "}";
|
||||||
|
});
|
||||||
|
|
||||||
|
return Utils::anyOf(func.Arguments(), [globVariables](const auto &arg) {
|
||||||
|
return globVariables.contains(arg.Value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
bool CMakeBuildSystem::addSrcFiles(Node *context, const FilePaths &filePaths, FilePaths *notAdded)
|
bool CMakeBuildSystem::addSrcFiles(Node *context, const FilePaths &filePaths, FilePaths *notAdded)
|
||||||
{
|
{
|
||||||
if (notAdded)
|
if (notAdded)
|
||||||
@@ -670,6 +689,11 @@ bool CMakeBuildSystem::addSrcFiles(Node *context, const FilePaths &filePaths, Fi
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool haveGlobbing = isGlobbingFunction(cmakeListFile.value(), function.value());
|
||||||
|
n->setVisibleAfterAddFileAction(!haveGlobbing);
|
||||||
|
if (haveGlobbing && settings(project()).autorunCMake()) {
|
||||||
|
runCMake();
|
||||||
|
} else {
|
||||||
const std::string target_name = function->Arguments().front().Value;
|
const std::string target_name = function->Arguments().front().Value;
|
||||||
auto qtAddModule = [target_name](const auto &func) {
|
auto qtAddModule = [target_name](const auto &func) {
|
||||||
return (func.LowerCaseName() == "qt_add_qml_module"
|
return (func.LowerCaseName() == "qt_add_qml_module"
|
||||||
@@ -691,6 +715,7 @@ bool CMakeBuildSystem::addSrcFiles(Node *context, const FilePaths &filePaths, Fi
|
|||||||
qCCritical(cmakeBuildSystemLog) << inserted.error();
|
qCCritical(cmakeBuildSystemLog) << inserted.error();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (notAdded)
|
if (notAdded)
|
||||||
notAdded->removeIf([filePaths](const FilePath &p) { return filePaths.contains(p); });
|
notAdded->removeIf([filePaths](const FilePath &p) { return filePaths.contains(p); });
|
||||||
@@ -770,22 +795,7 @@ CMakeBuildSystem::projectFileArgumentPosition(const QString &targetName, const Q
|
|||||||
return ProjectFileArgumentPosition{filePathArgument, targetCMakeFile, fileName};
|
return ProjectFileArgumentPosition{filePathArgument, targetCMakeFile, fileName};
|
||||||
} else {
|
} else {
|
||||||
// Check if the filename is part of globbing variable result
|
// Check if the filename is part of globbing variable result
|
||||||
const auto globFunctions = std::get<0>(
|
const auto haveGlobbing = isGlobbingFunction(cmakeListFile.value(), func.value());
|
||||||
Utils::partition(cmakeListFile->Functions, [](const auto &f) {
|
|
||||||
return f.LowerCaseName() == "file" && f.Arguments().size() > 2
|
|
||||||
&& (f.Arguments().front().Value == "GLOB"
|
|
||||||
|| f.Arguments().front().Value == "GLOB_RECURSE");
|
|
||||||
}));
|
|
||||||
|
|
||||||
const auto globVariables = Utils::transform<QSet>(globFunctions, [](const auto &func) {
|
|
||||||
return std::string("${") + func.Arguments()[1].Value + "}";
|
|
||||||
});
|
|
||||||
|
|
||||||
const auto haveGlobbing = Utils::anyOf(func->Arguments(),
|
|
||||||
[globVariables](const auto &arg) {
|
|
||||||
return globVariables.contains(arg.Value);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (haveGlobbing) {
|
if (haveGlobbing) {
|
||||||
return ProjectFileArgumentPosition{filePathArgument,
|
return ProjectFileArgumentPosition{filePathArgument,
|
||||||
targetCMakeFile,
|
targetCMakeFile,
|
||||||
@@ -833,6 +843,7 @@ RemovedFilesFromProject CMakeBuildSystem::removeFiles(Node *context,
|
|||||||
const FilePath projDir = n->filePath().canonicalPath();
|
const FilePath projDir = n->filePath().canonicalPath();
|
||||||
const QString targetName = n->buildKey();
|
const QString targetName = n->buildKey();
|
||||||
|
|
||||||
|
bool haveGlobbing = false;
|
||||||
for (const auto &file : filePaths) {
|
for (const auto &file : filePaths) {
|
||||||
const QString fileName
|
const QString fileName
|
||||||
= file.canonicalPath().relativePathFrom(projDir).cleanPath().toString();
|
= file.canonicalPath().relativePathFrom(projDir).cleanPath().toString();
|
||||||
@@ -847,6 +858,11 @@ RemovedFilesFromProject CMakeBuildSystem::removeFiles(Node *context,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (filePos.value().fromGlobbing) {
|
||||||
|
haveGlobbing = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
BaseTextEditor *editor = qobject_cast<BaseTextEditor *>(
|
BaseTextEditor *editor = qobject_cast<BaseTextEditor *>(
|
||||||
Core::EditorManager::openEditorAt({filePos.value().cmakeFile,
|
Core::EditorManager::openEditorAt({filePos.value().cmakeFile,
|
||||||
static_cast<int>(filePos.value().argumentPosition.Line),
|
static_cast<int>(filePos.value().argumentPosition.Line),
|
||||||
@@ -869,7 +885,6 @@ RemovedFilesFromProject CMakeBuildSystem::removeFiles(Node *context,
|
|||||||
if (filePos->argumentPosition.Delim == cmListFileArgument::Quoted)
|
if (filePos->argumentPosition.Delim == cmListFileArgument::Quoted)
|
||||||
extraChars = 2;
|
extraChars = 2;
|
||||||
|
|
||||||
if (!filePos.value().fromGlobbing)
|
|
||||||
editor->replace(filePos.value().relativeFileName.length() + extraChars, "");
|
editor->replace(filePos.value().relativeFileName.length() + extraChars, "");
|
||||||
|
|
||||||
editor->editorWidget()->autoIndent();
|
editor->editorWidget()->autoIndent();
|
||||||
@@ -889,6 +904,9 @@ RemovedFilesFromProject CMakeBuildSystem::removeFiles(Node *context,
|
|||||||
if (notRemoved && !badFiles.isEmpty())
|
if (notRemoved && !badFiles.isEmpty())
|
||||||
*notRemoved = badFiles;
|
*notRemoved = badFiles;
|
||||||
|
|
||||||
|
if (haveGlobbing && settings(project()).autorunCMake())
|
||||||
|
runCMake();
|
||||||
|
|
||||||
return badFiles.isEmpty() ? RemovedFilesFromProject::Ok : RemovedFilesFromProject::Error;
|
return badFiles.isEmpty() ? RemovedFilesFromProject::Ok : RemovedFilesFromProject::Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -949,7 +967,9 @@ bool CMakeBuildSystem::renameFile(Node *context,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool haveGlobbing = false;
|
||||||
do {
|
do {
|
||||||
|
if (!fileToRename->fromGlobbing) {
|
||||||
BaseTextEditor *editor = qobject_cast<BaseTextEditor *>(
|
BaseTextEditor *editor = qobject_cast<BaseTextEditor *>(
|
||||||
Core::EditorManager::openEditorAt(
|
Core::EditorManager::openEditorAt(
|
||||||
{fileToRename->cmakeFile,
|
{fileToRename->cmakeFile,
|
||||||
@@ -969,7 +989,6 @@ bool CMakeBuildSystem::renameFile(Node *context,
|
|||||||
if (fileToRename->argumentPosition.Delim == cmListFileArgument::Quoted)
|
if (fileToRename->argumentPosition.Delim == cmListFileArgument::Quoted)
|
||||||
editor->setCursorPosition(editor->position() + 1);
|
editor->setCursorPosition(editor->position() + 1);
|
||||||
|
|
||||||
if (!fileToRename->fromGlobbing)
|
|
||||||
editor->replace(fileToRename->relativeFileName.length(), newRelPathName);
|
editor->replace(fileToRename->relativeFileName.length(), newRelPathName);
|
||||||
|
|
||||||
editor->editorWidget()->autoIndent();
|
editor->editorWidget()->autoIndent();
|
||||||
@@ -978,11 +997,17 @@ bool CMakeBuildSystem::renameFile(Node *context,
|
|||||||
<< "Changes to" << fileToRename->cmakeFile.path() << "could not be saved.";
|
<< "Changes to" << fileToRename->cmakeFile.path() << "could not be saved.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
haveGlobbing = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Try the next occurrence. This can happen if set_source_file_properties is used
|
// Try the next occurrence. This can happen if set_source_file_properties is used
|
||||||
fileToRename = projectFileArgumentPosition(targetName, fileToRename->relativeFileName);
|
fileToRename = projectFileArgumentPosition(targetName, fileToRename->relativeFileName);
|
||||||
} while (fileToRename && !fileToRename->fromGlobbing);
|
} while (fileToRename && !fileToRename->fromGlobbing);
|
||||||
|
|
||||||
|
if (haveGlobbing && settings(project()).autorunCMake())
|
||||||
|
runCMake();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -187,9 +187,16 @@ void CMakeTargetNode::setConfig(const CMakeConfig &config)
|
|||||||
m_config = config;
|
m_config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CMakeTargetNode::setVisibleAfterAddFileAction(bool visibleAfterAddFileAction)
|
||||||
|
{
|
||||||
|
m_visibleAfterAddFileAction = visibleAfterAddFileAction;
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<FilePath> CMakeTargetNode::visibleAfterAddFileAction() const
|
std::optional<FilePath> CMakeTargetNode::visibleAfterAddFileAction() const
|
||||||
{
|
{
|
||||||
|
if (m_visibleAfterAddFileAction)
|
||||||
return filePath().pathAppended(Constants::CMAKE_LISTS_TXT);
|
return filePath().pathAppended(Constants::CMAKE_LISTS_TXT);
|
||||||
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMakeTargetNode::build()
|
void CMakeTargetNode::build()
|
||||||
|
@@ -57,11 +57,14 @@ public:
|
|||||||
QVariant data(Utils::Id role) const override;
|
QVariant data(Utils::Id role) const override;
|
||||||
void setConfig(const CMakeConfig &config);
|
void setConfig(const CMakeConfig &config);
|
||||||
|
|
||||||
|
void setVisibleAfterAddFileAction(bool visibleAfterAddFileAction);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_tooltip;
|
QString m_tooltip;
|
||||||
Utils::FilePath m_buildDirectory;
|
Utils::FilePath m_buildDirectory;
|
||||||
Utils::FilePath m_artifact;
|
Utils::FilePath m_artifact;
|
||||||
CMakeConfig m_config;
|
CMakeConfig m_config;
|
||||||
|
bool m_visibleAfterAddFileAction = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // CMakeProjectManager::Internal
|
} // CMakeProjectManager::Internal
|
||||||
|
Reference in New Issue
Block a user