Установка только одной цели (и ее зависимостей) из сложного проекта с помощью cmake (открытой для лучших решений)

Допустим, у меня есть проект, состоящий из нескольких подпроектов A, B, C, D ...Все подпроекты зависят от, который меняется довольно часто. Кроме того, могут быть некоторые дополнительные зависимости: в этом примереD зависит от B.

Сейчас: многие люди работают над этими проектами. Основной файл CMakeLists.txt должен включать в себя все каталоги, чтобы сборка собирала все. Но люди хотели бы также иметь возможность работать только над одним из этих проектов, и при этом не нужно каждый раз собирать / устанавливать все.

Если я работаю над D, я могу легко собрать "только" D, вызвав

cmake --build . --target D -- -j7

или же

ninja -j7 D

Это также создаст A и B, если что-то для них изменилось. Отлично.

Но как я могу вызвать install только для D, не вызывая build all? Я хотел бы, чтобы я позвонил:

ninja -j7 D install

он только построил D (и зависимости), а затем установил только Dи его зависимости (A и B). Вместо этого он создает цель all и устанавливает все.

Я хотел бы, чтобы цель все продолжала строить все. Так что EXCLUDE_FROM_ALL не будет вариантом. Но, двигаясь в этом направлении, я не мог найти никакого решения.

Поэтому я думаю о следующей стратегии:

За исключением подпроекта A, все остальные цели устанавливаются в EXCLUDE_FROM_ALL и OPTIONAL при установке.Я добавляю один дополнительный подпроект, который просто зависит от всех других подпроектов (возможно, я заставляю каждую цель публиковать свое имя, используя некоторую переменную, установленную в PARENT_SCOPE), и людям придется вызывать это, когда они хотят собрать и установить все.

Это сработает? Есть ли лучшее решение?

Мы хотели бы избежать того, что каждый должен редактировать основной файл CMakeLists.txt, чтобы исключить проекты, которые ему не интересны. Решение должно быть переносимым на разные ОС.

Редактировать:

Я попробовал предложенную мной стратегию, но она не сработала: в моем случае установка оператора установки для цели (даже если она указана как OPTIONAL) приведет к неэффективности EXCLUDE_FROM_ALL. Чтение лучше вдокументация Я узнал что:

Installing a target with EXCLUDE_FROM_ALL set to true has undefined behavior.

Я также получаю это предупреждение:

Target <targetname> has EXCLUDE_FROM_ALL set and will not be built by default but an install rule has been provided for it.  CMake does not define behavior for this case.

Изменить 2:

Я попытался поместить EXCLUDE_FROM_ALL в качестве опции add_subdirectory (вместо add_library / add_executable), но тогда все операторы установки в этих подкаталогах, похоже, игнорируются: будут устанавливаться только операторы установки в подкаталогах не исключенных из всех.

Изменить 3:

Даже если я активируюCMAKE_SKIP_INSTALL_ALL_DEPENDENCY:

set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY true)

в основном файле CMakeLists.txt, и я опускаю все EXCLUDE_FROM_ALL, помещаю установку столько целей, сколько я хочу, необязательно (в моем случае, все, кроме A), и если сборка конкретных целей предшествует установке, все же команда:

ninja -j7 D && ninja install

по какой-то причине произойдет сбой, заявив, что C (установка которого была установлена на OPTIONAL) не существует (он не был создан, потому что D зависел только от A и B) ...

file INSTALL cannot find "<name of dll file for C>"

Изменить 4:

Это похоже на ошибку cmake для меня. (Я использую 2.8.11 под Windows, также протестирован 2.8.10) Эта команда INSTALL

install(TARGETS ${targetname} RUNTIME DESTINATION . LIBRARY DESTINATION . OPTIONAL)

преобразуется в cmake_install.cmake как:

IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified")   

ФАЙЛ (УСТАНОВИТЬ НАЗНАЧЕНИЕ "$ {CMAKE_INSTALL_PREFIX} /." ТИП SHARED_LIBRARY FILES * path_to_dll *)

ЕСЛИ (СУЩЕСТВУЕТ "$ ENV {DESTDIR} $ {CMAKE_INSTALL_PREFIX} /./" И НЕ IS_SYMLINK "$ ENV {DESTDIR} $ {CMAKE_INSTALL_PREFIX} /./* dll_name *")

IF(CMAKE_INSTALL_DO_STRIP)

  EXECUTE_PROCESS(COMMAND "C:/Programs/MinGW/bin/strip.exe" "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/./*dll_name*")

ENDIF(CMAKE_INSTALL_DO_STRIP)   ENDIF() ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified")

с командой FILE отсутствует ДОПОЛНИТЕЛЬНО! Если я добавлю ДОПОЛНИТЕЛЬНО вручную, это работает! (примечание: я отредактировал здесь, чтобы поместить * dll_name * и * path_to_dll * заполнители)

Изменить 5:

Я подтверждаю, что это ошибка cmake или, по крайней мере, неправильная документация. Я сообщу об этом. Ситуация решена либо выкладываю более простую

install(TARGETS ${targetname} DESTINATION . OPTIONAL)

(но в моем случае это также установит файлы .lib.a, которые мне не нужны)

или передвигая ФАКУЛЬТАТИВНЫЙ флаг:

install(TARGETS ${targetname} OPTIONAL RUNTIME DESTINATION . LIBRARY DESTINATION .)

Что можно понять изcmake документация является то, что ДОПОЛНИТЕЛЬНО должно быть поставлено как последний вариант.

Ответы на вопрос(4)

Ваш ответ на вопрос