Пользовательский объект с зависимостями в CMake

Я добавляю пользовательскую функцию, скажем, MyFeature, в проект, который использует CMake и имеет отдельные каталоги исходного кода и сборки. MyFeature состоит из одного двоичного файла. (MyFeature на самом деле является пользовательской библиотекой Simulink, поэтому для ее создания мне приходится вызывать MATLAB — здесь важно то, что создание объекта не требует использования GCC или других стандартных инструментов сборки, которые использует CMake. по умолчанию.) Итак, у меня есть специальное правило для создания объекта, скажем, myRule. Я хочу, чтобы make запускал myRule, только если (a) MyFeature не существует или (b) единственный исходный файл, в котором MyFeature зависит, например, MySource, новее, чем существующий в настоящее время MyFeature. Небольшая дополнительная проблема заключается в том, что мне действительно нужен MyFeature только в исходном дереве, где его обычно размещает myRule. Как я могу выполнить все это?

Насколько я могу судить, я не могу использовать ни add_executable, ни add_library, потому что они предназначены исключительно для объектов, которые вы создаете с помощью цепочки инструментов GCC (или уже настроенной иным образом). . Я не могу использовать add_custom_target, так как полученная цель всегда устарела. До сих пор я добился определенного прогресса, используя комбинацию add_custom_target и add_custom_command, а именно:

add_custom_target(fakeTarget
    DEPENDS MyFeature)

add_custom_command(OUTPUT MyFeature
    COMMAND myRule && touch ${CMAKE_CURRENT_BINARY_DIR}/MyFeature
    DEPENDS mySource)

add_dependencies(targetThatAlwaysRuns fakeTarget)

Команды для создания пустого файла MyFeature в дереве сборки кажется достаточно, чтобы подделать make, чтобы он не перестраивался, если настоящий MyFeature существует (в исходном коде). tree), который достигает одной из моих целей. Однако, если этот поддельный файл существует, даже если я обновлю MySource в дереве исходного кода, make не перестроит MyFeature. Вот где я застрял. Это кажется особенно загадочным, потому что я вижу во внутренностях CMakeFiles, что существует цель для MyFeature, которая действительно перечисляет MySource (с правильным путем --в исходном дереве!) в качестве зависимости. Если бы я попытался воспроизвести эту ситуацию с гораздо более простым (игрушечным) файлом Makefile в одном каталоге, если бы я обновил один из исходных файлов, от которых зависит цель, даже если целевой файл вывода уже существует, make< /strong> сделает все правильно — перестроит объект из обновленного источника, а затем перестроит общую цель. Так почему же поведение сборки в этой ситуации отличается? И что я могу сделать, чтобы достичь цели (б) вместе с целью (а)? Спасибо!


person Amittai Aviram    schedule 30.05.2017    source источник
comment
Предполагая, что под add_custom_rule вы подразумеваете add_custom_command, ваш подход должен работать. Попробуйте использовать абсолютные пути в параметрах DEPENDS и OUTPUT. Небольшая дополнительная проблема заключается в том, что мне действительно нужна только MyFeature в исходном дереве - ничто не мешает вам создать файл в исходном дереве.   -  person Tsyvarev    schedule 31.05.2017
comment
Ой! Да, я имел в виду add_custom_command — отредактировал, чтобы исправить это. Правда, мне ничего не мешает создать файл в дереве исходников; Я объяснял причину моего хака по размещению пустого файла в дереве сборки. CMake не не позволяет мне определить цель в исходном дереве, поэтому выходной файл в add_custom_command также не может находиться в исходном дереве.   -  person Amittai Aviram    schedule 31.05.2017
comment
Добавление абсолютного пути к параметру DEPENDS в add_custom_command сработало! Спасибо!   -  person Amittai Aviram    schedule 31.05.2017
comment
Теперь вопрос заключается в том, как я могу избежать хака записи фиктивного файла MyFeature в дерево сборки, чтобы Make пропустил правило сборки, если настоящий MyFeature существует. Проблема с этим приемом заключается в том, что он не работает, если, скажем, пользователь удалит настоящий MyFeature в исходном дереве: до тех пор, пока поддельный MyFeature все еще находится в исходном дереве. построить дерево, Make не будет перегенерировать MyFeature.   -  person Amittai Aviram    schedule 31.05.2017
comment
Я не совсем понимаю: если вам нужно, чтобы MyFeature было сгенерировано в исходном дереве, зачем вы создаете его в бинарном дереве? ВЫВОД add_custom_command также может быть в исходном дереве, просто используйте абсолютные пути.   -  person Tsyvarev    schedule 31.05.2017


Ответы (1)


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

add_custom_target(fakeTarget
    DEPENDS MyFeature)

add_custom_command(OUTPUT MyFeature
    COMMAND myRule && touch ${CMAKE_CURRENT_BINARY_DIR}/MyFeature
    DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/mySource)

add_dependencies(targetThatAlwaysRuns fakeTarget)

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

person Amittai Aviram    schedule 31.05.2017