Как удалить дубликаты одинаковых источников зависимостей в зависимых проектах

1

У меня есть два проекта cmake. Один из них использует googletest, а второй из них также использует его. Что еще, я использовал первый проект во втором проекте.

У меня есть второй проект по github, а googletest также находится на github. Поэтому я хочу загрузить их, когда создаю свой первый проект, используя

ExternalProject_Add

команда.


Это упрощенная структура папок:

ProjectA
| build/
| include/
| src/
| modules/
| | ProjectB/
| | | CMakeLists.txt
| | googletest/
| | | CMakeLists.txt
| CMakeLists.txt

И упрощенная структура для ProjectB:

ProjectB/
| build/
| include/
| src/
| modules/
| | googletest/
| | | CMakeLists.txt
| CMakeLists.txt

И теперь у меня есть важный вопрос: можно скачать код googletest один раз? На данный момент я загружаю его дважды, один раз для ProjectA, и второй раз для ProjectB.

Я могу добавить упрощенный код CMakeLists.txt, но я не думаю, что он нужен здесь.

Теги:
cmake
build

2 ответа

1
Лучший ответ

Вы можете рассматривать googletest как третий внешний проект, а затем передать свое местоположение в оба ваших проекта в качестве переменных кэша CMake. Это обеспечит вам только один раз загрузить googletest, но это может быть немного менее удобно, чем при создании googletest непосредственно в рамках проекта. Вы могли бы создать четвертый проект верхнего уровня, чтобы объединить каждый из трех проектов (googletest, projectA и projectB), чтобы вы могли обеспечить, чтобы googletest был создан до того, как вам нужно настроить projectA или projectB. ExternalProject для googletest установит цели и gmock для своей области установки. Затем вы передаете этот каталог в projectA и projectB ExternalProjects в качестве места для поиска теста google. Вы можете использовать модуль FindGTest внутри projectA и projectB для этого, если ваш проект верхнего уровня GTEST_ROOT переменную кеша GTEST_ROOT для projectA и projectB. Вероятно, это самый простой вариант.

Другим вариантом было бы загрузить и построить googletest как часть projectA (см. Здесь метод, который я бы рекомендовал сделать), а затем заставить ProjectB повторно использовать источник googletest или еще лучше, построенные объекты из projectA. Вы могли бы привести projectA в projectB так же, как приведенная выше ссылка приносит googletest в projectA, если вы хотите. Мы используем такую схему на работе, чтобы объединить ряд различных проектов, каждый из которых может быть построен отдельно или как часть других проектов. Преимущество этого метода заключается в том, что если вы используете IDE, например Visual Studio, Xcode или Qt Creator, вы можете увидеть источники всех проектов в вашем исходном списке, а также проблемы обнаружения IDE, инструменты рефакторинга и т.д., Как правило, имеют более полное представление об общей сборке. Он также сводит к минимуму информацию, которая должна быть вручную передана между проектами, поскольку CMake видит весь набор источников и целей в одной сборке, и поэтому нет необходимости явно обращаться к именам библиотек, относящихся к платформе, различным структурам выходных каталогов сборки, и т.д.

Если вы хотите сохранить ProjectA в качестве внешнего проекта ProjectB, то вы все равно можете повторно использовать источник googletest из projectA, но вам нужно будет очень тщательно настроить межзадачные зависимости, чтобы обеспечить, чтобы projectA был построен до всего, что нужно для источников googletest, Вам, вероятно, также придется вручную разобраться, куда вещи загружаются и выстраиваются в projectA, и это может быть больно, если ваш проект построен на нескольких платформах. Похоже, что это самое близкое к тому, что вы спрашиваете, как это сделать, но я бы предположил попробовать один из двух подходов выше.

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

  • 0
    Спасибо за Ваш ответ! Я проверю это сегодня.
  • 0
    Спасибо за сложный ответ. Я проверил ваш пост в блоге и репозиторий Git и, вероятно, я использую этот метод в своей задаче
1

Если вы не хотите дважды загружать среду тестирования Google C++, вы можете просто использовать соответствующий модуль cmake и позволить ему находить то, что вам нужно из вашей среды.

См. FindGTest.

Пример использования приведенного выше:

enable_testing()
find_package(GTest REQUIRED)
add_executable(foo foo.cc)
target_link_libraries(foo GTest::GTest GTest::Main)
add_test(AllTestsInFoo foo)

Это, как говорится, это разные проекты с их собственными модулями. Лучше было бы говорить о них откровенно.
Вы все равно можете поместить пользовательский модуль поиска cmake в ProjectB который ищет gtest в ProjectA. В любом случае это хрупкое решение, поскольку оно будет ломаться, как только изменения в ProjectA меняются.


Вопрос в комментариях:

Кажется, это действительно хорошо для gtest, но мне интересно, есть ли у меня разные проекты, чем gtest (например ProjectC), то что мне делать? Я ищу более универсальное решение.

Если я не могу искать зависимости в своей системе через правильный модуль поиска (вместе с версиями, когда это необходимо), я обычно предпочитаю быть явным о них. Поэтому я добавляю необходимые зависимости к каждому проекту, даже если это означает их перекомпиляцию дважды.
Вопрос, который может ответить на whys: что, если ProjectA зависит от тега x для данного модуля, а ProjectB требует, чтобы тэг y работал? Если два тега нарушают API друг друга (к сожалению, иногда это происходит), у вас будут проблемы, если вы явно не зависите от каждого проекта.

  • 0
    Итак, если вы думаете, что будет лучше иметь две независимые копии тестовых источников Google?
  • 0
    @ BartekPL Нет, я думаю, вы можете безопасно использовать модуль FindGTest . Почему нет?
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню