Почему генератор CMake для Unix Makefiles удаляет файлы? - PullRequest
0 голосов
/ 11 октября 2019

У меня довольно сложная конфигурация CMake, которая содержит несколько команд execute_process, которые создают файлы на этапе настройки. Иногда после некоторых изменений в конфигурации CMake этап генерации удаляет эти файлы. Я могу воспроизвести это.

Я проверил, что файлы существуют после стадии конфигурации, но исчезли после генерации Makefile и перед тем, как фактически вызвать make.

Файлы созданы в некоторыхслучаи просто на ${CMAKE_COMMAND} -E copy, а в других случаях - на вызов скрипта с ${CMAKE_COMMAND} -P, который содержит вызов configure_file для замены некоторых заполнителей в шаблоне.

Файлы создаются в дереве исходного кода. Их цель - предоставить разработчику некоторый исходный код. После того, как разработчик отредактировал файлы, они должны перейти на контроль версий и не должны быть заново созданы, если они отсутствуют. У меня есть add_custom_command s для воссоздания файлов, если они отсутствуют, но они не виновны.

Я знаю, вы бы предпочли простой тестовый пример, но, к сожалению, это не так просто создать, поэтому мой вопрос:

В чем может быть причина и как я могу это отладить?

К сожалению, --trace опции cmake не даютлюбые данные журнала об этапе генерации.

Версии

  • ОС: Ubuntu 16.04
  • CMake 3.5.1 (принадлежит Ubuntu 16.04)

Обновление

Я сам скомпилировал CMake с текущим мастер-коммитом (696b2d4), и его поведение остается прежним.

Запустив CMake под отладчиком, я обнаружил, чтострока

cmSystemTools::RemoveFile(fname);

в функции cmGlobalGenerator::CheckRuleHashes(std::string const& pfile, std::string const& home) фактически удаляет файлы. Он вызывается с cmGlobalGenerator::Generate().

1 Ответ

0 голосов
/ 11 октября 2019

При дальнейшей отладке (см. Обновление в вопросе) я нашел причину моей проблемы.

Поведение CMake

Глобальный генератор CMake создает файл ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeRuleHashes.txt. Он содержит строку для каждой пользовательской команды с выводами. Каждая строка содержит хэш и путь к первому выводу пользовательской команды.

Хэш создается поверх текущего двоичного каталога пользовательской команды и всего содержимого аргументов COMMAND add_custom_command.

При генерации CMake выполняет cmGlobalGenerator::CheckRuleHashes для проверки актуальности хэшей. Если хеш не обновлен, соответствующий выходной файл будет удален, очевидно, чтобы вызвать повторное выполнение пользовательской команды на этапе сборки.

Причина моей проблемы

Как упоминалось ввопрос я выполняю команду создания файла с execute_process во время настройки и вызываю add_custom_command с той же командой создания файла, чтобы вызвать повторное создание файла в случае его отсутствия.

Итак, CMake создаетхэш-строка в CMakeRuleHashes.txt для создаваемого файла.

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

Таким образом, поскольку подкаталог является частью хеша пользовательской команды, хеш изменяется в зависимости от добавленного подкаталога. который включает в себя пользовательскую команду. Затем измененный хеш вызывает удаление выходного файла.

Заключение

Мне необходимо изменить конфигурацию моей CMake, чтобы разрешить зависимость пользовательской команды от двоичного каталога CMake.

Этап генерации отладки

Это можно сделать, скомпилировав сам CMake как Debug тип сборки и запустив его под отладчиком.

...