Скомпилируйте gtest из исходного кода с помощью catkin

Я пытаюсь скомпилировать gtest из исходного кода (вместо использования существующей установленной версии). Я работаю над проектом cmake на основе сережек.

Я добавил исходный код из https://github.com/google/googletest в свою рабочую область и включил папку с add_subdirectory.

Тем не менее, я получаю nameclash с существующим gtest:

CMake Error at src/test_env/GTest/googletest/cmake/internal_utils.cmake:151 (add_library):
  add_library cannot create target "gtest" because another target with the
  same name already exists.  The existing target is a shared library created
  in source directory "/usr/src/gtest".  See documentation for policy CMP0002
  for more details.

Из других сообщений и самой инструкции googletest ( https://github.com/google/googletest/tree/master/googletest) я понимаю, что это не должно быть проблемой.

Я думаю, что проблема может заключаться в том, как сережка обрабатывает gtest. И, по общему признанию, обычно я мог просто использовать установленную версию. Но я хочу убедиться, что все используют одну и ту же (в комплекте) версию gtest.

Любые предложения и советы приветствуются.

1 ответ

Решение

Итак, сообщение об ошибке на самом деле довольно ясно. "Target" cmake - это "то, что будет создано сборкой", будь то библиотека, или исполняемый файл, или что-то еще. Итак, проблема в том, что вы пытаетесь добавить цель с именем "gtest", и catkin уже делает то же самое. И то и другое создаст библиотеку "libgtest.so", и, конечно, в одной папке может быть только одна из них. Вы можете переименовать "свой" gtest, изменив имя цели в googletest / CMakelists.txt, но я настоятельно рекомендую вам не делать этого.

По моему мнению, gtest вообще не должен быть общей библиотекой, особенно если вы используете разные флаги сборки для разных проектов в вашем хранилище. Есть альтернатива, и это в основном только включение исходного кода gtest в папку, а затем включение заголовочных файлов и исходных файлов в ваши юнит-тесты main.cpp, GoogleTest уже идет с помощниками для этого, то есть src/gtest-main.cc,

Вот как я бы это структурировал:

  1. Добавьте нужную версию gtest в качестве подмодуля в git (если вы используете git). Таким образом, у вас есть указанная версия для всех проектов в вашем репо, и вы можете обновить ее в другой ветке. Я назову эту папку "GTEST_DIR".
  2. Напишите свои юнит-тесты в .cpp файлы, которые #include <gtest/gtest.h> по одному hpp вы хотите проверить, и #include оба hpp и cpp в вашем test.cpp, Это обеспечивает отделение ваших тестов от других классов и позволяет очень легко переключать зависимые классы с помощью ложных или фиктивных объектов. Вам не понадобится main() функция, так как тот уже находится в gtest-main.cc,
  3. Напишите макрос cmake следующим образом:

    macro(add_gtest NAME FILES)
    add_executable(my_gtest_$NAME
      $FILES
      GTEST_DIR/src/gtest.cc
      GTEST_DIR/src/gtest-death-test.cc
      GTEST_DIR/src/gtest-filepath.cc
      GTEST_DIR/src/gtest-port.cc
      GTEST_DIR/src/gtest-printers.cc
      GTEST_DIR/src/gtest-test-part.cc
      GTEST_DIR/src/gtest-typed-test.cc
      GTEST_DIR/src/gtest-main.cc
    )
    target_include_directories(my_gtest_$NAME GTEST_DIR/include)
    endmacro()
    

Конечно, вы можете сделать это более сложным или менее сложным, но это суть. Конечно, таким образом время компиляции будет больше, чем при использовании gtest в качестве разделяемой библиотеки, но это на самом деле гарантирует, что ваши модули будут тестироваться изолированно, что, на мой взгляд, очень ценно. Также вы можете использовать ccache значительно улучшить время компиляции в этом сценарии, потому что объектные файлы gtest никогда не меняются. Кроме того, это обеспечит компиляцию gtest именно с теми флагами, которые вам нужны. Например, вы можете создать 2 отдельных модульных теста для одного и того же класса, один с включенными исключениями и один без.

Другие вопросы по тегам