Мы используем CMake для управления нашими кодами, включая несколько продуктов и библиотек, в одном монолитном хранилище.В настоящее время эти проекты используются через add_subdirectory
.Например:
Расположение репо:
Foo
Bar
Baz
Product
Принимая во внимание, что Bar и Baz зависит от Foo и Продукт зависит от Бар и Баз .
В файле /Foo/CMakeLists.txt
:
cmake_minimum_required(VERSION 3.10)
include_guard(GLOBAL)
project(Foo)
add_library(foo ......)
# ......
В файле /Bar/CMakeLists.txt
:
cmake_minimum_required(VERSION 3.10)
include_guard(GLOBAL)
project(Bar)
add_subdirectory(../Foo sibling/Foo)
add_library(bar ......)
target_link_libraries(bar foo)
# ......
В файле /Baz/CMakeLists.txt
:
cmake_minimum_required(VERSION 3.10)
include_guard(GLOBAL)
project(Baz)
add_subdirectory(../Foo sibling/Foo)
add_library(baz
target_link_libraries(baz foo)
# ......
И в конечном продукте cmake /Product/CMakeLists.txt
:
cmake_minimum_required(VERSION 3.10)
include_guard(GLOBAL)
project(Product)
add_subdirectory(../Bar sibling/Bar)
add_subdirectory(../Baz sibling/Baz)
add_executable(product ......)
target_link_libraries(product bar baz)
# ......
Этот макет решает проблему алмазов и позволяеткаждый проект генерируется отдельно.Однако он имеет следующие недостатки:
-
CMakeLists.txt
становятся более сложными.Он содержит больше строк и использует больше концепций CMake, что усложняет обучение новых участников. - Когда номер проекта увеличивается, двоичный каталог становится беспорядочным, и очень трудно найти фактический двоичный каталог базового проекта.Например, фактический двоичный каталог Base может быть расположен в
${CMAKE_BINARY_DIR}/Some/sibling/Very/sibling/Deep/sibling/Dependencies/sibling/Base
или ${CMAKE_BINARY_DIR}/Another/sibling/Damn/sibling/Deep/sibling/Dependencies/sibling/Base
.
Мы также попробовали более монолитный способ: использовать корневой файл CMake, который включает все проекты:
В файле /CMakeLists.txt
:
cmake_minimum_required(VERSION 3.0)
project(MegaProject)
add_subdirectory(Base)
add_subdirectory(Foo)
add_subdirectory(Bar)
add_subdirectory(Product)
Для этого не нужно писать комплексный файл CMake для каждого проекта, вам нужны только такие вещи:
project(Product)
add_executable(product ......)
target_link_libraries(product bar baz)
, которыесокращено много строк.
Тем не менее, у него есть критическая проблема: требуется генерация всей кодовой базы, а когда появляются массивные проекты, время генерации становится слишком длинным.
Итак, какуправлять большим монолитным кодом с помощью CMake?