Я хочу настроить свой проект с помощью CMake, чтобы он мог быть разработан с использованием TDD, что означает , включая и тестируя внутренние заголовки .Но правильная настройка библиотеки с помощью CMake скрывает эти детали реализации (и правильно для внешнего использования) от моих модульных тестов.
При такой структуре файлов и папок:
Foo
|-- include
| `-- Foo
| `-- Foo.h
|-- CmakeLists.txt
|-- src
| |-- Bar
| | |-- Bar.h
| | `-- Bar.cpp
| |-- Baz
| | |-- Baz.h
| | `-- Baz.cpp
| |-- Foo.cpp
| `-- CMakeLists.txt
`-- test
|-- Bar
| `-- BarTest.cpp
|-- Baz
| `-- BazTest.cpp
|-- FooTest.cpp
`-- CMakeLists.txt
Foo/CMakeLists.txt
project(Foo)
include(CTest)
add_subdirectory(src)
if(BUILD_TESTING)
add_subdirectory(test)
endif()
Foo / src / CMakeLists.txt
add_library(Foo)
target_include_directories(Foo
PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
PRIVATE
${CMAKE_CURRENT_LIST_DIR}
)
target_sources(Foo
PRIVATE
Foo.cpp
Bar/Bar.cpp
Baz/Baz.cpp
)
Foo / test / CMakeLists.txt
find_package(Catch2 REQUIRED)
include(Catch)
add_executable(FooTest
FooTest.cpp
Bar/BarTest.cpp # This file can't #include "Bar/Bar.h"
Baz/BazTest.cpp # This file can't #include "Baz/Baz.h"
)
target_link_libraries(FooTest
PRIVATE
Foo
Catch2::Catch2
)
Теперь проблема заключается в том, чтоFooTest связывается с Foo так, как это делают другие проекты, когда им нужна библиотека Foo в качестве зависимости.Это создает проблему, из-за которой я не могу запустить модульные тесты в Bar/BarTest.cpp
и Baz/BazTest.cpp
, которые включают файлы #include "Bar/Bar.h"
и #include "Baz/Baz.h
.В идеале, на мой взгляд, решение могло бы получить внутреннюю цель shortcut
для Foo, которая включает в себя все как PUBLIC, на котором я могу запускать тесты.Но при установке внутренние заголовки являются частными, и только файлы в include/Foo/
являются общедоступными.
Решения, которые я видел, - это либо создать много подцелей и включить в них только то, что вам нужно для каждого теста.Но это кажется громоздким и не очень хорошо подходит для менеджеров пакетов, таких как Конан, в очень модульной конфигурации.
Другое решение - создать дублирующую цель Foo, где все открыто, но для этого нужно, чтобы я писал все дважды.Звучит как грязный путь для меня.
Последнее решение, о котором я подумал, - это создать внутреннюю цель FooInternal с каждым заголовком и источником, установленным в public, с которым затем FooTest может связать.Затем создайте библиотеку обёрток как Foo, которая связывает FooInternal как частную, но устанавливает папку include/Foo
в качестве общедоступных заголовков.Но для этого требуется, чтобы Foo был целью интерфейса, который затем не будет экспортировать libFoo
, чтобы я мог создать собственную логику для переименования или каким-то образом настроить CMake для использования libFooInternal
в качестве правильного файла lib.Опять же, это звучит грязно, и я не уверен, как это будет работать на практике.
Существуют ли очевидные решения, о которых я не замечаю, или у кого-нибудь есть хорошее решение этой проблемы?