我们正在使用CMake在一个整体存储库中管理我们的代码,包括多个产品和库。当前,这些项目通过add_subdirectory
使用。例如:
回购布局:
Foo
Bar
Baz
Product
Bar 和 Baz 取决于 Foo ,而 Product 取决于 Bar 和 Baz 。
在文件/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)
# ......
在最终产品中,/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概念,使培训新成员变得更加困难。${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管理大型的整体代码?