2015-04-21 4 views
3

См последний обновление статусаadd_custom_command - список зависимостей обновление через перестраивает

начальные условия

  • генератор кода, который генерирует набор из C++ источников принимать один входной файл в качестве параметра
  • входного файла может включать в себя другие входные файлы
  • уже решена задача получения списка выходных файлов, разбор входных данных co файлы degen, чтобы получить полный список входных данных codegen. I.e. add_custom_command обеспечивается правильным набором зависимостей впервые:

    add_custom_command(OUTPUT ${generatedSources} 
            COMMAND ${codegenCommand} ARGS ${codegenArgs} 
            DEPENDS ${codegenInputFiles}) 
    

Проблема сценария

  • Действующая система работает хорошо, пока кто-нибудь не изменяет один из входных Codegen файлов включить новый входной файл или удалить из существующего. Этот случай, необходимо обновить список Codegen входного файла предоставленного add_custom_command как зависимости, но я понятия не имею, как

Что недостающую

  • возможность обновлять зависимости add_custom_command над проектом перестройки

Есть ли способ решить проблему без полного восстановления проекта?

UPDATE - Альтернативное описание (? Лучше) проблема

I`ve нашел подобное не ответил на вопрос о списке рассылки CMake, разместить его здесь для большей ясности: http://article.gmane.org/gmane.comp.programming.tools.cmake.user/52279

Я пытаюсь получить инструмент генерации кода, чтобы вести себя «так же, как» исходный файл C в отношении зависимостей. Под этим я подразумеваю, предположим, что у вас есть C-файл «a.c». Поскольку он может # включать файлы, каждый раз, когда изменяется содержимое a.c, его зависимости также могут измениться. Зависимости получают rescanned с -MMD. Я хотел бы каким-то образом подражать этому для моего генератора кода. Сначала я попробовал add_custom_command, который принимает фиксированный список DEPENDS, определенный во время определения пользовательской команды. В частности, я имею в виду что-то вроде этого:

function(add_generated_library) 
    figure_out_dependencies(deps ${ARGN}) 
    add_custom_command(... DEPENDS ${deps}) 
endfunction() 

Но захватывает только зависимости во время сборки-система поколения. Каждый раз, когда запускается пользовательская команда, список DEPENDS может потребоваться изменить, поскольку изменения могут означать новые зависимости. Как мне это сделать?

UPDATE 2 - Возможное решение

После я считаю факты - есть голоса через сеть относительно Cmake поддержки динамических зависимостей, который требуется для плавной интеграции многих нетривиального кода инструменты поколения - там `нет готовых к использованию оптимальное решение, доступное, как то, что мы на самом деле нужно крюк, чтобы добавить поддержку пользовательских DSL в IMPLICIT_DEPENDS

с Cmake руководство:

Опция IMPLICIT_DEPENDS запрашивает сканирование неявных зависимостей входного файла. Указанный язык указывает язык программирования, на котором должен использоваться соответствующий сканер зависимостей. В настоящее время поддерживаются только сканеры языка C и CXX. Язык должен быть указан для каждого файла в списке IMPLICIT_DEPENDS. Зависимости, обнаруженные при сканировании, добавляются к значениям пользовательской команды во время сборки.

Решение ниже прилипает (надеюсь) следующие критерии:

  • избежать не обязательно сканировании зависимости восстановления
  • Чтобы не было необходимым кодом генератора работать на перестроения
  • позволяют обеспечить функции CMake для клиентов, чтобы зарегистрироваться их модели и генерировать код/​​создавать библиотеки из этого кода без навязывания каких-либо требований к структуре проекта (т. е. никакого подпроекта, ответственного за создание кода, модели распределяются по иерархии проектов с использованием политики проекта у)

Решение Идея

Это не возможно зарегистрировать пользовательский язык сканер, но можно повторно использовать существующий. Идея состоит в том, что зависимости/иерархия пользовательских файлов моделей отражаются как иерархия файлов заголовков «С». Каждый узел иерархии добавляется при регистрации файла модели, а файл C включает файл модели соответствия. Если файл модели включает в себя изменение, файл C включает в себя изменение. Таким образом, каждый вызов-код будет зависеть только от одного сгенерированного С-заголовка, отражающего пройденную модель. Каждый отраженный файл будет иметь зависимость от файла модели и будет затронут изменение файла модели.

Подводя итог: возможно, моя формулировка не так понятна на данный момент, но в отношении потребностей других людей и сообщества помогли мне исследовать эту проблему, я опубликую общее решение (+ ссылка на github или новый cmake wiki) без моей спецификации проекта, когда она будет готова (через 1-3 дня).

+0

Пожалуйста, посетите [Если вопросы включают «теги» в их названиях?] (Http://meta.stackexchange.com/q/19190). Вы также можете щелкнуть ссылку * Изменено прямо сейчас * или * Отредактировано XXX минут назад *, чтобы узнать, почему было сделано изменение. Он предоставляет историю изменений. – jww

+0

Извините за путаницу, не заметил вашего комментария и решил, что название было изменено каким-то сценарием. Вернуть название, как предлагается – Konstantin

+0

Нет проблем. На сайте есть несколько политик, которые не всегда приемлемы. Мне не нравится эта политика (я даже возражал против нее). – jww

ответ

1

Можете ли вы показать, как вы инициализируете переменную codegenInputFiles? Вероятно, вы можете использовать команду file(GLOB ...) или file(GLOB_RECURSE ...). См. documentation.

Обратите внимание, что вам придется перезапустить cmake, чтобы ваша команда была сгенерирована. Вы работаете с git? Тогда вы можете иметь a hook, который заставляет вызов cmake каждый раз, когда вы тянете (так что, если кто-то изменил codegenInputFiles, ваши автоматически сгенерированные файлы будут обновлены).


После выяснения проблемы, вы должны быть в состоянии найти обходной путь, используя IMPLICIT_DEPENDS вместо DEPENDS. Ограничения:

  1. Он может работать, только если входной файл C/C++ (проверить синтаксис, как вы должны указать язык для каждого файла, указанного)
  2. Вам может понадобиться, чтобы проверить CMake версии поддерживает эту команду , даже если он выглядит, что он уже некоторое время
  3. это поддерживается только для Makefile генератора, который звучит очень плохо ...

EDIT

После нескольких итераций, я наконец-то понял, в чем проблема. Я предлагаю следующее решение: отделить создание файла в отдельном подпроекте cmake. Когда вы создадите свой основной проект (вызвав make), вы вызовете оба cmake и сделаете для своего подпроекта. Вызов cmake необходим для поддержания обновленных зависимостей, а при вызове make фактически создавать ваши автоматически генерируемые источники.

Здесь я показываю пример проекта и подпроекта с проектом, вызывающим cmake и создающим для подпроекта.

Состав:

. 
├── CMakeLists.txt 
├── a.cpp 
├── build 
└── subProject 
    └── CMakeLists.txt 

Содержимое файла

./CMakeLists.txt:

cmake_minimum_required(VERSION 2.8) 

add_custom_target(subProjectTarget ALL) 
add_custom_command(TARGET subProjectTarget PRE_BUILD COMMAND mkdir -p ${CMAKE_BINARY_DIR}/subProject && cd ${CMAKE_BINARY_DIR}/subProject && ${CMAKE_COMMAND} ${CMAKE_SOURCE_DIR}/subProject && make) 

include_directories(${CMAKE_BINARY_DIR}/subProject) 
add_executable (dummy a.cpp) 
add_dependencies (dummy subProjectTarget) 

./a.cpp (Обратите внимание, что ЧД еще не существует)

#include "b.h" 

int main() { 
} 

./SubProject/CMakeLists.txt

cmake_minimum_required(VERSION 2.8) 
file(WRITE ${CMAKE_BINARY_DIR}/b.h "//I am a dummy file\n") 

Построение проекта (используется по умолчанию) make

[email protected]:~/example/build$ cmake .. 
-- The C compiler identification is GNU 4.8.2 
-- The CXX compiler identification is GNU 4.8.2 
-- Check for working C compiler: /usr/bin/cc 
-- Check for working C compiler: /usr/bin/cc -- works 
-- Detecting C compiler ABI info 
-- Detecting C compiler ABI info - done 
-- Check for working CXX compiler: /usr/bin/c++ 
-- Check for working CXX compiler: /usr/bin/c++ -- works 
-- Detecting CXX compiler ABI info 
-- Detecting CXX compiler ABI info - done 
-- Configuring done 
-- Generating done 
-- Build files have been written to: /home/me/example/build 

[email protected]:~/example/build$ make 
Scanning dependencies of target subProjectTarget 
-- The C compiler identification is GNU 4.8.2 
-- The CXX compiler identification is GNU 4.8.2 
-- Check for working C compiler: /usr/bin/cc 
-- Check for working C compiler: /usr/bin/cc -- works 
-- Detecting C compiler ABI info 
-- Detecting C compiler ABI info - done 
-- Check for working CXX compiler: /usr/bin/c++ 
-- Check for working CXX compiler: /usr/bin/c++ -- works 
-- Detecting CXX compiler ABI info 
-- Detecting CXX compiler ABI info - done 
-- Configuring done 
-- Generating done 
-- Build files have been written to: /home/me/example/build/subProject 
[ 0%] Built target subProjectTarget 
Scanning dependencies of target dummy 
[100%] Building CXX object CMakeFiles/dummy.dir/a.cpp.o 
Linking CXX executable dummy 
[100%] Built target dummy 

Обратите внимание, что второй раз CMake вызовов на подпроекта.

На очередном призыве все еще быстрее:

[email protected]:~/example/build$ make 
-- Configuring done 
-- Generating done 
-- Build files have been written to: /home/me/example/build/subProject 
[ 0%] Built target subProjectTarget 
Scanning dependencies of target dummy 
[100%] Building CXX object CMakeFiles/dummy.dir/a.cpp.o 
Linking CXX executable dummy 
[100%] Built target dummy 

(Хотя здесь файл ЬН записывается каждый раз вызывая a.cpp перекомпилировать)

Эта заглушка может быть очень улучшена используя команды cmake для генерации выходных каталогов (а не mkdir) и каскадирования генератора, выбранного для основного проекта (здесь я предполагаю, что все использует make)

Сообщите мне, если вам нужно какое-либо уточнение.

+0

Комментарии не предназначены для расширенного обсуждения; этот разговор был [перемещен в чат] (http://chat.stackoverflow.com/rooms/76171/discussion-on-answer-by-antonio-add-custom-command-update-dependency-list-ove). – Taryn

0

Я думаю, что ${codegenInputFiles} должен содержать список файлов с жесткой кодировкой и включать файлы, необходимые для пользовательской команды. Документация file(GLOB ...) состояний:

Мы не рекомендуем использовать Глоб собрать список исходных файлов из исходного дерева. Если файл CMakeLists.txt не изменяется, если источник добавлен или удален , то сгенерированная система сборки не может знать, когда до запросите CMake для регенерации.

Настоящая работа (за которую мы платим) должна поддерживать актуальную актуальность ${codegenInputFiles} (в результате чего происходит полная перестройка проекта). В любом случае, у вас возникла бы аналогичная проблема, если бы кто-то создал новый исходный файл и не добавил его в ${codegenInputFiles}, правильно? Поэтому я считаю, что к дополнительной зависимости от файла include следует относиться одинаково.

+0

GLOB не используется для создания $ {codegenInputFiles}. Codegen сам всегда снабжен одним файлом, который может включать в себя другие файлы. Поэтому для сгенерированных источников в соответствии с их моделью мне нужно, чтобы cmake наблюдал за зависимостями (например, файл i, предоставленный для codegen и других файлов, которые он включает) и запускать codegen, как только какая-либо зависимость изменяется. Тем не менее, я не вижу способа настроить список файлов для просмотра, как только он был добавлен в add_custom_command. Мне нужно сделать это, если из-за модификации включите добавление или удаление. – Konstantin

+0

$ {codegenInputFiles} предоставляется пользовательской функцией cmake, которая сканирует указанный входной файл для любых включений и рекурсивно вызывает себя, чтобы обрабатывать полное дерево зависимостей одного входного файла codegen. – Konstantin

+0

Дополнительная информация: в проекте есть несколько независимых вызовов-кодегенов, каждый из которых имеет один входной файл (+ его включает), соответствующие источники и вызывает add_custom_command для настройки денуденций с определенным набором источников и определенным набором входов – Konstantin