Hatred's Log Place

DON'T PANIC!

Nov 21, 2016 - 7 minute read

cmakeprojectmanager2

CMakeProjectManager2

Основные фичи

Зачёркнутое - уже в том или ином виде присутствует в апстриме.

  1. В диалоге конфигурирования (вкладка Projects основного окна, теперь он тут заинлайнен) 1. Добавлена возможность указывать тулчейн файл (может использоваться для всяких кастомизаций CMake), но если есть возможность обойтист средствами настройки Kit в QtC - лучше этим воспользоваться: легче будет парсеру. От этой опции я подумываю отказаться: если планируется не просто сборка, а разработка, то стоит завести набор (kit), где указать, откуда брать тулчейн-файл. 2. Для опций у которых задан набор вариантов значений(( раз, два, три)). Плюс задел, на будущее: обрабатывать выбор файла для FILEPATH и DIRECTORY типов опций.
  2. В дереве проекта 1. За несколькими но: 1) оно сделано не сильно оптимально, попадут, в том числе, всякие объекткники и прочая, 2) используются только заголовочники для отображения в дереве. Отображаеются все файлы проекта, кроме начинающихся с точки (скрытые), CVS и файлов с настройками проекта CMakeLists.txt.user
    • Для модели используются только файлы, которые видит CMake. Ровно как и пути поиска файлов для директивы #include.
    • Относительно прошлой реализации несколько ускорилось открытие. 1. Добавлена возможность создавать, удалять и переименовывать файлы в директориях проекта через контектсное меню в дереве проекта.
  3. Реализован более функциональный диалог создания проекта. Хотя, если убрать “2” во всех вхождениях “CMakeProjectManager2”, то он будет работать и для родной реализации. Стоит сделать сабмит в апстрим. Или поместить, просто, в отдельный репозиторий

Что случилось в апстриме:

  1. Апстрим теперь дал возможность использовать C++ компилятор из Kit. Для остальных компиляторов нужно дополнительно делать телодвижения в настройках CMake в Kit. Соответственно поддержка данной опции с моей стороны отброшена. Хотя, есть мнение, что нужно под свои задачи поведение несколько исправить.
  2. Проброс CMAKE_BUILD_TYPE. Тут всё чисто.
  3. Изменили диалог задания опций CMake. Сделали в виде таблицы. Так больше нравится.
  4. Подняли минимальную версию CMake до 3.0, начинают использовать новые фичи для лучшей интеграции, например т.н. cmake server mode(( https://cmake.org/pipermail/cmake-developers/2016-January/027424.html)) (пока не закончено).

Сборка и вообще

Это в репозитории есть: https://github.com/h4tr3d/cmakeprojectmanager2/blob/master/README.md

Процедура портирования комитов из апстрима

  1. Update Qt Creator git repository, moves to the master branch
  2. Create patches for new changes ``` git format-patch <REVISION_SINCE> – src/plugins/cmakeprojectmanager
REVISION_SINCE can be found via *git log* by comments or Change-Id.
  1. Go to CMakeProjectManager2 source tree and change branch to the `qtc-master`
  2. Copy patches from the step 2 to the CMakeProjectManager2 source tree root
  3. Apply patches:```
git am -p4 *.patch
  1. Change branch to the master, merge new changes and resolve conflicts

Запуск отдельного QtC для отладки

QTC_DEBUG=1 qtcreator-master -settingspath $HOME/.config/qtcreator-master

Стартовый скрипт QtC (qtcreator.sh) отредактировать, заменив последнюю строку на:

if [ -z "$QTC_DEBUG" ]; then
exec "$bindir/qtcreator" ${1+"$@"}
else
exec gdb --args "$bindir/qtcreator" ${1+"$@"}
fi

Фича 1: Построение дерева проектных файлов

В последних версиях сканирование файловой системы сделано асинхронно. Все изменения локализованы в файлах treebuilder.cpp, treebuilder.h.

Сканирование запускается параллельно с парсингом CMake проекта. Непосредственно список начинает формироваться когда закончатся оба процесса. Оба процесса можно прервать, тогда списки будут не полными.

Локализация изменений:

  1. BuildDirManager::BuildDirManager() - конструирование объекта TreeBuilder, связывание сигнала завершения и вызов функции completeParsing()
  2. BuildDirManager::extractData() - добавлен код, который выполняется при любом выходе из скоупа и формирует финальный список файлов для дерева.
  3. BuildDirManager::completeParsing() - новая функция с общим кодом, которая вызывается каждый раз, когда завершается cmake или TreeBuilder, проверяет все условия формирования дерева и запускает процесс извлечения полученных данных и сигнализирует о новых данных. Для cmake вызывается в самом конце BuildDirManager::cmakeFinished()
  4. BuildDirManager::startTreeBuilder() - новая функция. Запускат процесс сканирования дерева файлов. Вызывается в конце BuildDirManager::startCMake() перед посылкой уведомления о начале процессинга cmake.

Узкие места:

  1. Очень долго работает root->buildTree(...) * стоит посмотреть на appmanager/project/appmanagerproject.h/.cpp, там интересная идея с частичной модификацией дерева. Всё равно, так или иначе, создаются списки с добавленными или удалёнными файлами.
  2. Долгое сканирование файловой системы: * Сделать виджет для настройки исключений для проекта по маске и mime-типу. * Сканер файловой системы сделать единым для всех конфигураций, так как сканируется только дерево исходников. * Делать только инициирущее сканирование, а изменения отлавливать при помощи QFileSystemWatcher
  3. Частый вызов CMakeProject::files() * ограничить его только файлами из CMake: но будет неудобно для всяких поисков и прочих тулз. * не формировать список из дерева каждый раз, а хранить кешированный список и его возвращать. Его можно формировать в момент создания дерева. Тут только вопрос: хранить его внутри каждой конфигурации и из проекта туда просто обращаться: просто, но много памяти для больших проектов. Или отдавать наверх, но тут архитектура начинает малость рассыпаться.

По поводу вышеозначенных пунктов:

  • стоит попробовать вынести сканирование на уровень проекта, а не конкретной конфигурации
  • спрашивать список у проекта и дополнять им список билд-конфигурации
  • точечно модифицировать дерево

Идея отображения дерева принята апстримом. В текущем виде она не совсем готова, т.к. блокирует GUI на время сканирования файловой системы и построения дерева. Наработки по коду переданы Tobias Hunger, но следует ожидать не раньше QtC 4.1

Фича 2: Добавление, удаление и переименование файлов в файловой системе

Зависит от предыдущей. Без неё смысла не имеет.

Следующие функции для правки или создания:

bool CMakeProject::addFiles(const QStringList &filePaths)
bool CMakeProject::eraseFiles(const QStringList &filePaths)
bool CMakeProject::renameFile(const QString &filePath, const QString &newFilePath)

Они вызываются, соответственно, из:

bool CMakeProjectNode::addFiles(const QStringList &filePaths, QStringList *notAdded)
bool CMakeProjectNode::deleteFiles(const QStringList &filePaths)
bool CMakeProjectNode::renameFile(const QString &filePath, const QString &newFilePath)

Список поддерживаемых опций формируется в:

QList<ProjectExplorer::ProjectAction> CMakeProjectNode::supportedActions(Node *node) const

Из модификации класса CMakeProjectNode:

  1. Добавление ссылки на родительский проект (CMakeProject *m_project)
  2. и, соответственно, дополнительный параметр в конструктор

Всё это нужно, что бы можно было делегировать проекту задания по обновлению дерева.

Стоить отметить, что методы ноды будут вызваны всегда после завершения операции над файлами. Т.е. это просто уведомление о завершении операции.

Вообще список действий куда обширнее:

bool addFiles(const QStringList &filePaths, QStringList *notAdded = 0) override;
bool removeFiles(const QStringList &filePaths, QStringList *notRemoved = 0) override;
bool deleteFiles(const QStringList &filePaths) override;
bool canRenameFile(const QString &filePath, const QString &newFilePath) override;
bool renameFile(const QString &filePath, const QString &newFilePath) override;

нужно будет дополнительно рассмотреть canRenameFile() и removeFiles() (чем отличается от deleteFiles())

В старом варианте при обновлении нужно было звать CbpUpdate. Сейчас нужно сделать обращения к m_buildDirManager при добавлении файлов. (parse() / forceReparse())

  • вызываем m_buildDirManager->parse() потому как имеет смысл звать CMake только тогда, когда поменялись файлы, находящиеся под его контролем
    • с другой стороны, если используется глоббинг, то мы можем не отработать изменения по добавлению нового файла, варианты:
      • проверять расширения и форсировать только для всяких исходников - но тут нужно как-то определять, что это исходники. Не сильно хочется хардкодить такое. Вынести в настройки известные типы?
      • при добавлении файла, впринципе, можно всегда форсировать, а при удалении и переименовании - нет: если файла не было, вотчер про него и не знал, следовательно, нужно зафорсировать, если файл уже был: вотчер про него знает и сможет сам определить, нужно ли регенерировать список файлов. Тогда переименование и удаление файлов, которые не под управлением CMake регенерация зваться лишний раз не будет. Что есть хорошо.
        • FIXME идея не совсем работает. Пока оставляем везде forceReparse()

Нужно быть готовым к тому, что после переименования CMake зафейлится: если имя файла чётко прописано в качестве параметра таргета, а не через глобинг. Всё нормализуется после редактирования соответствующего CMakeLists.txt

Сама идея и не окончательно отвергнута и не принята. Ниже предположительные доработки

Доработки по фиче:

  1. При добавлении файла, смотреть, попал ли он в дерево исходников CMake после отработки парсера.
  2. Если нет, то выводить предупреждение, что файл не виден CMake и предложить руками добавить его к нужной цели.

Фича 3: Управление тулчейнами и форсированная очистка кеша

Форсированная очистка кеша, на основе моих наработок теперь в апстриме, но доступна через глобальное меню Build -> Clear CMake cache

Доработка 1: использование инициирующего кеша CMake

Проблема: последние версии плагина позволяют в настройках Kit указать параметры для CMake, в частности, компилятор. В текущем виде эти параметры передаются через опции командной строки, что имеет максимальный приоритет и может ломать некоторую пользовательскую логику (например использование тулчейнов).

Предложение: использовать инициирующего кеша CMake (cmake -C initial-cache-script). Этот кеш переопределяет поведение по умолчанию, но имеет минимальный приоритет. Так же он работает только в случае первоначального запуска CMake для данной конфигурации, а так же после удаления CMakeCache.txt файла. Соответственно, любое задание опций через интерфейс командной строки будет обладать приоритетом над параметрами из этого файла.

Использование тулчейна так же будет переопределять эти значения.

Ссылки по теме:

Сабмит изменений в Qt Creator Список желаний

comments powered by Disqus